Commit 5014cc8d authored by Tres Seaver's avatar Tres Seaver

Return to 100% coverage.

Also, fix bugs uncovered thereby in processing float / tuple arguments.
parent 9e187359
...@@ -36,3 +36,6 @@ def convert_int(value): ...@@ -36,3 +36,6 @@ def convert_int(value):
if value in TRUETYPES: if value in TRUETYPES:
return 1 return 1
return int(value) return int(value)
def convert_tuple(value):
return tuple(value.split(','))
...@@ -13,6 +13,7 @@ import ZConfig ...@@ -13,6 +13,7 @@ import ZConfig
from zodburi.datatypes import convert_bytesize from zodburi.datatypes import convert_bytesize
from zodburi.datatypes import convert_int from zodburi.datatypes import convert_int
from zodburi.datatypes import convert_tuple
class Resolver(object): class Resolver(object):
...@@ -26,15 +27,14 @@ class Resolver(object): ...@@ -26,15 +27,14 @@ class Resolver(object):
unused = kw.copy() unused = kw.copy()
new = {} new = {}
convert_string = lambda s: s convert_string = lambda s: s
converters = ( converters = [
convert_int, (convert_int, self._int_args),
convert_string, (convert_string, self._string_args),
convert_bytesize) (convert_bytesize, self._bytesize_args),
args = ( (float, self._float_args),
self._int_args, (convert_tuple, self._tuple_args),
self._string_args, ]
self._bytesize_args) for convert, arg_names in converters:
for convert, arg_names in zip(converters, args):
for arg_name in arg_names: for arg_name in arg_names:
value = unused.pop(arg_name, None) value = unused.pop(arg_name, None)
if value is not None: if value is not None:
......
import cgi import cgi
import urlparse import urlparse
from ZODB.DemoStorage import DemoStorage from ZODB.DemoStorage import DemoStorage
from relstorage.adapters.postgresql import PostgreSQLAdapter
from relstorage.options import Options
from relstorage.storage import RelStorage
from .resolvers import Resolver from .resolvers import Resolver
try:
# Not a real resolver, but we use interpret_kwargs from relstorage.adapters.postgresql import PostgreSQLAdapter
class PostgreSQLAdapterHelper(Resolver): from relstorage.options import Options
from relstorage.storage import RelStorage
except ImportError: #pragma NO COVER
pass
else:
# Not a real resolver, but we use interpret_kwargs
class PostgreSQLAdapterHelper(Resolver):
_int_args = ('connect_timeout', ) _int_args = ('connect_timeout', )
_string_args = ('ssl_mode', ) _string_args = ('ssl_mode', )
...@@ -32,19 +35,20 @@ class PostgreSQLAdapterHelper(Resolver): ...@@ -32,19 +35,20 @@ class PostgreSQLAdapterHelper(Resolver):
return factory, unused return factory, unused
# The relstorage support is inspired by django-zodb. # The relstorage support is inspired by django-zodb.
# Oracle and mysql should be easily implementable from here # Oracle and mysql should be easily implementable from here
class RelStorageURIResolver(Resolver): class RelStorageURIResolver(Resolver):
_int_args = ('poll_interval', 'cache_local_mb', 'commit_lock_timeout', _int_args = ('poll_interval', 'cache_local_mb', 'commit_lock_timeout',
'commit_lock_id', 'read_only', 'shared_blob_dir', 'commit_lock_id', 'read_only', 'shared_blob_dir',
'keep_history', 'pack_gc', 'pack_dry_run', 'strict_tpc', 'keep_history', 'pack_gc', 'pack_dry_run', 'strict_tpc',
'create', 'demostorage',) 'create', 'demostorage',)
_string_args = ('name', 'blob_dir', 'replica_conf', 'cache_module_name', _string_args = ('name', 'blob_dir', 'replica_conf',
'cache_prefix', 'cache_delta_size_limit') 'cache_module_name', 'cache_prefix',
'cache_delta_size_limit')
_bytesize_args = ('blob_cache_size', 'blob_cache_size_check', _bytesize_args = ('blob_cache_size', 'blob_cache_size_check',
'blob_cache_chunk_size') 'blob_cache_chunk_size')
_float_args = ('replica_timeout', 'pack_batch_timeout', 'pack_duty_cycle', _float_args = ('replica_timeout', 'pack_batch_timeout',
'pack_max_delay') 'pack_duty_cycle', 'pack_max_delay')
_tuple_args = ('cache_servers',) _tuple_args = ('cache_servers',)
def __init__(self, adapter_helper): def __init__(self, adapter_helper):
...@@ -69,4 +73,4 @@ class RelStorageURIResolver(Resolver): ...@@ -69,4 +73,4 @@ class RelStorageURIResolver(Resolver):
return storage return storage
return factory, unused return factory, unused
postgresql_resolver = RelStorageURIResolver(PostgreSQLAdapterHelper()) postgresql_resolver = RelStorageURIResolver(PostgreSQLAdapterHelper())
\ No newline at end of file
...@@ -10,20 +10,19 @@ class Base: ...@@ -10,20 +10,19 @@ class Base:
def test_bytesize_args(self): def test_bytesize_args(self):
resolver = self._makeOne() resolver = self._makeOne()
names = list(resolver._bytesize_args) names = sorted(resolver._bytesize_args)
kwargs = {} kwargs = {}
for name in names: for name in names:
kwargs[name] = '10MB' kwargs[name] = '10MB'
args = resolver.interpret_kwargs(kwargs)[0] args = resolver.interpret_kwargs(kwargs)[0]
keys = args.keys() keys = args.keys()
keys.sort() self.assertEqual(sorted(keys), names)
self.assertEqual(keys, names)
for name, value in args.items(): for name, value in args.items():
self.assertEqual(value, 10*1024*1024) self.assertEqual(value, 10*1024*1024)
def test_int_args(self): def test_int_args(self):
resolver = self._makeOne() resolver = self._makeOne()
names = list(resolver._int_args) names = sorted(resolver._int_args)
kwargs = {} kwargs = {}
for name in names: for name in names:
kwargs[name] = '10' kwargs[name] = '10'
...@@ -36,40 +35,37 @@ class Base: ...@@ -36,40 +35,37 @@ class Base:
def test_string_args(self): def test_string_args(self):
resolver = self._makeOne() resolver = self._makeOne()
names = list(resolver._string_args) names = sorted(resolver._string_args)
kwargs = {} kwargs = {}
for name in names: for name in names:
kwargs[name] = 'string' kwargs[name] = 'string'
args = resolver.interpret_kwargs(kwargs)[0] args = resolver.interpret_kwargs(kwargs)[0]
keys = args.keys() keys = args.keys()
keys.sort() self.assertEqual(sorted(keys), names)
self.assertEqual(keys, names)
for name, value in args.items(): for name, value in args.items():
self.assertEqual(value, 'string') self.assertEqual(value, 'string')
def test_float_args(self): def test_float_args(self):
resolver = self._makeOne() resolver = self._makeOne()
names = list(resolver._float_args) names = sorted(resolver._float_args)
kwargs = {} kwargs = {}
for name in names: for name in names:
kwargs[name] = '3.14' kwargs[name] = '3.14'
args = resolver.interpret_kwargs(kwargs)[0] args = resolver.interpret_kwargs(kwargs)[0]
keys = args.keys() keys = args.keys()
keys.sort() self.assertEqual(sorted(keys), names)
self.assertEqual(keys, names)
for name, value in args.items(): for name, value in args.items():
self.assertEqual(value, 3.14) self.assertEqual(value, 3.14)
def test_tuple_args(self): def test_tuple_args(self):
resolver = self._makeOne() resolver = self._makeOne()
names = list(resolver._tuple_args) names = sorted(resolver._tuple_args)
kwargs = {} kwargs = {}
for name in names: for name in names:
kwargs[name] = 'first,second,third' kwargs[name] = 'first,second,third'
args = resolver.interpret_kwargs(kwargs)[0] args = resolver.interpret_kwargs(kwargs)[0]
keys = args.keys() keys = args.keys()
keys.sort() self.assertEqual(sorted(keys), names)
self.assertEqual(keys, names)
for name, value in args.items(): for name, value in args.items():
self.assertEqual(value, ('first', 'second', 'third')) self.assertEqual(value, ('first', 'second', 'third'))
...@@ -412,8 +408,12 @@ class TestMappingStorageURIResolver(Base, unittest.TestCase): ...@@ -412,8 +408,12 @@ class TestMappingStorageURIResolver(Base, unittest.TestCase):
self.assertTrue(isinstance(storage, MappingStorage)) self.assertTrue(isinstance(storage, MappingStorage))
self.assertEqual(storage.__name__, 'storagename') self.assertEqual(storage.__name__, 'storagename')
try:
class TestPostgreSQLURIResolver(unittest.TestCase): from zodburi.resolvers_relstorage import RelStorageURIResolver
except ImportError: #pragma NO COVER
pass
else:
class TestPostgreSQLURIResolver(unittest.TestCase, Base):
def _getTargetClass(self): def _getTargetClass(self):
from zodburi.resolvers_relstorage import RelStorageURIResolver from zodburi.resolvers_relstorage import RelStorageURIResolver
return RelStorageURIResolver return RelStorageURIResolver
...@@ -450,29 +450,35 @@ class TestPostgreSQLURIResolver(unittest.TestCase): ...@@ -450,29 +450,35 @@ class TestPostgreSQLURIResolver(unittest.TestCase):
def test_call(self, RelStorage, PostgreSQLAdapter): def test_call(self, RelStorage, PostgreSQLAdapter):
from relstorage.options import Options from relstorage.options import Options
resolver = self._makeOne() resolver = self._makeOne()
factory, dbkw = resolver('postgres://someuser:somepass@somehost:5432/somedb?read_only=1') factory, dbkw = resolver(
'postgres://someuser:somepass@somehost:5432/somedb'
'?read_only=1')
factory() factory()
expected_options = Options(read_only=1) expected_options = Options(read_only=1)
PostgreSQLAdapter.assert_called_once_with(dsn="dbname='somedb' user='someuser' password='somepass' " PostgreSQLAdapter.assert_called_once_with(
"host='somehost' port='5432'", dsn="dbname='somedb' user='someuser' password='somepass' "
options=expected_options) "host='somehost' port='5432'", options=expected_options)
RelStorage.assert_called_once_with(adapter=PostgreSQLAdapter(), options=expected_options) RelStorage.assert_called_once_with(
adapter=PostgreSQLAdapter(), options=expected_options)
@mock.patch('zodburi.resolvers_relstorage.PostgreSQLAdapter') @mock.patch('zodburi.resolvers_relstorage.PostgreSQLAdapter')
@mock.patch('zodburi.resolvers_relstorage.RelStorage') @mock.patch('zodburi.resolvers_relstorage.RelStorage')
def test_call_adapter_options(self, RelStorage, PostgreSQLAdapter): def test_call_adapter_options(self, RelStorage, PostgreSQLAdapter):
from relstorage.options import Options from relstorage.options import Options
resolver = self._makeOne() resolver = self._makeOne()
factory, dbkw = resolver('postgres://someuser:somepass@somehost:5432/somedb?read_only=1' factory, dbkw = resolver(
'&connect_timeout=10') 'postgres://someuser:somepass@somehost:5432/somedb'
'?read_only=1&connect_timeout=10')
factory() factory()
expected_options = Options(read_only=1) expected_options = Options(read_only=1)
PostgreSQLAdapter.assert_called_once_with(dsn="dbname='somedb' user='someuser' password='somepass' " PostgreSQLAdapter.assert_called_once_with(
dsn="dbname='somedb' user='someuser' password='somepass' "
"host='somehost' port='5432' connect_timeout='10'", "host='somehost' port='5432' connect_timeout='10'",
options=expected_options) options=expected_options)
RelStorage.assert_called_once_with(adapter=PostgreSQLAdapter(), options=expected_options) RelStorage.assert_called_once_with(
adapter=PostgreSQLAdapter(), options=expected_options)
@mock.patch('zodburi.resolvers_relstorage.PostgreSQLAdapter') @mock.patch('zodburi.resolvers_relstorage.PostgreSQLAdapter')
...@@ -480,16 +486,17 @@ class TestPostgreSQLURIResolver(unittest.TestCase): ...@@ -480,16 +486,17 @@ class TestPostgreSQLURIResolver(unittest.TestCase):
def test_invoke_factory_demostorage(self, RelStorage, PostgreSQLAdapter): def test_invoke_factory_demostorage(self, RelStorage, PostgreSQLAdapter):
from ZODB.DemoStorage import DemoStorage from ZODB.DemoStorage import DemoStorage
resolver = self._makeOne() resolver = self._makeOne()
factory, dbkw = resolver('postgres://someuser:somepass@somehost:5432/somedb?read_only=1' factory, dbkw = resolver(
'&demostorage=true') 'postgres://someuser:somepass@somehost:5432/somedb'
'?read_only=1&demostorage=true')
self.assertTrue(isinstance(factory(), DemoStorage)) self.assertTrue(isinstance(factory(), DemoStorage))
def test_dbargs(self): def test_dbargs(self):
resolver = self._makeOne() resolver = self._makeOne()
factory, dbkw = resolver('postgres://someuser:somepass@somehost:5432/somedb?read_only=1&' factory, dbkw = resolver(
'connection_pool_size=1&' 'postgres://someuser:somepass@somehost:5432/somedb'
'connection_cache_size=1&' '?read_only=1&connection_pool_size=1&connection_cache_size=1'
'database_name=dbname') '&database_name=dbname')
self.assertEqual(dbkw, {'connection_pool_size': '1', self.assertEqual(dbkw, {'connection_pool_size': '1',
'connection_cache_size': '1', 'connection_cache_size': '1',
'database_name': 'dbname'}) 'database_name': 'dbname'})
...@@ -499,14 +506,20 @@ class TestEntryPoints(unittest.TestCase): ...@@ -499,14 +506,20 @@ class TestEntryPoints(unittest.TestCase):
def test_it(self): def test_it(self):
from pkg_resources import load_entry_point from pkg_resources import load_entry_point
from zodburi import resolvers, resolvers_relstorage from zodburi import resolvers
expected = [ expected = [
('memory', resolvers.MappingStorageURIResolver), ('memory', resolvers.MappingStorageURIResolver),
('zeo', resolvers.ClientStorageURIResolver), ('zeo', resolvers.ClientStorageURIResolver),
('file', resolvers.FileStorageURIResolver), ('file', resolvers.FileStorageURIResolver),
('zconfig', resolvers.ZConfigURIResolver), ('zconfig', resolvers.ZConfigURIResolver),
('postgres', resolvers_relstorage.RelStorageURIResolver),
] ]
try:
from zodburi.resolvers_relstorage import RelStorageURIResolver
except ImportError: #pragma NO COVER
pass
else:
expected.append(
('postgres', RelStorageURIResolver))
for name, cls in expected: for name, cls in expected:
target = load_entry_point('zodburi', 'zodburi.resolvers', name) target = load_entry_point('zodburi', 'zodburi.resolvers', name)
self.assertTrue(isinstance(target, cls)) self.assertTrue(isinstance(target, cls))
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