Commits

Anonymous committed f6c8b44

Don't cache None

Added the possibility to not cache None values

Comments (0)

Files changed (2)

dogpile/cache/region.py

 
         return value.payload
 
-    def get_or_create(self, key, creator, expiration_time=None):
+    def get_or_create(self, key, creator, expiration_time=None, cache_none=True):
         """Return a cached value based on the given key.
 
         If the value does not exist or is considered to be expired
         :param expiration_time: optional expiration time which will overide
          the expiration time already configured on this :class:`.CacheRegion`
          if not None.   To set no expiration, use the value -1.
+        :param cache_none: If True (the default) also cache when the
+         decorated function returns None.
 
         See also:
 
 
         def gen_value():
             value = self._value(creator())
-            self.backend.set(key, value)
+            if cache_none or value.payload:
+                self.backend.set(key, value)
             return value.payload, value.metadata["ct"]
 
         if expiration_time is None:
 
         self.backend.delete(key)
 
-    def cache_on_arguments(self, namespace=None, expiration_time=None):
+    def cache_on_arguments(self, namespace=None, expiration_time=None, cache_none=True):
         """A function decorator that will cache the return
         value of the function using a key derived from the
         function itself and its arguments.
          being declared.
         :param expiration_time: if not None, will override the normal
          expiration time.
+        :param cache_none: If True (the default) also cache when the
+         decorated function returns None.
         """
         def decorator(fn):
             key_generator = self.function_key_generator(namespace, fn)
                 @wraps(fn)
                 def creator():
                     return fn(*arg, **kw)
-                return self.get_or_create(key, creator, expiration_time)
+                return self.get_or_create(key, creator, expiration_time, cache_none)
 
             def invalidate(*arg, **kw):
                 key = key_generator(*arg, **kw)

tests/cache/test_region.py

         eq_(reg.get_or_create("some key", creator), 
                     "some value 2")
 
+    def test_not_cache_none(self):
+        reg = self._region()
+        def creator():
+            return None
+        reg.get_or_create("some key", creator)
+        value = reg.backend._cache["some key"]
+        eq_(value.payload, None)
+
+        reg = self._region()
+        reg.get_or_create("some key", creator, cache_none=False)
+        self.assertNotIn("some key", reg.backend._cache)
+
 class CacheDecoratorTest(TestCase):
     def _region(self, init_args={}, config_args={}, backend="mock"):
         reg = CacheRegion(**init_args)