Announcing packaging 26.3
I’m pleased to announce that packaging 26.3 has been released by the release manager @henryiii! As promised last time, Python 3.8 support is gone.
New features:
packaging.ranges- the range-based implementation behindis_unsatisfiableis now public asVersionRangeSpecifierSet.is_subset(),.is_superset(), and.is_disjoint()- compare the versions two specifier sets accept- PEP 808:
Metadata-Version: 2.6 packaging.tags.pure_python_tags()- the pure-Python tags for a Python version, without touching the running platformparse_tag(limit=...)- cap how many tags a compressed tag set expands toPylock.select(prefer_sdist_predicate=...)- prefer sdists over wheels for selected packages
Performance:
Specifier filtering now uses the range implementation too, up to 15x faster: 10,000 versions through ~=3.2 went from 31 ms to 2 ms on my machine. New caches speed up marker evaluation and tag generation.
Behavior changes:
- On Linux,
sys_tags()prefers nativelinux_*platform tags overmanylinux/musllinuxtags
Bug fixes:
There are also ~40 bug fixes; See all the changes at https://packaging.pypa.io/en/stable/changelog.html.
Range algebra:
The new VersionRange object is designed to support advanced resolver algorithms (e.g. pubgrub) that allows you to do intersection, union, compliment, and difference, while following version specifier specification (originally PEP 440), but there are some caveats.
Here are some examples of doing range algebra and converting back to a SpecifierSet (note: that you often can’t convert back as there is no SpecifierSet represents the range, so .to_specifier_set() returns None), you can also do .contains and .filter directly on the VersionRange object
>>> from packaging.specifiers import SpecifierSet
>>> a = SpecifierSet(">=1.0,<2.0").to_range()
>>> (a & SpecifierSet(">=1.5,<3.0").to_range()).to_specifier_set()
<SpecifierSet('<2.0,>=1.5')>
>>> (a - SpecifierSet("==1.4.*").to_range()).to_specifier_set()
<SpecifierSet('!=1.4.*,<2.0,>=1.0')>
>>> SpecifierSet(">=1.0,>1.2,<3.0,<2.5,!=0.9").to_range().to_specifier_set()
<SpecifierSet('<2.5,>1.2')>
Thanks to everyone who contributed to this release!