diff options
author | jonathan vanasco <jonathan@2xlp.com> | 2013-11-26 12:12:24 -0500 |
---|---|---|
committer | jonathan vanasco <jonathan@2xlp.com> | 2013-11-26 12:12:24 -0500 |
commit | 53f8a0711ddc72c6a4b2f41ddb67ba963b9df7cd (patch) | |
tree | 6c484ecbaffa446cb6d7f3696a2eb4253e0483eb | |
parent | c9deaf1b8879d295f8d2eac03b17bdf10033cd84 (diff) | |
download | dogpile-cache-53f8a0711ddc72c6a4b2f41ddb67ba963b9df7cd.tar.gz |
memory_pickle backend support
-rw-r--r-- | dogpile/cache/backends/__init__.py | 1 | ||||
-rw-r--r-- | dogpile/cache/backends/memory.py | 42 | ||||
-rw-r--r-- | tests/cache/test_memory_pickle_backend.py | 5 |
3 files changed, 42 insertions, 6 deletions
diff --git a/dogpile/cache/backends/__init__.py b/dogpile/cache/backends/__init__.py index a0c111b..a9b9c2e 100644 --- a/dogpile/cache/backends/__init__.py +++ b/dogpile/cache/backends/__init__.py @@ -5,4 +5,5 @@ register_backend("dogpile.cache.pylibmc", "dogpile.cache.backends.memcached", "P register_backend("dogpile.cache.bmemcached", "dogpile.cache.backends.memcached", "BMemcachedBackend") register_backend("dogpile.cache.memcached", "dogpile.cache.backends.memcached", "MemcachedBackend") register_backend("dogpile.cache.memory", "dogpile.cache.backends.memory", "MemoryBackend") +register_backend("dogpile.cache.memory_pickle", "dogpile.cache.backends.memory", "MemoryPickleBackend") register_backend("dogpile.cache.redis", "dogpile.cache.backends.redis", "RedisBackend") diff --git a/dogpile/cache/backends/memory.py b/dogpile/cache/backends/memory.py index e606bea..b79faa8 100644 --- a/dogpile/cache/backends/memory.py +++ b/dogpile/cache/backends/memory.py @@ -8,6 +8,11 @@ Provides a simple dictionary-based backend. from dogpile.cache.api import CacheBackend, NO_VALUE +try: + import cPickle as pickle +except ImportError: + import pickle + class MemoryBackend(CacheBackend): """A backend that uses a plain dictionary. @@ -41,24 +46,32 @@ class MemoryBackend(CacheBackend): """ + is_pickle = False + def __init__(self, arguments): self._cache = arguments.pop("cache_dict", {}) def get(self, key): - return self._cache.get(key, NO_VALUE) + value = self._cache.get(key, NO_VALUE) + if value is not NO_VALUE : + if self.is_pickle : + value = pickle.loads( value ) + return value def get_multi(self, keys): - return [ - self._cache.get(key, NO_VALUE) - for key in keys - ] + values = [] + for key in keys : + values.append( self.get( key ) ) + return values def set(self, key, value): + if self.is_pickle : + value = pickle.dumps( value ) self._cache[key] = value def set_multi(self, mapping): for key,value in mapping.items(): - self._cache[key] = value + self.set( key , value ) def delete(self, key): self._cache.pop(key, None) @@ -66,3 +79,20 @@ class MemoryBackend(CacheBackend): def delete_multi(self, keys): for key in keys: self._cache.pop(key, None) + + +class MemoryPickleBackend(MemoryBackend): + """A backend that uses a plain dictionary, but serializes objects on `set` + and deserializes the objects on `get`. This is because objects cached in + the MemoryBackend are cached as the actual object, so changes to them will + persist without a `set`. + + This backend takes a lightweight performance hit through pickling, in order + to achieve parity with other cache backends where the objects returned by + `get` are a discretely new object, and `set` must be called to persist + changes. + + MemoryPickleBackend will try to serialize with cPickle, and will fall back + to pickle if it is not available. + """ + is_pickle = True diff --git a/tests/cache/test_memory_pickle_backend.py b/tests/cache/test_memory_pickle_backend.py new file mode 100644 index 0000000..563718c --- /dev/null +++ b/tests/cache/test_memory_pickle_backend.py @@ -0,0 +1,5 @@ +from ._fixtures import _GenericBackendTest + +class MemoryBackendTest(_GenericBackendTest): + backend = "dogpile.cache.memory_pickle" + |