• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

aio-libs / yarl / 36456042200
98%

Build:
DEFAULT BRANCH: master
Ran 28 Sep 2026 05:10PM UTC
Jobs 1
Files 42
Run time 1min
Badge
Embed ▾
README BADGES
x

If you need to use a raster PNG badge, change the '.svg' to '.png' in the link

Markdown

Textile

RDoc

HTML

Rst

28 Sep 2026 05:08PM UTC coverage: 97.602% (+0.01%) from 97.591%
36456042200

push

github

web-flow
Keep empty authority, query and fragment apart from absent ones (#1929)

<!-- Thank you for your contribution! -->

## What do these changes do?

yarl stored the authority, query and fragment as plain strings, so an
empty component and a missing one were the same: `http://h/p?` printed
as `http://h/p`, `data:///test` as `data:/test`, and
`URL("file://host/").join(URL("///C:/"))` kept `host`. RFC 3986 section
5.3 and WHATWG both keep them apart. `URL` now has an `_empty` bitmask
slot marking which empty components are present; `str()`, `==`,
`hash()`, ordering, `join()` and pickling honour it, and the modifiers
keep or drop it the same way they keep or drop the component.

`//` used to be written for every scheme in `urllib.parse.uses_netloc`.
Following the per-URL `mode` from #1931, it is now written when an
authority is present and, in the default WHATWG mode only, always for
the special schemes (`http`, `https`, `ws`, `wss`, `ftp`, `file`), which
always have one there; `URL("http:/x", mode="rfc")` stays `http:/x`. RFC
3986 and WHATWG agree on keeping empty components, so that part does not
depend on the mode. A path starting with `//` in a URL without an
authority is written as `/.//path`, as WHATWG does, and parsed back to
`//path`.

## Are there changes in behavior for the user?

Yes, hence the `breaking` fragment:

- `URL("http://h/p?")` and `URL("http://h/p#")` keep the delimiter in
`str()` and `raw_path_qs`, and no longer compare equal to
`URL("http://h/p")`. The `raw_query_string` / `raw_fragment` style
properties still return `""`.
- `sc:///p`, `data:///x` and `foo://` keep the empty authority;
`gopher:/x` or `git:/x` are no longer rewritten to `gopher:///x`, and
`URL.build(scheme="git", path="/x")` prints `git:/x`. `file:/p` and
`file:///p` still compare equal in both modes (RFC 8089 section 2).
- `join()` takes an empty query, fragment or authority from the
reference (`"#"` or `"?"` against a base, `///C:/` against
`file://host/`). For sche... (continued)

96 of 192 branches covered (50.0%)

Branch coverage included in aggregate %.

494 of 501 new or added lines in 5 files covered. (98.6%)

1 existing line in 1 file now uncovered.

8574 of 8691 relevant lines covered (98.65%)

0.99 hits per line

Uncovered Changes

Lines Coverage ∆ File
6
96.41
tests/test_url_empty_components.py
1
96.59
0.47% yarl/_url.py

Coverage Regressions

Lines Coverage ∆ File
1
96.59
0.47% yarl/_url.py
Jobs
ID Job ID Ran Files Coverage
1 MyPy - 36456042200.1 28 Sep 2026 05:10PM UTC 42
97.6
GitHub Action Run
Source Files on build 36456042200
  • Tree
  • List 42
  • Changed 5
  • Source Changed 5
  • Coverage Changed 4
Coverage ∆ File Lines Relevant Covered Missed Hits/Line Branch Hits Branch Misses
  • Back to Repo
  • Github Actions Build #36456042200
  • f374a5cc on github
  • Prev Build on master (#36453675814)
  • Next Build on master (#36461803082)
  • Delete
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE TRIAL · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc