{"action":"opened","issue":{"url":"https://api.github.com/repos/pypa/pip/issues/2744","labels_url":"https://api.github.com/repos/pypa/pip/issues/2744/labels{/name}","comments_url":"https://api.github.com/repos/pypa/pip/issues/2744/comments","events_url":"https://api.github.com/repos/pypa/pip/issues/2744/events","html_url":"https://github.com/pypa/pip/issues/2744","id":72665077,"number":2744,"title":"Multiple requirements don't work as advertised","user":{"login":"Bouke","id":235882,"avatar_url":"https://avatars.githubusercontent.com/u/235882?v=3","gravatar_id":"","url":"https://api.github.com/users/Bouke","html_url":"https://github.com/Bouke","followers_url":"https://api.github.com/users/Bouke/followers","following_url":"https://api.github.com/users/Bouke/following{/other_user}","gists_url":"https://api.github.com/users/Bouke/gists{/gist_id}","starred_url":"https://api.github.com/users/Bouke/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/Bouke/subscriptions","organizations_url":"https://api.github.com/users/Bouke/orgs","repos_url":"https://api.github.com/users/Bouke/repos","events_url":"https://api.github.com/users/Bouke/events{/privacy}","received_events_url":"https://api.github.com/users/Bouke/received_events","type":"User","site_admin":false},"labels":[],"state":"open","locked":false,"assignee":null,"milestone":null,"comments":0,"created_at":"2015-05-02T16:16:08Z","updated_at":"2015-05-02T16:16:08Z","closed_at":null,"body":"Quoted from [my question][10] on StackOverflow:\r\n> Currently the Django Project supports 1.4, 1.7 and 1.8. In my `setup.py` I want to reflect these versions as being supported.\r\n> \r\n>     install_requires=['Django>=1.4.2,<1.8.99,!=1.5,!=1.6']\r\n> \r\n> However this still allows 1.5.x and 1.6.x releases. How can I exclude a complete range?\r\n> \r\n> [Setuptools lists][1] the following valid requirements as an example:\r\n> \r\n>     PickyThing<1.6,>1.9,!=1.9.6,<2.0a0,==2.4c1\r\n> \r\n> However this doesn't work with pip (it should at least match 1.4.x / 1.5.x):\r\n> \r\n> > No matching distribution found for PickyThing!=1.9.6,<1.6,<2.0a0,==2.4c1,>1.9\r\n> \r\n> **Update with example**  \r\n> For example; I only want to include [currently supported versions of Django][2]. This would be 1.4.x, 1.7.x and 1.8.x. So I would write;\r\n> \r\n>     #setup.py\r\n>     install_requires=['Django>=1.4.2,<1.4.99,>=1.7,<1.8.99']\r\n> \r\n> However if I run `pip install -e .` on this project, it fails with;\r\n> \r\n>     Collecting Django<1.4.99,<1.8.99,>=1.4.2,>=1.7 (from ...)\r\n>     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)\r\n>     No matching distribution found for Django<1.4.99,<1.8.99,>=1.4.2,>=1.7 (from ...)\r\n> \r\n> It is obvious that a 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) does suggest that something along these lines should be possible. However, this is non-obvious to me.\r\n> \r\n\r\nQuoted from [this answer by skyline75489][11] on StackOverflow:\r\n\r\n> I've read some related code of `pkg_resources`. I think the document [here](https://pythonhosted.org/setuptools/pkg_resources.html#requirement-objects) is not accurate. Not only `pip` fails to find the right package version, `python setup.py install`, which actually uses `setuptools`, also fails. \r\n> \r\n> Some of the related code:\r\n> \r\n> *pip/_vendor/packaging/specifiers.py*\r\n> \r\n>     # If we have any specifiers, then we want to wrap our iterable in the\r\n>     # filter method for each one, this will act as a logical AND amongst\r\n>     # each specifier.\r\n>     if self._specs:\r\n>         for spec in self._specs:\r\n>             iterable = spec.filter(iterable, prereleases=prereleases)\r\n>         return iterable\r\n>     \r\n> You can see that in the comment, the author emphasized that this will cause an `AND` amongst each specifier, not `OR`. So if you do this:\r\n> \r\n>     PickyThing<1.6,>1.9,!=1.9.6,<2.0a0,==2.4c1\r\n> \r\n> You will get nothing! \r\n> \r\n> I tried with this code below:\r\n> \r\n>     import pkg_resources\r\n>     \r\n>     a = ['1.4', '1.8', '1.9.2']\r\n>     d = pkg_resources.Requirement.parse('PickyThing<1.6,>1.9,!=1.9.6')\r\n>     r = d.specifier.filter(a)\r\n> \r\n>     print(list(r)) # Nothing, just an empty list []\r\n> \r\n> You may want to file a bug to [pip](https://github.com/pypa/pip) so they can fix it.\r\n> \r\n\r\n\r\n[1]: https://pythonhosted.org/setuptools/pkg_resources.html#requirements-parsing\r\n[2]: https://www.djangoproject.com/download/\r\n[10]: http://stackoverflow.com/q/29499542/58107\r\n[11]: http://stackoverflow.com/a/30003340/58107"}}