mirror of
				https://github.com/django/django.git
				synced 2025-11-03 21:25:09 +00:00 
			
		
		
		
	Fixed #9595 -- Allow non-expiring cache timeouts.
Also, streamline the use of 0 and None between cache backends.
This commit is contained in:
		
							parent
							
								
									e0df647143
								
							
						
					
					
						commit
						89955cc35f
					
				
					 10 changed files with 97 additions and 40 deletions
				
			
		
							
								
								
									
										1
									
								
								AUTHORS
									
										
									
									
									
								
							
							
						
						
									
										1
									
								
								AUTHORS
									
										
									
									
									
								
							| 
						 | 
					@ -123,6 +123,7 @@ answer newbie questions, and generally made Django that much better:
 | 
				
			||||||
    bthomas
 | 
					    bthomas
 | 
				
			||||||
    btoll@bestweb.net
 | 
					    btoll@bestweb.net
 | 
				
			||||||
    Jonathan Buchanan <jonathan.buchanan@gmail.com>
 | 
					    Jonathan Buchanan <jonathan.buchanan@gmail.com>
 | 
				
			||||||
 | 
					    Jacob Burch <jacobburch@gmail.com>
 | 
				
			||||||
    Keith Bussell <kbussell@gmail.com>
 | 
					    Keith Bussell <kbussell@gmail.com>
 | 
				
			||||||
    C8E
 | 
					    C8E
 | 
				
			||||||
    Chris Cahoon <chris.cahoon@gmail.com>
 | 
					    Chris Cahoon <chris.cahoon@gmail.com>
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
							
								
								
									
										10
									
								
								django/core/cache/backends/base.py
									
										
									
									
										vendored
									
									
								
							
							
						
						
									
										10
									
								
								django/core/cache/backends/base.py
									
										
									
									
										vendored
									
									
								
							| 
						 | 
					@ -15,6 +15,10 @@ class CacheKeyWarning(DjangoRuntimeWarning):
 | 
				
			||||||
    pass
 | 
					    pass
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Stub class to ensure not passing in a `timeout` argument results in
 | 
				
			||||||
 | 
					# the default timeout
 | 
				
			||||||
 | 
					DEFAULT_TIMEOUT = object()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
# Memcached does not accept keys longer than this.
 | 
					# Memcached does not accept keys longer than this.
 | 
				
			||||||
MEMCACHE_MAX_KEY_LENGTH = 250
 | 
					MEMCACHE_MAX_KEY_LENGTH = 250
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -84,7 +88,7 @@ class BaseCache(object):
 | 
				
			||||||
        new_key = self.key_func(key, self.key_prefix, version)
 | 
					        new_key = self.key_func(key, self.key_prefix, version)
 | 
				
			||||||
        return new_key
 | 
					        return new_key
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def add(self, key, value, timeout=None, version=None):
 | 
					    def add(self, key, value, timeout=DEFAULT_TIMEOUT, version=None):
 | 
				
			||||||
        """
 | 
					        """
 | 
				
			||||||
        Set a value in the cache if the key does not already exist. If
 | 
					        Set a value in the cache if the key does not already exist. If
 | 
				
			||||||
        timeout is given, that timeout will be used for the key; otherwise
 | 
					        timeout is given, that timeout will be used for the key; otherwise
 | 
				
			||||||
| 
						 | 
					@ -101,7 +105,7 @@ class BaseCache(object):
 | 
				
			||||||
        """
 | 
					        """
 | 
				
			||||||
        raise NotImplementedError
 | 
					        raise NotImplementedError
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def set(self, key, value, timeout=None, version=None):
 | 
					    def set(self, key, value, timeout=DEFAULT_TIMEOUT, version=None):
 | 
				
			||||||
        """
 | 
					        """
 | 
				
			||||||
        Set a value in the cache. If timeout is given, that timeout will be
 | 
					        Set a value in the cache. If timeout is given, that timeout will be
 | 
				
			||||||
        used for the key; otherwise the default cache timeout will be used.
 | 
					        used for the key; otherwise the default cache timeout will be used.
 | 
				
			||||||
