Skip to content

26.3

Latest

Choose a tag to compare

@henryiii henryiii released this 04 Aug 21:42
Immutable release. Only release title and notes can be modified.
26.3

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: 26.2...26.3