diff options
| author | Malcolm Tredinnick <malcolm.tredinnick@gmail.com> | 2010-09-12 18:45:26 +0000 |
|---|---|---|
| committer | Malcolm Tredinnick <malcolm.tredinnick@gmail.com> | 2010-09-12 18:45:26 +0000 |
| commit | fc26da645aea2361d78cf5a5543214a240d82527 (patch) | |
| tree | 0809482a6ff1e3e1f6f55e376dfca19ad336fdce /django/core/cache | |
| parent | bfbc259de0813cd2d1c29755994de3bbf77551fe (diff) | |
Add warning when using cache keys that might not work with memcached.
This means testing with local dev caches (not memcache) will warn
developers if they are introducing inadvertent importabilities. There is
also the ability to silence the warning if a dev is not planning to use
memcache and knows what they are doing with their keys.
Thanks to Carl Meyer for the patch. Fixed #6447.
git-svn-id: http://code.djangoproject.com/svn/django/trunk@13766 bcc190cf-cafb-0310-a4f2-bffc1f526a37
Diffstat (limited to 'django/core/cache')
| -rw-r--r-- | django/core/cache/__init__.py | 2 | ||||
| -rw-r--r-- | django/core/cache/backends/base.py | 28 | ||||
| -rw-r--r-- | django/core/cache/backends/db.py | 5 | ||||
| -rw-r--r-- | django/core/cache/backends/dummy.py | 15 | ||||
| -rw-r--r-- | django/core/cache/backends/filebased.py | 5 | ||||
| -rw-r--r-- | django/core/cache/backends/locmem.py | 5 |
6 files changed, 52 insertions, 8 deletions
diff --git a/django/core/cache/__init__.py b/django/core/cache/__init__.py index 1b602908cb..680f724f94 100644 --- a/django/core/cache/__init__.py +++ b/django/core/cache/__init__.py @@ -18,7 +18,7 @@ See docs/cache.txt for information on the public API. from cgi import parse_qsl from django.conf import settings from django.core import signals -from django.core.cache.backends.base import InvalidCacheBackendError +from django.core.cache.backends.base import InvalidCacheBackendError, CacheKeyWarning from django.utils import importlib # Name for use in settings file --> name of module in "backends" directory. diff --git a/django/core/cache/backends/base.py b/django/core/cache/backends/base.py index e58267a2e9..83dd461804 100644 --- a/django/core/cache/backends/base.py +++ b/django/core/cache/backends/base.py @@ -1,10 +1,18 @@ "Base Cache class." -from django.core.exceptions import ImproperlyConfigured +import warnings + +from django.core.exceptions import ImproperlyConfigured, DjangoRuntimeWarning class InvalidCacheBackendError(ImproperlyConfigured): pass +class CacheKeyWarning(DjangoRuntimeWarning): + pass + +# Memcached does not accept keys longer than this. +MEMCACHE_MAX_KEY_LENGTH = 250 + class BaseCache(object): def __init__(self, params): timeout = params.get('timeout', 300) @@ -116,3 +124,21 @@ class BaseCache(object): def clear(self): """Remove *all* values from the cache at once.""" raise NotImplementedError + + def validate_key(self, key): + """ + Warn about keys that would not be portable to the memcached + backend. This encourages (but does not force) writing backend-portable + cache code. + + """ + if len(key) > MEMCACHE_MAX_KEY_LENGTH: + warnings.warn('Cache key will cause errors if used with memcached: ' + '%s (longer than %s)' % (key, MEMCACHE_MAX_KEY_LENGTH), + CacheKeyWarning) + for char in key: + if ord(char) < 33 or ord(char) == 127: + warnings.warn('Cache key contains characters that will cause ' + 'errors if used with memcached: %r' % key, + CacheKeyWarning) + diff --git a/django/core/cache/backends/db.py b/django/core/cache/backends/db.py index 833fa749aa..c4429c80b3 100644 --- a/django/core/cache/backends/db.py +++ b/django/core/cache/backends/db.py @@ -46,6 +46,7 @@ class CacheClass(BaseCache): self._cull_frequency = 3 def get(self, key, default=None): + self.validate_key(key) db = router.db_for_read(self.cache_model_class) table = connections[db].ops.quote_name(self._table) cursor = connections[db].cursor() @@ -65,9 +66,11 @@ class CacheClass(BaseCache): return pickle.loads(base64.decodestring(value)) def set(self, key, value, timeout=None): + self.validate_key(key) self._base_set('set', key, value, timeout) def add(self, key, value, timeout=None): + self.validate_key(key) return self._base_set('add', key, value, timeout) def _base_set(self, mode, key, value, timeout=None): @@ -103,6 +106,7 @@ class CacheClass(BaseCache): return True def delete(self, key): + self.validate_key(key) db = router.db_for_write(self.cache_model_class) table = connections[db].ops.quote_name(self._table) cursor = connections[db].cursor() @@ -111,6 +115,7 @@ class CacheClass(BaseCache): transaction.commit_unless_managed(using=db) def has_key(self, key): + self.validate_key(key) db = router.db_for_read(self.cache_model_class) table = connections[db].ops.quote_name(self._table) cursor = connections[db].cursor() diff --git a/django/core/cache/backends/dummy.py b/django/core/cache/backends/dummy.py index 4337484cb1..f73b7408bc 100644 --- a/django/core/cache/backends/dummy.py +++ b/django/core/cache/backends/dummy.py @@ -6,22 +6,25 @@ class CacheClass(BaseCache): def __init__(self, *args, **kwargs): pass - def add(self, *args, **kwargs): + def add(self, key, *args, **kwargs): + self.validate_key(key) return True def get(self, key, default=None): + self.validate_key(key) return default - def set(self, *args, **kwargs): - pass + def set(self, key, *args, **kwargs): + self.validate_key(key) - def delete(self, *args, **kwargs): - pass + def delete(self, key, *args, **kwargs): + self.validate_key(key) def get_many(self, *args, **kwargs): return {} - def has_key(self, *args, **kwargs): + def has_key(self, key, *args, **kwargs): + self.validate_key(key) return False def set_many(self, *args, **kwargs): diff --git a/django/core/cache/backends/filebased.py b/django/core/cache/backends/filebased.py index 6057f11ef7..46e69f3091 100644 --- a/django/core/cache/backends/filebased.py +++ b/django/core/cache/backends/filebased.py @@ -32,6 +32,7 @@ class CacheClass(BaseCache): self._createdir() def add(self, key, value, timeout=None): + self.validate_key(key) if self.has_key(key): return False @@ -39,6 +40,7 @@ class CacheClass(BaseCache): return True def get(self, key, default=None): + self.validate_key(key) fname = self._key_to_file(key) try: f = open(fname, 'rb') @@ -56,6 +58,7 @@ class CacheClass(BaseCache): return default def set(self, key, value, timeout=None): + self.validate_key(key) fname = self._key_to_file(key) dirname = os.path.dirname(fname) @@ -79,6 +82,7 @@ class CacheClass(BaseCache): pass def delete(self, key): + self.validate_key(key) try: self._delete(self._key_to_file(key)) except (IOError, OSError): @@ -95,6 +99,7 @@ class CacheClass(BaseCache): pass def has_key(self, key): + self.validate_key(key) fname = self._key_to_file(key) try: f = open(fname, 'rb') diff --git a/django/core/cache/backends/locmem.py b/django/core/cache/backends/locmem.py index eff1201b97..fe33d33307 100644 --- a/django/core/cache/backends/locmem.py +++ b/django/core/cache/backends/locmem.py @@ -30,6 +30,7 @@ class CacheClass(BaseCache): self._lock = RWLock() def add(self, key, value, timeout=None): + self.validate_key(key) self._lock.writer_enters() try: exp = self._expire_info.get(key) @@ -44,6 +45,7 @@ class CacheClass(BaseCache): self._lock.writer_leaves() def get(self, key, default=None): + self.validate_key(key) self._lock.reader_enters() try: exp = self._expire_info.get(key) @@ -76,6 +78,7 @@ class CacheClass(BaseCache): self._expire_info[key] = time.time() + timeout def set(self, key, value, timeout=None): + self.validate_key(key) self._lock.writer_enters() # Python 2.4 doesn't allow combined try-except-finally blocks. try: @@ -87,6 +90,7 @@ class CacheClass(BaseCache): self._lock.writer_leaves() def has_key(self, key): + self.validate_key(key) self._lock.reader_enters() try: exp = self._expire_info.get(key) @@ -127,6 +131,7 @@ class CacheClass(BaseCache): pass def delete(self, key): + self.validate_key(key) self._lock.writer_enters() try: self._delete(key) |