| 
						 | 
					@ -163,7 +167,7 @@ class BaseCache(object):
 | 
				
			||||||
        # if a subclass overrides it.
 | 
					        # if a subclass overrides it.
 | 
				
			||||||
        return self.has_key(key)
 | 
					        return self.has_key(key)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def set_many(self, data, timeout=None, version=None):
 | 
					    def set_many(self, data, timeout=DEFAULT_TIMEOUT, version=None):
 | 
				
			||||||
        """
 | 
					        """
 | 
				
			||||||
        Set a bunch of values in the cache at once from a dict of key/value
 | 
					        Set a bunch of values in the cache at once from a dict of key/value
 | 
				
			||||||
        pairs.  For certain backends (memcached), this is much more efficient
 | 
					        pairs.  For certain backends (memcached), this is much more efficient
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
							
								
								
									
										15
									
								
								django/core/cache/backends/db.py
									
										
									
									
										vendored
									
									
								
							
							
						
						
									
										15
									
								
								django/core/cache/backends/db.py
									
										
									
									
										vendored
									
									
								
							| 
						 | 
					@ -9,7 +9,7 @@ except ImportError:
 | 
				
			||||||
    import pickle
 | 
					    import pickle
 | 
				
			||||||
 | 
					
 | 
				
			||||||
from django.conf import settings
 | 
					from django.conf import settings
 | 
				
			||||||
from django.core.cache.backends.base import BaseCache
 | 
					from django.core.cache.backends.base import BaseCache, DEFAULT_TIMEOUT
 | 
				
			||||||
from django.db import connections, transaction, router, DatabaseError
 | 
					from django.db import connections, transaction, router, DatabaseError
 | 
				
			||||||
from django.utils import timezone, six
 | 
					from django.utils import timezone, six
 | 
				
			||||||
from django.utils.encoding import force_bytes
 | 
					from django.utils.encoding import force_bytes
 | 
				
			||||||
| 
						 | 
					@ -65,6 +65,7 @@ class DatabaseCache(BaseDatabaseCache):
 | 
				
			||||||
        if row is None:
 | 
					        if row is None:
 | 
				
			||||||
            return default
 | 
					            return default
 | 
				
			||||||
        now = timezone.now()
 | 
					        now = timezone.now()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if row[2] < now:
 | 
					        if row[2] < now:
 | 
				
			||||||
            db = router.db_for_write(self.cache_model_class)
 | 
					            db = router.db_for_write(self.cache_model_class)
 | 
				
			||||||
            cursor = connections[db].cursor()
 | 
					            cursor = connections[db].cursor()
 | 
				
			||||||
| 
						 | 
					@ -74,18 +75,18 @@ class DatabaseCache(BaseDatabaseCache):
 | 
				
			||||||
        value = connections[db].ops.process_clob(row[1])
 | 
					        value = connections[db].ops.process_clob(row[1])
 | 
				
			||||||
        return pickle.loads(base64.b64decode(force_bytes(value)))
 | 
					        return pickle.loads(base64.b64decode(force_bytes(value)))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def set(self, key, value, timeout=None, version=None):
 | 
					    def set(self, key, value, timeout=DEFAULT_TIMEOUT, version=None):
 | 
				
			||||||
        key = self.make_key(key, version=version)
 | 
					        key = self.make_key(key, version=version)
 | 
				
			||||||
        self.validate_key(key)
 | 
					        self.validate_key(key)
 | 
				
			||||||
        self._base_set('set', key, value, timeout)
 | 
					        self._base_set('set', key, value, timeout)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def add(self, key, value, timeout=None, version=None):
 | 
					    def add(self, key, value, timeout=DEFAULT_TIMEOUT, version=None):
 | 
				
			||||||
        key = self.make_key(key, version=version)
 | 
					        key = self.make_key(key, version=version)
 | 
				
			||||||
        self.validate_key(key)
 | 
					        self.validate_key(key)
 | 
				
			||||||
        return self._base_set('add', key, value, timeout)
 | 
					        return self._base_set('add', key, value, timeout)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def _base_set(self, mode, key, value, timeout=None):
 | 
					    def _base_set(self, mode, key, value, timeout=DEFAULT_TIMEOUT):
 | 
				
			||||||
        if timeout is None:
 | 
					        if timeout == DEFAULT_TIMEOUT:
 | 
				
			||||||
            timeout = self.default_timeout
 | 
					            timeout = self.default_timeout
 | 
				
			||||||
        db = router.db_for_write(self.cache_model_class)
 | 
					        db = router.db_for_write(self.cache_model_class)
 | 
				
			||||||
        table = connections[db].ops.quote_name(self._table)
 | 
					        table = connections[db].ops.quote_name(self._table)
 | 
				
			||||||
