Skip to main content

WHATWG URLPattern for Python. 100% specification strict, pure Python, optimized and yarl-compatible.

Project description

yarlpattern

WPT conformance WPT auxiliary suites Stable spec API Tentative spec API Python License

WHATWG URLPattern for Python — 100% conformance to the upstream WPT corpus: 469 / 469 cases passing across all five test suites, the same files Chromium, Safari, and Firefox validate against.

Pure Python on top of yarl — immutable pattern objects, component properties named after their URL counterparts, zero non-Python dependencies. The pattern is the API: compile once, then ask .test(url) or .exec(url) from anywhere a yarl.URL lives.

from yarlpattern import URLPattern

# Multi-tenant API: the subdomain identifies the tenant, the path
# captures the API version and the resource tail — all extracted in
# one match call.
pat = URLPattern({
    "hostname": ":tenant.myapp.com",
    "pathname": "/api/v:version/*",
})

result = pat.exec("https://acme.myapp.com/api/v2/users/42")
result.hostname["groups"]["tenant"]    # 'acme'
result.pathname["groups"]["version"]   # '2'
result.pathname["groups"]["0"]         # 'users/42'

pat.test("https://foo.example.com/api/v2/users")  # False — wrong host
pat.test("https://acme.myapp.com/api/users")      # False — no version

That's the differentiator. Flask-style :id routers match the path component in isolation; URLPattern matches across protocol, hostname, port, path, and search at once, returning structured named groups per component.

WHATWG conformance

366 / 366 Web Platform Tests pass (100%) on urlpattern.any.js — the canonical end-to-end suite driven by urlpatterntestdata.json, the same corpus Chromium, Safari, Firefox, Ada, and rust-urlpattern validate against. Every auxiliary WPT suite that covers the stable spec also passes in full.

The corpus is SHA-pinned by scripts/fetch_references.sh to commit dd54691 (2026-05-11) so the reported pass count is reproducible at any future date. Bump the pin in the script and re-run just check + just compliance-report to refresh against a newer corpus.

Test corpus matrix

Summary below; the full per-case report (regenerate via just compliance-report) lists every one of the 469 WPT cases with its status.

Status legend: all passing  ·  ~ engine-dependent  ·  tentative spec, tracked but not implemented  ·  not implemented.

WPT runner Data file Count Result
urlpattern.any.js urlpatterntestdata.json 366   366 / 366   100%
urlpattern-constructor.any.js (inline) 4   4 / 4   100%
urlpattern-hasregexpgroups.any.js urlpattern-hasregexpgroups-tests.js 55   55 / 55   100%
urlpattern-compare.tentative.any.js urlpattern-compare-test-data.json 25   25 / 25   100%
urlpattern-generate.tentative.any.js urlpattern-generate-test-data.json 19   opt-in via WHATWG_URLPATTERN_RUN_TENTATIVE=1

Stdlib-only mode. Under stdlib re without the [regex] extra, conformance on urlpattern.any.js is 364 / 366 (99.5%). The two outlier patterns — [a&&b] (intersection) and [a--b] (difference) from the JS v-flag — require Matthew Barnett's regex package; they're marked xfail with an install hint when it's absent. pip install yarlpattern[regex] activates them.

API surface

Surface Spec status Status
URLPattern(input) — dict or string constructor Stable   Implemented
URLPattern(string, baseURL, options?) — full signature Stable   Implemented
URLPattern(input, options?) — two-arg overload Stable   Implemented
test(input, baseURL?) Stable   Implemented
exec(input, baseURL?) Stable   Implemented
8 component properties (protocol, hostname, pathname, …) Stable   Implemented
hasRegExpGroups property Stable   Implemented
URLPattern.compareComponent() Tentative   Implemented
generate() Tentative   Tracked

How this differs from aiohttp.web.UrlDispatcher

aiohttp.web.UrlDispatcher is a mature path-router shaped around web-request dispatch. yarlpattern is a predicate: it matches across all eight URL components (not just the path), works standalone (no server context required), and uses the same WHATWG pattern syntax browsers, Deno, Bun, and Cloudflare Workers all implement.

Use UrlDispatcher if you're building an aiohttp service. Use yarlpattern if you're matching URLs outside a server context, need to constrain on hostname / port / scheme alongside path, or want patterns that match what browsers do.

Full comparison

How this differs from yarl

