From 8a090c21f10c503dd5f29885e78bfb0cb5588ba4 Mon Sep 17 00:00:00 2001 From: Malcolm Box Date: Fri, 9 May 2014 11:23:28 +0100 Subject: [PATCH] [1.7.x] Fixed #22606 -- Locmemcache has_key() failed for infinite cache expiry Refactored cache expiry logic for Locmemcache to make consistent across all places where accessed, and correctly handle None as expiry time. Backport of 66880e4cd from master. --- django/core/cache/backends/locmem.py | 17 +++++++++-------- tests/cache/tests.py | 2 ++ 2 files changed, 11 insertions(+), 8 deletions(-) diff --git a/django/core/cache/backends/locmem.py b/django/core/cache/backends/locmem.py index aba8b61a4de..7c2609c2373 100644 --- a/django/core/cache/backends/locmem.py +++ b/django/core/cache/backends/locmem.py @@ -29,8 +29,7 @@ class LocMemCache(BaseCache): self.validate_key(key) pickled = pickle.dumps(value, pickle.HIGHEST_PROTOCOL) with self._lock.writer(): - exp = self._expire_info.get(key, 0) - if exp is not None and exp <= time.time(): + if self._has_expired(key): self._set(key, pickled, timeout) return True return False @@ -40,8 +39,7 @@ class LocMemCache(BaseCache): self.validate_key(key) pickled = None with self._lock.reader(): - exp = self._expire_info.get(key, 0) - if exp is None or exp > time.time(): + if not self._has_expired(key): pickled = self._cache[key] if pickled is not None: try: @@ -85,10 +83,7 @@ class LocMemCache(BaseCache): key = self.make_key(key, version=version) self.validate_key(key) with self._lock.reader(): - exp = self._expire_info.get(key) - if exp is None: - return False - elif exp > time.time(): + if not self._has_expired(key): return True with self._lock.writer(): @@ -99,6 +94,12 @@ class LocMemCache(BaseCache): pass return False + def _has_expired(self, key): + exp = self._expire_info.get(key, -1) + if exp is None or exp > time.time(): + return False + return True + def _cull(self): if self._cull_frequency == 0: self.clear() diff --git a/tests/cache/tests.py b/tests/cache/tests.py index a9f5927c83d..94af45c03e4 100644 --- a/tests/cache/tests.py +++ b/tests/cache/tests.py @@ -286,6 +286,8 @@ class BaseCacheTests(object): cache.set("hello1", "goodbye1") self.assertEqual(cache.has_key("hello1"), True) self.assertEqual(cache.has_key("goodbye1"), False) + cache.set("no_expiry", "here", None) + self.assertEqual(cache.has_key("no_expiry"), True) def test_in(self): # The in operator can be used to inspect cache contents