| 
						 | 
					@ -95,7 +96,9 @@ class DatabaseCache(BaseDatabaseCache):
 | 
				
			||||||
        num = cursor.fetchone()[0]
 | 
					        num = cursor.fetchone()[0]
 | 
				
			||||||
        now = timezone.now()
 | 
					        now = timezone.now()
 | 
				
			||||||
        now = now.replace(microsecond=0)
 | 
					        now = now.replace(microsecond=0)
 | 
				
			||||||
        if settings.USE_TZ:
 | 
					        if timeout is None:
 | 
				
			||||||
 | 
					            exp = datetime.max
 | 
				
			||||||
 | 
					        elif settings.USE_TZ:
 | 
				
			||||||
            exp = datetime.utcfromtimestamp(time.time() + timeout)
 | 
					            exp = datetime.utcfromtimestamp(time.time() + timeout)
 | 
				
			||||||
        else:
 | 
					        else:
 | 
				
			||||||
            exp = datetime.fromtimestamp(time.time() + timeout)
 | 
					            exp = datetime.fromtimestamp(time.time() + timeout)
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
							
								
								
									
										8
									
								
								django/core/cache/backends/dummy.py
									
										
									
									
										vendored
									
									
								
							
							
						
						
									
										8
									
								
								django/core/cache/backends/dummy.py
									
										
									
									
										vendored
									
									
								
							| 
						 | 
					@ -1,12 +1,12 @@
 | 
				
			||||||
"Dummy cache backend"
 | 
					"Dummy cache backend"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
from django.core.cache.backends.base import BaseCache
 | 
					from django.core.cache.backends.base import BaseCache, DEFAULT_TIMEOUT
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class DummyCache(BaseCache):
 | 
					class DummyCache(BaseCache):
 | 
				
			||||||
    def __init__(self, host, *args, **kwargs):
 | 
					    def __init__(self, host, *args, **kwargs):
 | 
				
			||||||
        BaseCache.__init__(self, *args, **kwargs)
 | 
					        BaseCache.__init__(self, *args, **kwargs)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def add(self, key, value, timeout=None, version=None):
 | 
					    def add(self, key, value, timeout=DEFAULT_TIMEOUT, version=None):
 | 
				
			||||||
        key = self.make_key(key, version=version)
 | 
					        key = self.make_key(key, version=version)
 | 
				
			||||||
        self.validate_key(key)
 | 
					        self.validate_key(key)
 | 
				
			||||||
        return True
 | 
					        return True
 | 
				
			||||||
