Skip to content
Open
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
35 changes: 35 additions & 0 deletions Doc/library/urllib.parse.rst
Original file line number Diff line number Diff line change
Expand Up @@ -193,6 +193,11 @@ or on combining URL components into a URL string.
Characters that affect netloc parsing under NFKC normalization will
now raise :exc:`ValueError`.

.. versionchanged:: 3.14
Values for ``url`` and ``scheme`` other than strings or bytes raise
:exc:`TypeError` if true or :exc:`DeprecationWarning` if false (to be
changed to :exc:`TypeError` in future versions of Python).


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

Expand Down Expand Up @@ -282,6 +287,11 @@ 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.

.. versionchanged:: 3.14
Values for ``qs`` and ``separator`` other than strings or bytes raise
:exc:`TypeError` if true or :exc:`DeprecationWarning` if false (to be
changed to :exc:`TypeError` in future versions of Python).


.. function:: urlunparse(parts)

Expand All @@ -291,6 +301,11 @@ or on combining URL components into a URL string.
unnecessary delimiters (for example, a ``?`` with an empty query; the RFC
states that these are equivalent).

.. versionchanged:: 3.14
Items in ``parts`` other than strings or bytes raise
:exc:`TypeError` if true or :exc:`DeprecationWarning` if false (to be
changed to :exc:`TypeError` in future versions of Python).


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

Expand Down Expand Up @@ -364,6 +379,11 @@ or on combining URL components into a URL string.
.. versionchanged:: 3.12
Leading WHATWG C0 control and space characters are stripped from the URL.

.. versionchanged:: 3.14
Values for the url argument and ``scheme`` other than strings or bytes raise
:exc:`TypeError` if true or :exc:`DeprecationWarning` if false (to be
changed to :exc:`TypeError` in future versions of Python).

.. _WHATWG spec: https://url.spec.whatwg.org/#concept-basic-url-parser

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

.. versionchanged:: 3.14
Items in ``parts`` other than strings or bytes raise
:exc:`TypeError` if true or :exc:`DeprecationWarning` if false (to be
changed to :exc:`TypeError` in future versions of Python).


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

Expand Down Expand Up @@ -408,6 +433,11 @@ or on combining URL components into a URL string.

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

.. versionchanged:: 3.14
Values for ``base`` and ``url`` other than strings or bytes raise
:exc:`TypeError` if true or :exc:`DeprecationWarning` if false (to be
changed to :exc:`TypeError` in future versions of Python).


.. function:: urldefrag(url)

Expand All @@ -433,6 +463,11 @@ or on combining URL components into a URL string.
.. versionchanged:: 3.2
Result is a structured object rather than a simple 2-tuple.

.. versionchanged:: 3.14
Values other than strings or bytes raise
:exc:`TypeError` if true or :exc:`DeprecationWarning` if false (to be
changed to :exc:`TypeError` in future versions of Python).

.. function:: unwrap(url)

Extract the url from a wrapped URL (that is, a string formatted as
Expand Down
5 changes: 5 additions & 0 deletions Doc/whatsnew/3.14.rst
Original file line number Diff line number Diff line change
Expand Up @@ -552,6 +552,11 @@ Deprecated
use :func:`inspect.iscoroutinefunction` instead.
(Contributed by Jiahao Li and Kumar Aditya in :gh:`122875`.)

* Providing anything but a string or bytes object to :mod:`urllib.parse`
functions expecting strings or bytes now raises :exc:`DeprecationWarning`
if the value tests false, or :exc:`TypeError` if it tests true.
(Contributed by Jacob Walls in :issue:`19094`.)

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

.. include:: ../deprecations/c-api-pending-removal-in-3.15.rst
Expand Down
27 changes: 27 additions & 0 deletions Lib/test/test_urlparse.py
Original file line number Diff line number Diff line change
Expand Up @@ -1128,6 +1128,12 @@ def test_mixed_types_rejected(self):
with self.assertRaisesRegex(TypeError, "Cannot mix str"):
urllib.parse.urljoin(b"http://python.org", "http://python.org")

def test_non_string_true_values_rejected(self):
# True values raise informative TypeErrors
msg = "Expected a string or bytes object: got <class "
with self.assertRaisesRegex(TypeError, msg):
urllib.parse.urlsplit(1, b'http')

def _check_result_type(self, str_type):
num_args = len(str_type._fields)
bytes_type = str_type._encoded_counterpart
Expand Down Expand Up @@ -1665,6 +1671,27 @@ def test_to_bytes_deprecation(self):
self.assertEqual(str(cm.warning),
'urllib.parse.to_bytes() is deprecated as of 3.8')

def test_falsey_deprecation(self):
pattern = (
"Providing false values other than strings or bytes to urllib.parse "
"is deprecated: got <class "
)
cases = [
(urllib.parse.urljoin, ['http://www.python.org', []]),
(urllib.parse.urljoin, [[], b'docs']),
(urllib.parse.urlparse, [b'www.python.org', None]),
(urllib.parse.urlparse, [{}, '']),
(urllib.parse.urlsplit, [0, b'http']),
(urllib.parse.urlsplit, [b'http://www.python.org', None]),
(urllib.parse.urldefrag, [{}]),
(urllib.parse.urlunparse, [[None, b'www.python.org', None, None, None, None]]),
(urllib.parse.urlunsplit, [['http', 0, '', '', '']]),
]
for callable, args in cases:
with self.subTest(callable=callable):
with self.assertWarnsRegex(DeprecationWarning, pattern):
callable(*args)


if __name__ == "__main__":
unittest.main()
15 changes: 12 additions & 3 deletions Lib/urllib/parse.py
Original file line number Diff line number Diff line change
Expand Up @@ -122,6 +122,15 @@ def _coerce_args(*args):
# an appropriate result coercion function
# - noop for str inputs
# - encoding function otherwise
for arg in args:
if not (isinstance(arg, str) or hasattr(arg, 'decode')):
if arg:
raise TypeError(f"Expected a string or bytes object: got {type(arg)}")
else:
warnings.warn(
f"Providing false values other than strings or bytes "
f"to urllib.parse is deprecated: got {type(arg)}",
DeprecationWarning, stacklevel=3)
str_input = isinstance(args[0], str)
for arg in args[1:]:
# We special-case the empty string to support the
Expand Down Expand Up @@ -564,12 +573,12 @@ def _urlunsplit(scheme, netloc, url, query, fragment):
def urljoin(base, url, allow_fragments=True):
"""Join a base URL and a possibly relative URL to form an absolute
interpretation of the latter."""
base, url, _coerce_result = _coerce_args(base, url)
if not base:
return url
return _coerce_result(url)
if not url:
return base
return _coerce_result(base)

base, url, _coerce_result = _coerce_args(base, url)
bscheme, bnetloc, bpath, bquery, bfragment = \
_urlsplit(base, None, allow_fragments)
scheme, netloc, path, query, fragment = \
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
Providing anything but a string or bytes object to :mod:`urllib.parse`
functions expecting strings or bytes now raises :exc:`DeprecationWarning`
if the value tests false, or :exc:`TypeError` if it tests true.
Loading