unstale

pypi / packaging

packaging

What changed in packaging 26, from its official release notes, upgrade guides and advisories. Sources checked 2026-10-18.

23 breaking21 new APIs and options1 performance9 behavior and defaults21 fixes and other

See which of these apply to your code, ranked, in your agent:

npx @unstale/cli init

@unstale/cli 0.1.1 on npm

packaging 2675 changes

Breaking changes 23

  • Malformed Description-Content-Type values are now rejected.

    26.3release notes

  • Local directories in direct_url now require absolute file URLs.

    26.3release notes

  • Misplaced WITH clauses and empty LicenseRef- names now raise InvalidLicenseExpression.

    26.3release notes

  • Names containing collapsed double hyphens, such as a--b, are now rejected.

    26.3release notes

  • Linux tag generation now prefers native linux_* tags over manylinux and musllinux tags.

    26.3release notes

  • Serialization now retains parentheses around nested marker groups.

    26.3release notes

  • Tags with the wrong number of components now raise InvalidTag.

    26.3release notes

  • Empty tag components are now rejected.

    26.3release notes

  • TOML booleans are now rejected where integers are expected.

    26.3release notes

  • Python 3.8 is no longer supported; packaging requires Python 3.9 or later.

    26.3release notes

  • An invalid specifier inside a requirement now raises InvalidRequirement instead of InvalidSpecifier.

    26.3release notes

  • Requirements and markers ending in a line break are now rejected.

    26.3release notes

  • Set-valued variables such as extras now raise UndefinedComparison when used outside the membership form.

    26.3release notes

  • Marker evaluation raises this KeyError subclass when an environment key is missing.

    26.3release notes

  • Passing a non-string to Version now raises InvalidVersion instead of TypeError.

    26.3release notes

  • Non-string pre-release letters now raise InvalidVersion.

    26.3release notes

  • Wheel filenames ending in a newline are now rejected.

    26.3release notes

  • Wheel tags with a non-identifier interpreter component are now rejected.

    26.3release notes

  • The helper is renamed to _format_full_version to make it visibly private.

    26.1release notes

  • ValueError from int-max-str-digits is now propagated.

    26.1release notes

  • Local version identifiers are now restricted to ASCII.

    26.1release notes

  • Pylock now gives preference to a path over a URL.

    26.1release notes

  • The === operator uses the original string when available instead of its normalized form.

    26.1release notes

New APIs and options 21

  • Adds a limit argument for parsing compressed tag sets.

    26.3release notes

  • Generates pure-Python tags for a Python version without consulting the running platform.

    26.3release notes

  • Adds a predicate to prefer source distributions over wheels for selected packages.

    26.3release notes

  • Compares the versions accepted by two specifier sets to determine whether they are disjoint.

    26.3release notes

  • Compares the versions accepted by two specifier sets to determine whether one is a subset of the other.

    26.3release notes

  • Compares the versions accepted by two specifier sets to determine whether one is a superset of the other.

    26.3release notes

  • Converts a SpecifierSet to a VersionRange representing the versions it accepts.

    26.3release notes

  • Adds an interval-set API for version ranges, with set operations, relations, membership tests, filtering, and conversion to a SpecifierSet where a PEP 440 form exists.

    26.3release notes

  • Converts a VersionRange back to a SpecifierSet when a PEP 440 form exists.

    26.3release notes

  • Adds a function for selecting compatible tags.

    26.1release notes

  • Marker objects can now be combined with the & and | operators.

    26.1release notes

  • Adds a filename property to PackageSdist.

    26.1release notes

  • Adds a filename property to PackageWheel.

    26.1release notes

  • Adds a module for working with dependency groups, based on the dependency-groups package.

    26.1release notes

  • Adds the packaging.direct_url module.

    26.1release notes

  • Adds the packaging.errors module.

    26.1release notes

  • Adds an option to validate the sort order of compressed tag sets when parsing wheel filenames.

    26.1release notes

  • Adds a select function for pylock.

    26.1release notes

  • Adds a key argument for filtering values with a SpecifierSet.

    26.1release notes

  • Adds a method that determines whether a SpecifierSet is unsatisfiable using ranges.

    26.1release notes

  • Adds Version.from_parts; Version.__replace__ also normalizes its result.

    26.1release notes

Performance 1

  • Complex SpecifierSet filtering is faster through cost-based ordering.

    26.1release notes

Behavior and default changes 9

  • Values in nested markers are normalized at parse time.

    26.3release notes

  • Requested extra names are normalized before requirements are compared or hashed.

    26.3release notes

  • InvalidMetadata and CyclicDependencyGroup can now be pickled.

    26.3release notes

  • Metadata parsing now accepts Metadata-Version 2.6.

    26.3release notes

  • Specifier and SpecifierSet filtering now use the new range engine.

    26.3release notes

  • The warn argument is now forwarded to generic_tags.

    26.3release notes

  • Wheel tag handling now recognizes the free-threading abi3.abi3t tag.

    26.1release notes

  • Pylock validates that names and versions are consistent with file names.

    26.1release notes

  • Specifiers are now canonicalized when deduplicating them in a SpecifierSet.

    26.1release notes

Fixes and other changes 21

  • Malformed dependency-group parses are no longer cached.

    26.3release notes

  • InvalidRequirement errors are collected during dependency-group resolution instead of leaking.

    26.3release notes

  • Hashing internally trimmed versions no longer raises AttributeError.

    26.3release notes

  • Malformed string literal errors are wrapped in InvalidMarker or InvalidRequirement rather than leaking a low-level error.

    26.3release notes

  • Marker serialization preserves quoting semantics so serialized markers parse back to the same marker.

    26.3release notes

  • Empty tag components are now rejected.

    26.3release notes

  • An explicitly empty tags sequence is used as-is instead of falling back to sys_tags().

    26.3release notes

  • PylockSelectError is now included in packaging.pylock.__all__.

    26.3release notes

  • A requirement's specifier prereleases override is preserved across a pickle round trip.

    26.3release notes

  • Hashing now agrees with equality for trailing-zero-equivalent specifiers, allowing equal requirements to deduplicate in sets and dictionaries.

    26.3release notes

  • Corrects unsatisfiability results for post-release boundary intersections.

    26.3release notes

  • An empty project name is now rejected by both filename parsers.

    26.3release notes

  • Re-exports ExceptionGroup for now.

    26.2release notes

  • Version, Specifier, SpecifierSet, Tag, Marker, and Requirement are pickle-safe and backward-compatible with pickles created in 25.0–26.1, including references to the removed packaging._structures module.

    26.2release notes

  • Corrects the sysconfig variable name for pyemscripten.

    26.2release notes

  • Fixes incorrect self-comparison for InfinityType.

    26.1release notes

  • Fixes incorrect self-comparison for NegativeInfinityType.

    26.1release notes

  • Post-release exclusion for >V is narrowed to match the specification.

    26.1release notes

  • Pre-release exclusion for <V.postN is narrowed to match the specification.

    26.1release notes

  • Fixes handling of key when the specifier set is empty and prerelease is False.

    26.1release notes

  • Fixes > comparisons for versions with dev and local segments.

    26.1release notes