Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 6 additions & 1 deletion Doc/library/urllib.parse.rst
Original file line number Diff line number Diff line change
Expand Up @@ -571,14 +571,19 @@ task isn't already covered by the URL parsing functions above.
percent-encoded sequences into Unicode characters, as accepted by the
:meth:`bytes.decode` method.

*string* must be a :class:`str`.
*string* may be either a :class:`str` or a :class:`bytes`.

*encoding* defaults to ``'utf-8'``.
*errors* defaults to ``'replace'``, meaning invalid sequences are replaced
by a placeholder character.

Example: ``unquote('/El%20Ni%C3%B1o/')`` yields ``'/El Niño/'``.

.. versionchanged:: 3.9
*string* parameter supports bytes and str objects (previously only str).




.. function:: unquote_plus(string, encoding='utf-8', errors='replace')

Expand Down
25 changes: 23 additions & 2 deletions Lib/test/test_urllib.py
Original file line number Diff line number Diff line change
Expand Up @@ -1049,8 +1049,6 @@ def test_unquoting(self):
"%s" % result)
self.assertRaises((TypeError, AttributeError), urllib.parse.unquote, None)
self.assertRaises((TypeError, AttributeError), urllib.parse.unquote, ())
with support.check_warnings(('', BytesWarning), quiet=True):
self.assertRaises((TypeError, AttributeError), urllib.parse.unquote, b'')

def test_unquoting_badpercent(self):
# Test unquoting on bad percent-escapes
Expand Down Expand Up @@ -1210,6 +1208,29 @@ def test_unquote_with_unicode(self):
self.assertEqual(expect, result,
"using unquote(): %r != %r" % (expect, result))

def test_unquoting_with_bytes_input(self):
# ASCII characters decoded to a string
given = b'blueberryjam'
expect = 'blueberryjam'
result = urllib.parse.unquote(given)
self.assertEqual(expect, result,
"using unquote(): %r != %r" % (expect, result))

# A mix of non-ASCII hex-encoded characters and ASCII characters
given = b'bl\xc3\xa5b\xc3\xa6rsyltet\xc3\xb8y'

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please add a simpler test case here in addition to the others. Also, please add a (short) comment explaining what each of the more complex test cases is checking.

expect = 'bl\u00e5b\u00e6rsyltet\u00f8y'
result = urllib.parse.unquote(given)
self.assertEqual(expect, result,
"using unquote(): %r != %r" % (expect, result))

# A mix of non-ASCII percent-encoded characters and ASCII characters
given = b'bl%c3%a5b%c3%a6rsyltet%c3%b8j'
expect = 'bl\u00e5b\u00e6rsyltet\u00f8j'
result = urllib.parse.unquote(given)
self.assertEqual(expect, result,
"using unquote(): %r != %r" % (expect, result))


class urlencode_Tests(unittest.TestCase):
"""Tests for urlencode()"""

Expand Down
2 changes: 2 additions & 0 deletions Lib/urllib/parse.py
Original file line number Diff line number Diff line change
Expand Up @@ -631,6 +631,8 @@ def unquote(string, encoding='utf-8', errors='replace'):

unquote('abc%20def') -> 'abc def'.
"""
if isinstance(string, bytes):
return unquote_to_bytes(string).decode(encoding, errors)
if '%' not in string:
string.split
return string
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
Made :func:`urllib.parse.unquote()` accept bytes in addition to strings.
Patch by Stein Karlsen.