From b06a5f17e4f23df511c04c744a018fd22b0a37ba Mon Sep 17 00:00:00 2001 From: Jeong YunWon Date: Sun, 1 Jul 2018 13:12:50 +0900 Subject: [PATCH] dynamic editable ring + wrong .ring -> .rope --- ring/django.py | 4 ++-- ring/func/asyncio.py | 52 ++++++++++++++++++++-------------------- ring/func/base.py | 50 ++++++++++++++++++++++++++++---------- ring/func/sync.py | 44 +++++++++++++++++----------------- tests/_test_interface.py | 24 +++++++++---------- tests/test_customize.py | 31 ++++++++++++++++++++++++ 6 files changed, 130 insertions(+), 75 deletions(-) create mode 100644 tests/test_customize.py diff --git a/ring/django.py b/ring/django.py index e97b3a1..217fc99 100644 --- a/ring/django.py +++ b/ring/django.py @@ -78,7 +78,7 @@ class CachePageUserInterface(fbase.BaseUserInterface): @property def middleware(self): - return self.ring.storage.backend + return self.rope.storage.backend @fbase.interface_attrs( transform_args=transform_cache_page_args, @@ -123,7 +123,7 @@ def get(self, wire, request, *args, **kwargs): # result = middleware.process_view(request, view_func, args, kwargs) # if result is not None: # return result - return self.ring.miss_value + return self.rope.miss_value @fbase.interface_attrs( transform_args=transform_cache_page_args, return_annotation=None) diff --git a/ring/func/asyncio.py b/ring/func/asyncio.py index f16940e..8bde497 100644 --- a/ring/func/asyncio.py +++ b/ring/func/asyncio.py @@ -120,13 +120,13 @@ class CommonMixinStorage(fbase.BaseStorage): # Working only as mixin @asyncio.coroutine def get(self, key): value = yield from self.get_value(key) - return self.ring.coder.decode(value) + return self.rope.decode(value) @asyncio.coroutine def set(self, key, value, expire=...): if expire is ...: - expire = self.ring.expire_default - encoded = self.ring.coder.encode(value) + expire = self.rope.expire_default + encoded = self.rope.encode(value) result = yield from self.set_value(key, encoded, expire) return result @@ -143,7 +143,7 @@ def has(self, key): @asyncio.coroutine def touch(self, key, expire=...): if expire is ...: - expire = self.ring.expire_default + expire = self.rope.expire_default result = yield from self.touch_value(key, expire) return result @@ -162,9 +162,9 @@ class CacheUserInterface(fbase.BaseUserInterface): def get(self, wire, **kwargs): key = self.key(wire, **kwargs) try: - result = yield from self.ring.storage.get(key) + result = yield from self.rope.storage.get(key) except fbase.NotFound: - result = self.ring.miss_value + result = self.rope.miss_value return result @fbase.interface_attrs(transform_args=fbase.transform_kwargs_only) @@ -172,7 +172,7 @@ def get(self, wire, **kwargs): def update(self, wire, **kwargs): key = self.key(wire, **kwargs) result = yield from self.execute(wire, **kwargs) - yield from self.ring.storage.set(key, result) + yield from self.rope.storage.set(key, result) return result @fbase.interface_attrs(transform_args=fbase.transform_kwargs_only) @@ -180,10 +180,10 @@ def update(self, wire, **kwargs): def get_or_update(self, wire, **kwargs): key = self.key(wire, **kwargs) try: - result = yield from self.ring.storage.get(key) + result = yield from self.rope.storage.get(key) except fbase.NotFound: result = yield from self.execute(wire, **kwargs) - yield from self.ring.storage.set(key, result) + yield from self.rope.storage.set(key, result) return result @fbase.interface_attrs( @@ -191,25 +191,25 @@ def get_or_update(self, wire, **kwargs): return_annotation=None) def set(self, wire, _value, **kwargs): key = self.key(wire, **kwargs) - return self.ring.storage.set(key, _value) + return self.rope.storage.set(key, _value) @fbase.interface_attrs( transform_args=fbase.transform_kwargs_only, return_annotation=None) def delete(self, wire, **kwargs): key = self.key(wire, **kwargs) - return self.ring.storage.delete(key) + return self.rope.storage.delete(key) @fbase.interface_attrs( transform_args=fbase.transform_kwargs_only, return_annotation=bool) def has(self, wire, **kwargs): key = self.key(wire, **kwargs) - return self.ring.storage.has(key) + return self.rope.storage.has(key) @fbase.interface_attrs( transform_args=fbase.transform_kwargs_only, return_annotation=None) def touch(self, wire, **kwargs): key = self.key(wire, **kwargs) - return self.ring.storage.touch(key) + return self.rope.storage.touch(key) class BulkInterfaceMixin(fbase.AbstractBulkUserInterfaceMixin): @@ -229,8 +229,8 @@ def execute_many(self, wire, *args_list): return_annotation=lambda a: List[Optional[a.get('return', Any)]]) def get_many(self, wire, *args_list): keys = self.key_many(wire, *args_list) - return self.ring.storage.get_many( - keys, miss_value=self.ring.miss_value) + return self.rope.storage.get_many( + keys, miss_value=self.rope.miss_value) @fbase.interface_attrs( return_annotation=lambda a: List[a.get('return', Any)]) @@ -238,7 +238,7 @@ def get_many(self, wire, *args_list): def update_many(self, wire, *args_list): keys = self.key_many(wire, *args_list) values = yield from self.execute_many(wire, *args_list) - yield from self.ring.storage.set_many(keys, values) + yield from self.rope.storage.set_many(keys, values) return values @fbase.interface_attrs( @@ -247,7 +247,7 @@ def update_many(self, wire, *args_list): def get_or_update_many(self, wire, *args_list): keys = self.key_many(wire, *args_list) miss_value = object() - results = yield from self.ring.storage.get_many( + results = yield from self.rope.storage.get_many( keys, miss_value=miss_value) miss_indices = [] @@ -260,7 +260,7 @@ def get_or_update_many(self, wire, *args_list): new_results = yield from asyncio.gather(*( fbase.execute_bulk_item(wire, args_list[i]) for i in miss_indices)) new_keys = [keys[i] for i in miss_indices] - yield from self.ring.storage.set_many(new_keys, new_results) + yield from self.rope.storage.set_many(new_keys, new_results) for new_i, old_i in enumerate(miss_indices): results[old_i] = new_results[new_i] @@ -269,22 +269,22 @@ def get_or_update_many(self, wire, *args_list): @fbase.interface_attrs(return_annotation=None) def set_many(self, wire, args_list, value_list): keys = self.key_many(wire, *args_list) - return self.ring.storage.set_many(keys, value_list) + return self.rope.storage.set_many(keys, value_list) @fbase.interface_attrs(return_annotation=None) def delete_many(self, wire, *args_list): keys = self.key_many(wire, *args_list) - return self.ring.storage.delete_many(keys) + return self.rope.storage.delete_many(keys) @fbase.interface_attrs(return_annotation=None) def has_many(self, wire, *args_list): keys = self.key_many(wire, *args_list) - return self.ring.storage.has_many(keys) + return self.rope.storage.has_many(keys) @fbase.interface_attrs(return_annotation=None) def touch_many(self, wire, *args_list): keys = self.key_many(wire, *args_list) - return self.ring.storage.touch_many(keys) + return self.rope.storage.touch_many(keys) class BulkStorageMixin(object): @@ -294,16 +294,16 @@ def get_many(self, keys, miss_value): """Get and return values for the given key.""" values = yield from self.get_many_values(keys) results = [ - self.ring.coder.decode(v) if v is not fbase.NotFound else miss_value # noqa + self.rope.decode(v) if v is not fbase.NotFound else miss_value # noqa for v in values] return results def set_many(self, keys, values, expire=Ellipsis): """Set values for the given keys.""" if expire is Ellipsis: - expire = self.ring.expire_default + expire = self.rope.expire_default return self.set_many_values( - keys, [self.ring.coder.encode(v) for v in values], expire) + keys, [self.rope.encode(v) for v in values], expire) def delete_many(self, keys): """Delete values for the given keys.""" @@ -316,7 +316,7 @@ def has_many(self, keys): def touch_many(self, keys, expire=Ellipsis): """Touch values for the given keys.""" if expire is Ellipsis: - expire = self.ring.expire_default + expire = self.rope.expire_default return self.touch_many_values(keys, expire) diff --git a/ring/func/base.py b/ring/func/base.py index 599e3ea..9ae9c60 100644 --- a/ring/func/base.py +++ b/ring/func/base.py @@ -116,7 +116,7 @@ def create_key_builder( key_generator = CallableKey( c, format_prefix=key_prefix, ignorable_keys=ignorable_keys) - def compose_key(bound_args, kwargs): + def compose_key(*bound_args, **kwargs): full_kwargs = kwargs.copy() for i, prearg in enumerate(bound_args): full_kwargs[c.parameters[i].name] = bound_args[i] @@ -228,8 +228,8 @@ class BaseUserInterface(object): :func:`ring.func.base.transform_kwargs_only` """ - def __init__(self, ring): - self.ring = ring + def __init__(self, rope): + self.rope = rope @interface_attrs( transform_args=transform_kwargs_only, return_annotation=str) @@ -240,7 +240,7 @@ def key(self, wire, **kwargs): :return: The composed key with given arguments. :rtype: str """ - return self.ring.compose_key(wire._bound_objects, kwargs) + return self.rope.compose_key(*wire._bound_objects, **kwargs) @interface_attrs(transform_args=transform_kwargs_only) def execute(self, wire, **kwargs): @@ -487,15 +487,19 @@ def touch_many(self, wire, *args_list): # pragma: no cover class RingWire(Wire): - __slots__ = ('encode', 'decode', 'storage') + __slots__ = ('storage', ) def __init__(self, rope, *args, **kwargs): super(RingWire, self).__init__(rope, *args, **kwargs) - self.encode = rope.coder.encode - self.decode = rope.coder.decode self.storage = rope.storage + def encode(self, v): + return self._rope.encode(v) + + def decode(self, v): + return self._rope.decode(v) + def _merge_args(self, args, kwargs): """Create a fake kwargs object by merging actual arguments. @@ -515,6 +519,21 @@ def run(self, action, *args, **kwargs): return attr(*args, **kwargs) +class PublicRing(object): + + def __init__(self, rope): + self._rope = rope + + def key(self, func): + self._rope.compose_key = func + + def encode(self, func): + self._rope.encode = func + + def decode(self, func): + self._rope.decode = func + + def factory( storage_backend, # actual storage key_prefix, # manual key prefix @@ -605,6 +624,11 @@ def __init__(self, *args, **kwargs): self.compose_key = create_key_builder( self.callable, _key_prefix, _ignorable_keys, encoding=key_encoding, key_refactor=key_refactor) + self.compose_key.ignorable_keys = _ignorable_keys + self.encode = self.coder.encode + self.decode = self.coder.decode + + self.ring = PublicRing(self) func = f if type(f) is types.FunctionType else f.__func__ # noqa interface_keys = tuple(k for k in dir(user_interface) if k[0] != '_') @@ -698,8 +722,8 @@ class BaseStorage(object): are mandatory; Otherwise not. """ - def __init__(self, ring, backend): - self.ring = ring + def __init__(self, rope, backend): + self.rope = rope self.backend = backend @abc.abstractmethod @@ -733,12 +757,12 @@ class CommonMixinStorage(BaseStorage): def get(self, key): value = self.get_value(key) - return self.ring.coder.decode(value) + return self.rope.decode(value) def set(self, key, value, expire=Ellipsis): if expire is Ellipsis: - expire = self.ring.expire_default - encoded = self.ring.coder.encode(value) + expire = self.rope.expire_default + encoded = self.rope.encode(value) result = self.set_value(key, encoded, expire) return result @@ -752,7 +776,7 @@ def has(self, key): def touch(self, key, expire=Ellipsis): if expire is Ellipsis: - expire = self.ring.expire_default + expire = self.rope.expire_default result = self.touch_value(key, expire) return result diff --git a/ring/func/sync.py b/ring/func/sync.py index 208feca..974d6f6 100644 --- a/ring/func/sync.py +++ b/ring/func/sync.py @@ -27,26 +27,26 @@ class CacheUserInterface(fbase.BaseUserInterface): def get(self, wire, **kwargs): key = self.key(wire, **kwargs) try: - result = self.ring.storage.get(key) + result = self.rope.storage.get(key) except fbase.NotFound: - result = self.ring.miss_value + result = self.rope.miss_value return result @fbase.interface_attrs(transform_args=fbase.transform_kwargs_only) def update(self, wire, **kwargs): key = wire.key(**kwargs) result = wire.execute(**kwargs) - self.ring.storage.set(key, result) + self.rope.storage.set(key, result) return result @fbase.interface_attrs(transform_args=fbase.transform_kwargs_only) def get_or_update(self, wire, **kwargs): key = self.key(wire, **kwargs) try: - result = self.ring.storage.get(key) + result = self.rope.storage.get(key) except fbase.NotFound: result = self.execute(wire, **kwargs) - self.ring.storage.set(key, result) + self.rope.storage.set(key, result) return result @fbase.interface_attrs( @@ -54,25 +54,25 @@ def get_or_update(self, wire, **kwargs): return_annotation=None) def set(self, wire, _value, **kwargs): key = self.key(wire, **kwargs) - self.ring.storage.set(key, _value) + self.rope.storage.set(key, _value) @fbase.interface_attrs( transform_args=fbase.transform_kwargs_only, return_annotation=None) def delete(self, wire, **kwargs): key = self.key(wire, **kwargs) - self.ring.storage.delete(key) + self.rope.storage.delete(key) @fbase.interface_attrs( transform_args=fbase.transform_kwargs_only, return_annotation=bool) def has(self, wire, **kwargs): key = self.key(wire, **kwargs) - return self.ring.storage.has(key) + return self.rope.storage.has(key) @fbase.interface_attrs( transform_args=fbase.transform_kwargs_only, return_annotation=None) def touch(self, wire, **kwargs): key = self.key(wire, **kwargs) - self.ring.storage.touch(key) + self.rope.storage.touch(key) class BulkInterfaceMixin(fbase.AbstractBulkUserInterfaceMixin): @@ -92,8 +92,8 @@ def execute_many(self, wire, *args_list): return_annotation=lambda a: List[Optional[a.get('return', Any)]]) def get_many(self, wire, *args_list): keys = self.key_many(wire, *args_list) - results = self.ring.storage.get_many( - keys, miss_value=self.ring.miss_value) + results = self.rope.storage.get_many( + keys, miss_value=self.rope.miss_value) return results @fbase.interface_attrs( @@ -101,7 +101,7 @@ def get_many(self, wire, *args_list): def update_many(self, wire, *args_list): keys = self.key_many(wire, *args_list) values = self.execute_many(wire, *args_list) - self.ring.storage.set_many(keys, values) + self.rope.storage.set_many(keys, values) return values @fbase.interface_attrs( @@ -109,7 +109,7 @@ def update_many(self, wire, *args_list): def get_or_update_many(self, wire, *args_list): keys = self.key_many(wire, *args_list) miss_value = object() - results = self.ring.storage.get_many(keys, miss_value=miss_value) + results = self.rope.storage.get_many(keys, miss_value=miss_value) miss_indices = [] for i, akr in enumerate(zip(args_list, keys, results)): @@ -121,7 +121,7 @@ def get_or_update_many(self, wire, *args_list): new_results = [ fbase.execute_bulk_item(wire, args_list[i]) for i in miss_indices] new_keys = [keys[i] for i in miss_indices] - self.ring.storage.set_many(new_keys, new_results) + self.rope.storage.set_many(new_keys, new_results) for new_i, old_i in enumerate(miss_indices): results[old_i] = new_results[new_i] @@ -130,22 +130,22 @@ def get_or_update_many(self, wire, *args_list): @fbase.interface_attrs(return_annotation=None) def set_many(self, wire, args_list, value_list): keys = self.key_many(wire, *args_list) - self.ring.storage.set_many(keys, value_list) + self.rope.storage.set_many(keys, value_list) @fbase.interface_attrs(return_annotation=None) def delete_many(self, wire, *args_list): keys = self.key_many(wire, *args_list) - self.ring.storage.delete_many(keys) + self.rope.storage.delete_many(keys) @fbase.interface_attrs(return_annotation=None) def has_many(self, wire, *args_list): keys = self.key_many(wire, *args_list) - self.ring.storage.has_many(keys) + self.rope.storage.has_many(keys) @fbase.interface_attrs(return_annotation=None) def touch_many(self, wire, *args_list): keys = self.key_many(wire, *args_list) - self.ring.storage.touch_many(keys) + self.rope.storage.touch_many(keys) class BulkStorageMixin(object): @@ -153,15 +153,15 @@ class BulkStorageMixin(object): def get_many(self, keys, miss_value): values = self.get_many_values(keys) results = [ - self.ring.coder.decode(v) if v is not fbase.NotFound else miss_value # noqa + self.rope.decode(v) if v is not fbase.NotFound else miss_value # noqa for v in values] return results def set_many(self, keys, values, expire=Ellipsis): if expire is Ellipsis: - expire = self.ring.expire_default + expire = self.rope.expire_default self.set_many_values( - keys, [self.ring.coder.encode(v) for v in values], expire) + keys, [self.rope.encode(v) for v in values], expire) def delete_many(self, keys): self.delete_many_values(keys) @@ -171,7 +171,7 @@ def has_many(self, keys): def touch_many(self, keys, expire=Ellipsis): if expire is Ellipsis: - expire = self.ring.expire_default + expire = self.rope.expire_default self.touch_many_values(keys, expire) diff --git a/tests/_test_interface.py b/tests/_test_interface.py index bf17e8d..ef92d16 100644 --- a/tests/_test_interface.py +++ b/tests/_test_interface.py @@ -23,13 +23,13 @@ def get(self, wire, **kwargs): result = ... for key in [key1, key2]: try: - result = yield from self.ring.storage.get(key) + result = yield from self.rope.storage.get(key) except NotFound: continue else: break if result is ...: - result = self.ring.miss_value + result = self.rope.miss_value return result @asyncio.coroutine @@ -37,8 +37,8 @@ def update(self, wire, **kwargs): key = wire.key(**kwargs) key2 = wire.key2(**kwargs) result = yield from wire.execute(**kwargs) - yield from self.ring.storage.set(key, result) - yield from self.ring.storage.set(key2, result, None) + yield from self.rope.storage.set(key, result) + yield from self.rope.storage.set(key2, result, None) return result @asyncio.coroutine @@ -46,36 +46,36 @@ def get_or_update(self, wire, **kwargs): key = wire.key(**kwargs) key2 = wire.key2(**kwargs) try: - result = yield from self.ring.storage.get(key) + result = yield from self.rope.storage.get(key) except NotFound: try: result = yield from wire.execute(**kwargs) except Exception: try: - result = yield from self.ring.storage.get(key2) + result = yield from self.rope.storage.get(key2) except NotFound: pass else: return result raise else: - yield from self.ring.storage.set(key, result) - yield from self.ring.storage.set(key2, result, None) + yield from self.rope.storage.set(key, result) + yield from self.rope.storage.set(key2, result, None) return result @asyncio.coroutine def delete(self, wire, **kwargs): key = wire.key(**kwargs) key2 = wire.key2(**kwargs) - yield from self.ring.storage.delete(key) - yield from self.ring.storage.delete(key2) + yield from self.rope.storage.delete(key) + yield from self.rope.storage.delete(key2) @asyncio.coroutine def touch(self, wire, **kwargs): key = wire.key(**kwargs) key2 = wire.key(**kwargs) - yield from self.ring.storage.touch(key) - yield from self.ring.storage.touch(key2) + yield from self.rope.storage.touch(key) + yield from self.rope.storage.touch(key2) def doublecache( diff --git a/tests/test_customize.py b/tests/test_customize.py new file mode 100644 index 0000000..c5c87d6 --- /dev/null +++ b/tests/test_customize.py @@ -0,0 +1,31 @@ + +import ring + + +def test_override_key(): + + @ring.dict({}) + def f(v): + return v + + @f.ring.key + def f_key(v): + return 'test:' + str(v) + + assert f.key(10) == 'test:10' + + @f.ring.encode + def f_encode(v): + return 'encoded', v + + @f.ring.decode + def f_decode(v): + assert v[0] == 'encoded' + return v[1] + 1 # for test + + assert f.encode(10) == ('encoded', 10) + assert f.decode(('encoded', 10)) == 11 + f.update(5) + + assert f.storage.backend['test:5'] == ('encoded', 5) + assert f.get(5) == 6