Commit a45a0786 authored by Fred Drake's avatar Fred Drake

Merge ZConfig schema support integration from the zconfig-schema-devel-branch.

parent 47dd73d4
...@@ -22,14 +22,15 @@ import socket ...@@ -22,14 +22,15 @@ import socket
import asyncore import asyncore
import ThreadedAsync.LoopCallback import ThreadedAsync.LoopCallback
import ZConfig import ZConfig.Context
import zLOG import zLOG
from ZODB import StorageConfig from ZODB import StorageConfig
import ZEO.StorageServer import ZEO.StorageServer
def load_storage(fp): def load_storage(fp):
rootconf = ZConfig.loadfile(fp) context = ZConfig.Context.Context()
rootconf = context.loadFile(fp)
storageconf = rootconf.getSection('Storage') storageconf = rootconf.getSection('Storage')
return StorageConfig.createStorage(storageconf) return StorageConfig.createStorage(storageconf)
......
##############################################################################
#
# Copyright (c) 2001, 2002 Zope Corporation and Contributors.
# All Rights Reserved.
#
# This software is subject to the provisions of the Zope Public License,
# Version 2.0 (ZPL). A copy of the ZPL should accompany this distribution.
# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
# FOR A PARTICULAR PURPOSE
#
##############################################################################
"""Open database and storage from a configuration.
$Id: config.py,v 1.2 2003/01/03 21:19:06 fdrake Exp $"""
import os
import StringIO
import ZConfig
import ZODB
schema_path = os.path.join(ZODB.__path__[0], "config.xml")
_schema = None
def getSchema():
global _schema
if _schema is None:
_schema = ZConfig.loadSchema(schema_path)
return _schema
def databaseFromString(s):
return databaseFromFile(StringIO.StringIO(s))
def databaseFromFile(f):
config, handle = ZConfig.loadConfigFile(getSchema(), f)
return databaseFromConfig(config)
def databaseFromURL(url):
config, handler = ZConfig.loadConfig(getSchema(), url)
return databaseFromConfig(config)
def databaseFromConfig(config):
return ZODB.DB(config.storage.open(),
pool_size=config.pool_size,
cache_size=config.cache_size,
version_pool_size=config.version_pool_size,
version_cache_size=config.version_cache_size)
class StorageConfig:
def __init__(self, config):
self.config = config
def open(self):
raise NotImplementedError
class MappingStorage(StorageConfig):
def open(self):
from ZODB.MappingStorage import MappingStorage
return MappingStorage(self.config.name)
class FileStorage(StorageConfig):
def open(self):
from ZODB.FileStorage import FileStorage
return FileStorage(self.config.path,
create=self.config.create,
read_only=self.config.read_only,
stop=self.config.stop,
quota=self.config.quota)
class ZEOClient(StorageConfig):
def open(self):
from ZEO.ClientStorage import ClientStorage
# config.server is a multikey of socket-address values
# where the value is a socket family, address tuple.
L = [addr for family, addr in self.config.server]
return ClientStorage(
L,
storage=self.config.storage,
cache_size=self.config.cache_size,
name=self.config.name,
client=self.config.client,
var=self.config.var,
min_disconnect_poll=self.config.min_disconnect_poll,
max_disconnect_poll=self.config.max_disconnect_poll,
wait=self.config.wait,
read_only=self.config.read_only,
read_only_fallback=self.config.read_only_fallback)
class BDBStorage(StorageConfig):
def open(self):
from BDBStorage.BerkeleyBase import BerkeleyConfig
from BDBStorage.BDBFullStorage import BDBFullStorage
from BDBStorage.BDBMinimalStorage import BDBMinimalStorage
# Figure out which class we want
sectiontype = self.config.getSectionType()
storageclass = {'fullstorage': BDBFullStorage,
'minimalstorage': BDBMinimalStorage,
}[sectiontype]
bconf = BerkeleyConfig()
for name in dir(BerkeleyConfig):
if name.startswith('_'):
continue
setattr(bconf, name, getattr(self.config, name))
return storageclass(self.config.name, config=bconf)
<schema type="database">
<sectiongroup type="storage">
<sectiontype type="filestorage" datatype="ZODB.config.FileStorage">
<key name="path" required="yes"/>
<key name="create" datatype="boolean" default="true"/>
<key name="read_only" datatype="boolean" default="false"/>
<key name="stop"/>
<key name="quota" datatype="integer"/>
</sectiontype>
<sectiontype type="mappingstorage" datatype="ZODB.config.MappingStorage">
<key name="name" default="Mapping Storage"/>
</sectiontype>
<sectiontype type="fullstorage" datatype="ZODB.config.BDBStorage">
<key name="name" required="yes" />
<key name="interval" datatype="time-interval" default="2m" />
<key name="kbyte" datatype="integer" default="0" />
<key name="min" datatype="integer" default="0" />
<key name="logdir" />
<key name="cachesize" datatype="byte-size" default="128MB" />
<key name="frequency" datatype="time-interval" default="0" />
<key name="packtime" datatype="time-interval" default="4h" />
<key name="classicpack" datatype="integer" default="0" />
<key name="read_only" datatype="boolean" default="off"/>
</sectiontype>
<!-- XXX Fred promises to make it so minimal storage is just an
extension of fullstorage -->
<sectiontype type="minimalstorage" datatype="ZODB.config.BDBStorage">
<key name="name" required="yes" />
<key name="interval" datatype="time-interval" default="2m" />
<key name="kbyte" datatype="integer" default="0" />
<key name="min" datatype="integer" default="0" />
<key name="logdir" />
<key name="cachesize" datatype="byte-size" default="128MB" />
<key name="frequency" datatype="time-interval" default="0" />
<key name="packtime" datatype="time-interval" default="4h" />
<key name="classicpack" datatype="integer" default="0" />
<key name="read_only" datatype="boolean" default="off"/>
</sectiontype>
<sectiontype type="zeoclient" datatype="ZODB.config.ZEOClient">
<multikey name="server" datatype="socket-address" required="yes"/>
<key name="storage" default="1"/>
<key name="cache_size" datatype="integer" default="20000000"/>
<key name="name" default=""/>
<key name="client"/>
<key name="var"/>
<key name="min_disconnect_poll" datatype="integer" default="5"/>
<key name="max_disconnect_poll" datatype="integer" default="300"/>
<key name="wait" datatype="boolean" default="on"/>
<key name="read_only" datatype="boolean" default="off"/>
<key name="read_only_fallback" datatype="boolean" default="off"/>
</sectiontype>
<sectiontype type="demostorage">
<!--datatype="ZODB.config.DemoStorage"-->
<key name="name" default="Demo Storage"/>
<section type="storage" name="*" attribute="base"/>
<key name="quota" datatype="integer"/>
</sectiontype>
</sectiongroup>
<!-- the rest is the actual configuration for the database -->
<section type="storage" name="*" attribute="storage"/>
<key name="cache_size" datatype="integer" default="5000"/>
<key name="pool_size" datatype="integer" default="7"/>
<key name="version_pool_size" datatype="integer" default="3"/>
<key name="version_cache_size" datatype="integer" default="100"/>
</schema>
##############################################################################
#
# Copyright (c) 2001, 2002 Zope Corporation and Contributors.
# All Rights Reserved.
#
# This software is subject to the provisions of the Zope Public License,
# Version 2.0 (ZPL). A copy of the ZPL should accompany this distribution.
# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
# FOR A PARTICULAR PURPOSE.
#
##############################################################################
import os
import errno
import shutil
import tempfile
import unittest
import ZODB.config
import ZODB.tests
from ZODB.POSException import ReadOnlyError
from ZEO.ClientStorage import ClientDisconnected
class ConfigTestBase(unittest.TestCase):
def _opendb(self, s):
return ZODB.config.databaseFromString(s)
def _test(self, s):
db = self._opendb(s)
# Do something with the database to make sure it works
cn = db.open()
rt = cn.root()
rt["test"] = 1
get_transaction().commit()
db.close()
class ZODBConfigTest(ConfigTestBase):
def test_map_config1(self):
self._test("<mappingstorage/>")
def test_map_config2(self):
self._test(
"""<mappingstorage/>
cache_size 1000
""")
def test_file_config1(self):
path = tempfile.mktemp()
self._test(
"""<filestorage>
path %s
</filestorage>
""" % path)
os.unlink(path)
def test_file_config2(self):
path = tempfile.mktemp()
cfg = """
<filestorage>
path %s
create false
read_only true
</filestorage>
""" % path
self.assertRaises(ReadOnlyError, self._test, cfg)
def test_zeo_config(self):
cfg = """
<zeoclient>
server /no/path/var/test/foo
wait false
</zeoclient>
"""
self.assertRaises(ClientDisconnected, self._test, cfg)
class BDBConfigTest(ConfigTestBase):
def setUp(self):
self._path = tempfile.mktemp()
try:
os.mkdir(self._path)
except OSError, e:
if e.errno <> errno.EEXIST:
raise
def tearDown(self):
shutil.rmtree(self._path)
def test_bdbfull_simple(self):
cfg = """
<fullstorage>
name %s
</fullstorage>
""" % self._path
self._test(cfg)
def test_bdbminimal_simple(self):
cfg = """
<minimalstorage>
name %s
</minimalstorage>
""" % self._path
self._test(cfg)
def test_suite():
suite = unittest.TestSuite()
suite.addTest(unittest.makeSuite(ZODBConfigTest))
try:
import BDBStorage.BDBFullStorage
except ImportError:
pass
else:
suite.addTest(unittest.makeSuite(BDBConfigTest))
return suite
if __name__ == '__main__':
unittest.main(defaultTest='test_suite')
...@@ -17,7 +17,7 @@ import tempfile ...@@ -17,7 +17,7 @@ import tempfile
import unittest import unittest
from StringIO import StringIO from StringIO import StringIO
import ZConfig import ZConfig.Context
from ZODB import StorageConfig from ZODB import StorageConfig
...@@ -46,6 +46,11 @@ class StorageTestCase(unittest.TestCase): ...@@ -46,6 +46,11 @@ class StorageTestCase(unittest.TestCase):
except os.error: except os.error:
pass pass
def loadConfigText(self, text):
context = ZConfig.Context.Context()
io = StringIO(text)
return context.loadFile(io)
def testFileStorage(self): def testFileStorage(self):
from ZODB.FileStorage import FileStorage from ZODB.FileStorage import FileStorage
sample = """ sample = """
...@@ -55,8 +60,7 @@ class StorageTestCase(unittest.TestCase): ...@@ -55,8 +60,7 @@ class StorageTestCase(unittest.TestCase):
create yes create yes
</Storage> </Storage>
""" % self.tmpfn """ % self.tmpfn
io = StringIO(sample) rootconf = self.loadConfigText(sample)
rootconf = ZConfig.loadfile(io)
storageconf = rootconf.getSection("Storage") storageconf = rootconf.getSection("Storage")
cls, args = StorageConfig.getStorageInfo(storageconf) cls, args = StorageConfig.getStorageInfo(storageconf)
self.assertEqual(cls, FileStorage) self.assertEqual(cls, FileStorage)
...@@ -73,8 +77,7 @@ class StorageTestCase(unittest.TestCase): ...@@ -73,8 +77,7 @@ class StorageTestCase(unittest.TestCase):
wait no wait no
</Storage> </Storage>
""" """
io = StringIO(sample) rootconf = self.loadConfigText(sample)
rootconf = ZConfig.loadfile(io)
storageconf = rootconf.getSection("Storage") storageconf = rootconf.getSection("Storage")
cls, args = StorageConfig.getStorageInfo(storageconf) cls, args = StorageConfig.getStorageInfo(storageconf)
self.assertEqual(cls, ClientStorage) self.assertEqual(cls, ClientStorage)
...@@ -89,8 +92,7 @@ class StorageTestCase(unittest.TestCase): ...@@ -89,8 +92,7 @@ class StorageTestCase(unittest.TestCase):
type DemoStorage type DemoStorage
</Storage> </Storage>
""" """
io = StringIO(sample) rootconf = self.loadConfigText(sample)
rootconf = ZConfig.loadfile(io)
storageconf = rootconf.getSection("Storage") storageconf = rootconf.getSection("Storage")
cls, args = StorageConfig.getStorageInfo(storageconf) cls, args = StorageConfig.getStorageInfo(storageconf)
self.assertEqual(cls, DemoStorage) self.assertEqual(cls, DemoStorage)
...@@ -106,8 +108,7 @@ class StorageTestCase(unittest.TestCase): ...@@ -106,8 +108,7 @@ class StorageTestCase(unittest.TestCase):
type ZODB.DemoStorage.DemoStorage type ZODB.DemoStorage.DemoStorage
</Storage> </Storage>
""" """
io = StringIO(sample) rootconf = self.loadConfigText(sample)
rootconf = ZConfig.loadfile(io)
storageconf = rootconf.getSection("Storage") storageconf = rootconf.getSection("Storage")
cls, args = StorageConfig.getStorageInfo(storageconf) cls, args = StorageConfig.getStorageInfo(storageconf)
self.assertEqual(cls, DemoStorage) self.assertEqual(cls, DemoStorage)
...@@ -128,8 +129,7 @@ class StorageTestCase(unittest.TestCase): ...@@ -128,8 +129,7 @@ class StorageTestCase(unittest.TestCase):
</Storage> </Storage>
""" % self.tmpfn """ % self.tmpfn
os.mkdir(self.tmpfn) os.mkdir(self.tmpfn)
io = StringIO(sample) rootconf = self.loadConfigText(sample)
rootconf = ZConfig.loadfile(io)
storageconf = rootconf.getSection("Storage") storageconf = rootconf.getSection("Storage")
cls, args = StorageConfig.getStorageInfo(storageconf) cls, args = StorageConfig.getStorageInfo(storageconf)
self.assertEqual(cls, BDBFullStorage) self.assertEqual(cls, BDBFullStorage)
...@@ -155,8 +155,7 @@ class StorageTestCase(unittest.TestCase): ...@@ -155,8 +155,7 @@ class StorageTestCase(unittest.TestCase):
</Storage> </Storage>
""" % self.tmpfn """ % self.tmpfn
os.mkdir(self.tmpfn) os.mkdir(self.tmpfn)
io = StringIO(sample) rootconf = self.loadConfigText(sample)
rootconf = ZConfig.loadfile(io)
storageconf = rootconf.getSection("Storage") storageconf = rootconf.getSection("Storage")
cls, args = StorageConfig.getStorageInfo(storageconf) cls, args = StorageConfig.getStorageInfo(storageconf)
self.assertEqual(cls, BDBMinimalStorage) self.assertEqual(cls, BDBMinimalStorage)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment