From b3a5a710ccd9f797e769400e6f71cd573ad4957f Mon Sep 17 00:00:00 2001 From: commonism Date: Tue, 28 Nov 2023 23:09:12 +0100 Subject: [PATCH] Raise `TypeError` when a string is passed for `port` to `URL.build()` PR #959 Fixes #883 Co-authored-by: Sviatoslav Sydorenko --- CHANGES/883.bugfix | 4 ++++ tests/test_url_build.py | 28 ++++++++++++++++++++++------ yarl/_url.py | 2 ++ 3 files changed, 28 insertions(+), 6 deletions(-) create mode 100644 CHANGES/883.bugfix diff --git a/CHANGES/883.bugfix b/CHANGES/883.bugfix new file mode 100644 index 000000000..9864377db --- /dev/null +++ b/CHANGES/883.bugfix @@ -0,0 +1,4 @@ +Started raising :py:exc:`TypeError` when a string value is passed into +:py:meth:`~yarl.URL.build` as the ``port`` argument -- by :user:`commonism`. + +Previously the empty string as port would create malformed URLs when rendered as string representations. diff --git a/tests/test_url_build.py b/tests/test_url_build.py index 51969fa84..ed077368a 100644 --- a/tests/test_url_build.py +++ b/tests/test_url_build.py @@ -32,12 +32,28 @@ def test_build_with_scheme_and_host(): assert u == URL("http://127.0.0.1") -def test_build_with_port(): - with pytest.raises(ValueError): - URL.build(port=8000) - - u = URL.build(scheme="http", host="127.0.0.1", port=8000) - assert str(u) == "http://127.0.0.1:8000" +@pytest.mark.parametrize( + ("port", "exc", "match"), + [ + pytest.param( + 8000, + ValueError, + r"""(?x) + ^ + Can't\ build\ URL\ with\ "port"\ but\ without\ "host"\. + $ + """, + id="port-only", + ), + pytest.param( + "", TypeError, r"^The port is required to be int\.$", id="port-str" + ), + ], +) +def test_build_with_port(port, exc, match): + print(match) + with pytest.raises(exc, match=match): + URL.build(port=port) def test_build_with_user(): diff --git a/yarl/_url.py b/yarl/_url.py index c8f2acb39..d5202db16 100644 --- a/yarl/_url.py +++ b/yarl/_url.py @@ -233,6 +233,8 @@ def build( raise ValueError( 'Can\'t mix "authority" with "user", "password", "host" or "port".' ) + if not isinstance(port, (int, type(None))): + raise TypeError("The port is required to be int.") if port and not host: raise ValueError('Can\'t build URL with "port" but without "host".') if query and query_string: