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

aio-libs / yarl / 37009328384
98%

Build:
DEFAULT BRANCH: master
Ran 02 Oct 2026 12:53PM UTC
Jobs 1
Files 51
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

02 Oct 2026 12:52PM UTC coverage: 97.844% (+0.008%) from 97.836%
37009328384

push

github

web-flow
Give file URLs a non-empty path in WHATWG mode (#1963)

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

## What do these changes do?

In WHATWG mode a `file` URL always has an authority and a path, and an
empty path serializes as `/`, as the WHATWG URL Standard does. `file:`
is now `file:///`, `file:?q=v` is `file:///?q=v`, `file:#frag` is
`file:///#frag` and `file://test` is `file://test/`. The parser,
`URL.build()`, `with_path()`, `parent` and the host moving helper behind
`with_scheme()`, `join()` and a change of mode apply the same rule, so
`URL(str(u)) == u` holds for all of them. As a reference, `file:` and
`file:?q` still keep the path of a `file` base in `join()` (`file:?q`
against `file://host/dir/page` is `file://host/dir/page?q`), also after
a change of mode or `with_scheme("file")` made them. RFC mode is
unchanged.

Conformance report: the 4 *empty file path* rows (`file:`, `file:?q=v`,
`file:#frag`, and `file://test` against `file:///tmp/mock/path`) move
from *WHATWG mode differs from WHATWG, RFC mode follows RFC 3986+3987*
to *yarl follows each standard in its mode*, as do two *empty host* rows
with the same cause: `//` against `file:///tmp/mock/path` and `file://`
against `file://ape/` (both were `file://`, now `file:///`). The
sections go from 95 to 89 and from 300 to 306. No other row moves, and
*yarl differs, RFC 3986+3987 and WHATWG agree* stays at 0 rows.

## Are there changes in behavior for the user?

Yes, in WHATWG mode only, for `file` URLs with an empty path:
`str(URL("file:"))` is `file:///` instead of `file://`,
`URL("file://h")` prints `file://h/`, and `URL("file:///a").parent`,
`URL("file:///C:").parent`, `URL("file:a/..")` and
`URL("file:///x").with_path("a/..")` are `file:///` instead of
`file://`. `URL("file://h").with_scheme("http")` now prints `http://h/`,
which is equal to `http://h`. `URL("sc:?q").with_scheme("file")` is
`file:///?q` instead of `file://?q`. `encoded=True` parsing and building
keep the empty path, as they... (continued)

97 of 194 branches covered (50.0%)

Branch coverage included in aggregate %.

254 of 258 new or added lines in 2 files covered. (98.45%)

10660 of 10800 relevant lines covered (98.7%)

0.99 hits per line

Uncovered Changes

Lines Coverage ∆ File
4
98.17
tests/test_url_file_path.py
Jobs
ID Job ID Ran Files Coverage
1 MyPy - 37009328384.1 02 Oct 2026 12:53PM UTC 51
97.84
GitHub Action Run
Source Files on build 37009328384
  • Tree
  • List 51
  • Changed 1
  • Source Changed 1
  • Coverage Changed 1
Coverage ∆ File Lines Relevant Covered Missed Hits/Line Branch Hits Branch Misses
  • Back to Repo
  • Github Actions Build #37009328384
  • 909ff609 on github
  • Prev Build on master (#37000909309)
  • Next Build on master (#37020030388)
  • 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