Commits

jvanasco committed 53f8a07

memory_pickle backend support

Comments (0)

Files changed (3)

dogpile/cache/backends/__init__.py

 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")

dogpile/cache/backends/memory.py

 
 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.
 
 
 
     """
+    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)
     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

tests/cache/test_memory_pickle_backend.py

+from ._fixtures import _GenericBackendTest
+
+class MemoryBackendTest(_GenericBackendTest):
+    backend = "dogpile.cache.memory_pickle"
+