Environment
Description
From my testing, it appears that pip is not treating equivalent versions as truly equivalent as specified in PEP440 when installing requirements.
Specifically, the PEP states that a version string like ==2.8.0
is considered equivalent to ==2.8
, as the later should have implicit padding added on the end. Pip seems to fail with a Double requirement given
error message. It appears that it is not smart enough to detect the equivalency between the two explicit version specifiers.
Would it be possible to check for this scenario by attempting to compare the two version specifiers for equivalency using the Version
object somehow?
Expected behavior
When installing two different requirements files that both specify an equivalent version of a package, I would expect that pip sees that the versions are equivalent and installs the correct version.
How to Reproduce
One liner reproduction: pip install cryptography==2.8 cryptography==2.8.0
ERROR: Double requirement given: cryptography==2.8 (already in cryptography==2.8.0, name='cryptography')
Real world repro:
requirements.txt
file containing cryptography==2.8.0
requirements_dev.txt
file containing cryptography==2.8
pip install -r requirements.txt -r requirements_dev.txt
ERROR: Double requirement given: cryptography==2.8 (from -r Divvy/requirements_dev.txt (line 24)) (already in cryptography==2.8.0 (from -r Divvy/requirements.txt (line 63)), name='cryptography')
Output
pip install cryptography==2.8.0 cryptography==2.8
ERROR: Double requirement given: cryptography==2.8 (already in cryptography==2.8.0, name='cryptography')
pip install -r requirements.txt -r requirements_dev.txt
ERROR: Double requirement given: cryptography==2.8 (from -r requirements_dev.txt (line 24)) (already in cryptography==2.8.0 (from -r requirements.txt (line 63)), name='cryptography')
This should be fixed when the new resolver is released. It's unlikely to be worth fixing in the current (legacy) resolver, which makes no attempt to merge or otherwise unify requirements (which is what I suspect is the cause of this issue).
I consider this a bug in packaging. The legacy resolver doesn鈥檛 need to do anything if we fix that:
>>> from packaging.specifiers import SpecifierSet
>>> SpecifierSet("==2.8.0") == SpecifierSet("==2.8.0")
True
>>> SpecifierSet("==2.8.0") == SpecifierSet("==2.8")
False
I filed pypa/packaging#282 for this.
Good point, I'd missed that specifier equality was handled by the packaging library.
The __eq__
issue has been fixed in upstream. We will be able to close this when we upgrade to the next (not yet released) packaging version.
@uranusjr is faster than me. 馃檭
Most helpful comment
I consider this a bug in packaging. The legacy resolver doesn鈥檛 need to do anything if we fix that: