summaryrefslogtreecommitdiff
path: root/django/utils
diff options
context:
space:
mode:
authorJeremy Dunck <jdunck@gmail.com>2007-12-01 22:12:44 +0000
committerJeremy Dunck <jdunck@gmail.com>2007-12-01 22:12:44 +0000
commit23384af79b2f43f08e8395d0a84a57c2a98df392 (patch)
tree77e45f0e0fc6cb9b3380982313f45febf2ebf6f0 /django/utils
parent85ce45bc441e4ace2fba83bc2d2432e22ec9da94 (diff)
gis: Merged 6672-6783 vis svnmerge from trunk
git-svn-id: http://code.djangoproject.com/svn/django/branches/gis@6815 bcc190cf-cafb-0310-a4f2-bffc1f526a37
Diffstat (limited to 'django/utils')
-rw-r--r--django/utils/cache.py43
-rw-r--r--django/utils/datastructures.py76
-rw-r--r--django/utils/html.py19
-rw-r--r--django/utils/safestring.py2
-rw-r--r--django/utils/translation/trans_null.py6
-rw-r--r--django/utils/translation/trans_real.py22
-rw-r--r--django/utils/tzinfo.py8
7 files changed, 117 insertions, 59 deletions
diff --git a/django/utils/cache.py b/django/utils/cache.py
index ae4de6dd87..4fcf493944 100644
--- a/django/utils/cache.py
+++ b/django/utils/cache.py
@@ -20,6 +20,10 @@ An example: i18n middleware would need to distinguish caches by the
import md5
import re
import time
+try:
+ set
+except NameError:
+ from sets import Set as set # Python 2.3 fallback
from django.conf import settings
from django.core.cache import cache
@@ -70,7 +74,20 @@ def patch_cache_control(response, **kwargs):
cc = ', '.join([dictvalue(el) for el in cc.items()])
response['Cache-Control'] = cc
-vary_delim_re = re.compile(r',\s*')
+def get_max_age(response):
+ """
+ Returns the max-age from the response Cache-Control header as an integer
+ (or ``None`` if it wasn't found or wasn't an integer.
+ """
+ if not response.has_header('Cache-Control'):
+ return
+ cc = dict([_to_tuple(el) for el in
+ cc_delim_re.split(response['Cache-Control'])])
+ if 'max-age' in cc:
+ try:
+ return int(cc['max-age'])
+ except (ValueError, TypeError):
+ pass
def patch_response_headers(response, cache_timeout=None):
"""
@@ -109,14 +126,15 @@ def patch_vary_headers(response, newheaders):
# Note that we need to keep the original order intact, because cache
# implementations may rely on the order of the Vary contents in, say,
# computing an MD5 hash.
- vary = []
if response.has_header('Vary'):
- vary = vary_delim_re.split(response['Vary'])
- oldheaders = dict([(el.lower(), 1) for el in vary])
- for newheader in newheaders:
- if not newheader.lower() in oldheaders:
- vary.append(newheader)
- response['Vary'] = ', '.join(vary)
+ vary_headers = cc_delim_re.split(response['Vary'])
+ else:
+ vary_headers = []
+ # Use .lower() here so we treat headers as case-insensitive.
+ existing_headers = set([header.lower() for header in vary_headers])
+ additional_headers = [newheader for newheader in newheaders
+ if newheader.lower() not in existing_headers]
+ response['Vary'] = ', '.join(vary_headers + additional_headers)
def _generate_cache_key(request, headerlist, key_prefix):
"""Returns a cache key from the headers given in the header list."""
@@ -169,7 +187,7 @@ def learn_cache_key(request, response, cache_timeout=None, key_prefix=None):
key_prefix, iri_to_uri(request.path))
if response.has_header('Vary'):
headerlist = ['HTTP_'+header.upper().replace('-', '_')
- for header in vary_delim_re.split(response['Vary'])]
+ for header in cc_delim_re.split(response['Vary'])]
cache.set(cache_key, headerlist, cache_timeout)
return _generate_cache_key(request, headerlist, key_prefix)
else:
@@ -177,3 +195,10 @@ def learn_cache_key(request, response, cache_timeout=None, key_prefix=None):
# for the request.path
cache.set(cache_key, [], cache_timeout)
return _generate_cache_key(request, [], key_prefix)
+
+
+def _to_tuple(s):
+ t = s.split('=',1)
+ if len(t) == 2:
+ return t[0].lower(), t[1]
+ return t[0].lower(), True
diff --git a/django/utils/datastructures.py b/django/utils/datastructures.py
index 549aa3f183..ee156b11d0 100644
--- a/django/utils/datastructures.py
+++ b/django/utils/datastructures.py
@@ -7,9 +7,9 @@ class MergeDict(object):
self.dicts = dicts
def __getitem__(self, key):
- for dict in self.dicts:
+ for dict_ in self.dicts:
try:
- return dict[key]
+ return dict_[key]
except KeyError:
pass
raise KeyError
@@ -24,22 +24,22 @@ class MergeDict(object):
return default
def getlist(self, key):
- for dict in self.dicts:
+ for dict_ in self.dicts:
try:
- return dict.getlist(key)
+ return dict_.getlist(key)
except KeyError:
pass
raise KeyError
def items(self):
item_list = []
- for dict in self.dicts:
- item_list.extend(dict.items())
+ for dict_ in self.dicts:
+ item_list.extend(dict_.items())
return item_list
def has_key(self, key):
- for dict in self.dicts:
- if key in dict:
+ for dict_ in self.dicts:
+ if key in dict_:
return True
return False
@@ -56,11 +56,14 @@ class SortedDict(dict):
def __init__(self, data=None):
if data is None:
data = {}
- dict.__init__(self, data)
+ super(SortedDict, self).__init__(data)
if isinstance(data, dict):
self.keyOrder = data.keys()
else:
- self.keyOrder = [key for key, value in data]
+ self.keyOrder = []
+ for key, value in data:
+ if key not in self.keyOrder:
+ self.keyOrder.append(key)
def __deepcopy__(self, memo):
from copy import deepcopy
@@ -68,12 +71,12 @@ class SortedDict(dict):
for key, value in self.iteritems()])
def __setitem__(self, key, value):
- dict.__setitem__(self, key, value)
+ super(SortedDict, self).__setitem__(key, value)
if key not in self.keyOrder:
self.keyOrder.append(key)
def __delitem__(self, key):
- dict.__delitem__(self, key)
+ super(SortedDict, self).__delitem__(key)
self.keyOrder.remove(key)
def __iter__(self):
@@ -81,7 +84,7 @@ class SortedDict(dict):
yield k
def pop(self, k, *args):
- result = dict.pop(self, k, *args)
+ result = super(SortedDict, self).pop(k, *args)
try:
self.keyOrder.remove(k)
except ValueError:
@@ -90,7 +93,7 @@ class SortedDict(dict):
return result
def popitem(self):
- result = dict.popitem(self)
+ result = super(SortedDict, self).popitem()
self.keyOrder.remove(result[0])
return result
@@ -99,7 +102,7 @@ class SortedDict(dict):
def iteritems(self):
for key in self.keyOrder:
- yield key, dict.__getitem__(self, key)
+ yield key, super(SortedDict, self).__getitem__(key)
def keys(self):
return self.keyOrder[:]
@@ -108,20 +111,20 @@ class SortedDict(dict):
return iter(self.keyOrder)
def values(self):
- return [dict.__getitem__(self, k) for k in self.keyOrder]
+ return [super(SortedDict, self).__getitem__(k) for k in self.keyOrder]
def itervalues(self):
for key in self.keyOrder:
- yield dict.__getitem__(self, key)
+ yield super(SortedDict, self).__getitem__(key)
- def update(self, dict):
- for k, v in dict.items():
+ def update(self, dict_):
+ for k, v in dict_.items():
self.__setitem__(k, v)
def setdefault(self, key, default):
if key not in self.keyOrder:
self.keyOrder.append(key)
- return dict.setdefault(self, key, default)
+ return super(SortedDict, self).setdefault(key, default)
def value_for_index(self, index):
"""Returns the value of the item at the given zero-based index."""
@@ -135,7 +138,7 @@ class SortedDict(dict):
if n < index:
index -= 1
self.keyOrder.insert(index, key)
- dict.__setitem__(self, key, value)
+ super(SortedDict, self).__setitem__(key, value)
def copy(self):
"""Returns a copy of this object."""
@@ -173,10 +176,11 @@ class MultiValueDict(dict):
single name-value pairs.
"""
def __init__(self, key_to_list_mapping=()):
- dict.__init__(self, key_to_list_mapping)
+ super(MultiValueDict, self).__init__(key_to_list_mapping)
def __repr__(self):
- return "<%s: %s>" % (self.__class__.__name__, dict.__repr__(self))
+ return "<%s: %s>" % (self.__class__.__name__,
+ super(MultiValueDict, self).__repr__())
def __getitem__(self, key):
"""
@@ -184,7 +188,7 @@ class MultiValueDict(dict):
raises KeyError if not found.
"""
try:
- list_ = dict.__getitem__(self, key)
+ list_ = super(MultiValueDict, self).__getitem__(key)
except KeyError:
raise MultiValueDictKeyError, "Key %r not found in %r" % (key, self)
try:
@@ -193,10 +197,10 @@ class MultiValueDict(dict):
return []
def __setitem__(self, key, value):
- dict.__setitem__(self, key, [value])
+ super(MultiValueDict, self).__setitem__(key, [value])
def __copy__(self):
- return self.__class__(dict.items(self))
+ return self.__class__(super(MultiValueDict, self).items())
def __deepcopy__(self, memo=None):
import copy
@@ -210,7 +214,10 @@ class MultiValueDict(dict):
return result
def get(self, key, default=None):
- """Returns the default value if the requested data doesn't exist."""
+ """
+ Returns the last data value for the passed key. If key doesn't exist
+ or value is an empty list, then default is returned.
+ """
try:
val = self[key]
except KeyError:
@@ -220,14 +227,17 @@ class MultiValueDict(dict):
return val
def getlist(self, key):
- """Returns an empty list if the requested data doesn't exist."""
+ """
+ Returns the list of values for the passed key. If key doesn't exist,
+ then an empty list is returned.
+ """
try:
- return dict.__getitem__(self, key)
+ return super(MultiValueDict, self).__getitem__(key)
except KeyError:
return []
def setlist(self, key, list_):
- dict.__setitem__(self, key, list_)
+ super(MultiValueDict, self).__setitem__(key, list_)
def setdefault(self, key, default=None):
if key not in self:
@@ -242,7 +252,7 @@ class MultiValueDict(dict):
def appendlist(self, key, value):
"""Appends an item to the internal list associated with key."""
self.setlistdefault(key, [])
- dict.__setitem__(self, key, self.getlist(key) + [value])
+ super(MultiValueDict, self).__setitem__(key, self.getlist(key) + [value])
def items(self):
"""
@@ -253,7 +263,7 @@ class MultiValueDict(dict):
def lists(self):
"""Returns a list of (key, list) pairs."""
- return dict.items(self)
+ return super(MultiValueDict, self).items()
def values(self):
"""Returns a list of the last value on every key list."""
@@ -315,7 +325,7 @@ class DotExpandedDict(dict):
try:
current[bits[-1]] = v
except TypeError: # Special-case if current isn't a dict.
- current = {bits[-1] : v}
+ current = {bits[-1]: v}
class FileDict(dict):
"""
diff --git a/django/utils/html.py b/django/utils/html.py
index 8eeaa66330..cb786db1e4 100644
--- a/django/utils/html.py
+++ b/django/utils/html.py
@@ -6,6 +6,7 @@ import string
from django.utils.safestring import SafeData, mark_safe
from django.utils.encoding import force_unicode
from django.utils.functional import allow_lazy
+from django.utils.http import urlquote
# Configuration for urlize() function
LEADING_PUNCTUATION = ['(', '<', '&lt;']
@@ -101,14 +102,24 @@ def urlize(text, trim_url_limit=None, nofollow=False, autoescape=False):
if middle.startswith('www.') or ('@' not in middle and not middle.startswith('http://') and \
len(middle) > 0 and middle[0] in string.letters + string.digits and \
(middle.endswith('.org') or middle.endswith('.net') or middle.endswith('.com'))):
- middle = '<a href="http://%s"%s>%s</a>' % (middle, nofollow_attr, trim_url(middle))
+ middle = '<a href="http://%s"%s>%s</a>' % (
+ urlquote(middle, safe='/&=:;#?+'), nofollow_attr,
+ trim_url(middle))
if middle.startswith('http://') or middle.startswith('https://'):
- middle = '<a href="%s"%s>%s</a>' % (middle, nofollow_attr, trim_url(middle))
- if '@' in middle and not middle.startswith('www.') and not ':' in middle \
- and simple_email_re.match(middle):
+ middle = '<a href="%s"%s>%s</a>' % (
+ urlquote(middle, safe='/&=:;#?+'), nofollow_attr,
+ trim_url(middle))
+ if '@' in middle and not middle.startswith('www.') and \
+ not ':' in middle and simple_email_re.match(middle):
middle = '<a href="mailto:%s">%s</a>' % (middle, middle)
if lead + middle + trail != word:
words[i] = lead + middle + trail
+ elif autoescape and not safe_input:
+ words[i] = escape(word)
+ elif safe_input:
+ words[i] = mark_safe(word)
+ elif autoescape:
+ words[i] = escape(word)
return u''.join(words)
urlize = allow_lazy(urlize, unicode)
diff --git a/django/utils/safestring.py b/django/utils/safestring.py
index c7234af0f3..f6f4c1eb2f 100644
--- a/django/utils/safestring.py
+++ b/django/utils/safestring.py
@@ -57,7 +57,6 @@ class SafeString(str, SafeData):
else:
return SafeUnicode(data)
- encode = curry(_proxy_method, method = str.encode)
decode = curry(_proxy_method, method = str.decode)
class SafeUnicode(unicode, SafeData):
@@ -89,7 +88,6 @@ class SafeUnicode(unicode, SafeData):
return SafeUnicode(data)
encode = curry(_proxy_method, method = unicode.encode)
- decode = curry(_proxy_method, method = unicode.decode)
def mark_safe(s):
"""
diff --git a/django/utils/translation/trans_null.py b/django/utils/translation/trans_null.py
index 0b62907e44..98c6de6197 100644
--- a/django/utils/translation/trans_null.py
+++ b/django/utils/translation/trans_null.py
@@ -4,6 +4,7 @@
from django.conf import settings
from django.utils.encoding import force_unicode
+from django.utils.safestring import mark_safe, SafeData
def ngettext(singular, plural, number):
if number == 1: return singular
@@ -31,7 +32,10 @@ TECHNICAL_ID_MAP = {
}
def gettext(message):
- return TECHNICAL_ID_MAP.get(message, message)
+ result = TECHNICAL_ID_MAP.get(message, message)
+ if isinstance(message, SafeData):
+ return mark_safe(result)
+ return result
def ugettext(message):
return force_unicode(gettext(message))
diff --git a/django/utils/translation/trans_real.py b/django/utils/translation/trans_real.py
index 98b4769031..a7259b3ce5 100644
--- a/django/utils/translation/trans_real.py
+++ b/django/utils/translation/trans_real.py
@@ -8,6 +8,7 @@ import gettext as gettext_module
from cStringIO import StringIO
from django.utils.encoding import force_unicode
+from django.utils.safestring import mark_safe, SafeData
try:
import threading
@@ -167,10 +168,9 @@ def translation(language):
res.merge(t)
return res
- if hasattr(settings, 'LOCALE_PATHS'):
- for localepath in settings.LOCALE_PATHS:
- if os.path.isdir(localepath):
- res = _merge(localepath)
+ for localepath in settings.LOCALE_PATHS:
+ if os.path.isdir(localepath):
+ res = _merge(localepath)
if projectpath and os.path.isdir(projectpath):
res = _merge(projectpath)
@@ -271,11 +271,15 @@ def do_translate(message, translation_function):
global _default, _active
t = _active.get(currentThread(), None)
if t is not None:
- return getattr(t, translation_function)(message)
- if _default is None:
- from django.conf import settings
- _default = translation(settings.LANGUAGE_CODE)
- return getattr(_default, translation_function)(message)
+ result = getattr(t, translation_function)(message)
+ else:
+ if _default is None:
+ from django.conf import settings
+ _default = translation(settings.LANGUAGE_CODE)
+ result = getattr(_default, translation_function)(message)
+ if isinstance(message, SafeData):
+ return mark_safe(result)
+ return result
def gettext(message):
return do_translate(message, 'gettext')
diff --git a/django/utils/tzinfo.py b/django/utils/tzinfo.py
index e2e1d10fc1..7d5ead9290 100644
--- a/django/utils/tzinfo.py
+++ b/django/utils/tzinfo.py
@@ -54,6 +54,12 @@ class LocalTimezone(tzinfo):
def _isdst(self, dt):
tt = (dt.year, dt.month, dt.day, dt.hour, dt.minute, dt.second, dt.weekday(), 0, -1)
- stamp = time.mktime(tt)
+ try:
+ stamp = time.mktime(tt)
+ except OverflowError:
+ # 32 bit systems can't handle dates after Jan 2038, so we fake it
+ # in that case (since we only care about the DST flag here).
+ tt = (2037,) + tt[1:]
+ stamp = time.mktime(tt)
tt = time.localtime(stamp)
return tt.tm_isdst > 0