diff options
author | Mike Bayer <mike_mp@zzzcomputing.com> | 2013-11-26 22:35:44 -0500 |
---|---|---|
committer | Mike Bayer <mike_mp@zzzcomputing.com> | 2013-11-26 22:35:44 -0500 |
commit | 4cc0af95d626fa89bfc903a6a454191ae0b7a104 (patch) | |
tree | f23a58a09dc969f953fa86354df9d794225521e7 | |
parent | 5817129f3beaeeb170b4611dfb4a416177ef993e (diff) | |
download | dogpile-cache-4cc0af95d626fa89bfc903a6a454191ae0b7a104.tar.gz |
- changelog
- consolidate memory tests under one test_memory.py script
- fix API doc
- use util.compat.pickle and also use pickle.HIGHEST_PROTOCOL
- some inlining to the combination of get/set + pickle
-rw-r--r-- | docs/build/api.rst | 3 | ||||
-rw-r--r-- | docs/build/changelog.rst | 10 | ||||
-rw-r--r-- | dogpile/cache/backends/memory.py | 92 | ||||
-rw-r--r-- | tests/cache/test_memory_backend.py | 3 | ||||
-rw-r--r-- | tests/cache/test_memory_pickle_backend.py | 5 |
5 files changed, 71 insertions, 42 deletions
diff --git a/docs/build/api.rst b/docs/build/api.rst index 1f79c73..cfb9ffc 100644 --- a/docs/build/api.rst +++ b/docs/build/api.rst @@ -27,9 +27,6 @@ Backends .. automodule:: dogpile.cache.backends.memory :members: -.. automodule:: dogpile.cache.backends.memory_pickle - :members: - .. automodule:: dogpile.cache.backends.memcached :members: diff --git a/docs/build/changelog.rst b/docs/build/changelog.rst index 65984f5..15a3e80 100644 --- a/docs/build/changelog.rst +++ b/docs/build/changelog.rst @@ -5,6 +5,16 @@ Changelog :version: 0.5.3 .. change:: + :tags: feature + :pullreq: 11 + + Added a new variant on :class:`.MemoryBackend`, :class:`.MemoryPickleBackend`. + This backend applies ``pickle.dumps()`` and ``pickle.loads()`` to cached + values upon set and get, so that similar copy-on-cache behavior as that + of other backends is employed, guarding cached values against subsequent + in-memory state changes. Pullreq courtesy Jonathan Vanasco. + + .. change:: :tags: bug :pullreq: 9 diff --git a/dogpile/cache/backends/memory.py b/dogpile/cache/backends/memory.py index a37b3d9..cee989b 100644 --- a/dogpile/cache/backends/memory.py +++ b/dogpile/cache/backends/memory.py @@ -1,17 +1,17 @@ """ -Memory Backend --------------- +Memory Backends +--------------- -Provides a simple dictionary-based backend. +Provides simple dictionary-based backends. + +The two backends are :class:`.MemoryBackend` and :class:`.MemoryPickleBackend`; +the latter applies a serialization step to cached values while the former +places the value as given into the dictionary. """ from dogpile.cache.api import CacheBackend, NO_VALUE - -try: - import cPickle as pickle -except ImportError: - import pickle +from dogpile.cache.compat import pickle class MemoryBackend(CacheBackend): """A backend that uses a plain dictionary. @@ -46,32 +46,39 @@ class MemoryBackend(CacheBackend): """ - is_pickle = False + pickle_values = False def __init__(self, arguments): self._cache = arguments.pop("cache_dict", {}) def get(self, key): value = self._cache.get(key, NO_VALUE) - if value is not NO_VALUE : - if self.is_pickle : - value = pickle.loads(value) - return value + if value is not NO_VALUE and self.pickle_values: + value = pickle.loads(value) + return value def get_multi(self, keys): - values = [] - for key in keys : - values.append(self.get(key)) - return values + ret = [self._cache.get(key, NO_VALUE) + for key in keys] + if self.pickle_values: + ret = [ + pickle.loads(value) + if value is not NO_VALUE else value + for value in ret + ] + return ret def set(self, key, value): - if self.is_pickle : - value = pickle.dumps(value) + if self.pickle_values: + value = pickle.dumps(value, pickle.HIGHEST_PROTOCOL) self._cache[key] = value def set_multi(self, mapping): - for key,value in mapping.items(): - self.set(key, value) + pickle_values = self.pickle_values + for key, value in mapping.items(): + if pickle_values: + value = pickle.dumps(value, pickle.HIGHEST_PROTOCOL) + self._cache[key] = value def delete(self, key): self._cache.pop(key, None) @@ -82,17 +89,34 @@ class MemoryBackend(CacheBackend): 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. + """A backend that uses a plain dictionary, but serializes objects on + :meth:`.MemoryBackend.set` and deserializes :meth:`.MemoryBackend.get`. + + E.g.:: + + from dogpile.cache import make_region + + region = make_region().configure( + 'dogpile.cache.memory_pickle' + ) + + The usage of pickle to serialize cached values allows an object + as placed in the cache to be a copy of the original given object, so + that any subsequent changes to the given object aren't reflected + in the cached value, thus making the backend behave the same way + as other backends which make use of serialization. + + The serialization is performed via pickle, and incurs the same + performance hit in doing so as that of other backends; in this way + the :class:`.MemoryPickleBackend` performance is somewhere in between + that of the pure :class:`.MemoryBackend` and the remote server oriented + backends such as that of Memcached or Redis. + + Pickle behavior here is the same as that of the Redis backend, using + either ``cPickle`` or ``pickle`` and specifying ``HIGHEST_PROTOCOL`` + upon serialize. + + .. versionadded:: 0.5.3 + """ - is_pickle = True + pickle_values = True diff --git a/tests/cache/test_memory_backend.py b/tests/cache/test_memory_backend.py index 1746c7a..00c23b8 100644 --- a/tests/cache/test_memory_backend.py +++ b/tests/cache/test_memory_backend.py @@ -3,3 +3,6 @@ from ._fixtures import _GenericBackendTest class MemoryBackendTest(_GenericBackendTest): backend = "dogpile.cache.memory" + +class MemoryPickleBackendTest(_GenericBackendTest): + backend = "dogpile.cache.memory_pickle" diff --git a/tests/cache/test_memory_pickle_backend.py b/tests/cache/test_memory_pickle_backend.py deleted file mode 100644 index 563718c..0000000 --- a/tests/cache/test_memory_pickle_backend.py +++ /dev/null @@ -1,5 +0,0 @@ -from ._fixtures import _GenericBackendTest - -class MemoryBackendTest(_GenericBackendTest): - backend = "dogpile.cache.memory_pickle" - |