| 
						 | 
					@ -16,7 +16,7 @@ class DummyCache(BaseCache):
 | 
				
			||||||
        self.validate_key(key)
 | 
					        self.validate_key(key)
 | 
				
			||||||
        return default
 | 
					        return default
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def set(self, key, value, timeout=None, version=None):
 | 
					    def set(self, key, value, timeout=DEFAULT_TIMEOUT, version=None):
 | 
				
			||||||
        key = self.make_key(key, version=version)
 | 
					        key = self.make_key(key, version=version)
 | 
				
			||||||
        self.validate_key(key)
 | 
					        self.validate_key(key)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -32,7 +32,7 @@ class DummyCache(BaseCache):
 | 
				
			||||||
        self.validate_key(key)
 | 
					        self.validate_key(key)
 | 
				
			||||||
        return False
 | 
					        return False
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def set_many(self, data, timeout=0, version=None):
 | 
					    def set_many(self, data, timeout=DEFAULT_TIMEOUT, version=None):
 | 
				
			||||||
        pass
 | 
					        pass
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def delete_many(self, keys, version=None):
 | 
					    def delete_many(self, keys, version=None):
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
							
								
								
									
										15
									
								
								django/core/cache/backends/filebased.py
									
										
									
									
										vendored
									
									
								
							
							
						
						
									
										15
									
								
								django/core/cache/backends/filebased.py
									
										
									
									
										vendored
									
									
								
							| 
						 | 
					@ -9,9 +9,10 @@ try:
 | 
				
			||||||
except ImportError:
 | 
					except ImportError:
 | 
				
			||||||
    import pickle
 | 
					    import pickle
 | 
				
			||||||
 | 
					
 | 
				
			||||||
from django.core.cache.backends.base import BaseCache
 | 
					from django.core.cache.backends.base import BaseCache, DEFAULT_TIMEOUT
 | 
				
			||||||
from django.utils.encoding import force_bytes
 | 
					from django.utils.encoding import force_bytes
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class FileBasedCache(BaseCache):
 | 
					class FileBasedCache(BaseCache):
 | 
				
			||||||
    def __init__(self, dir, params):
 | 
					    def __init__(self, dir, params):
 | 
				
			||||||
        BaseCache.__init__(self, params)
 | 
					        BaseCache.__init__(self, params)
 | 
				
			||||||
| 
						 | 
					@ -19,7 +20,7 @@ class FileBasedCache(BaseCache):
 | 
				
			||||||
        if not os.path.exists(self._dir):
 | 
					        if not os.path.exists(self._dir):
 | 
				
			||||||
            self._createdir()
 | 
					            self._createdir()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def add(self, key, value, timeout=None, version=None):
 | 
					    def add(self, key, value, timeout=DEFAULT_TIMEOUT, version=None):
 | 
				
			||||||
        if self.has_key(key, version=version):
 | 
					        if self.has_key(key, version=version):
 | 
				
			||||||
            return False
 | 
					            return False
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -35,7 +36,7 @@ class FileBasedCache(BaseCache):
 | 
				
			||||||
            with open(fname, 'rb') as f:
 | 
					            with open(fname, 'rb') as f:
 | 
				
			||||||
                exp = pickle.load(f)
 | 
					                exp = pickle.load(f)
 | 
				
			||||||
                now = time.time()
 | 
					                now = time.time()
 | 
				
			||||||
                if exp < now:
 | 
					                if exp is not None and exp < now:
 | 
				
			||||||
                    self._delete(fname)
 | 
					                    self._delete(fname)
 | 
				
			||||||
                else:
 | 
					                else:
 | 
				
			||||||
                    return pickle.load(f)
 | 
					                    return pickle.load(f)
 | 
				
			||||||
| 
						 | 
					@ -43,14 +44,14 @@ class FileBasedCache(BaseCache):
 | 
				
			||||||
            pass
 | 
					            pass
 | 
				
			||||||
        return default
 | 
					        return default
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def set(self, key, value, timeout=None, version=None):
 | 
					    def set(self, key, value, timeout=DEFAULT_TIMEOUT, version=None):
 | 
				
			||||||
        key = self.make_key(key, version=version)
 | 
					        key = self.make_key(key, version=version)
 | 
				
			||||||
        self.validate_key(key)
 | 
					        self.validate_key(key)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        fname = self._key_to_file(key)
 | 
					        fname = self._key_to_file(key)
 | 
				
			||||||
        dirname = os.path.dirname(fname)
 | 
					        dirname = os.path.dirname(fname)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if timeout is None:
 | 
					        if timeout == DEFAULT_TIMEOUT:
 | 
				
			||||||
            timeout = self.default_timeout
 | 
					            timeout = self.default_timeout
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        self._cull()
 | 
					        self._cull()
 | 
				
			||||||
