Exclude specific dependency version ranges in setuptools / pip

The Django project currently supports 1.4, 1.7, and 1.8. In my setup.py I want to reflect these versions as supported.

 install_requires=['Django>=1.4.2,<1.8.99,!=1.5,!=1.6'] 

However, this still allows the release of versions 1.5.x and 1.6.x. How can I exclude the full range?

Setuptools lists the following valid requirements as an example:

 PickyThing<1.6,>1.9,!=1.9.6,<2.0a0,==2.4c1 

However, this does not work with pip (it should at least match 1.4.x / 1.5.x):

No suitable distribution found for PickyThing! = 1.9.6, <1.6, <2.0a0, == 2.4c1,> 1.9

Update with an example
For instance; I want to enable the currently supported versions of Django . It will be 1.4.x, 1.7.x and 1.8.x. Therefore, I would write:

 #setup.py install_requires=['Django>=1.4.2,<1.4.99,>=1.7,<1.8.99'] 

However, if I ran pip install -e . in this project, it fails with:

 Collecting Django<1.4.99,<1.8.99,>=1.4.2,>=1.7 (from ...) Could not find a version that satisfies the requirement Django<1.4.99,<1.8.99,>=1.4.2,>=1.7 (from django-two-factor-auth==1.2.0) (from versions: 1.1.3, 1.1.4, 1.2, 1.2.1, 1.2.2, 1.2.3, 1.2.4, 1.2.5, 1.2.6, 1.2.7, 1.3, 1.3.1, 1.3.2, 1.3.3, 1.3.4, 1.3.5, 1.3.6, 1.3.7, 1.4, 1.4.1, 1.4.2, 1.4.3, 1.4.4, 1.4.5, 1.4.6, 1.4.7, 1.4.8, 1.4.9, 1.4.10, 1.4.11, 1.4.12, 1.4.13, 1.4.14, 1.4.15, 1.4.16, 1.4.17, 1.4.18, 1.4.19, 1.4.20, 1.5, 1.5.1, 1.5.2, 1.5.3, 1.5.4, 1.5.5, 1.5.6, 1.5.7, 1.5.8, 1.5.9, 1.5.10, 1.5.11, 1.5.12, 1.6, 1.6.1, 1.6.2, 1.6.3, 1.6.4, 1.6.5, 1.6.6, 1.6.7, 1.6.8, 1.6.9, 1.6.10, 1.6.11, 1.7, 1.7.1, 1.7.2, 1.7.3, 1.7.4, 1.7.5, 1.7.6, 1.7.7, 1.7.8, 1.8a1, 1.8b1, 1.8b2, 1.8rc1, 1.8, 1.8.1) No matching distribution found for Django<1.4.99,<1.8.99,>=1.4.2,>=1.7 (from ...) 

Obviously, version number 1.4.20 cannot satisfy >=1.7 , and 1.8.1 cannot satisfy <1.4.99 . However, the documentation from Setuptools (see above) suggests that something in this direction should be possible. However, this is not obvious to me.

+6
source share
2 answers

I read some pkg_resources code. I think the document here is not accurate. Not only pip fails to find the right version of the package, python setup.py install , which actually uses setuptools , also fails.

Some of the related code:

pip / _vendor / packaging / specifiers.py

 # If we have any specifiers, then we want to wrap our iterable in the # filter method for each one, this will act as a logical AND amongst # each specifier. if self._specs: for spec in self._specs: iterable = spec.filter(iterable, prereleases=prereleases) return iterable 

You can see that in the commentary, the author emphasized that this would result in AND among each qualifier, not OR . Therefore, if you do this:

 PickyThing<1.6,>1.9,!=1.9.6,<2.0a0,==2.4c1 

You will not get anything!

I tried using this code below:

 import pkg_resources a = ['1.4', '1.8', '1.9.2'] d = pkg_resources.Requirement.parse('PickyThing<1.6,>1.9,!=1.9.6') r = d.specifier.filter(a) print(list(r)) # Nothing, just an empty list [] 

You might want to write a pip error so that they can fix it.

+1
source

You can use Django>=1.4.2,<1.9,!=1.5.*,!=1.6.*

This is defined internally by PEP440 .

You can test this behavior with the packaging module, which is sold in the latest versions of setuptools and pip.

 In [1]: from packaging import specifiers In [2]: sp=specifiers.SpecifierSet(">=1.4.2,<1.9,!=1.5.*,!=1.6.*") In [3]: sp.contains("1.4.2") Out[3]: True In [4]: sp.contains("1.6.4") Out[4]: False In [5]: sp.contains("1.8.2") Out[5]: True 
+2
source

Source: https://habr.com/ru/post/984812/


All Articles