summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorjonathan vanasco <jonathan@2xlp.com>2013-11-26 12:12:24 -0500
committerjonathan vanasco <jonathan@2xlp.com>2013-11-26 12:12:24 -0500
commit53f8a0711ddc72c6a4b2f41ddb67ba963b9df7cd (patch)
tree6c484ecbaffa446cb6d7f3696a2eb4253e0483eb
parentc9deaf1b8879d295f8d2eac03b17bdf10033cd84 (diff)
downloaddogpile-cache-53f8a0711ddc72c6a4b2f41ddb67ba963b9df7cd.tar.gz
memory_pickle backend support
-rw-r--r--dogpile/cache/backends/__init__.py1
-rw-r--r--dogpile/cache/backends/memory.py42
-rw-r--r--tests/cache/test_memory_pickle_backend.py5
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"
+