diff --git a/ring/__init__.py b/ring/__init__.py index e8de637..a50459a 100644 --- a/ring/__init__.py +++ b/ring/__init__.py @@ -6,7 +6,7 @@ import ring.coder # noqa from ring.__version__ import __version__ # noqa from ring.func import ( - lru, dict, shelve, disk, memcache, redis, redis_hash) + lru, dict, shelve, disk, memcache, redis, redis_hash, dogpile) try: import asyncio from ring.func.asyncio import aiomcache, aioredis, aioredis_hash @@ -22,4 +22,4 @@ __all__ = ( 'lru', 'dict', 'shelve', 'memcache', 'redis', 'redis_hash', 'disk', - 'aiomcache', 'aioredis', 'aioredis_hash') + 'aiomcache', 'aioredis', 'aioredis_hash', 'dogpile') diff --git a/ring/func/__init__.py b/ring/func/__init__.py index da73c22..b8849f2 100644 --- a/ring/func/__init__.py +++ b/ring/func/__init__.py @@ -13,9 +13,11 @@ else: from ring.func import asyncio +from .sync import dogpile __all__ = ( - 'lru', 'dict', 'memcache', 'redis', 'redis_hash', 'shelve', 'disk') + 'lru', 'dict', 'memcache', 'redis', 'redis_hash', 'shelve', 'disk', + 'dogpile') if _has_asyncio: diff --git a/ring/func/sync.py b/ring/func/sync.py index 4ce4ccd..4cf8b94 100644 --- a/ring/func/sync.py +++ b/ring/func/sync.py @@ -397,6 +397,23 @@ def delete_value(self, key): self.backend.delete(key) +class DogpileStorage(fbase.CommonMixinStorage, fbase.StorageMixin): + + def get_value(self, key): + import dogpile.cache + expire = self.rope.expire_default # FIXME + value = self.backend.get(key, expiration_time=expire) + if value == dogpile.cache.api.NO_VALUE: + raise fbase.NotFound + return value + + def set_value(self, key, value, expire): + self.backend.set(key, value) + + def delete_value(self, key): + self.backend.delete(key) + + def lru( lru=None, key_prefix=None, expire=None, coder=None, user_interface=CacheUserInterface, storage_class=LruStorage, @@ -672,6 +689,38 @@ def diskcache( **kwargs) +def dogpile( + region, key_prefix=None, coder=None, + user_interface=CacheUserInterface, storage_class=DogpileStorage, + **kwargs): + """dogpile_ interface. + + .. _dogpile: https://dogpilecache.sqlalchemy.org/ + + :param dogpile.cache.region.CacheRegion region: dogpile region object. + + >>> region = dogpile.cache.make_region().configure( + 'dogpile.cache.pylibmc', + expiration_time = 3600, + arguments = { + 'url': ["127.0.0.1"], + } + ) + >>> @ring.dogpile(region, ...) + ... ... + + :see: :func:`ring.func.sync.CacheUserInterface` for sub-functions. + """ + expire = None # set by dogpile region + + return fbase.factory( + region, key_prefix=key_prefix, on_manufactured=None, + user_interface=user_interface, storage_class=storage_class, + miss_value=None, expire_default=expire, coder=coder, + key_refactor=region.key_mangler, + **kwargs) + + def arcus( client, key_prefix=None, expire=0, coder=None, default_action='get_or_update', diff --git a/setup.py b/setup.py index ef7575e..b8b5e41 100644 --- a/setup.py +++ b/setup.py @@ -24,6 +24,7 @@ def get_version(): 'redis', 'requests', 'diskcache', 'django', + 'dogpile.cache', ] docs_require = [ 'sphinx', diff --git a/tests/test_func_sync.py b/tests/test_func_sync.py index a94c553..2706ad6 100644 --- a/tests/test_func_sync.py +++ b/tests/test_func_sync.py @@ -6,6 +6,9 @@ import memcache import redis import diskcache +from dogpile.cache import make_region + +from ring._memcache import key_refactor from ring.func.lru_cache import LruCache import pytest @@ -76,6 +79,26 @@ def storage_diskcache(request): return client +@pytest.fixture(scope='session', params=[ + make_region(key_mangler=key_refactor).configure( + 'dogpile.cache.pylibmc', + expiration_time=10, + arguments={ + 'url': ["127.0.0.1"], + } + ) +]) +def storage_dogpile(request): + client = request.param + client.ring = ring.dogpile + client.is_binary = False + client.has_has = False + client.has_touch = False + client.has_expire = False + assert(client.is_configured) + return client + + @pytest.fixture(scope='session', ids=['python-memcached', 'pymemcache', 'pylibmc'], params=[ # client, binary, has_touch (pythonmemcache_client, False, sys.version_info[0] == 2), @@ -114,6 +137,7 @@ def redis_client(request): lazy_fixture('memcache_client'), lazy_fixture('redis_client'), lazy_fixture('storage_diskcache'), + lazy_fixture('storage_dogpile'), ]) def storage(request): return request.param @@ -344,7 +368,7 @@ def test_common_value(storage): base = [b'a'] - @storage.ring(storage, key_prefix=str(storage), **options) + @storage.ring(storage, key_prefix=str(storage) + '::', **options) def ff(): base[0] += b'b' return base[0]