summaryrefslogtreecommitdiff
path: root/django/core/cache
diff options
context:
space:
mode:
authorMalcolm Tredinnick <malcolm.tredinnick@gmail.com>2010-09-12 18:45:26 +0000
committerMalcolm Tredinnick <malcolm.tredinnick@gmail.com>2010-09-12 18:45:26 +0000
commitfc26da645aea2361d78cf5a5543214a240d82527 (patch)
tree0809482a6ff1e3e1f6f55e376dfca19ad336fdce /django/core/cache
parentbfbc259de0813cd2d1c29755994de3bbf77551fe (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__.py2
-rw-r--r--django/core/cache/backends/base.py28
-rw-r--r--django/core/cache/backends/db.py5
-rw-r--r--django/core/cache/backends/dummy.py15
-rw-r--r--django/core/cache/backends/filebased.py5
-rw-r--r--django/core/cache/backends/locmem.py5
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)