packaging

Frameworks & Libraries

packaging release notes.

Latest 26.3 · by packagingWritten in PythonWebsitepypa/packagingRSS

Release activity

Release activity — 7 releases across 7 days in the last year. Each cell is one day; darker means more releases that day. Older weeks are hidden at this screen width.
JunJulAugSep
SundayNo releases on May 24, 2026No releases on May 31, 2026No releases on Jun 7, 2026No releases on Jun 14, 2026No releases on Jun 21, 2026No releases on Jun 28, 2026No releases on Jul 5, 2026No releases on Jul 12, 2026No releases on Jul 19, 2026No releases on Jul 26, 2026No releases on Aug 2, 2026No releases on Aug 9, 2026No releases on Aug 16, 2026No releases on Aug 23, 2026No releases on Aug 30, 2026No releases on Sep 6, 2026
MondayNo releases on May 25, 2026No releases on Jun 1, 2026No releases on Jun 8, 2026No releases on Jun 15, 2026No releases on Jun 22, 2026No releases on Jun 29, 2026No releases on Jul 6, 2026No releases on Jul 13, 2026No releases on Jul 20, 2026No releases on Jul 27, 2026No releases on Aug 3, 2026No releases on Aug 10, 2026No releases on Aug 17, 2026No releases on Aug 24, 2026No releases on Aug 31, 2026No releases on Sep 7, 2026
TuesdayNo releases on May 26, 2026No releases on Jun 2, 2026No releases on Jun 9, 2026No releases on Jun 16, 2026No releases on Jun 23, 2026No releases on Jun 30, 2026No releases on Jul 7, 2026No releases on Jul 14, 2026No releases on Jul 21, 2026No releases on Jul 28, 20261 release on Aug 4, 2026No releases on Aug 11, 2026No releases on Aug 18, 2026No releases on Aug 25, 2026No releases on Sep 1, 2026
WednesdayNo releases on May 27, 2026No releases on Jun 3, 2026No releases on Jun 10, 2026No releases on Jun 17, 2026No releases on Jun 24, 2026No releases on Jul 1, 2026No releases on Jul 8, 2026No releases on Jul 15, 2026No releases on Jul 22, 2026No releases on Jul 29, 2026No releases on Aug 5, 2026No releases on Aug 12, 2026No releases on Aug 19, 2026No releases on Aug 26, 2026No releases on Sep 2, 2026
ThursdayNo releases on May 28, 2026No releases on Jun 4, 2026No releases on Jun 11, 2026No releases on Jun 18, 2026No releases on Jun 25, 2026No releases on Jul 2, 2026No releases on Jul 9, 2026No releases on Jul 16, 2026No releases on Jul 23, 2026No releases on Jul 30, 2026No releases on Aug 6, 2026No releases on Aug 13, 2026No releases on Aug 20, 2026No releases on Aug 27, 2026No releases on Sep 3, 2026
FridayNo releases on May 29, 2026No releases on Jun 5, 2026No releases on Jun 12, 2026No releases on Jun 19, 2026No releases on Jun 26, 2026No releases on Jul 3, 2026No releases on Jul 10, 2026No releases on Jul 17, 2026No releases on Jul 24, 2026No releases on Jul 31, 2026No releases on Aug 7, 2026No releases on Aug 14, 2026No releases on Aug 21, 2026No releases on Aug 28, 2026No releases on Sep 4, 2026
SaturdayNo releases on May 30, 2026No releases on Jun 6, 2026No releases on Jun 13, 2026No releases on Jun 20, 2026No releases on Jun 27, 2026No releases on Jul 4, 2026No releases on Jul 11, 2026No releases on Jul 18, 2026No releases on Jul 25, 2026No releases on Aug 1, 2026No releases on Aug 8, 2026No releases on Aug 15, 2026No releases on Aug 22, 2026No releases on Aug 29, 2026No releases on Sep 5, 2026

7 releases in the last year

Changelog

What changed from 25 to 26

26.3

Latest
Added 7
  • Add a public VersionRange API and SpecifierSet.to_range(), representing the versions a specifier set accepts as an interval set that supports intersection, union, difference, complement, set relations, membership tests, and filtering
  • Add VersionRange.to_specifier_set() to convert a range back to a SpecifierSet where a PEP 440 form exists
  • Accept Metadata-Version: 2.6 per PEP 808
  • Add a limit argument to parse_tag() for compressed tag sets
  • Add a prefer_sdist_predicate argument to Pylock.select() to prefer source distributions over wheels for selected packages
  • Add pure_python_tags() to generate the pure-Python tags for a Python version without touching the running platform
  • Add SpecifierSet.is_subset(), SpecifierSet.is_superset(), and SpecifierSet.is_disjoint() to compare the versions two specifier sets accept