| 
						 | 
					@ -60,8 +61,8 @@ class FileBasedCache(BaseCache):
 | 
				
			||||||
                os.makedirs(dirname)
 | 
					                os.makedirs(dirname)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            with open(fname, 'wb') as f:
 | 
					            with open(fname, 'wb') as f:
 | 
				
			||||||
                now = time.time()
 | 
					                expiry = None if timeout is None else time.time() + timeout
 | 
				
			||||||
                pickle.dump(now + timeout, f, pickle.HIGHEST_PROTOCOL)
 | 
					                pickle.dump(expiry, f, pickle.HIGHEST_PROTOCOL)
 | 
				
			||||||
                pickle.dump(value, f, pickle.HIGHEST_PROTOCOL)
 | 
					                pickle.dump(value, f, pickle.HIGHEST_PROTOCOL)
 | 
				
			||||||
        except (IOError, OSError):
 | 
					        except (IOError, OSError):
 | 
				
			||||||
            pass
 | 
					            pass
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
							
								
								
									
										19
									
								
								django/core/cache/backends/locmem.py
									
										
									
									
										vendored
									
									
								
							
							
						
						
									
										19
									
								
								django/core/cache/backends/locmem.py
									
										
									
									
										vendored
									
									
								
							| 
						 | 
					@ -6,7 +6,7 @@ try:
 | 
				
			||||||
except ImportError:
 | 
					except ImportError:
 | 
				
			||||||
    import pickle
 | 
					    import pickle
 | 
				
			||||||
 | 
					
 | 
				
			||||||
from django.core.cache.backends.base import BaseCache
 | 
					from django.core.cache.backends.base import BaseCache, DEFAULT_TIMEOUT
 | 
				
			||||||
from django.utils.synch import RWLock
 | 
					from django.utils.synch import RWLock
 | 
				
			||||||
 | 
					
 | 
				
			||||||
# Global in-memory store of cache data. Keyed by name, to provide
 | 
					# Global in-memory store of cache data. Keyed by name, to provide
 | 
				
			||||||
| 
						 | 
					@ -23,7 +23,7 @@ class LocMemCache(BaseCache):
 | 
				
			||||||
        self._expire_info = _expire_info.setdefault(name, {})
 | 
					        self._expire_info = _expire_info.setdefault(name, {})
 | 
				
			||||||
        self._lock = _locks.setdefault(name, RWLock())
 | 
					        self._lock = _locks.setdefault(name, RWLock())
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def add(self, key, value, timeout=None, version=None):
 | 
					    def add(self, key, value, timeout=DEFAULT_TIMEOUT, version=None):
 | 
				
			||||||
        key = self.make_key(key, version=version)
 | 
					        key = self.make_key(key, version=version)
 | 
				
			||||||
        self.validate_key(key)
 | 
					        self.validate_key(key)
 | 
				
			||||||
        with self._lock.writer():
 | 
					        with self._lock.writer():
 | 
				
			||||||
| 
						 | 
					@ -41,10 +41,8 @@ class LocMemCache(BaseCache):
 | 
				
			||||||
        key = self.make_key(key, version=version)
 | 
					        key = self.make_key(key, version=version)
 | 
				
			||||||
        self.validate_key(key)
 | 
					        self.validate_key(key)
 | 
				
			||||||
        with self._lock.reader():
 | 
					        with self._lock.reader():
 | 
				
			||||||
            exp = self._expire_info.get(key)
 | 
					            exp = self._expire_info.get(key, 0)
 | 
				
			||||||
            if exp is None:
 | 
					            if exp is None or exp > time.time():
 | 
				
			||||||
                return default
 | 
					 | 
				
			||||||
            elif exp > time.time():
 | 
					 | 
				
			||||||
                try:
 | 
					                try:
 | 
				
			||||||
                    pickled = self._cache[key]
 | 
					                    pickled = self._cache[key]
 | 
				
			||||||
                    return pickle.loads(pickled)
 | 
					                    return pickle.loads(pickled)
 | 
				
			||||||