yarl is a URL parser / builder; yarlpattern is a URLPattern matcher. They're complementary — yarlpattern depends on yarl for URL parsing and IDNA hostname encoding, accepts yarl.URL directly in .test(...) and .exec(...) calls (no str() round-trip), and uses WHATWG component names (protocol / hostname / pathname / search / hash) rather than yarl's (scheme / host / path / query / fragment).

Three places where yarlpattern is stricter than yarl, all because the WHATWG URLPattern spec requires it:

  • Percent-encoded %XX case is preserved verbatim (yarl normalizes to uppercase).
  • Unpaired surrogates substitute U+FFFD before UTF-8 encoding (yarl drops them).
  • Hostname patterns truncate at ? / # / / / \ (yarl rejects).

Component-name mapping for muscle-memory porting:

yarl yarlpattern WHATWG / browser JS
scheme protocol protocol
user username username
host hostname hostname
path pathname pathname
query (MultiDict) search (str) search
fragment hash hash

Full comparison, including the WPT cases that pin down each strictness rule, the with_* ergonomics, and the encoding philosophy yarlpattern shares with the rest of aio-libs.

Install

pip install yarlpattern            # stdlib re backend (99.5% WPT conformance)
pip install 'yarlpattern[regex]'   # full 100% conformance via Matthew Barnett's regex package

Bring your own regex engine

The matcher's regex backend is pluggable behind a @runtime_checkable Protocol. Two adapters ship in-tree:

Engine Trigger Conformance Cost
stdlib re always available; default fallback 99.5% no extra deps
regex (Matthew Barnett) pip install yarlpattern[regex]  ·  auto-detected 100% one extension wheel

Selection priority: explicit engine= argument › URLPATTERN_REGEX_ENGINE env var › auto-probe (prefers regex when importable, falls back to re). See src/yarlpattern/_regex_engine/protocols.py for the Protocol definitions; a future PyO3-backed engine slots in as one new adapter module.

Quick start

uv sync --all-groups
uv run pytest                  # full test suite
just check                     # lint + types + tests (requires `just`)
from yarlpattern import URLPattern

# Dict form, fully wildcarded except path
api = URLPattern({"pathname": "/api/v:version/users/:id(\\d+)"})
api.test({"pathname": "/api/v2/users/42"})              # True
api.exec({"pathname": "/api/v2/users/42"}).pathname     # {'input': '...', 'groups': {'version': '2', 'id': '42'}}

# String form with base URL
route = URLPattern("/posts/:slug", "https://blog.example.com")
route.test("https://blog.example.com/posts/hello")      # True

# Match a full URL against the constructed pattern
pat = URLPattern("https://*.shop.example/products/:sku")
pat.test("https://eu.shop.example/products/SKU-991")    # True

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

yarlpattern-0.1.0.tar.gz (119.2 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

yarlpattern-0.1.0-py3-none-any.whl (64.7 kB view details)

Uploaded Python 3

File details

Details for the file yarlpattern-0.1.0.tar.gz.

File metadata

  • Download URL: yarlpattern-0.1.0.tar.gz
  • Upload date:
  • Size: 119.2 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.13

File hashes

Hashes for yarlpattern-0.1.0.tar.gz
Algorithm Hash digest
SHA256 ad2a9e8698f5627594523ad12908f9e0dc888f955b74349c4688794f87644969
MD5 02c92508543e8b42064026557790c50c
BLAKE2b-256 16801bf13596230eb5b67138de25ac593141ea2a2abe0eed958b3178a019548e

See more details on using hashes here.

Provenance

The following attestation bundles were made for yarlpattern-0.1.0.tar.gz:

Publisher: release.yml on chad-loder/yarlpattern

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file yarlpattern-0.1.0-py3-none-any.whl.

File metadata

  • Download URL: yarlpattern-0.1.0-py3-none-any.whl
  • Upload date:
  • Size: 64.7 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.13

File hashes

Hashes for yarlpattern-0.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 74944dad6cc9c318931525136b322e46b6e4a0165c570b58179c7b892d352991
MD5 4b7d445eda468bcbf3f18939b369ce5a
BLAKE2b-256 03ef77fe3bef103bf73cdea294f079ce4ffa339452fe923644e7e96459f892dd

See more details on using hashes here.

Provenance

The following attestation bundles were made for yarlpattern-0.1.0-py3-none-any.whl:

Publisher: release.yml on chad-loder/yarlpattern

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page