Changelog¶
All notable changes to this project are documented in this file.
The format is based on Keep a Changelog, and this project adheres to Semantic Versioning.
Updating this file. Add a bullet under
## [Unreleased]as part of your PR. Do not bump the version or add a dated## [X.Y.Z]section — the version is bumped once, at release time, from everything accumulated under[Unreleased]. See CONTRIBUTING.md.What warrants an entry. Record notable, user-facing changes — new features, behavior or API changes, bug fixes, deprecations, and removals — under the appropriate
Added/Changed/Fixed/Deprecated/Removedheading. Changes with no effect on users generally do not need an entry: internal refactors, test-only changes, CI config, and documentation edits. A refresh of the vendored Public Suffix List always warrants one, since it changes what the package returns.
Unreleased¶
0.2.1 - 2026-07-26¶
No code changes. The package behaves exactly as 0.2.0 did; this release exists to carry the corrected README links and the new
DocumentationURL onto the PyPI project page, which renders only the newest release's metadata and cannot revise an existing one.
Added¶
- A documentation site (MkDocs + Material), published to https://andrewadlof.github.io/polars-tldextract/ from
main. The narrative pages include their content fromREADME.mdrather than restating it, and the API reference is generated from the NumPy docstrings pydoclint already enforces, so neither can drift from what it documents.just docs-serveruns it locally;just docsbuilds it with--strict, which turns a broken link or an unresolved API reference into a failure. TheDocumentationproject URL now points at the site instead of the README anchor.
Changed¶
- Relative links to repository files in
README.md,CONTRIBUTING.mdandCHANGELOG.mdare now absolute URLs. They resolved on GitHub but nowhere else — PyPI does not rewrite them either, so the links on the published project page were already broken. - Releases publish to PyPI with Trusted Publishing (OIDC) instead of a stored API token. The
publishjob now carriespermissions: id-token: writeand passes nopassword:— an explicit password silently disabled both Trusted Publishing and the PEP 740 attestationspypa/gh-action-pypi-publishproduces by default, which is why the 0.2.0 release loggedthe attestations input is ignored. Requires a publisher registered on PyPI for this repo/workflow/environment; see CONTRIBUTING.md. - CI and release workflows moved off actions pinned to the deprecated Node 20 runtime:
actions/checkoutv4 → v7,actions/download-artifactv4 → v8,actions/upload-artifactv4 → v7,actions/setup-pythonv5 → v7, andastral-sh/setup-uvv5 → v9. Every input in use (merge-multiple,architecture,name,path) exists in the new majors.
0.2.0 - 2026-07-25¶
Added¶
fqdn— the whole hostname, e.g.www.bbc.co.uk. Nothing previously returned it in one call. It is the normalized netloc (scheme, userinfo, port, path, query and fragment stripped, trailing root labels dropped, non-ASCII IDNA separators folded to.), rebuilt from the parse so it agrees with the other expressions by construction. Unlikeregistrable_domainit is lax about suffixes: a host with no recognized suffix still has a name, so127.0.0.1andlocalhostcome back as themselves and only input with no host at all is null.domain— the registrable label (bbcinbbc.co.uk), replacingtop_domain.
Changed¶
- The API is now one struct and one vocabulary.
extractremains thetldextract-faithful struct; everything else is a single Utf8 column with null semantics. Previously the same two concepts had two names each —sld/domainfor the registrable label andtld/suffixfor the public suffix — depending on which expression you called. subdomain,domain, andsuffixreturn null where a part does not exist, rather than the empty stringextractreports. They are now their own Rust kernels rather thanstruct.fieldaccessors overextract, so asking for one part no longer materializes the other three.extract().struct.field(...)still gives the empty-string form.registrable_domainis unchanged in behavior, but is no longer documented in terms ofparts.- The benchmark measures
extractagainst amap_elementsbaseline returning the same three parts. It previously measuredpartsagainst a baseline that also lowercased and stripped each URL — work the plugin was not doing, which flattered the ratio. The figures in the README were re-measured on the same machine as a result.
Deprecated¶
parts— emits aDeprecationWarningand will be removed in 0.3.0. Its fields are now separate expressions carrying the same null semantics:full_domain→registrable_domain(),sld→domain(),tld→suffix(). The namefull_domainwas a misnomer for the registrable domain (bbc.co.uk); the actual full domain isfqdn()(www.bbc.co.uk).top_domain— emits aDeprecationWarningand will be removed in 0.3.0; usedomain(). Note the absent value is now null rather than an empty string.
0.1.1 - 2026-07-24¶
Changed¶
- The README's performance figures are now a measured run on a stated machine (AMD Ryzen 9 3950X, 16 cores) rather than unattributed numbers, and carry the speedup ratios and a note that the parallel figure scales with core count. The previous single-threaded claim of 2.9M rows/s overstated what the reference machine reproduces (2.06M). PyPI renders the description of the newest release and cannot revise an existing one, so correcting the published page needed a release of its own.
just benchnow builds an optimized extension. It previously depended onjust dev, which builds unoptimized, so the benchmark measured a debug build and reported a meaningless ratio against an optimizedtldextract.
0.1.0 - 2026-07-24¶
Added¶
- Initial release. A native Polars expression plugin (Rust) reimplementing
tldextract's URL parsing against the Mozilla Public Suffix List, so domain extraction runs vectorized instead of row-by-row throughExpr.map_elements. - Expressions:
extract(tldextract-faithful struct),parts(full_domain/sld/tldwith null semantics),registrable_domain,subdomain,top_domain,suffix, plus the.tldexpression namespace. - Scalar helpers
extract_scalar/extract_scalar_fullfor callers that are not holding a DataFrame. - The Public Suffix List is compiled into the binary (no network at runtime) and can be overridden without a rebuild via
POLARS_TLDEXTRACT_PSL.psl_version()reports which list is in use. refresh_psl()downloads the current Public Suffix List and loads it into the running process, andload_psl()does the same for a list you already have (a path or the text itself). Both return the newVERSION:stamp and take effect for extractions that start after they return, so a long-lived process does not have to restart to pick up a newer list. A list that fails to parse, or that is missing the ICANN/private section markers, is rejected and the working list stays in use.refresh_pslis the only function in the package that touches the network, and only when called.- Dual licensed MIT OR Apache-2.0. The vendored Public Suffix List keeps its own MPL-2.0 terms and the
tldextractalgorithm its BSD-3-Clause attribution — see NOTICE. - Wheels for Linux (
manylinux2014andmusllinux_1_2, x86_64 and aarch64), macOS (x86_64 and arm64), and Windows (x64 and arm64), plus an sdist. One wheel per platform, since the extension is built against the stable ABI (abi3-py310), so a single wheel serves Python 3.10 through 3.13+.