according to PEP-440:
For purposes of prefix matching, the pre-release segment is considered to have an implied preceding
., so given the version
1.1a1, the following clauses would match or not as shown:
== 1.1.* # Same prefix, so 1.1a1 matches clause
However, when I test this example with the relevant tools from
packaging, the outcome is different than the above:
$ pip install --upgrade packaging
Successfully installed packaging-23.1
Python 3.9.9 (main, Dec 22 2021, 01:10:49)
>>> from packaging.specifiers import SpecifierSet
>>> from packaging.version import Version
>>> s = SpecifierSet('== 1.1.*')
>>> v = Version('1.1a1')
Is PEP-440 or
packaging right? Or, maybe, what am I missing?
You’re not supplying the
prereleases argument, so the specifier won’t match prereleases by default.
Thanks for the reply, Paul!
I felt I must be missing something…
Am I correct, that the
prereleases=True behavior is used – in practice, by such tools as
setuptools – when there is no available non-prerelease version or the user explicitly demands on using prereleases?
I don’t recall the details of what pip does offhand (feel free to go and check the code yourself if you want ) but how tools should handle prereleases is covered in PEP 440.
Hm… But then it seems that this fragment of PEP 440 is not correct:
== 3.1.*: any version that starts with 3.1. Equivalent to the ~=3.1.0 compatible release clause.’
(PEP 440 – Version Identification and Dependency Specification | peps.python.org)
>>> s1 = SpecifierSet('== 3.1.*')
>>> s2 = SpecifierSet('~= 3.1.0')
>>> s1.contains('3.1a1', prereleases=True)
>>> s2.contains('3.1a1', prereleases=True)
(or am I missing something again? )
I think that example is not quite right. PEP 440 – Version Identification and Dependency Specification | peps.python.org says:
For a given release identifier
V.N, the compatible release clause is approximately equivalent to the pair of comparison clauses:
>= V.N, == V.*
So the equivalent set would actually be:
>>> s3 = SpecifierSet('>=3.1.0, ==3.1.*')
>>> s3.contains('3.1a1', prereleases=True)
>>> Version("3.1a1") < Version("3.1.0")
I think that example is not quite right.
I agree it is not, and please note that this example is from the PEP itself.
What I am trying to say is that the fragment of the PEP quoted by me (i.e., the following bullet point in the Examples section:
== 3.1.*: any version that starts with 3.1. Equivalent to the
~=3.1.0 compatible release clause.) – seems to contradict the specification in earlier parts of the document.
Yes, I’m saying that I think the example in the PEP is wrong, we’re saying the same thing.