| 
						 | 
					@ -58,15 +56,16 @@ class LocMemCache(BaseCache):
 | 
				
			||||||
                pass
 | 
					                pass
 | 
				
			||||||
            return default
 | 
					            return default
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def _set(self, key, value, timeout=None):
 | 
					    def _set(self, key, value, timeout=DEFAULT_TIMEOUT):
 | 
				
			||||||
        if len(self._cache) >= self._max_entries:
 | 
					        if len(self._cache) >= self._max_entries:
 | 
				
			||||||
            self._cull()
 | 
					            self._cull()
 | 
				
			||||||
        if timeout is None:
 | 
					        if timeout == DEFAULT_TIMEOUT:
 | 
				
			||||||
            timeout = self.default_timeout
 | 
					            timeout = self.default_timeout
 | 
				
			||||||
 | 
					        expiry = None if timeout is None else time.time() + timeout
 | 
				
			||||||
        self._cache[key] = value
 | 
					        self._cache[key] = value
 | 
				
			||||||
        self._expire_info[key] = time.time() + timeout
 | 
					        self._expire_info[key] = expiry
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def set(self, key, value, timeout=None, version=None):
 | 
					    def set(self, key, value, timeout=DEFAULT_TIMEOUT, version=None):
 | 
				
			||||||
        key = self.make_key(key, version=version)
 | 
					        key = self.make_key(key, version=version)
 | 
				
			||||||
        self.validate_key(key)
 | 
					        self.validate_key(key)
 | 
				
			||||||
        with self._lock.writer():
 | 
					        with self._lock.writer():
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
							
								
								
									
										22
									
								
								django/core/cache/backends/memcached.py
									
										
									
									
										vendored
									
									
								
							
							
						
						
									
										22
									
								
								django/core/cache/backends/memcached.py
									
										
									
									
										vendored
									
									
								
							| 
						 | 
					@ -4,7 +4,7 @@ import time
 | 
				
			||||||
import pickle
 | 
					import pickle
 | 
				
			||||||
from threading import local
 | 
					from threading import local
 | 
				
			||||||
 | 
					
 | 
				
			||||||
from django.core.cache.backends.base import BaseCache, InvalidCacheBackendError
 | 
					from django.core.cache.backends.base import BaseCache, DEFAULT_TIMEOUT
 | 
				
			||||||
 | 
					
 | 
				
			||||||
from django.utils import six
 | 
					from django.utils import six
 | 
				
			||||||
from django.utils.encoding import force_str
 | 
					from django.utils.encoding import force_str
 | 
				
			||||||
| 
						 | 
					@ -36,12 +36,22 @@ class BaseMemcachedCache(BaseCache):
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        return self._client
 | 
					        return self._client
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def _get_memcache_timeout(self, timeout):
 | 
					    def _get_memcache_timeout(self, timeout=DEFAULT_TIMEOUT):
 | 
				
			||||||
        """
 | 
					        """
 | 
				
			||||||
        Memcached deals with long (> 30 days) timeouts in a special
 | 
					        Memcached deals with long (> 30 days) timeouts in a special
 | 
				
			||||||
        way. Call this function to obtain a safe value for your timeout.
 | 
					        way. Call this function to obtain a safe value for your timeout.
 | 
				
			||||||
        """
 | 
					        """
 | 
				
			||||||
        timeout = timeout or self.default_timeout
 | 
					        if timeout == DEFAULT_TIMEOUT:
 | 
				
			||||||
 | 
					            return self.default_timeout
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if timeout is None:
 | 
				
			||||||
 | 
					            # Using 0 in memcache sets a non-expiring timeout.
 | 
				
			||||||
 | 
					            return 0
 | 
				
			||||||
 | 
					        elif int(timeout) == 0:
 | 
				
			||||||
 | 
					            # Other cache backends treat 0 as set-and-expire. To achieve this
 | 
				
			||||||
 | 
					            # in memcache backends, a negative timeout must be passed.
 | 
				
			||||||
 | 
					            timeout = -1
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if timeout > 2592000: # 60*60*24*30, 30 days
 | 
					        if timeout > 2592000: # 60*60*24*30, 30 days
 | 
				
			||||||
            # See http://code.google.com/p/memcached/wiki/FAQ
 | 
					            # See http://code.google.com/p/memcached/wiki/FAQ
 | 
				
			||||||
            # "You can set expire times up to 30 days in the future. After that
 | 
					            # "You can set expire times up to 30 days in the future. After that
 | 
				
			||||||
