Skip to content

Commit 7577307

Browse files
gh-116897: Deprecate generic false values in urllib.parse.parse_qsl() (GH-116903)
Accepting objects with false values (like 0 and []) except empty strings and byte-like objects and None in urllib.parse functions parse_qsl() and parse_qs() is now deprecated.
1 parent 03924b5 commit 7577307

File tree

5 files changed

+45
-9
lines changed

5 files changed

+45
-9
lines changed

Doc/library/urllib.parse.rst

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -239,6 +239,10 @@ or on combining URL components into a URL string.
239239
query parameter separator. This has been changed to allow only a single
240240
separator key, with ``&`` as the default separator.
241241

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

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

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

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

749757
.. seealso::
750758

Doc/whatsnew/3.14.rst

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -583,6 +583,13 @@ Deprecated
583583
Deprecate :meth:`symtable.Class.get_methods` due to the lack of interest.
584584
(Contributed by Bénédikt Tran in :gh:`119698`.)
585585

586+
* :mod:`urllib.parse`:
587+
Accepting objects with false values (like ``0`` and ``[]``) except empty
588+
strings, byte-like objects and ``None`` in :mod:`urllib.parse` functions
589+
:func:`~urllib.parse.parse_qsl` and :func:`~urllib.parse.parse_qs` is now
590+
deprecated.
591+
(Contributed by Serhiy Storchaka in :gh:`116897`.)
592+
586593
.. Add deprecations above alphabetically, not here at the end.
587594
588595
.. include:: ../deprecations/pending-removal-in-3.15.rst

Lib/test/test_urlparse.py

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1314,9 +1314,17 @@ def test_parse_qsl_bytes(self):
13141314

13151315
def test_parse_qsl_false_value(self):
13161316
kwargs = dict(keep_blank_values=True, strict_parsing=True)
1317-
for x in '', b'', None, 0, 0.0, [], {}, memoryview(b''):
1317+
for x in '', b'', None, memoryview(b''):
13181318
self.assertEqual(urllib.parse.parse_qsl(x, **kwargs), [])
13191319
self.assertRaises(ValueError, urllib.parse.parse_qsl, x, separator=1)
1320+
for x in 0, 0.0, [], {}:
1321+
with self.assertWarns(DeprecationWarning) as cm:
1322+
self.assertEqual(urllib.parse.parse_qsl(x, **kwargs), [])
1323+
self.assertEqual(cm.filename, __file__)
1324+
with self.assertWarns(DeprecationWarning) as cm:
1325+
self.assertEqual(urllib.parse.parse_qs(x, **kwargs), {})
1326+
self.assertEqual(cm.filename, __file__)
1327+
self.assertRaises(ValueError, urllib.parse.parse_qsl, x, separator=1)
13201328

13211329
def test_parse_qsl_errors(self):
13221330
self.assertRaises(TypeError, urllib.parse.parse_qsl, list(b'a=b'))

Lib/urllib/parse.py

Lines changed: 17 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -753,7 +753,8 @@ def parse_qs(qs, keep_blank_values=False, strict_parsing=False,
753753
parsed_result = {}
754754
pairs = parse_qsl(qs, keep_blank_values, strict_parsing,
755755
encoding=encoding, errors=errors,
756-
max_num_fields=max_num_fields, separator=separator)
756+
max_num_fields=max_num_fields, separator=separator,
757+
_stacklevel=2)
757758
for name, value in pairs:
758759
if name in parsed_result:
759760
parsed_result[name].append(value)
@@ -763,7 +764,7 @@ def parse_qs(qs, keep_blank_values=False, strict_parsing=False,
763764

764765

765766
def parse_qsl(qs, keep_blank_values=False, strict_parsing=False,
766-
encoding='utf-8', errors='replace', max_num_fields=None, separator='&'):
767+
encoding='utf-8', errors='replace', max_num_fields=None, separator='&', *, _stacklevel=1):
767768
"""Parse a query given as a string argument.
768769
769770
Arguments:
@@ -791,7 +792,6 @@ def parse_qsl(qs, keep_blank_values=False, strict_parsing=False,
791792
792793
Returns a list, as G-d intended.
793794
"""
794-
795795
if not separator or not isinstance(separator, (str, bytes)):
796796
raise ValueError("Separator must be of type string or bytes.")
797797
if isinstance(qs, str):
@@ -800,12 +800,21 @@ def parse_qsl(qs, keep_blank_values=False, strict_parsing=False,
800800
eq = '='
801801
def _unquote(s):
802802
return unquote_plus(s, encoding=encoding, errors=errors)
803+
elif qs is None:
804+
return []
803805
else:
804-
if not qs:
805-
return []
806-
# Use memoryview() to reject integers and iterables,
807-
# acceptable by the bytes constructor.
808-
qs = bytes(memoryview(qs))
806+
try:
807+
# Use memoryview() to reject integers and iterables,
808+
# acceptable by the bytes constructor.
809+
qs = bytes(memoryview(qs))
810+
except TypeError:
811+
if not qs:
812+
warnings.warn(f"Accepting {type(qs).__name__} objects with "
813+
f"false value in urllib.parse.parse_qsl() is "
814+
f"deprecated as of 3.14",
815+
DeprecationWarning, stacklevel=_stacklevel + 1)
816+
return []
817+
raise
809818
if isinstance(separator, str):
810819
separator = bytes(separator, 'ascii')
811820
eq = b'='
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
Accepting objects with false values (like ``0`` and ``[]``) except empty
2+
strings, byte-like objects and ``None`` in :mod:`urllib.parse` functions
3+
:func:`~urllib.parse.parse_qsl` and :func:`~urllib.parse.parse_qs` is now
4+
deprecated.

0 commit comments

Comments
 (0)