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
import asyncore
import ThreadedAsync.LoopCallback
import ZConfig
import ZConfig.Context
import zLOG
from ZODB import StorageConfig
import ZEO.StorageServer
def load_storage(fp):
rootconf = ZConfig.loadfile(fp)
context = ZConfig.Context.Context()
rootconf = context.loadFile(fp)
storageconf = rootconf.getSection('Storage')
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
import unittest
from StringIO import StringIO
import ZConfig
import ZConfig.Context
from ZODB import StorageConfig
......@@ -46,6 +46,11 @@ class StorageTestCase(unittest.TestCase):
except os.error:
pass
def loadConfigText(self, text):
context = ZConfig.Context.Context()
io = StringIO(text)
return context.loadFile(io)
def testFileStorage(self):
from ZODB.FileStorage import FileStorage
sample = """
......@@ -55,8 +60,7 @@ class StorageTestCase(unittest.TestCase):
create yes
</Storage>
""" % self.tmpfn
io = StringIO(sample)
rootconf = ZConfig.loadfile(io)
rootconf = self.loadConfigText(sample)
storageconf = rootconf.getSection("Storage")
cls, args = StorageConfig.getStorageInfo(storageconf)
self.assertEqual(cls, FileStorage)
......@@ -73,8 +77,7 @@ class StorageTestCase(unittest.TestCase):
wait no
</Storage>
"""
io = StringIO(sample)
rootconf = ZConfig.loadfile(io)
rootconf = self.loadConfigText(sample)
storageconf = rootconf.getSection("Storage")
cls, args = StorageConfig.getStorageInfo(storageconf)
self.assertEqual(cls, ClientStorage)
......@@ -89,8 +92,7 @@ class StorageTestCase(unittest.TestCase):
type DemoStorage
</Storage>
"""
io = StringIO(sample)
rootconf = ZConfig.loadfile(io)
rootconf = self.loadConfigText(sample)
storageconf = rootconf.getSection("Storage")
cls, args = StorageConfig.getStorageInfo(storageconf)
self.assertEqual(cls, DemoStorage)
......@@ -106,8 +108,7 @@ class StorageTestCase(unittest.TestCase):
type ZODB.DemoStorage.DemoStorage
</Storage>
"""
io = StringIO(sample)
rootconf = ZConfig.loadfile(io)
rootconf = self.loadConfigText(sample)
storageconf = rootconf.getSection("Storage")
cls, args = StorageConfig.getStorageInfo(storageconf)
self.assertEqual(cls, DemoStorage)
......@@ -128,8 +129,7 @@ class StorageTestCase(unittest.TestCase):
</Storage>
""" % self.tmpfn
os.mkdir(self.tmpfn)
io = StringIO(sample)
rootconf = ZConfig.loadfile(io)
rootconf = self.loadConfigText(sample)
storageconf = rootconf.getSection("Storage")
cls, args = StorageConfig.getStorageInfo(storageconf)
self.assertEqual(cls, BDBFullStorage)
......@@ -155,8 +155,7 @@ class StorageTestCase(unittest.TestCase):
</Storage>
""" % self.tmpfn
os.mkdir(self.tmpfn)
io = StringIO(sample)
rootconf = ZConfig.loadfile(io)
rootconf = self.loadConfigText(sample)
storageconf = rootconf.getSection("Storage")
cls, args = StorageConfig.getStorageInfo(storageconf)
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