packaging
packaging copied to clipboard
utils.canonicalize_version produces an abnormal version
In https://github.com/pypa/setuptools/issues/4302, we learned that using packaging.utils.canonicalize_version
to canonicalize a version produces an aberrant version.
@ pip-run packaging -- -c 'import packaging.utils; print(packaging.utils.canonicalize_version("69.3.0"))'
69.3
Instead of matching the convention of wheels, which will produce a wheel with a version of "69.3.0", canonicalize_version
strips the trailing zero and produces 69.3
.
Moreover, semver indicates that the version number should include a trailing zero, so it's not possible to honor both semver and the canonicalized_version.
In https://github.com/pypa/setuptools/issues/3593#issuecomment-2052518260, @pfmoore says that wheels and sdists should use the same format.
What's the correct format?
Also, why does a function called canonicalize_version
produce both canonical and non-canonical versions depending on a flag?
https://github.com/pypa/packaging/blob/32deafe8668a2130a3366b98154914d188f3718e/src/packaging/utils.py#L81-L83
I see that wheel implements its own safer_version function.
If packaging.utils.canonicalize_version
isn't the right implementation for a PEP 625 canonicalized version, what is?
In https://github.com/pypa/setuptools/issues/3593#issuecomment-2053639467, I confirmed that the spec actually considers 1.0
to be a canonical version. Therefore, the fact that canonicalize_version
transforms it is operating against the spec.
If packaging.utils.canonicalize_version isn't the right implementation for a PEP 625 canonicalized version, what is?
canonicalize_version(..., strip_trailing_zeros=False)
does.
It might be worthwhile to make that the default on this helper function.
This was missing from the API doc, I made a PR #801.
I feel like there should be two functions - one for users to use when normalizing a version and another to use when comparing two versions, so it's clear that there are two purposes here and can give the user clear guidance as to which form to use for a given circumstance. It's an oxymoron for a version to have multiple canonical forms.
For comparison I think Version
should be the preferred API.
It might be worthwhile to make that the default on this helper function.
How would you want to handle the transition on this? The parameter is 2.5 years old, so you know there are people out there using this as-is. We could remove the default for a release or two and re-introduce it flipped.
Or we can document it and not worry about it.
It's an oxymoron for a version to have multiple canonical forms.
Not necessarily. If you think there's One True Representation For All Cases, then I would agree. But versions get used in so many cases for so many reasons, I think the canonical version for comparison and canonical version for display can be different. I can see how that would then make sense to have two functions, but we also already have the one function w/ a toggle, so I'm not if it's worth the hassle of adding two more functions for this.