Skip to content

URL.build: reject bool port with a clear TypeError before netloc is built#1786

Open
HrachShah wants to merge 2 commits into
aio-libs:masterfrom
HrachShah:patch-3
Open

URL.build: reject bool port with a clear TypeError before netloc is built#1786
HrachShah wants to merge 2 commits into
aio-libs:masterfrom
HrachShah:patch-3

Conversation

@HrachShah

Copy link
Copy Markdown

Summary

URL.build(..., port=True) (or port=False) used to slip past the
isinstance(port, int) check because bool is a subclass of int.
The port got stringified to "True" / "False" by make_netloc
and the resulting URL looked valid at construction time but blew up
deep inside split_netloc the first time the URL was rendered or
its explicit_port / raw_host was accessed:

ValueError: Invalid URL: port can't be converted to integer

The user had no way to know from the message that the port was the
problem — it pointed at split_netloc 7 frames deep, not at the
port=True they passed to URL.build.

Fix

Mirror the bool-rejection in with_port (which already has
isinstance(port, bool) or not isinstance(port, int)) on the
URL.build constructor:

if port is not None and (isinstance(port, bool) or not isinstance(port, int)):
    raise TypeError(f"The port is required to be int, got {type(port)!r}.")

Now URL.build(port=True) raises TypeError: The port is required to be int, got <class 'bool'>. at the call site, before any netloc
is built and before the URL is constructed.

Test

New test in tests/test_url.py:

def test_build_with_bool_port_rejected() -> None:
    with pytest.raises(TypeError):
        URL.build(port=True)
    with pytest.raises(TypeError):
        URL.build(port=False)

Verified the test fails on baseline with
ValueError: Can't build URL with "port" but without "host".
(the if port and not host check fires next because True is
truthy and host="" by default), and passes on the fix.
All 510 existing yarl tests still pass.

Precedent

The same bool-subclass-of-int footgun is already rejected in
URL.with_port (line 1189 of _url.py). This PR brings URL.build
in line with the same defensive check.

@codspeed-hq

codspeed-hq Bot commented Jul 6, 2026

Copy link
Copy Markdown

Merging this PR will degrade performance by 9.88%

⚠️ Different runtime environments detected

Some benchmarks with significant performance changes were compared across different runtime environments,
which may affect the accuracy of the results.

Open the report in CodSpeed to investigate

❌ 1 regressed benchmark
✅ 96 untouched benchmarks

Warning

Please fix the performance issues or acknowledge them on CodSpeed.

Performance Changes

Benchmark BASE HEAD Efficiency
test_url_build_encoded_with_host_and_port 254.4 µs 282.3 µs -9.88%

Tip

Investigate this regression by commenting @codspeedbot fix this regression on this PR, or directly use the CodSpeed MCP with your agent.


Comparing HrachShah:patch-3 (de95bb5) with master (94274c2)1

Open in CodSpeed

Footnotes

  1. No successful run was found on master (35c2895) during the generation of this report, so 94274c2 was used instead as the comparison base. There might be some changes unrelated to this pull request in this report.

@codecov

codecov Bot commented Jul 6, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 99.86%. Comparing base (b0d27e4) to head (de95bb5).
⚠️ Report is 3 commits behind head on master.

Additional details and impacted files
@@           Coverage Diff           @@
##           master    #1786   +/-   ##
=======================================
  Coverage   99.86%   99.86%           
=======================================
  Files          21       21           
  Lines        4310     4315    +5     
  Branches      252      252           
=======================================
+ Hits         4304     4309    +5     
  Misses          4        4           
  Partials        2        2           
Flag Coverage Δ
CI-GHA 99.79% <100.00%> (+<0.01%) ⬆️
OS-Linux 99.79% <100.00%> (+<0.01%) ⬆️
OS-Windows 98.53% <100.00%> (+<0.01%) ⬆️
OS-macOS 98.72% <100.00%> (+<0.01%) ⬆️
Py-3.10 99.69% <100.00%> (+<0.01%) ⬆️
Py-3.11 99.69% <100.00%> (+<0.01%) ⬆️
Py-3.12 99.69% <100.00%> (+<0.01%) ⬆️
Py-3.13 99.74% <100.00%> (+<0.01%) ⬆️
Py-3.14 99.74% <100.00%> (+<0.01%) ⬆️
Py-3.14t 99.74% <100.00%> (+<0.01%) ⬆️
Py-pypy-3.11 99.37% <100.00%> (+<0.01%) ⬆️
VM-macos-latest 98.72% <100.00%> (+<0.01%) ⬆️
VM-ubuntu-latest 99.79% <100.00%> (+<0.01%) ⬆️
VM-windows-latest 98.53% <100.00%> (+<0.01%) ⬆️
pytest 99.79% <100.00%> (+<0.01%) ⬆️

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@coveralls

Copy link
Copy Markdown

Coverage Report for CI Build 28830767677

Coverage increased (+0.001%) to 98.741%

Details

  • Coverage increased (+0.001%) from the base build.
  • Patch coverage: 6 of 6 lines across 2 files are fully covered (100%).
  • No coverage regressions found.

Uncovered Changes

No uncovered changes found.

Coverage Regressions

No coverage regressions found.


Coverage Stats

Coverage Status
Relevant Lines: 6215
Covered Lines: 6136
Line Coverage: 98.73%
Relevant Branches: 61
Covered Branches: 61
Branch Coverage: 100.0%
Branches in Coverage %: Yes
Coverage Strength: 0.99 hits per line

💛 - Coveralls

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants