Permalink
Browse files

[2.0.x] Fixed #28679 -- Fixed urlencode()'s handling of bytes.

Regression in fee42fd.

Thanks Claude Paroz, Jon Dufresne, and Tim Graham for the guidance.

Backport of 41be858 from master
  • Loading branch information...
francoisfreitag authored and timgraham committed Oct 9, 2017
1 parent 2a55063 commit 51998a2988e076f811ec27bab5de4c17a6ae6828
Showing with 35 additions and 5 deletions.
  1. +18 −5 django/utils/http.py
  2. +17 −0 tests/utils_tests/test_http.py
View
@@ -90,11 +90,24 @@ def urlencode(query, doseq=False):
query = query.lists()
elif hasattr(query, 'items'):
query = query.items()
- return original_urlencode(
- [(k, [str(i) for i in v] if isinstance(v, (list, tuple)) else str(v))
- for k, v in query],
- doseq
- )
+ query_params = []
+ for key, value in query:
+ if isinstance(value, (str, bytes)):
+ query_val = value
+ else:
+ try:
+ iter(value)
+ except TypeError:
+ query_val = value
+ else:
+ # Consume generators and iterators, even when doseq=True, to
+ # work around https://bugs.python.org/issue31706.
+ query_val = [
+ item if isinstance(item, bytes) else str(item)
+ for item in value
+ ]
+ query_params.append((key, query_val))
+ return original_urlencode(query_params, doseq)
def cookie_date(epoch_seconds=None):
@@ -49,6 +49,23 @@ def test_multivaluedict(self):
'position=Developer&name=Adrian&name=Simon',
])
+ def test_dict_with_bytes_values(self):
+ self.assertEqual(urlencode({'a': b'abc'}, doseq=True), 'a=abc')
+
+ def test_dict_with_sequence_of_bytes(self):
+ self.assertEqual(urlencode({'a': [b'spam', b'eggs', b'bacon']}, doseq=True), 'a=spam&a=eggs&a=bacon')
+
+ def test_dict_with_bytearray(self):
+ self.assertEqual(urlencode({'a': bytearray(range(2))}, doseq=True), 'a=0&a=1')
+ self.assertEqual(urlencode({'a': bytearray(range(2))}, doseq=False), 'a=%5B%270%27%2C+%271%27%5D')
+
+ def test_generator(self):
+ def gen():
+ yield from range(2)
+
+ self.assertEqual(urlencode({'a': gen()}, doseq=True), 'a=0&a=1')
+ self.assertEqual(urlencode({'a': gen()}, doseq=False), 'a=%5B%270%27%2C+%271%27%5D')
+
class Base36IntTests(SimpleTestCase):
def test_roundtrip(self):

0 comments on commit 51998a2

Please sign in to comment.