Pip: `pip install` fails on equivalent versions

Created on 25 Mar 2020  路  6Comments  路  Source: pypa/pip

Environment

  • pip version: 20.0.2
  • Python version: 3.7.5
  • OS: OSX

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:

  1. Create a requirements.txt file containing cryptography==2.8.0
  2. Create a requirements_dev.txt file containing cryptography==2.8
  3. Run pip install -r requirements.txt -r requirements_dev.txt
  4. Observe error:

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')
vendored dependency

Most helpful comment

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

All 6 comments

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. 馃檭

Was this page helpful?
0 / 5 - 0 ratings