summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMike Bayer <mike_mp@zzzcomputing.com>2013-11-26 22:35:44 -0500
committerMike Bayer <mike_mp@zzzcomputing.com>2013-11-26 22:35:44 -0500
commit4cc0af95d626fa89bfc903a6a454191ae0b7a104 (patch)
treef23a58a09dc969f953fa86354df9d794225521e7
parent5817129f3beaeeb170b4611dfb4a416177ef993e (diff)
downloaddogpile-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.rst3
-rw-r--r--docs/build/changelog.rst10
-rw-r--r--dogpile/cache/backends/memory.py92
-rw-r--r--tests/cache/test_memory_backend.py3
-rw-r--r--tests/cache/test_memory_pickle_backend.py5
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"
-