Commits

Mike Bayer committed 6e0491a Merge

Merged in jvanasco/dogpile.cache (pull request #11)

memory_pickle backend support

  • Participants
  • Parent commits c9deaf1, 4ff86bd

Comments (0)

Files changed (4)

File docs/build/api.rst

 =============
 
 See the section :ref:`creating_backends` for details on how to
-register new backends or :ref:`changing_backend_behavior` for details on 
-how to alter the behavior of existing backends.  
+register new backends or :ref:`changing_backend_behavior` for details on
+how to alter the behavior of existing backends.
 
 .. automodule:: dogpile.cache.api
     :members:
-    
+
 
 Backends
 ==========
 .. automodule:: dogpile.cache.backends.memory
     :members:
 
+.. automodule:: dogpile.cache.backends.memory_pickle
+    :members:
+
 .. automodule:: dogpile.cache.backends.memcached
     :members:
 
 
 .. automodule:: dogpile.cache.backends.file
     :members:
-    
+
 .. automodule:: dogpile.cache.proxy
     :members:
-    
- 
+
+
 Plugins
 ========
 

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

File 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

File tests/cache/test_memory_pickle_backend.py

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