Commit 3833be7e authored by Chris Rossi's avatar Chris Rossi

Convert db resolvers to storage resolvers.

parent 085b1577
...@@ -13,6 +13,7 @@ except: ...@@ -13,6 +13,7 @@ except:
CHANGES = '' CHANGES = ''
requires = ['ZODB3'] requires = ['ZODB3']
tests_require = requires + ['mock']
setup(name='zodburi', setup(name='zodburi',
version='0.1a1', version='0.1a1',
...@@ -31,7 +32,7 @@ setup(name='zodburi', ...@@ -31,7 +32,7 @@ setup(name='zodburi',
include_package_data=True, include_package_data=True,
zip_safe=False, zip_safe=False,
tests_require = requires, tests_require = requires,
install_requires = requires, install_requires = tests_require,
test_suite="zodburi", test_suite="zodburi",
) )
...@@ -23,6 +23,16 @@ class SuffixMultiplier: ...@@ -23,6 +23,16 @@ class SuffixMultiplier:
return int(v[:-self._keysz]) * m return int(v[:-self._keysz]) * m
return int(v) * self._default return int(v) * self._default
byte_size = SuffixMultiplier({'kb': 1024, convert_bytesize = SuffixMultiplier({'kb': 1024,
'mb': 1024*1024, 'mb': 1024*1024,
'gb': 1024*1024*1024L,}) 'gb': 1024*1024*1024L,})
def convert_int(value):
# boolean values are also treated as integers
value = value.lower()
if value in FALSETYPES:
return 0
if value in TRUETYPES:
return 1
return int(value)
...@@ -3,10 +3,7 @@ import cgi ...@@ -3,10 +3,7 @@ import cgi
from cStringIO import StringIO from cStringIO import StringIO
import urlparse import urlparse
from zodburi.datatypes import byte_size from ZEO.ClientStorage import ClientStorage
from zodburi.datatypes import FALSETYPES
from zodburi.datatypes import TRUETYPES
from ZODB.FileStorage.FileStorage import FileStorage from ZODB.FileStorage.FileStorage import FileStorage
from ZODB.DemoStorage import DemoStorage from ZODB.DemoStorage import DemoStorage
from ZODB.MappingStorage import MappingStorage from ZODB.MappingStorage import MappingStorage
...@@ -14,58 +11,39 @@ from ZODB.blob import BlobStorage ...@@ -14,58 +11,39 @@ from ZODB.blob import BlobStorage
from ZODB.DB import DB from ZODB.DB import DB
import ZConfig import ZConfig
def interpret_int_args(argnames, kw): from zodburi.datatypes import convert_bytesize
newkw = {} from zodburi.datatypes import convert_int
# boolean values are also treated as integers
for name in argnames:
value = kw.get(name)
if value is not None:
value = value.lower()
if value in FALSETYPES:
value = 0
if value in TRUETYPES:
value = 1
value = int(value)
newkw[name] = value
return newkw
def interpret_string_args(argnames, kw):
newkw = {}
# strings
for name in argnames:
value = kw.get(name)
if value is not None:
newkw[name] = value
return newkw
def interpret_bytesize_args(argnames, kw):
newkw = {}
# suffix multiplied
for name in argnames:
value = kw.get(name)
if value is not None:
newkw[name] = byte_size(value)
return newkw
class Resolver(object): class Resolver(object):
_int_args = ()
_string_args = ()
_bytesize_args = ()
def interpret_kwargs(self, kw): def interpret_kwargs(self, kw):
unused = kw.copy()
new = {} new = {}
newkw = interpret_int_args(self._int_args, kw) convert_string = lambda s: s
new.update(newkw) converters = (
newkw = interpret_string_args(self._string_args, kw) convert_int,
new.update(newkw) convert_string,
newkw = interpret_bytesize_args(self._bytesize_args, kw) convert_bytesize)
new.update(newkw) args = (
return new self._int_args,
self._string_args,
self._bytesize_args)
for convert, arg_names in zip(converters, args):
for arg_name in arg_names:
value = unused.pop(arg_name, None)
if value is not None:
value = convert(value)
new[arg_name] = value
return new, unused
class MappingStorageURIResolver(Resolver): class MappingStorageURIResolver(Resolver):
_int_args = ('connection_cache_size', 'connection_pool_size')
_string_args = ('database_name',)
_bytesize_args = ()
def __call__(self, uri): def __call__(self, uri):
prefix, rest = uri.split('memory://', 1) prefix, rest = uri.split('memory://', 1)
result = rest.split('?', 1) result = rest.split('?', 1)
...@@ -75,23 +53,19 @@ class MappingStorageURIResolver(Resolver): ...@@ -75,23 +53,19 @@ class MappingStorageURIResolver(Resolver):
else: else:
name, query = result name, query = result
kw = dict(cgi.parse_qsl(query)) kw = dict(cgi.parse_qsl(query))
kw = self.interpret_kwargs(kw) kw, unused = self.interpret_kwargs(kw)
dbkw = get_dbkw(kw)
args = (name,) args = (name,)
dbitems = dbkw.items()
dbitems.sort()
key = (args, tuple(dbitems))
def factory(): def factory():
storage = MappingStorage(*args) return MappingStorage(*args)
return DB(storage, **dbkw) return factory, unused
return key, args, kw, factory
class FileStorageURIResolver(Resolver): class FileStorageURIResolver(Resolver):
# XXX missing: blob_dir, packer, pack_keep_old, pack_gc, stop # XXX missing: blob_dir, packer, pack_keep_old, pack_gc, stop
_int_args = ('create', 'read_only', 'demostorage', 'connection_cache_size', _int_args = ('create', 'read_only', 'demostorage')
'connection_pool_size') _string_args = ('blobstorage_dir', 'blobstorage_layout')
_string_args = ('blobstorage_dir', 'blobstorage_layout', 'database_name')
_bytesize_args = ('quota',) _bytesize_args = ('quota',)
def __call__(self, uri): def __call__(self, uri):
# we can't use urlparse.urlsplit here due to Windows filenames # we can't use urlparse.urlsplit here due to Windows filenames
prefix, rest = uri.split('file://', 1) prefix, rest = uri.split('file://', 1)
...@@ -102,15 +76,9 @@ class FileStorageURIResolver(Resolver): ...@@ -102,15 +76,9 @@ class FileStorageURIResolver(Resolver):
else: else:
path, query = result path, query = result
path = os.path.normpath(path) path = os.path.normpath(path)
kw = dict(cgi.parse_qsl(query))
kw = self.interpret_kwargs(kw)
dbkw = get_dbkw(kw)
items = kw.items()
items.sort()
args = (path,) args = (path,)
dbitems = dbkw.items() kw = dict(cgi.parse_qsl(query))
dbitems.sort() kw, unused = self.interpret_kwargs(kw)
key = (args, tuple(items), tuple(dbitems))
demostorage = False demostorage = False
if 'demostorage'in kw: if 'demostorage'in kw:
...@@ -129,34 +97,30 @@ class FileStorageURIResolver(Resolver): ...@@ -129,34 +97,30 @@ class FileStorageURIResolver(Resolver):
filestorage = FileStorage(*args, **kw) filestorage = FileStorage(*args, **kw)
blobstorage = BlobStorage(blobstorage_dir, filestorage, blobstorage = BlobStorage(blobstorage_dir, filestorage,
layout=blobstorage_layout) layout=blobstorage_layout)
demostorage = DemoStorage(base=blobstorage) return DemoStorage(base=blobstorage)
return DB(demostorage, **dbkw)
elif blobstorage_dir: elif blobstorage_dir:
def factory(): def factory():
filestorage = FileStorage(*args, **kw) filestorage = FileStorage(*args, **kw)
blobstorage = BlobStorage(blobstorage_dir, filestorage, return BlobStorage(blobstorage_dir, filestorage,
layout=blobstorage_layout) layout=blobstorage_layout)
return DB(blobstorage, **dbkw)
elif demostorage: elif demostorage:
def factory(): def factory():
filestorage = FileStorage(*args, **kw) filestorage = FileStorage(*args, **kw)
demostorage = DemoStorage(base=filestorage) return DemoStorage(base=filestorage)
return DB(demostorage, **dbkw)
else: else:
def factory(): def factory():
filestorage = FileStorage(*args, **kw) return FileStorage(*args, **kw)
return DB(filestorage, **dbkw)
return factory, unused
return key, args, kw, factory
class ClientStorageURIResolver(Resolver): class ClientStorageURIResolver(Resolver):
_int_args = ('debug', 'min_disconnect_poll', 'max_disconnect_poll', _int_args = ('debug', 'min_disconnect_poll', 'max_disconnect_poll',
'wait_for_server_on_startup', 'wait', 'wait_timeout', 'wait_for_server_on_startup', 'wait', 'wait_timeout',
'read_only', 'read_only_fallback', 'shared_blob_dir', 'read_only', 'read_only_fallback', 'shared_blob_dir',
'demostorage', 'connection_cache_size', 'demostorage')
'connection_pool_size')
_string_args = ('storage', 'name', 'client', 'var', 'username', _string_args = ('storage', 'name', 'client', 'var', 'username',
'password', 'realm', 'blob_dir', 'database_name') 'password', 'realm', 'blob_dir')
_bytesize_args = ('cache_size', ) _bytesize_args = ('cache_size', )
def __call__(self, uri): def __call__(self, uri):
...@@ -177,28 +141,15 @@ class ClientStorageURIResolver(Resolver): ...@@ -177,28 +141,15 @@ class ClientStorageURIResolver(Resolver):
path = os.path.normpath(path) path = os.path.normpath(path)
args = (path,) args = (path,)
kw = dict(cgi.parse_qsl(query)) kw = dict(cgi.parse_qsl(query))
kw = self.interpret_kwargs(kw) kw, unused = self.interpret_kwargs(kw)
dbkw = get_dbkw(kw)
items = kw.items()
items.sort()
dbitems = dbkw.items()
dbitems.sort()
key = (args, tuple(items), tuple(dbitems))
if 'demostorage' in kw: if 'demostorage' in kw:
kw.pop('demostorage') kw.pop('demostorage')
def factory(): def factory():
from ZEO.ClientStorage import ClientStorage return DemoStorage(base=ClientStorage(*args, **kw))
from ZODB.DB import DB
from ZODB.DemoStorage import DemoStorage
demostorage = DemoStorage(base=ClientStorage(*args, **kw))
return DB(demostorage, **dbkw) #pragma NO COVERAGE
else: else:
def factory(): def factory():
from ZEO.ClientStorage import ClientStorage return ClientStorage(*args, **kw)
from ZODB.DB import DB return factory, unused
clientstorage = ClientStorage(*args, **kw)
return DB(clientstorage, **dbkw) #pragma NO COVERAGE
return key, args, kw, factory
def get_dbkw(kw): def get_dbkw(kw):
dbkw = {} dbkw = {}
...@@ -220,7 +171,7 @@ class ZConfigURIResolver(object): ...@@ -220,7 +171,7 @@ class ZConfigURIResolver(object):
schema_xml_template = """ schema_xml_template = """
<schema> <schema>
<import package="ZODB"/> <import package="ZODB"/>
<multisection type="ZODB.database" attribute="databases" /> <multisection type="ZODB.storage" attribute="storages" />
</schema> </schema>
""" """
...@@ -232,16 +183,16 @@ class ZConfigURIResolver(object): ...@@ -232,16 +183,16 @@ class ZConfigURIResolver(object):
schema_xml = self.schema_xml_template schema_xml = self.schema_xml_template
schema = ZConfig.loadSchemaFile(StringIO(schema_xml)) schema = ZConfig.loadSchemaFile(StringIO(schema_xml))
config, handler = ZConfig.loadConfig(schema, path) config, handler = ZConfig.loadConfig(schema, path)
for database in config.databases: for factory in config.storages:
if not frag: if not frag:
# use the first defined in the file # use the first defined in the file
break break
elif frag == database.name: elif frag == factory.name:
# match found # match found
break break
else: else:
raise KeyError("No database named %s found" % frag) raise KeyError("No storage named %s found" % frag)
return (path, frag), (), {}, database.open return factory.open, {}
RESOLVERS = { RESOLVERS = {
......
This diff is collapsed.
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