From f2477b6450afb99b5c34c54cfd121ddfbabc904e Mon Sep 17 00:00:00 2001 From: Malcolm Tredinnick Date: Thu, 21 Aug 2008 13:55:21 +0000 Subject: [PATCH] Fixed #7233 -- Ensured that QueryDict classes are always unpicklable. This problem only arose on some systems, since it depends upon the order in which the attributes are pickled. Makes reliable testing kind of tricky. git-svn-id: http://code.djangoproject.com/svn/django/trunk@8460 bcc190cf-cafb-0310-a4f2-bffc1f526a37 --- django/http/__init__.py | 19 ++++++++++- tests/regressiontests/httpwrappers/tests.py | 37 +++++++++++++-------- 2 files changed, 41 insertions(+), 15 deletions(-) diff --git a/django/http/__init__.py b/django/http/__init__.py index 0124022478..bbbd1ba99a 100644 --- a/django/http/__init__.py +++ b/django/http/__init__.py @@ -128,6 +128,11 @@ class QueryDict(MultiValueDict): Values retrieved from this class are converted from the given encoding (DEFAULT_CHARSET by default) to unicode. """ + # These are both reset in __init__, but is specified here at the class + # level so that unpickling will have valid values + _mutable = True + _encoding = None + def __init__(self, query_string, mutable=False, encoding=None): MultiValueDict.__init__(self) if not encoding: @@ -136,12 +141,24 @@ class QueryDict(MultiValueDict): from django.conf import settings encoding = settings.DEFAULT_CHARSET self.encoding = encoding - self._mutable = True for key, value in parse_qsl((query_string or ''), True): # keep_blank_values=True self.appendlist(force_unicode(key, encoding, errors='replace'), force_unicode(value, encoding, errors='replace')) self._mutable = mutable + def _get_encoding(self): + if self._encoding is None: + # *Important*: do not import settings at the module level because + # of the note in core.handlers.modpython. + from django.conf import settings + self._encoding = settings.DEFAULT_CHARSET + return self._encoding + + def _set_encoding(self, value): + self._encoding = value + + encoding = property(_get_encoding, _set_encoding) + def _assert_mutable(self): if not self._mutable: raise AttributeError("This QueryDict instance is immutable") diff --git a/tests/regressiontests/httpwrappers/tests.py b/tests/regressiontests/httpwrappers/tests.py index 31b956a99d..5e42ff3b63 100644 --- a/tests/regressiontests/httpwrappers/tests.py +++ b/tests/regressiontests/httpwrappers/tests.py @@ -392,17 +392,26 @@ u'\ufffd' [u'bar', u'\ufffd'] -###################################### -# HttpResponse with Unicode headers # -###################################### - ->>> r = HttpResponse() - +######################## +# Pickling a QueryDict # +######################## +>>> import pickle +>>> q = QueryDict('a=b&c=d') +>>> q1 = pickle.loads(pickle.dumps(q)) +>>> q == q1 +True + +###################################### +# HttpResponse with Unicode headers # +###################################### + +>>> r = HttpResponse() + If we insert a unicode value it will be converted to an ascii string. This makes sure we comply with the HTTP specifications. - ->>> r['value'] = u'test value' ->>> isinstance(r['value'], str) + +>>> r['value'] = u'test value' +>>> isinstance(r['value'], str) True An error is raised When a unicode object with non-ascii is assigned. @@ -411,10 +420,10 @@ An error is raised When a unicode object with non-ascii is assigned. Traceback (most recent call last): ... UnicodeEncodeError: ..., HTTP response headers must be in US-ASCII format - -The response also converts unicode keys to strings. - ->>> r[u'test'] = 'testing key' + +The response also converts unicode keys to strings. + +>>> r[u'test'] = 'testing key' >>> l = list(r.items()) >>> l.sort() >>> l[1] @@ -426,7 +435,7 @@ It will also raise errors for keys with non-ascii data. Traceback (most recent call last): ... UnicodeEncodeError: ..., HTTP response headers must be in US-ASCII format - + """ from django.http import QueryDict, HttpResponse