diff options
| author | Jeremy Dunck <jdunck@gmail.com> | 2007-12-01 22:12:44 +0000 |
|---|---|---|
| committer | Jeremy Dunck <jdunck@gmail.com> | 2007-12-01 22:12:44 +0000 |
| commit | 23384af79b2f43f08e8395d0a84a57c2a98df392 (patch) | |
| tree | 77e45f0e0fc6cb9b3380982313f45febf2ebf6f0 /django/utils | |
| parent | 85ce45bc441e4ace2fba83bc2d2432e22ec9da94 (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.py | 43 | ||||
| -rw-r--r-- | django/utils/datastructures.py | 76 | ||||
| -rw-r--r-- | django/utils/html.py | 19 | ||||
| -rw-r--r-- | django/utils/safestring.py | 2 | ||||
| -rw-r--r-- | django/utils/translation/trans_null.py | 6 | ||||
| -rw-r--r-- | django/utils/translation/trans_real.py | 22 | ||||
| -rw-r--r-- | django/utils/tzinfo.py | 8 |
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 = ['(', '<', '<'] @@ -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 |
