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
8 changes: 8 additions & 0 deletions Doc/library/urllib.parse.rst
Original file line number Diff line number Diff line change
Expand Up @@ -239,6 +239,10 @@ or on combining URL components into a URL string.
query parameter separator. This has been changed to allow only a single
separator key, with ``&`` as the default separator.

.. deprecated:: 3.14
Accepting objects with false values (like ``0`` and ``[]``) except empty
strings and byte-like objects and ``None`` is now deprecated.


.. function:: parse_qsl(qs, keep_blank_values=False, strict_parsing=False, encoding='utf-8', errors='replace', max_num_fields=None, separator='&')

Expand Down Expand Up @@ -745,6 +749,10 @@ task isn't already covered by the URL parsing functions above.
.. versionchanged:: 3.5
Added the *quote_via* parameter.

.. deprecated:: 3.14
Accepting objects with false values (like ``0`` and ``[]``) except empty
strings and byte-like objects and ``None`` is now deprecated.


.. seealso::

Expand Down
7 changes: 7 additions & 0 deletions Doc/whatsnew/3.14.rst
Original file line number Diff line number Diff line change
Expand Up @@ -570,6 +570,13 @@ Deprecated
Deprecate :meth:`symtable.Class.get_methods` due to the lack of interest.
(Contributed by Bénédikt Tran in :gh:`119698`.)

* :mod:`urllib.parse`:
Accepting objects with false values (like ``0`` and ``[]``) except empty
strings, byte-like objects and ``None`` in :mod:`urllib.parse` functions
:func:`~urllib.parse.parse_qsl` and :func:`~urllib.parse.parse_qs` is now
deprecated.
(Contributed by Serhiy Storchaka in :gh:`116897`.)

.. Add deprecations above alphabetically, not here at the end.

.. include:: ../deprecations/pending-removal-in-3.15.rst
Expand Down
10 changes: 9 additions & 1 deletion Lib/test/test_urlparse.py
Original file line number Diff line number Diff line change
Expand Up @@ -1314,9 +1314,17 @@ def test_parse_qsl_bytes(self):

def test_parse_qsl_false_value(self):
kwargs = dict(keep_blank_values=True, strict_parsing=True)
for x in '', b'', None, 0, 0.0, [], {}, memoryview(b''):
for x in '', b'', None, memoryview(b''):
self.assertEqual(urllib.parse.parse_qsl(x, **kwargs), [])
self.assertRaises(ValueError, urllib.parse.parse_qsl, x, separator=1)
for x in 0, 0.0, [], {}:
with self.assertWarns(DeprecationWarning) as cm:
self.assertEqual(urllib.parse.parse_qsl(x, **kwargs), [])
self.assertEqual(cm.filename, __file__)
with self.assertWarns(DeprecationWarning) as cm:
self.assertEqual(urllib.parse.parse_qs(x, **kwargs), {})
self.assertEqual(cm.filename, __file__)
self.assertRaises(ValueError, urllib.parse.parse_qsl, x, separator=1)

def test_parse_qsl_errors(self):
self.assertRaises(TypeError, urllib.parse.parse_qsl, list(b'a=b'))
Expand Down
25 changes: 17 additions & 8 deletions Lib/urllib/parse.py
Original file line number Diff line number Diff line change
Expand Up @@ -753,7 +753,8 @@ def parse_qs(qs, keep_blank_values=False, strict_parsing=False,
parsed_result = {}
pairs = parse_qsl(qs, keep_blank_values, strict_parsing,
encoding=encoding, errors=errors,
max_num_fields=max_num_fields, separator=separator)
max_num_fields=max_num_fields, separator=separator,
_stacklevel=2)
for name, value in pairs:
if name in parsed_result:
parsed_result[name].append(value)
Expand All @@ -763,7 +764,7 @@ def parse_qs(qs, keep_blank_values=False, strict_parsing=False,


def parse_qsl(qs, keep_blank_values=False, strict_parsing=False,
encoding='utf-8', errors='replace', max_num_fields=None, separator='&'):
encoding='utf-8', errors='replace', max_num_fields=None, separator='&', *, _stacklevel=1):
"""Parse a query given as a string argument.

Arguments:
Expand Down Expand Up @@ -791,7 +792,6 @@ def parse_qsl(qs, keep_blank_values=False, strict_parsing=False,

Returns a list, as G-d intended.
"""

if not separator or not isinstance(separator, (str, bytes)):
raise ValueError("Separator must be of type string or bytes.")
if isinstance(qs, str):
Expand All @@ -800,12 +800,21 @@ def parse_qsl(qs, keep_blank_values=False, strict_parsing=False,
eq = '='
def _unquote(s):
return unquote_plus(s, encoding=encoding, errors=errors)
elif qs is None:
return []
else:
if not qs:
return []
# Use memoryview() to reject integers and iterables,
# acceptable by the bytes constructor.
qs = bytes(memoryview(qs))
try:
# Use memoryview() to reject integers and iterables,
# acceptable by the bytes constructor.
qs = bytes(memoryview(qs))
except TypeError:
if not qs:
warnings.warn(f"Accepting {type(qs).__name__} objects with "
f"false value in urllib.parse.parse_qsl() is "
f"deprecated as of 3.14",
DeprecationWarning, stacklevel=_stacklevel + 1)
return []
raise
if isinstance(separator, str):
separator = bytes(separator, 'ascii')
eq = b'='
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
Accepting objects with false values (like ``0`` and ``[]``) except empty
strings, byte-like objects and ``None`` in :mod:`urllib.parse` functions
:func:`~urllib.parse.parse_qsl` and :func:`~urllib.parse.parse_qs` is now
deprecated.
Loading