| 
						 | 
					@ -56,7 +66,7 @@ class BaseMemcachedCache(BaseCache):
 | 
				
			||||||
        # Python 2 memcache requires the key to be a byte string.
 | 
					        # Python 2 memcache requires the key to be a byte string.
 | 
				
			||||||
        return force_str(super(BaseMemcachedCache, self).make_key(key, version))
 | 
					        return force_str(super(BaseMemcachedCache, self).make_key(key, version))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def add(self, key, value, timeout=0, version=None):
 | 
					    def add(self, key, value, timeout=DEFAULT_TIMEOUT, version=None):
 | 
				
			||||||
        key = self.make_key(key, version=version)
 | 
					        key = self.make_key(key, version=version)
 | 
				
			||||||
        return self._cache.add(key, value, self._get_memcache_timeout(timeout))
 | 
					        return self._cache.add(key, value, self._get_memcache_timeout(timeout))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -67,7 +77,7 @@ class BaseMemcachedCache(BaseCache):
 | 
				
			||||||
            return default
 | 
					            return default
 | 
				
			||||||
        return val
 | 
					        return val
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def set(self, key, value, timeout=0, version=None):
 | 
					    def set(self, key, value, timeout=DEFAULT_TIMEOUT, version=None):
 | 
				
			||||||
        key = self.make_key(key, version=version)
 | 
					        key = self.make_key(key, version=version)
 | 
				
			||||||
        self._cache.set(key, value, self._get_memcache_timeout(timeout))
 | 
					        self._cache.set(key, value, self._get_memcache_timeout(timeout))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -125,7 +135,7 @@ class BaseMemcachedCache(BaseCache):
 | 
				
			||||||
            raise ValueError("Key '%s' not found" % key)
 | 
					            raise ValueError("Key '%s' not found" % key)
 | 
				
			||||||
        return val
 | 
					        return val
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def set_many(self, data, timeout=0, version=None):
 | 
					    def set_many(self, data, timeout=DEFAULT_TIMEOUT, version=None):
 | 
				
			||||||
        safe_data = {}
 | 
					        safe_data = {}
 | 
				
			||||||
        for key, value in data.items():
 | 
					        for key, value in data.items():
 | 
				
			||||||
            key = self.make_key(key, version=version)
 | 
					            key = self.make_key(key, version=version)
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -485,6 +485,12 @@ Miscellaneous
 | 
				
			||||||
  changes in 1.6 particularly affect :class:`~django.forms.DecimalField` and
 | 
					  changes in 1.6 particularly affect :class:`~django.forms.DecimalField` and
 | 
				
			||||||
  :class:`~django.forms.ModelMultipleChoiceField`.
 | 
					  :class:`~django.forms.ModelMultipleChoiceField`.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					* There have been changes in the way timeouts are handled in cache backends.
 | 
				
			||||||
 | 
					  Explicitly passing in ``timeout=None`` no longer results in using the
 | 
				
			||||||
 | 
					  default timeout. It will now set a non-expiring timeout. Passing 0 into the
 | 
				
			||||||
 | 
					  memcache backend no longer uses the default timeout, and now will
 | 
				
			||||||
 | 
					  set-and-expire-immediately the value.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
Features deprecated in 1.6
 | 
					Features deprecated in 1.6
 | 
				
			||||||
