[py3] Ported django.http according to PEP 3333.

Perfomed some style cleanup while I was in the area.
This commit is contained in:
Aymeric Augustin 2012-08-14 09:44:04 +02:00
parent 0df0cf70d4
commit e04230e2e4
3 changed files with 132 additions and 107 deletions

View File

@ -113,7 +113,7 @@ def build_request_repr(request, path_override=None, GET_override=None,
get = (pformat(GET_override) get = (pformat(GET_override)
if GET_override is not None if GET_override is not None
else pformat(request.GET)) else pformat(request.GET))
except: except Exception:
get = '<could not parse>' get = '<could not parse>'
if request._post_parse_error: if request._post_parse_error:
post = '<could not parse>' post = '<could not parse>'
@ -122,19 +122,19 @@ def build_request_repr(request, path_override=None, GET_override=None,
post = (pformat(POST_override) post = (pformat(POST_override)
if POST_override is not None if POST_override is not None
else pformat(request.POST)) else pformat(request.POST))
except: except Exception:
post = '<could not parse>' post = '<could not parse>'
try: try:
cookies = (pformat(COOKIES_override) cookies = (pformat(COOKIES_override)
if COOKIES_override is not None if COOKIES_override is not None
else pformat(request.COOKIES)) else pformat(request.COOKIES))
except: except Exception:
cookies = '<could not parse>' cookies = '<could not parse>'
try: try:
meta = (pformat(META_override) meta = (pformat(META_override)
if META_override is not None if META_override is not None
else pformat(request.META)) else pformat(request.META))
except: except Exception:
meta = '<could not parse>' meta = '<could not parse>'
path = path_override if path_override is not None else request.path path = path_override if path_override is not None else request.path
return smart_str('<%s\npath:%s,\nGET:%s,\nPOST:%s,\nCOOKIES:%s,\nMETA:%s>' % return smart_str('<%s\npath:%s,\nGET:%s,\nPOST:%s,\nCOOKIES:%s,\nMETA:%s>' %
@ -177,14 +177,14 @@ class HttpRequest(object):
# Reconstruct the host using the algorithm from PEP 333. # Reconstruct the host using the algorithm from PEP 333.
host = self.META['SERVER_NAME'] host = self.META['SERVER_NAME']
server_port = str(self.META['SERVER_PORT']) server_port = str(self.META['SERVER_PORT'])
if server_port != (self.is_secure() and '443' or '80'): if server_port != ('443' if self.is_secure() else '80'):
host = '%s:%s' % (host, server_port) host = '%s:%s' % (host, server_port)
return host return host
def get_full_path(self): def get_full_path(self):
# RFC 3986 requires query string arguments to be in the ASCII range. # RFC 3986 requires query string arguments to be in the ASCII range.
# Rather than crash if this doesn't happen, we encode defensively. # Rather than crash if this doesn't happen, we encode defensively.
return '%s%s' % (self.path, self.META.get('QUERY_STRING', '') and ('?' + iri_to_uri(self.META.get('QUERY_STRING', ''))) or '') return '%s%s' % (self.path, ('?' + iri_to_uri(self.META.get('QUERY_STRING', ''))) if self.META.get('QUERY_STRING', '') else '')
def get_signed_cookie(self, key, default=RAISE_ERROR, salt='', max_age=None): def get_signed_cookie(self, key, default=RAISE_ERROR, salt='', max_age=None):
""" """
@ -218,7 +218,7 @@ class HttpRequest(object):
if not location: if not location:
location = self.get_full_path() location = self.get_full_path()
if not absolute_http_url_re.match(location): if not absolute_http_url_re.match(location):
current_uri = '%s://%s%s' % (self.is_secure() and 'https' or 'http', current_uri = '%s://%s%s' % ('https' if self.is_secure() else 'http',
self.get_host(), self.path) self.get_host(), self.path)
location = urljoin(current_uri, location) location = urljoin(current_uri, location)
return iri_to_uri(location) return iri_to_uri(location)
@ -281,7 +281,7 @@ class HttpRequest(object):
"""Returns a tuple of (POST QueryDict, FILES MultiValueDict).""" """Returns a tuple of (POST QueryDict, FILES MultiValueDict)."""
self.upload_handlers = ImmutableList( self.upload_handlers = ImmutableList(
self.upload_handlers, self.upload_handlers,
warning = "You cannot alter upload handlers after the upload has been processed." warning="You cannot alter upload handlers after the upload has been processed."
) )
parser = MultiPartParser(META, post_data, self.upload_handlers, self.encoding) parser = MultiPartParser(META, post_data, self.upload_handlers, self.encoding)
return parser.parse() return parser.parse()
@ -294,7 +294,7 @@ class HttpRequest(object):
try: try:
self._body = self.read() self._body = self.read()
except IOError as e: except IOError as e:
six.reraise(UnreadablePostError, UnreadablePostError(*tuple(e.args)), sys.exc_info()[2]) six.reraise(UnreadablePostError, UnreadablePostError(*e.args), sys.exc_info()[2])
self._stream = BytesIO(self._body) self._stream = BytesIO(self._body)
return self._body return self._body
@ -360,6 +360,7 @@ class HttpRequest(object):
if not buf: if not buf:
break break
yield buf yield buf
__iter__ = xreadlines __iter__ = xreadlines
def readlines(self): def readlines(self):
@ -384,9 +385,16 @@ class QueryDict(MultiValueDict):
if not encoding: if not encoding:
encoding = settings.DEFAULT_CHARSET encoding = settings.DEFAULT_CHARSET
self.encoding = encoding self.encoding = encoding
for key, value in parse_qsl((query_string or ''), True): # keep_blank_values=True if six.PY3:
self.appendlist(force_text(key, encoding, errors='replace'), for key, value in parse_qsl(query_string or '',
force_text(value, encoding, errors='replace')) keep_blank_values=True,
encoding=encoding):
self.appendlist(key, value)
else:
for key, value in parse_qsl(query_string or '',
keep_blank_values=True):
self.appendlist(force_text(key, encoding, errors='replace'),
force_text(value, encoding, errors='replace'))
self._mutable = mutable self._mutable = mutable
def _get_encoding(self): def _get_encoding(self):
@ -405,8 +413,8 @@ class QueryDict(MultiValueDict):
def __setitem__(self, key, value): def __setitem__(self, key, value):
self._assert_mutable() self._assert_mutable()
key = str_to_unicode(key, self.encoding) key = bytes_to_text(key, self.encoding)
value = str_to_unicode(value, self.encoding) value = bytes_to_text(value, self.encoding)
super(QueryDict, self).__setitem__(key, value) super(QueryDict, self).__setitem__(key, value)
def __delitem__(self, key): def __delitem__(self, key):
@ -428,8 +436,8 @@ class QueryDict(MultiValueDict):
def setlist(self, key, list_): def setlist(self, key, list_):
self._assert_mutable() self._assert_mutable()
key = str_to_unicode(key, self.encoding) key = bytes_to_text(key, self.encoding)
list_ = [str_to_unicode(elt, self.encoding) for elt in list_] list_ = [bytes_to_text(elt, self.encoding) for elt in list_]
super(QueryDict, self).setlist(key, list_) super(QueryDict, self).setlist(key, list_)
def setlistdefault(self, key, default_list=None): def setlistdefault(self, key, default_list=None):
@ -438,8 +446,8 @@ class QueryDict(MultiValueDict):
def appendlist(self, key, value): def appendlist(self, key, value):
self._assert_mutable() self._assert_mutable()
key = str_to_unicode(key, self.encoding) key = bytes_to_text(key, self.encoding)
value = str_to_unicode(value, self.encoding) value = bytes_to_text(value, self.encoding)
super(QueryDict, self).appendlist(key, value) super(QueryDict, self).appendlist(key, value)
def pop(self, key, *args): def pop(self, key, *args):
@ -456,8 +464,8 @@ class QueryDict(MultiValueDict):
def setdefault(self, key, default=None): def setdefault(self, key, default=None):
self._assert_mutable() self._assert_mutable()
key = str_to_unicode(key, self.encoding) key = bytes_to_text(key, self.encoding)
default = str_to_unicode(default, self.encoding) default = bytes_to_text(default, self.encoding)
return super(QueryDict, self).setdefault(key, default) return super(QueryDict, self).setdefault(key, default)
def copy(self): def copy(self):
@ -531,6 +539,7 @@ class HttpResponse(object):
if not content_type: if not content_type:
content_type = "%s; charset=%s" % (settings.DEFAULT_CONTENT_TYPE, content_type = "%s; charset=%s" % (settings.DEFAULT_CONTENT_TYPE,
self._charset) self._charset)
# content is a bytestring. See _get_content / _set_content.
self.content = content self.content = content
self.cookies = SimpleCookie() self.cookies = SimpleCookie()
if status: if status:
@ -538,30 +547,40 @@ class HttpResponse(object):
self['Content-Type'] = content_type self['Content-Type'] = content_type
def __str__(self): def serialize(self):
"""Full HTTP message, including headers.""" """Full HTTP message, including headers, as a bytestring."""
return '\n'.join(['%s: %s' % (key, value) headers = [
for key, value in self._headers.values()]) \ b'%s: %s' % (key.encode('us-ascii'), value.encode('us-ascii'))
+ '\n\n' + self.content for key, value in self._headers.values()
]
return b'\r\n'.join(headers) + b'\r\n\r\n' + self.content
if six.PY3:
__bytes__ = serialize
else:
__str__ = serialize
def _convert_to_ascii(self, *values): def _convert_to_ascii(self, *values):
"""Converts all values to ascii strings.""" """Converts all values to ascii strings."""
for value in values: for value in values:
if isinstance(value, six.text_type): if not isinstance(value, six.string_types):
try:
if not six.PY3:
value = value.encode('us-ascii')
else:
# In Python 3, use a string in headers,
# but ensure in only contains ASCII characters.
value.encode('us-ascii')
except UnicodeError as e:
e.reason += ', HTTP response headers must be in US-ASCII format'
raise
else:
value = str(value) value = str(value)
try:
if six.PY3:
# Ensure string only contains ASCII
value.encode('us-ascii')
else:
if isinstance(value, str):
# Ensure string only contains ASCII
value.decode('us-ascii')
else:
# Convert unicode to an ASCII string
value = value.encode('us-ascii')
except UnicodeError as e:
e.reason += ', HTTP response headers must be in US-ASCII format'
raise
if '\n' in value or '\r' in value: if '\n' in value or '\r' in value:
raise BadHeaderError("Header values can't contain newlines (got %r)" % (value)) raise BadHeaderError("Header values can't contain newlines (got %r)" % value)
yield value yield value
def __setitem__(self, header, value): def __setitem__(self, header, value):
@ -652,11 +671,12 @@ class HttpResponse(object):
def _get_content(self): def _get_content(self):
if self.has_header('Content-Encoding'): if self.has_header('Content-Encoding'):
return b''.join([str(e) for e in self._container]) # XXX this doesn't work under Python 3 when e is an integer (#18764)
return b''.join([bytes(e) for e in self._container])
return b''.join([smart_bytes(e, self._charset) for e in self._container]) return b''.join([smart_bytes(e, self._charset) for e in self._container])
def _set_content(self, value): def _set_content(self, value):
if hasattr(value, '__iter__') and not isinstance(value, (bytes, six.text_type)): if hasattr(value, '__iter__') and not isinstance(value, six.string_types):
self._container = value self._container = value
self._base_content_is_iter = True self._base_content_is_iter = True
else: else:
@ -673,7 +693,7 @@ class HttpResponse(object):
chunk = next(self._iterator) chunk = next(self._iterator)
if isinstance(chunk, six.text_type): if isinstance(chunk, six.text_type):
chunk = chunk.encode(self._charset) chunk = chunk.encode(self._charset)
return str(chunk) return bytes(chunk)
next = __next__ # Python 2 compatibility next = __next__ # Python 2 compatibility
@ -743,8 +763,8 @@ def get_host(request):
# It's neither necessary nor appropriate to use # It's neither necessary nor appropriate to use
# django.utils.encoding.smart_text for parsing URLs and form inputs. Thus, # django.utils.encoding.smart_text for parsing URLs and form inputs. Thus,
# this slightly more restricted function. # this slightly more restricted function, used by QueryDict.
def str_to_unicode(s, encoding): def bytes_to_text(s, encoding):
""" """
Converts basestring objects to unicode, using the given encoding. Illegally Converts basestring objects to unicode, using the given encoding. Illegally
encoded input characters are replaced with Unicode "unknown" codepoint encoded input characters are replaced with Unicode "unknown" codepoint

View File

@ -9,16 +9,17 @@ from django.http import (QueryDict, HttpResponse, HttpResponseRedirect,
HttpResponsePermanentRedirect, HttpResponsePermanentRedirect,
SimpleCookie, BadHeaderError, SimpleCookie, BadHeaderError,
parse_cookie) parse_cookie)
from django.utils import six
from django.utils import unittest from django.utils import unittest
class QueryDictTests(unittest.TestCase): class QueryDictTests(unittest.TestCase):
def test_missing_key(self): def test_missing_key(self):
q = QueryDict('') q = QueryDict(str(''))
self.assertRaises(KeyError, q.__getitem__, 'foo') self.assertRaises(KeyError, q.__getitem__, 'foo')
def test_immutability(self): def test_immutability(self):
q = QueryDict('') q = QueryDict(str(''))
self.assertRaises(AttributeError, q.__setitem__, 'something', 'bar') self.assertRaises(AttributeError, q.__setitem__, 'something', 'bar')
self.assertRaises(AttributeError, q.setlist, 'foo', ['bar']) self.assertRaises(AttributeError, q.setlist, 'foo', ['bar'])
self.assertRaises(AttributeError, q.appendlist, 'foo', ['bar']) self.assertRaises(AttributeError, q.appendlist, 'foo', ['bar'])
@ -28,26 +29,26 @@ class QueryDictTests(unittest.TestCase):
self.assertRaises(AttributeError, q.clear) self.assertRaises(AttributeError, q.clear)
def test_immutable_get_with_default(self): def test_immutable_get_with_default(self):
q = QueryDict('') q = QueryDict(str(''))
self.assertEqual(q.get('foo', 'default'), 'default') self.assertEqual(q.get('foo', 'default'), 'default')
def test_immutable_basic_operations(self): def test_immutable_basic_operations(self):
q = QueryDict('') q = QueryDict(str(''))
self.assertEqual(q.getlist('foo'), []) self.assertEqual(q.getlist('foo'), [])
self.assertEqual(q.has_key('foo'), False) if not six.PY3:
self.assertEqual(q.has_key('foo'), False)
self.assertEqual('foo' in q, False) self.assertEqual('foo' in q, False)
self.assertEqual(q.items(), []) self.assertEqual(list(six.iteritems(q)), [])
self.assertEqual(q.lists(), []) self.assertEqual(list(six.iterlists(q)), [])
self.assertEqual(q.items(), []) self.assertEqual(list(six.iterkeys(q)), [])
self.assertEqual(q.keys(), []) self.assertEqual(list(six.itervalues(q)), [])
self.assertEqual(q.values(), [])
self.assertEqual(len(q), 0) self.assertEqual(len(q), 0)
self.assertEqual(q.urlencode(), '') self.assertEqual(q.urlencode(), '')
def test_single_key_value(self): def test_single_key_value(self):
"""Test QueryDict with one key/value pair""" """Test QueryDict with one key/value pair"""
q = QueryDict('foo=bar') q = QueryDict(str('foo=bar'))
self.assertEqual(q['foo'], 'bar') self.assertEqual(q['foo'], 'bar')
self.assertRaises(KeyError, q.__getitem__, 'bar') self.assertRaises(KeyError, q.__getitem__, 'bar')
self.assertRaises(AttributeError, q.__setitem__, 'something', 'bar') self.assertRaises(AttributeError, q.__setitem__, 'something', 'bar')
@ -60,15 +61,17 @@ class QueryDictTests(unittest.TestCase):
self.assertRaises(AttributeError, q.setlist, 'foo', ['bar']) self.assertRaises(AttributeError, q.setlist, 'foo', ['bar'])
self.assertRaises(AttributeError, q.appendlist, 'foo', ['bar']) self.assertRaises(AttributeError, q.appendlist, 'foo', ['bar'])
self.assertTrue(q.has_key('foo')) if not six.PY3:
self.assertTrue(q.has_key('foo'))
self.assertTrue('foo' in q) self.assertTrue('foo' in q)
self.assertFalse(q.has_key('bar')) if not six.PY3:
self.assertFalse(q.has_key('bar'))
self.assertFalse('bar' in q) self.assertFalse('bar' in q)
self.assertEqual(q.items(), [('foo', 'bar')]) self.assertEqual(list(six.iteritems(q)), [('foo', 'bar')])
self.assertEqual(q.lists(), [('foo', ['bar'])]) self.assertEqual(list(six.iterlists(q)), [('foo', ['bar'])])
self.assertEqual(q.keys(), ['foo']) self.assertEqual(list(six.iterkeys(q)), ['foo'])
self.assertEqual(q.values(), ['bar']) self.assertEqual(list(six.itervalues(q)), ['bar'])
self.assertEqual(len(q), 1) self.assertEqual(len(q), 1)
self.assertRaises(AttributeError, q.update, {'foo': 'bar'}) self.assertRaises(AttributeError, q.update, {'foo': 'bar'})
@ -80,30 +83,30 @@ class QueryDictTests(unittest.TestCase):
self.assertEqual(q.urlencode(), 'foo=bar') self.assertEqual(q.urlencode(), 'foo=bar')
def test_urlencode(self): def test_urlencode(self):
q = QueryDict('', mutable=True) q = QueryDict(str(''), mutable=True)
q['next'] = '/a&b/' q['next'] = '/a&b/'
self.assertEqual(q.urlencode(), 'next=%2Fa%26b%2F') self.assertEqual(q.urlencode(), 'next=%2Fa%26b%2F')
self.assertEqual(q.urlencode(safe='/'), 'next=/a%26b/') self.assertEqual(q.urlencode(safe='/'), 'next=/a%26b/')
q = QueryDict('', mutable=True) q = QueryDict(str(''), mutable=True)
q['next'] = '/t\xebst&key/' q['next'] = '/t\xebst&key/'
self.assertEqual(q.urlencode(), 'next=%2Ft%C3%ABst%26key%2F') self.assertEqual(q.urlencode(), 'next=%2Ft%C3%ABst%26key%2F')
self.assertEqual(q.urlencode(safe='/'), 'next=/t%C3%ABst%26key/') self.assertEqual(q.urlencode(safe='/'), 'next=/t%C3%ABst%26key/')
def test_mutable_copy(self): def test_mutable_copy(self):
"""A copy of a QueryDict is mutable.""" """A copy of a QueryDict is mutable."""
q = QueryDict('').copy() q = QueryDict(str('')).copy()
self.assertRaises(KeyError, q.__getitem__, "foo") self.assertRaises(KeyError, q.__getitem__, "foo")
q['name'] = 'john' q['name'] = 'john'
self.assertEqual(q['name'], 'john') self.assertEqual(q['name'], 'john')
def test_mutable_delete(self): def test_mutable_delete(self):
q = QueryDict('').copy() q = QueryDict(str('')).copy()
q['name'] = 'john' q['name'] = 'john'
del q['name'] del q['name']
self.assertFalse('name' in q) self.assertFalse('name' in q)
def test_basic_mutable_operations(self): def test_basic_mutable_operations(self):
q = QueryDict('').copy() q = QueryDict(str('')).copy()
q['name'] = 'john' q['name'] = 'john'
self.assertEqual(q.get('foo', 'default'), 'default') self.assertEqual(q.get('foo', 'default'), 'default')
self.assertEqual(q.get('name', 'default'), 'john') self.assertEqual(q.get('name', 'default'), 'john')
@ -117,13 +120,14 @@ class QueryDictTests(unittest.TestCase):
q.appendlist('foo', 'another') q.appendlist('foo', 'another')
self.assertEqual(q.getlist('foo'), ['bar', 'baz', 'another']) self.assertEqual(q.getlist('foo'), ['bar', 'baz', 'another'])
self.assertEqual(q['foo'], 'another') self.assertEqual(q['foo'], 'another')
self.assertTrue(q.has_key('foo')) if not six.PY3:
self.assertTrue(q.has_key('foo'))
self.assertTrue('foo' in q) self.assertTrue('foo' in q)
self.assertEqual(q.items(), [('foo', 'another'), ('name', 'john')]) self.assertEqual(list(six.iteritems(q)), [('foo', 'another'), ('name', 'john')])
self.assertEqual(q.lists(), [('foo', ['bar', 'baz', 'another']), ('name', ['john'])]) self.assertEqual(list(six.iterlists(q)), [('foo', ['bar', 'baz', 'another']), ('name', ['john'])])
self.assertEqual(q.keys(), ['foo', 'name']) self.assertEqual(list(six.iterkeys(q)), ['foo', 'name'])
self.assertEqual(q.values(), ['another', 'john']) self.assertEqual(list(six.itervalues(q)), ['another', 'john'])
self.assertEqual(len(q), 2) self.assertEqual(len(q), 2)
q.update({'foo': 'hello'}) q.update({'foo': 'hello'})
@ -144,7 +148,7 @@ class QueryDictTests(unittest.TestCase):
def test_multiple_keys(self): def test_multiple_keys(self):
"""Test QueryDict with two key/value pairs with same keys.""" """Test QueryDict with two key/value pairs with same keys."""
q = QueryDict('vote=yes&vote=no') q = QueryDict(str('vote=yes&vote=no'))
self.assertEqual(q['vote'], 'no') self.assertEqual(q['vote'], 'no')
self.assertRaises(AttributeError, q.__setitem__, 'something', 'bar') self.assertRaises(AttributeError, q.__setitem__, 'something', 'bar')
@ -158,14 +162,16 @@ class QueryDictTests(unittest.TestCase):
self.assertRaises(AttributeError, q.setlist, 'foo', ['bar', 'baz']) self.assertRaises(AttributeError, q.setlist, 'foo', ['bar', 'baz'])
self.assertRaises(AttributeError, q.appendlist, 'foo', ['bar']) self.assertRaises(AttributeError, q.appendlist, 'foo', ['bar'])
self.assertEqual(q.has_key('vote'), True) if not six.PY3:
self.assertEqual(q.has_key('vote'), True)
self.assertEqual('vote' in q, True) self.assertEqual('vote' in q, True)
self.assertEqual(q.has_key('foo'), False) if not six.PY3:
self.assertEqual(q.has_key('foo'), False)
self.assertEqual('foo' in q, False) self.assertEqual('foo' in q, False)
self.assertEqual(q.items(), [('vote', 'no')]) self.assertEqual(list(six.iteritems(q)), [('vote', 'no')])
self.assertEqual(q.lists(), [('vote', ['yes', 'no'])]) self.assertEqual(list(six.iterlists(q)), [('vote', ['yes', 'no'])])
self.assertEqual(q.keys(), ['vote']) self.assertEqual(list(six.iterkeys(q)), ['vote'])
self.assertEqual(q.values(), ['no']) self.assertEqual(list(six.itervalues(q)), ['no'])
self.assertEqual(len(q), 1) self.assertEqual(len(q), 1)
self.assertRaises(AttributeError, q.update, {'foo': 'bar'}) self.assertRaises(AttributeError, q.update, {'foo': 'bar'})
@ -175,45 +181,49 @@ class QueryDictTests(unittest.TestCase):
self.assertRaises(AttributeError, q.setdefault, 'foo', 'bar') self.assertRaises(AttributeError, q.setdefault, 'foo', 'bar')
self.assertRaises(AttributeError, q.__delitem__, 'vote') self.assertRaises(AttributeError, q.__delitem__, 'vote')
def test_invalid_input_encoding(self): if not six.PY3:
""" def test_invalid_input_encoding(self):
QueryDicts must be able to handle invalid input encoding (in this """
case, bad UTF-8 encoding). QueryDicts must be able to handle invalid input encoding (in this
""" case, bad UTF-8 encoding).
q = QueryDict(b'foo=bar&foo=\xff')
self.assertEqual(q['foo'], '\ufffd') This test doesn't apply under Python 3 because the URL is a string
self.assertEqual(q.getlist('foo'), ['bar', '\ufffd']) and not a bytestring.
"""
q = QueryDict(str(b'foo=bar&foo=\xff'))
self.assertEqual(q['foo'], '\ufffd')
self.assertEqual(q.getlist('foo'), ['bar', '\ufffd'])
def test_pickle(self): def test_pickle(self):
q = QueryDict('') q = QueryDict(str(''))
q1 = pickle.loads(pickle.dumps(q, 2)) q1 = pickle.loads(pickle.dumps(q, 2))
self.assertEqual(q == q1, True) self.assertEqual(q == q1, True)
q = QueryDict('a=b&c=d') q = QueryDict(str('a=b&c=d'))
q1 = pickle.loads(pickle.dumps(q, 2)) q1 = pickle.loads(pickle.dumps(q, 2))
self.assertEqual(q == q1, True) self.assertEqual(q == q1, True)
q = QueryDict('a=b&c=d&a=1') q = QueryDict(str('a=b&c=d&a=1'))
q1 = pickle.loads(pickle.dumps(q, 2)) q1 = pickle.loads(pickle.dumps(q, 2))
self.assertEqual(q == q1, True) self.assertEqual(q == q1, True)
def test_update_from_querydict(self): def test_update_from_querydict(self):
"""Regression test for #8278: QueryDict.update(QueryDict)""" """Regression test for #8278: QueryDict.update(QueryDict)"""
x = QueryDict("a=1&a=2", mutable=True) x = QueryDict(str("a=1&a=2"), mutable=True)
y = QueryDict("a=3&a=4") y = QueryDict(str("a=3&a=4"))
x.update(y) x.update(y)
self.assertEqual(x.getlist('a'), ['1', '2', '3', '4']) self.assertEqual(x.getlist('a'), ['1', '2', '3', '4'])
def test_non_default_encoding(self): def test_non_default_encoding(self):
"""#13572 - QueryDict with a non-default encoding""" """#13572 - QueryDict with a non-default encoding"""
q = QueryDict(b'sbb=one', encoding='rot_13') q = QueryDict(str('cur=%A4'), encoding='iso-8859-15')
self.assertEqual(q.encoding , 'rot_13' ) self.assertEqual(q.encoding, 'iso-8859-15')
self.assertEqual(q.items() , [('foo', 'bar')] ) self.assertEqual(list(six.iteritems(q)), [('cur', '')])
self.assertEqual(q.urlencode() , 'sbb=one' ) self.assertEqual(q.urlencode(), 'cur=%A4')
q = q.copy() q = q.copy()
self.assertEqual(q.encoding , 'rot_13' ) self.assertEqual(q.encoding, 'iso-8859-15')
self.assertEqual(q.items() , [('foo', 'bar')] ) self.assertEqual(list(six.iteritems(q)), [('cur', '')])
self.assertEqual(q.urlencode() , 'sbb=one' ) self.assertEqual(q.urlencode(), 'cur=%A4')
self.assertEqual(copy.copy(q).encoding , 'rot_13' ) self.assertEqual(copy.copy(q).encoding, 'iso-8859-15')
self.assertEqual(copy.deepcopy(q).encoding , 'rot_13') self.assertEqual(copy.deepcopy(q).encoding, 'iso-8859-15')
class HttpResponseTests(unittest.TestCase): class HttpResponseTests(unittest.TestCase):
def test_unicode_headers(self): def test_unicode_headers(self):
@ -283,13 +293,8 @@ class HttpResponseTests(unittest.TestCase):
#test retrieval explicitly using iter and odd inputs #test retrieval explicitly using iter and odd inputs
r = HttpResponse() r = HttpResponse()
r.content = ['1', '2', 3, '\u079e'] r.content = ['1', '2', 3, '\u079e']
result = []
my_iter = r.__iter__() my_iter = r.__iter__()
while True: result = list(my_iter)
try:
result.append(next(my_iter))
except StopIteration:
break
#'\xde\x9e' == unichr(1950).encode('utf-8') #'\xde\x9e' == unichr(1950).encode('utf-8')
self.assertEqual(result, ['1', '2', '3', b'\xde\x9e']) self.assertEqual(result, ['1', '2', '3', b'\xde\x9e'])
self.assertEqual(r.content, b'123\xde\x9e') self.assertEqual(r.content, b'123\xde\x9e')

View File

@ -40,8 +40,8 @@ class WSGITest(TestCase):
response_data["headers"], response_data["headers"],
[('Content-Type', 'text/html; charset=utf-8')]) [('Content-Type', 'text/html; charset=utf-8')])
self.assertEqual( self.assertEqual(
six.text_type(response), bytes(response),
"Content-Type: text/html; charset=utf-8\n\nHello World!") b"Content-Type: text/html; charset=utf-8\r\n\r\nHello World!")
class GetInternalWSGIApplicationTest(unittest.TestCase): class GetInternalWSGIApplicationTest(unittest.TestCase):