Changed 1
  • Prefer native linux_* platform tags over manylinux and musllinux tags on Linux
Fixed 12
  • Raise InvalidVersion instead of TypeError when Version is given a non-string
  • Raise InvalidVersion for non-string pre-release letters passed to Version.from_parts
  • Fix an AttributeError when hashing internally trimmed versions
  • Fix SpecifierSet.is_unsatisfiable for post-release boundary intersections
  • Make Requirement.__hash__ consistent with __eq__ for trailing-zero-equivalent specifiers so equal requirements hash equal and deduplicate in sets and dicts
  • Normalize requested extra names before comparing or hashing requirements
Removed 1
  • Drop support for Python 3.8; packaging now requires Python 3.9 or later

From packaging

What's Changed
Features
  • Add a public VersionRange API and SpecifierSet.to_range(), representing the versions a specifier set accepts as an interval set that supports intersection, union, difference, complement, set relations, membership tests, and filtering. VersionRange.to_specifier_set() converts a range back to a SpecifierSet where a PEP 440 form exists. (#1267, #1270, #1298)
  • PEP 808: accept Metadata-Version: 2.6. (#1194)
  • Add a limit argument to parse_tag() for compressed tag sets. (#1220)
  • Add a prefer_sdist_predicate argument to Pylock.select() to prefer source distributions over wheels for selected packages. (#1334)
  • Add pure_python_tags() to generate the pure-Python tags for a Python version without touching the running platform. (#1346)
  • Add SpecifierSet.is_subset(), SpecifierSet.is_superset(), and SpecifierSet.is_disjoint(), which compare the versions two specifier sets accept. (#1313)
Behavior adaptations
  • Drop support for Python 3.8; packaging now requires Python 3.9 or later. (#1157)
  • Prefer native linux_* platform tags over manylinux and musllinux tags on Linux. (#160)
Fixes for versions and specifiers
  • Raise InvalidVersion instead of TypeError when Version is given a non-string. (#1319)
  • Raise InvalidVersion for non-string pre-release letters passed to Version.from_parts. (#1241)
  • Fix an AttributeError when hashing internally trimmed versions. (#1242)
  • Fix SpecifierSet.is_unsatisfiable for post-release boundary intersections. (#1257)
Fixes for requirements and markers
  • Make Requirement.__hash__ consistent with __eq__ for trailing-zero-equivalent specifiers (e.g. foo==1.0.0 and foo==1.0.0.0), so equal requirements hash equal and deduplicate in sets and dicts. (#1232)
  • Normalize requested extra names before comparing or hashing requirements. (#644)
  • Preserve a Requirement's specifier prereleases override across a pickle round trip. (#1204)
  • Raise InvalidRequirement instead of InvalidSpecifier when a requirement contains an invalid specifier. (#1332)
  • Clarify the error for post-release prefix wildcards like ==1.0.post1.*. (#1299)
  • Preserve quoting semantics when serializing marker values, so round-tripped markers parse back to the same marker. (#1213)
  • Keep the parentheses of a nested group when serializing markers. (#1316)
  • Normalize extra and dependency_groups values in nested markers at parse time. (#1246, #1310)
  • Raise UndefinedComparison when a set-valued variable like extras is used outside the membership form. (#1265)
  • Raise UndefinedEnvironmentName (a KeyError subclass) for missing environment keys during marker evaluation. (#1276)
  • Wrap malformed string literal errors in InvalidMarker / InvalidRequirement instead of leaking a low-level error. (#1249)
  • Reject requirements and markers with a trailing line break. (#1345)
Fixes for metadata and licenses
  • Collect all from_email validation errors into one ExceptionGroup instead of raising the first. (#1268)
  • Accept the UTF-8 charset case-insensitively in email payloads. (#1330)
  • Reject malformed Description-Content-Type values. (#1329)
  • Don't rewrite user values that contain {field} placeholders in error messages. (#1327)
  • Route multipart email payloads to unparsed instead of asserting. (#1247)
  • Make InvalidMetadata and CyclicDependencyGroup picklable. (#1328)
  • Fold every line boundary str.splitlines recognizes when writing a header with RFC822Message. (#1356)
  • Raise InvalidLicenseExpression for misplaced WITH clauses and empty LicenseRef- names. (#1266)
  • Raise InvalidLicenseExpression instead of KeyError for a LicenseRef- with a + suffix. (#1219)
Fixes for tags and filenames
  • Raise InvalidTag from parse_tag() for tags with the wrong number of components. (#1238)
  • Reject empty tag components in parse_wheel_filename() and parse_tag(). (#1234)
  • Reject an empty project name in the wheel and sdist filename parsers. (#1305)
  • Reject wheel filenames with a trailing newline. (#1341)
  • Reject wheel tags whose interpreter component is not an identifier. (#577)
  • is_normalized_name now rejects names with collapsed double hyphens like a--b. (#1230)
  • Fix duplicate explicit abi3t tags. (#1245)
  • Forward the warn argument to generic_tags() in sys_tags(). (#1264)
  • Raise SystemError for an empty or malformed CPython EXT_SUFFIX. (#1271, #1301)
  • Fix a typo in the macOS fat3 architecture name (was fat32). (#1199)
Fixes for pylock, direct URLs, and dependency groups
  • Percent-decode pylock artifact file names derived from a url so that local versions (e.g. a wheel with 2.12.1+cu130 encoded as 2.12.1%2Bcu130) yield a valid file name. (#1314)
  • Use an explicitly empty tags sequence in Pylock.select() instead of falling back to sys_tags(). (#1349)
  • Fix Pylock.select() on Python builds that report a non-PEP 440 python_full_version (e.g. 3.15.0+). (#1179)
  • Reject TOML booleans where integers are expected in pylock files. (#1244)
  • Add PylockSelectError to packaging.pylock.__all__. (#1202)
  • Fix DirectUrl credential stripping for passwords containing @. (#1218)
  • Parse the URL scheme case-insensitively when checking for file URLs in direct_url. (#1240)
  • Require absolute file URLs for local directories in direct_url. (#1297)
  • Collect InvalidRequirement errors while resolving dependency groups instead of leaking them. (#1302)
  • Don't cache malformed dependency group parses. (#1248)
Performance
  • Implement Specifier and SpecifierSet filtering with the new range engine. (#1120, #1259)
  • Cache the default marker environment. (#1250)
  • Cache the _manylinux module lookup process-wide. (#1254)
  • Add __slots__ to Requirement and the token classes. (#1320, #1258)
  • Keep range caches across canonicalization, precompile the wheel project-name pattern, simplify parse_tag(), and skip platform.mac_ver() when the version and arch are given. (#1253, #1256, #1236, #1255)
Documentation
Internal
  • Add Python 3.15 to the test matrix. (#1190)
  • Add a musl/Alpine test job and make the test suite pass on musl. (#1226, #1227)
  • Expand the downstream test matrix by ten projects. (#1261)
  • Update to mypy 2. (#1191)
  • Use nox's uv integration. (#1057)
New Contributors

Full Changelog: https://github.com/pypa/packaging/compare/26.2...26.3

View originalPermalink
How 26.3 went

26.2

Fixed 3
  • Fix incorrect sysconfig var name for pyemscripten
  • Make Version, Specifier, SpecifierSet, Tag, Marker, and Requirement pickle-safe and backward-compatible with pickles created in 25.0-26.1 including references to the removed packaging._structures module
  • Re-export ExceptionGroup for now

From packaging

What's Changed

Fixes:

Documentation:

Internal:

New Contributors

Full Changelog: https://github.com/pypa/packaging/compare/26.1...26.2

View originalPermalink
How 26.2 went

26.1

Added 13
  • Add handling for Emscripten wheel tags per PEP 783
  • Add handling for the abi3.abi3t free-threading tag per PEP 803
  • Add packaging.dependency_groups module based on PEP 723
  • Add the packaging.direct_url module
  • Add the packaging.errors module
  • Add SpecifierSet.is_unsatisfiable using ranges
Changed 5
  • Narrow exclusion of pre-releases for <V.postN to match spec
  • Narrow exclusion of post-releases for >V to match spec
  • Rename format_full_version to _format_full_version to make it visibly private
  • Restrict local version to ASCII
  • Give preference to path over url in pylock
Fixed 7
  • Fix > comparison for versions with dev+local segments
  • Fix incorrect self-comparison for InfinityType and NegativeInfinityType
  • Canonicalize when deduplicating specifiers in SpecifierSet
  • Fix charset error message formatting
  • Handle the key parameter in SpecifierSet.filter when specifiers are empty and prerelease is False
  • Specifier === uses original string, not normalized, when available
  • Propagate int-max-str-digits ValueError

From packaging

Features:

Behavior adaptations:

Pylock (PEP 751) updates:

Fixes:

Performance:

Internal:

Documentation:

Benchmarks

Performance improvements since 26.0, from the new integrated benchmark suite:

uv run asv run 26.0..HEAD
New Contributors

Full Changelog: https://github.com/pypa/packaging/compare/26.0...26.1

View originalPermalink
How 26.1 went

26.0

Added 5
  • Support PEP 751 for pylock
  • Support PEP 794 import name metadata
  • Support writing metadata
  • Support __replace__ for Version
  • Support positional pattern matching for Version and Specifier
Changed 6
  • Adjust PEP 440 handling of prereleases for Specifier.contains, SpecifierSet.contains, and SpecifierSet.filter
  • Handle PEP 440 edge case in SpecifierSet.filter
  • Adjust arbitrary equality intersection preservation in SpecifierSet
  • Return False instead of raising for .contains with invalid version
  • Support arbitrary equality on arbitrary strings for Specifier and SpecifierSet's filter and contains methods
  • Only try to parse as Version on certain marker keys, return False on unequal ordered comparisons
Fixed 9
  • Update _hash when unpickling Tag()
  • Correct comment and simplify implicit prerelease handling in Specifier.prereleases
  • Use explicit _GLibCVersion NamedTuple in _manylinux
  • Detect invalid license expressions containing ()
  • Correct regex for metadata 'name' format
  • Improve the message around expecting a semicolon

From packaging

Read about the performance improvements here: https://iscinumpy.dev/post/packaging-faster.

What's Changed

Features:

Behavior adaptations:

Fixes:

Performance:

Type annotations:

Internal:

New Contributors
Since last RC

Fixes:

Performance:

Documentaiton:

Full Changelog: https://github.com/pypa/packaging/compare/26.0rc3...26.0

View originalPermalink
How 26.0 went

26.0rc3

Pre-release
Changed 1
  • Faster zero stripping
Fixed 2
  • Support CPython 3.11.0-3.11.4 and older PyPy3.11
  • Fix formatting of distribution types in metadata.rst

From packaging

What's Changed

Fixes:

Performance:

CI:

Documentation:

Full Changelog: https://github.com/pypa/packaging/compare/26.0rc2...26.0rc3

View originalPermalink
How 26.0rc3 went

26.0rc2

Pre-release
Changed 1
  • Improve import time with simplification
Fixed 2
  • Fix regression in (private) Version._key for packaging_legacy
  • Fix type hint of function used with contextlib.contextmanager

From packaging

What's Changed

Fixes:

Performance:

Internal:

Full Changelog: https://github.com/pypa/packaging/compare/26.0rc1...26.0rc2

View originalPermalink
How 26.0rc2 went

26.0rc1

Pre-release
Added 5
  • Support PEP 751 pylock
  • Support PEP 794 import name metadata
  • Support writing metadata
  • Support __replace__ for Version
  • Support positional pattern matching for Version and Specifier
Changed 6
  • Improve PEP 440 handling of prereleases for Specifier.contains, SpecifierSet.contains, and SpecifierSet.filter
  • Handle PEP 440 edge case in SpecifierSet.filter
  • Adjust arbitrary equality intersection preservation in SpecifierSet
  • Return False instead of raising for .contains with invalid version
  • Support arbitrary equality on arbitrary strings for Specifier and SpecifierSet's filter and contains methods
  • Only try to parse as Version on certain marker keys, return False on unequal ordered comparisons
Fixed 9
  • Update _hash when unpickling Tag()
  • Correct regex for metadata 'name' format
  • Detect invalid license expressions containing ()
  • Support nested parens in license expressions
  • Add space before at symbol in Requirements string
  • Use packaging logger instead of root logger

From packaging

What's Changed

Features:

Behavior adaptations:

Fixes:

Performance:

Type annotations:

Internal:

New Contributors

Full Changelog: https://github.com/pypa/packaging/compare/25.0...26.0rc1

View originalPermalink
How 26.0rc1 went

25.0

Added 2
  • Support for PEP 738 Android tags
  • Support for 'extras' and 'dependency_groups' markers
Changed 1
  • Upgrade to ruff 0.9.1

From packaging

What's Changed
New Contributors

Full Changelog: https://github.com/pypa/packaging/compare/24.2...25.0

View originalPermalink
How 25.0 went

24.2

Added 3
  • Allow creating a SpecifierSet from a list of specifiers
  • Add support for PEP 730 iOS tags
  • Implement License-Expression and License-File from PEP 639
Changed 2
  • Refactor canonicalize_version
  • Patch python_full_version unconditionally
Fixed 4
  • Fix typo in Version __str__
  • Fix doc for canonicalize_version and a typo in a docstring
  • Fix uninformative error message
  • Fix prerelease detection for > and <

From packaging

What's Changed
New Contributors

Full Changelog: https://github.com/pypa/packaging/compare/24.1...24.2

View originalPermalink
How 24.2 went

24.1

Added 2
  • Add support for Python 3.13
  • Document markers.default_environment()
Changed 2
  • Replace pyupgrade, black, isort, and flake8 with ruff
  • Modernise type annotations using FA rules from ruff
Fixed 2
  • Fix typo in _parser docstring
  • Work around platform.python_version() returning non PEP 440 compliant version for non-tagged CPython builds
Removed 1
  • Drop support for Python 3.7

From packaging

What's Changed
New Contributors

Full Changelog: https://github.com/pypa/packaging/compare/24.0...24.1

View originalPermalink
How 24.1 went
View all

Discussion

If you publish packaging, you can claim this product by proving you administer its repository.