==========================
 | 
					==========================
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -707,10 +707,15 @@ The basic interface is ``set(key, value, timeout)`` and ``get(key)``::
 | 
				
			||||||
    >>> cache.get('my_key')
 | 
					    >>> cache.get('my_key')
 | 
				
			||||||
    'hello, world!'
 | 
					    'hello, world!'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
The ``timeout`` argument is optional and defaults to the ``timeout``
 | 
					The ``timeout`` argument is optional and defaults to the ``timeout`` argument
 | 
				
			||||||
argument of the appropriate backend in the :setting:`CACHES` setting
 | 
					of the appropriate backend in the :setting:`CACHES` setting (explained above).
 | 
				
			||||||
(explained above). It's the number of seconds the value should be stored
 | 
					It's the number of seconds the value should be stored in the cache. Passing in
 | 
				
			||||||
in the cache.
 | 
					``None`` for ``timeout`` will cache the value forever.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					.. versionchanged:: 1.6
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    Previously, passing ``None`` explicitly would use the default timeout
 | 
				
			||||||
 | 
					    value.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
If the object doesn't exist in the cache, ``cache.get()`` returns ``None``::
 | 
					If the object doesn't exist in the cache, ``cache.get()`` returns ``None``::
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
							
								
								
									
										28
									
								
								tests/cache/tests.py
									
										
									
									
										vendored
									
									
								
							
							
						
						
									
										28
									
								
								tests/cache/tests.py
									
										
									
									
										vendored
									
									
								
							| 
						 | 
					@ -441,6 +441,34 @@ class BaseCacheTests(object):
 | 
				
			||||||
        self.assertEqual(self.cache.get('key3'), 'sausage')
 | 
					        self.assertEqual(self.cache.get('key3'), 'sausage')
 | 
				
			||||||
        self.assertEqual(self.cache.get('key4'), 'lobster bisque')
 | 
					        self.assertEqual(self.cache.get('key4'), 'lobster bisque')
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def test_forever_timeout(self):
 | 
				
			||||||
 | 
					        '''
 | 
				
			||||||
 | 
					        Passing in None into timeout results in a value that is cached forever
 | 
				
			||||||
 | 
					        '''
 | 
				
			||||||
 | 
					        self.cache.set('key1', 'eggs', None)
 | 
				
			||||||
 | 
					        self.assertEqual(self.cache.get('key1'), 'eggs')
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        self.cache.add('key2', 'ham', None)
 | 
				
			||||||
 | 
					        self.assertEqual(self.cache.get('key2'), 'ham')
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        self.cache.set_many({'key3': 'sausage', 'key4': 'lobster bisque'}, None)
 | 
				
			||||||
 | 
					        self.assertEqual(self.cache.get('key3'), 'sausage')
 | 
				
			||||||
 | 
					        self.assertEqual(self.cache.get('key4'), 'lobster bisque')
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def test_zero_timeout(self):
 | 
				
			||||||
 | 
					        '''
 | 
				
			||||||
 | 
					        Passing in None into timeout results in a value that is cached forever
 | 
				
			||||||
 | 
					        '''
 | 
				
			||||||
 | 
					        self.cache.set('key1', 'eggs', 0)
 | 
				
			||||||
 | 
					        self.assertEqual(self.cache.get('key1'), None)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        self.cache.add('key2', 'ham', 0)
 | 
				
			||||||
 | 
					        self.assertEqual(self.cache.get('key2'), None)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        self.cache.set_many({'key3': 'sausage', 'key4': 'lobster bisque'}, 0)
 | 
				
			||||||
 | 
					        self.assertEqual(self.cache.get('key3'), None)
 | 
				
			||||||
 | 
					        self.assertEqual(self.cache.get('key4'), None)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def test_float_timeout(self):
 | 
					    def test_float_timeout(self):
 | 
				
			||||||
        # Make sure a timeout given as a float doesn't crash anything.
 | 
					        # Make sure a timeout given as a float doesn't crash anything.
 | 
				
			||||||
        self.cache.set("key1", "spam", 100.2)
 | 
					        self.cache.set("key1", "spam", 100.2)
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue