Skip to content

Commit e2f454a

Browse files
Emit DeprecationWarning
1 parent bd6191a commit e2f454a

4 files changed

Lines changed: 78 additions & 48 deletions

File tree

Doc/library/urllib.parse.rst

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -175,6 +175,11 @@ or on combining URL components into a URL string.
175175
Characters that affect netloc parsing under NFKC normalization will
176176
now raise :exc:`ValueError`.
177177

178+
.. versionchanged:: 3.11
179+
Values for `url` and `scheme` other than strings or bytes raise
180+
:exc:`TypeError` if true or emit `DeprecationWarning` if false (to be
181+
changed to `TypeError` in future versions of Python).
182+
178183

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

@@ -264,6 +269,11 @@ or on combining URL components into a URL string.
264269
query parameter separator. This has been changed to allow only a single
265270
separator key, with ``&`` as the default separator.
266271

272+
.. versionchanged:: 3.11
273+
Values for `qs` and `separator` other than strings or bytes raise
274+
:exc:`TypeError` if true or emit `DeprecationWarning` if false (to be
275+
changed to `TypeError` in future versions of Python).
276+
267277

268278
.. function:: urlunparse(parts)
269279

@@ -273,6 +283,11 @@ or on combining URL components into a URL string.
273283
unnecessary delimiters (for example, a ``?`` with an empty query; the RFC
274284
states that these are equivalent).
275285

286+
.. versionchanged:: 3.11
287+
Items in `parts` other than strings or bytes raise
288+
:exc:`TypeError` if true or emit `DeprecationWarning` if false (to be
289+
changed to `TypeError` in future versions of Python).
290+
276291

277292
.. function:: urlsplit(urlstring, scheme='', allow_fragments=True)
278293

@@ -337,6 +352,12 @@ or on combining URL components into a URL string.
337352
.. versionchanged:: 3.10
338353
ASCII newline and tab characters are stripped from the URL.
339354

355+
.. versionchanged:: 3.11
356+
Values for the url argument and `scheme` other than strings or bytes raise
357+
:exc:`TypeError` if true or emit `DeprecationWarning` if false (to be
358+
changed to `TypeError` in future versions of Python).
359+
360+
340361
.. _WHATWG spec: https://url.spec.whatwg.org/#concept-basic-url-parser
341362

342363
.. function:: urlunsplit(parts)
@@ -347,6 +368,11 @@ or on combining URL components into a URL string.
347368
URL that was parsed originally had unnecessary delimiters (for example, a ?
348369
with an empty query; the RFC states that these are equivalent).
349370

371+
.. versionchanged:: 3.11
372+
Items in `parts` other than strings or bytes raise
373+
:exc:`TypeError` if true or emit `DeprecationWarning` if false (to be
374+
changed to `TypeError` in future versions of Python).
375+
350376

351377
.. function:: urljoin(base, url, allow_fragments=True)
352378

@@ -381,6 +407,11 @@ or on combining URL components into a URL string.
381407

382408
Behavior updated to match the semantics defined in :rfc:`3986`.
383409

410+
.. versionchanged:: 3.11
411+
Values for `base` and `url` other than strings or bytes raise
412+
:exc:`TypeError` if true or emit `DeprecationWarning` if false (to be
413+
changed to `TypeError` in future versions of Python).
414+
384415

385416
.. function:: urldefrag(url)
386417

@@ -406,6 +437,11 @@ or on combining URL components into a URL string.
406437
.. versionchanged:: 3.2
407438
Result is a structured object rather than a simple 2-tuple.
408439

440+
.. versionchanged:: 3.11
441+
Values other than strings or bytes raise
442+
:exc:`TypeError` if true or emit `DeprecationWarning` if false (to be
443+
changed to `TypeError` in future versions of Python).
444+
409445
.. function:: unwrap(url)
410446

411447
Extract the url from a wrapped URL (that is, a string formatted as

Lib/test/test_urlparse.py

Lines changed: 31 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -847,47 +847,11 @@ def test_mixed_types_rejected(self):
847847
with self.assertRaisesRegex(TypeError, "Cannot mix str"):
848848
urllib.parse.urljoin(b"http://python.org", "http://python.org")
849849

850-
def test_forbidden_types(self):
851-
with self.assertRaisesRegex(
852-
TypeError,
853-
"Expected a string or bytes object: got <class 'list'>"):
854-
urllib.parse.urljoin('http://www.python.org', [])
855-
with self.assertRaisesRegex(
856-
TypeError,
857-
"Expected a string or bytes object: got <class 'list'>"):
858-
urllib.parse.urljoin([], b'docs')
859-
with self.assertRaisesRegex(
860-
TypeError,
861-
"Expected a string or bytes object: got <class 'NoneType'>"):
862-
urllib.parse.urlparse(b'www.python.org', None)
863-
with self.assertRaisesRegex(
864-
TypeError,
865-
"Expected a string or bytes object: got <class 'dict'>"):
866-
urllib.parse.urlparse({}, '')
867-
with self.assertRaisesRegex(
868-
TypeError,
869-
"Expected a string or bytes object: got <class 'int'>"):
870-
urllib.parse.urlsplit(0, 'http')
871-
with self.assertRaisesRegex(
872-
TypeError,
873-
"Expected a string or bytes object: got <class 'NoneType'>"):
874-
urllib.parse.urlsplit('http://www.python.org', None)
875-
with self.assertRaisesRegex(
876-
TypeError,
877-
"Expected a string or bytes object: got <class 'tuple'>"):
878-
urllib.parse.urldefrag(())
879-
with self.assertRaisesRegex(
880-
TypeError,
881-
"Expected a string or bytes object: got <class 'NoneType'>"):
882-
urllib.parse.urlunparse([None, './Python','x-newscheme://foo.com/stuff','x://y','x:/y','x:/','/',])
883-
with self.assertRaisesRegex(
884-
TypeError,
885-
"Expected a string or bytes object: got <class 'int'>"):
886-
urllib.parse.urlunsplit(['http', 0, '', '', ''])
887-
with self.assertRaisesRegex(
888-
TypeError,
889-
"Expected a string or bytes object: got <class 'NoneType'>"):
890-
urllib.parse.parse_qsl(None, encoding='latin-1')
850+
def test_non_string_true_values_rejected(self):
851+
# True values raise informative TypeErrors
852+
msg = "Expected a string or bytes object: got <class "
853+
with self.assertRaisesRegex(TypeError, msg):
854+
urllib.parse.urlsplit(1, b'http')
891855

892856
def _check_result_type(self, str_type):
893857
num_args = len(str_type._fields)
@@ -1378,6 +1342,32 @@ def test_to_bytes_deprecation(self):
13781342
self.assertEqual(str(cm.warning),
13791343
'urllib.parse.to_bytes() is deprecated as of 3.8')
13801344

1345+
def test_false_value_deprecation(self):
1346+
pattern = (
1347+
"Providing false values other than strings or bytes to urllib.parse "
1348+
"is deprecated: got <class "
1349+
)
1350+
with self.assertWarnsRegex(DeprecationWarning, pattern):
1351+
urllib.parse.urljoin('http://www.python.org', [])
1352+
with self.assertWarnsRegex(DeprecationWarning, pattern):
1353+
urllib.parse.urljoin([], b'docs')
1354+
with self.assertWarnsRegex(DeprecationWarning, pattern):
1355+
urllib.parse.urlparse(b'www.python.org', None)
1356+
with self.assertWarnsRegex(DeprecationWarning, pattern):
1357+
urllib.parse.urlparse({}, '')
1358+
with self.assertWarnsRegex(DeprecationWarning, pattern):
1359+
urllib.parse.urlsplit(0, b'http')
1360+
with self.assertWarnsRegex(DeprecationWarning, pattern):
1361+
urllib.parse.urlsplit(b'http://www.python.org', None)
1362+
with self.assertWarnsRegex(DeprecationWarning, pattern):
1363+
urllib.parse.urldefrag(())
1364+
with self.assertWarnsRegex(DeprecationWarning, pattern):
1365+
urllib.parse.urlunparse([None, b'www.python.org', None, None, None, None])
1366+
with self.assertWarnsRegex(DeprecationWarning, pattern):
1367+
urllib.parse.urlunsplit(['http', 0, '', '', ''])
1368+
with self.assertWarnsRegex(DeprecationWarning, pattern):
1369+
urllib.parse.parse_qsl(None, encoding='latin-1')
1370+
13811371

13821372
if __name__ == "__main__":
13831373
unittest.main()

Lib/urllib/parse.py

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -114,8 +114,14 @@ def _coerce_args(*args):
114114
# - noop for str inputs
115115
# - encoding function otherwise
116116
for arg in args:
117-
if not isinstance(arg, (str, bytes, bytearray)):
118-
raise TypeError(f'Expected a string or bytes object: got {type(arg)}')
117+
if not (isinstance(arg, str) or hasattr(arg, 'decode')):
118+
if arg:
119+
raise TypeError(f"Expected a string or bytes object: got {type(arg)}")
120+
else:
121+
warnings.warn(
122+
f"Providing false values other than strings or bytes "
123+
f"to urllib.parse is deprecated: got {type(arg)}",
124+
DeprecationWarning, 3)
119125
str_input = isinstance(args[0], str)
120126
for arg in args[1:]:
121127
# We special-case the empty string to support the
Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,3 @@
1-
Raised ``TypeError`` when providing anything but a string or bytes
2-
object to :func:`urllib.parse.urljoin`, :func:`urllib.parse.urlparse`,
3-
:func:`urllib.parse.urlsplit`, :func:`urllib.parse.urldefrag`, or
4-
:func:`urllib.parse.parse_qsl`, or when providing the same in an iterable
5-
passed to :func:`urllib.parse.urlunparse` or :func:`urllib.parse.urlunsplit`.
1+
Providing anything but a string or bytes object to :mod:`urllib.parse`
2+
functions expecting strings or bytes now raises :exc:`DeprecationWarning`
3+
if the value tests false, or :exc:`TypeError` if it tests true.

0 commit comments

Comments
 (0)