Repository: pypa/pip

Issue:
`--ignore-requires-python` has no effect
**Environment**

* pip version:
```console
$ ./venv/bin/pip --version
pip 19.0.3 from /tmp/t/venv/site-packages/pip (python 3.5)
```
* Python version:
```console
$ ./venv/bin/python --version
Python 3.5.3 (fdd60ed87e94, Apr 24 2018, 06:10:04)
[PyPy 6.0.0 with GCC 6.2.0 20160901]
```
* OS:
```console
$ uname -a
Linux asottile-VirtualBox 4.15.0-46-generic #49-Ubuntu SMP Wed Feb 6 09:33:07 UTC 2019 x86_64 x86_64 x86_64 GNU/Linux
$ lsb_release -a
No LSB modules are available.
Distributor ID:	Ubuntu
Description:	Ubuntu 18.04.2 LTS
Release:	18.04
Codename:	bionic
```

<!-- Feel free to add more information about your environment here -->

**Description** / **Expected behaviour** / **How to Reproduce**

I expect this to succeed:

```console
$ ./venv/bin/pip install --ignore-requires-python black -v
```

black requires `python>=3.6`, though I am running pypy3.5 and explicitly asking pip to `--ignore-requires-python`


**Output**

```console
$ ./venv/bin/pip install --ignore-requires-python black -v
Created temporary directory: /tmp/pip-ephem-wheel-cache-7_gvlskb
Created temporary directory: /tmp/pip-req-tracker-t4ef_ow9
Created requirements tracker '/tmp/pip-req-tracker-t4ef_ow9'
Created temporary directory: /tmp/pip-install-3x0i9w7v
Collecting black
  1 location(s) to search for versions of black:
  * https://pypi.org/simple/black/
  Getting page https://pypi.org/simple/black/
  Looking up "https://pypi.org/simple/black/" in the cache
  Request header has "max_age" as 0, cache bypassed
  Starting new HTTPS connection (1): pypi.org:443
  https://pypi.org:443 "GET /simple/black/ HTTP/1.1" 304 0
  Analyzing links from page https://pypi.org/simple/black/
    The package https://files.pythonhosted.org/packages/22/5a/ebe5881cbf07435ea1ad76119ee142f42fb7a333d562c202db015b959ae7/black-18.3a0-py3-none-any.whl#sha256=7183263650ba3071034e90b40a1ea74abccbd32cf525cef6d7914479dbe7f2fb (from https://pypi.org/simple/black/) (requires-python:>=3.6) is incompatible with the python version in use. Acceptable python versions are: >=3.6
    The package https://files.pythonhosted.org/packages/83/a2/fae3ddb516a52a0f37e6e2ef3bd789b6d093d2c7015a41a41bff30f39897/black-18.3a0.tar.gz#sha256=0461c7a52b5beb378936bf642753dec7a45305c96c6129d540b9c53227121a5a (from https://pypi.org/simple/black/) (requires-python:>=3.6) is incompatible with the python version in use. Acceptable python versions are: >=3.6
    The package https://files.pythonhosted.org/packages/61/b4/3a39dcf59342f53680c59a5e44c0b172ea5d6470a5aaba8ae3cdbfccc1e7/black-18.3a1-py3-none-any.whl#sha256=04edc87b51b34a7aa093f39bf207e2ebc3612b26f2c79fdf8ff13b2d60622c9a (from https://pypi.org/simple/black/) (requires-python:>=3.6) is incompatible with the python version in use. Acceptable python versions are: >=3.6

[ many repeated lines removed ]


    The package https://files.pythonhosted.org/packages/e8/5f/0f79fcd943ba465cbd4bf303c9794970c13a95e5456630de9f72e7f37ad4/black-18.9b0.tar.gz#sha256=e030a9a28f542debc08acceb273f228ac422798e5215ba2a791a6ddeaaca22a5 (from https://pypi.org/simple/black/) (requires-python:>=3.6) is incompatible with the python version in use. Acceptable python versions are: >=3.6
    Skipping link https://files.pythonhosted.org/packages/30/62/cf549544a5fe990bbaeca21e9c419501b2de7a701ab0afb377bc81676600/black-19.3b0-py36-none-any.whl#sha256=09a9dcb7c46ed496a9850b76e4e825d6049ecd38b611f1224857a79bd985a8cf (from https://pypi.org/simple/black/) (requires-python:>=3.6); it is not compatible with this Python
    The package https://files.pythonhosted.org/packages/89/07/aebb10fb8f2ffbac672dfbebffa724643bc84cf012a57737a622d1dabddb/black-19.3b0.tar.gz#sha256=68950ffd4d9169716bcb8719a56c07a2f4485354fec061cdd5910aa07369731c (from https://pypi.org/simple/black/) (requires-python:>=3.6) is incompatible with the python version in use. Acceptable python versions are: >=3.6
  Could not find a version that satisfies the requirement black (from versions: )
Cleaning up...
Removed build tracker '/tmp/pip-req-tracker-t4ef_ow9'
No matching distribution found for black
Exception information:
Traceback (most recent call last):
  File "/tmp/t/venv/site-packages/pip/_internal/cli/base_command.py", line 179, in main
    status = self.run(options, args)
  File "/tmp/t/venv/site-packages/pip/_internal/commands/install.py", line 315, in run
    resolver.resolve(requirement_set)
  File "/tmp/t/venv/site-packages/pip/_internal/resolve.py", line 131, in resolve
    self._resolve_one(requirement_set, req)
  File "/tmp/t/venv/site-packages/pip/_internal/resolve.py", line 294, in _resolve_one
    abstract_dist = self._get_abstract_dist_for(req_to_install)
  File "/tmp/t/venv/site-packages/pip/_internal/resolve.py", line 242, in _get_abstract_dist_for
    self.require_hashes
  File "/tmp/t/venv/site-packages/pip/_internal/operations/prepare.py", line 269, in prepare_linked_requirement
    req.populate_link(finder, upgrade_allowed, require_hashes)
  File "/tmp/t/venv/site-packages/pip/_internal/req/req_install.py", line 196, in populate_link
    self.link = finder.find_requirement(self, upgrade)
  File "/tmp/t/venv/site-packages/pip/_internal/index.py", line 688, in find_requirement
    'No matching distribution found for %s' % req
pip._internal.exceptions.DistributionNotFound: No matching distribution found for black

```

`--ignore-requires-python` has no effect
**Environment**

* pip version:
```console
$ ./venv/bin/pip --version
pip 19.0.3 from /tmp/t/venv/site-packages/pip (python 3.5)
```
* Python version:
```console
$ ./venv/bin/python --version
Python 3.5.3 (fdd60ed87e94, Apr 24 2018, 06:10:04)
[PyPy 6.0.0 with GCC 6.2.0 20160901]
```
* OS:
```console
$ uname -a
Linux asottile-VirtualBox 4.15.0-46-generic #49-Ubuntu SMP Wed Feb 6 09:33:07 UTC 2019 x86_64 x86_64 x86_64 GNU/Linux
$ lsb_release -a
No LSB modules are available.
Distributor ID:	Ubuntu
Description:	Ubuntu 18.04.2 LTS
Release:	18.04
Codename:	bionic
```

<!-- Feel free to add more information about your environment here -->

**Description** / **Expected behaviour** / **How to Reproduce**

I expect this to succeed:

```console
$ ./venv/bin/pip install --ignore-requires-python black -v
```

black requires `python>=3.6`, though I am running pypy3.5 and explicitly asking pip to `--ignore-requires-python`


**Output**

```console
$ ./venv/bin/pip install --ignore-requires-python black -v
Created temporary directory: /tmp/pip-ephem-wheel-cache-7_gvlskb
Created temporary directory: /tmp/pip-req-tracker-t4ef_ow9
Created requirements tracker '/tmp/pip-req-tracker-t4ef_ow9'
Created temporary directory: /tmp/pip-install-3x0i9w7v
Collecting black
  1 location(s) to search for versions of black:
  * https://pypi.org/simple/black/
  Getting page https://pypi.org/simple/black/
  Looking up "https://pypi.org/simple/black/" in the cache
  Request header has "max_age" as 0, cache bypassed
  Starting new HTTPS connection (1): pypi.org:443
  https://pypi.org:443 "GET /simple/black/ HTTP/1.1" 304 0
  Analyzing links from page https://pypi.org/simple/black/
    The package https://files.pythonhosted.org/packages/22/5a/ebe5881cbf07435ea1ad76119ee142f42fb7a333d562c202db015b959ae7/black-18.3a0-py3-none-any.whl#sha256=7183263650ba3071034e90b40a1ea74abccbd32cf525cef6d7914479dbe7f2fb (from https://pypi.org/simple/black/) (requires-python:>=3.6) is incompatible with the python version in use. Acceptable python versions are: >=3.6
    The package https://files.pythonhosted.org/packages/83/a2/fae3ddb516a52a0f37e6e2ef3bd789b6d093d2c7015a41a41bff30f39897/black-18.3a0.tar.gz#sha256=0461c7a52b5beb378936bf642753dec7a45305c96c6129d540b9c53227121a5a (from https://pypi.org/simple/black/) (requires-python:>=3.6) is incompatible with the python version in use. Acceptable python versions are: >=3.6
    The package https://files.pythonhosted.org/packages/61/b4/3a39dcf59342f53680c59a5e44c0b172ea5d6470a5aaba8ae3cdbfccc1e7/black-18.3a1-py3-none-any.whl#sha256=04edc87b51b34a7aa093f39bf207e2ebc3612b26f2c79fdf8ff13b2d60622c9a (from https://pypi.org/simple/black/) (requires-python:>=3.6) is incompatible with the python version in use. Acceptable python versions are: >=3.6

[ many repeated lines removed ]


    The package https://files.pythonhosted.org/packages/e8/5f/0f79fcd943ba465cbd4bf303c9794970c13a95e5456630de9f72e7f37ad4/black-18.9b0.tar.gz#sha256=e030a9a28f542debc08acceb273f228ac422798e5215ba2a791a6ddeaaca22a5 (from https://pypi.org/simple/black/) (requires-python:>=3.6) is incompatible with the python version in use. Acceptable python versions are: >=3.6
    Skipping link https://files.pythonhosted.org/packages/30/62/cf549544a5fe990bbaeca21e9c419501b2de7a701ab0afb377bc81676600/black-19.3b0-py36-none-any.whl#sha256=09a9dcb7c46ed496a9850b76e4e825d6049ecd38b611f1224857a79bd985a8cf (from https://pypi.org/simple/black/) (requires-python:>=3.6); it is not compatible with this Python
    The package https://files.pythonhosted.org/packages/89/07/aebb10fb8f2ffbac672dfbebffa724643bc84cf012a57737a622d1dabddb/black-19.3b0.tar.gz#sha256=68950ffd4d9169716bcb8719a56c07a2f4485354fec061cdd5910aa07369731c (from https://pypi.org/simple/black/) (requires-python:>=3.6) is incompatible with the python version in use. Acceptable python versions are: >=3.6
  Could not find a version that satisfies the requirement black (from versions: )
Cleaning up...
Removed build tracker '/tmp/pip-req-tracker-t4ef_ow9'
No matching distribution found for black
Exception information:
Traceback (most recent call last):
  File "/tmp/t/venv/site-packages/pip/_internal/cli/base_command.py", line 179, in main
    status = self.run(options, args)
  File "/tmp/t/venv/site-packages/pip/_internal/commands/install.py", line 315, in run
    resolver.resolve(requirement_set)
  File "/tmp/t/venv/site-packages/pip/_internal/resolve.py", line 131, in resolve
    self._resolve_one(requirement_set, req)
  File "/tmp/t/venv/site-packages/pip/_internal/resolve.py", line 294, in _resolve_one
    abstract_dist = self._get_abstract_dist_for(req_to_install)
  File "/tmp/t/venv/site-packages/pip/_internal/resolve.py", line 242, in _get_abstract_dist_for
    self.require_hashes
  File "/tmp/t/venv/site-packages/pip/_internal/operations/prepare.py", line 269, in prepare_linked_requirement
    req.populate_link(finder, upgrade_allowed, require_hashes)
  File "/tmp/t/venv/site-packages/pip/_internal/req/req_install.py", line 196, in populate_link
    self.link = finder.find_requirement(self, upgrade)
  File "/tmp/t/venv/site-packages/pip/_internal/index.py", line 688, in find_requirement
    'No matching distribution found for %s' % req
pip._internal.exceptions.DistributionNotFound: No matching distribution found for black

```



Discussion:
I'm ok with this being closed as "works as intended" though the option should probably be deprecated and/or removed if it has no effect
Are you able to get the install to work by passing something for `--python-version`? My understanding is that `--ignore-requires-python` has a slightly different purpose (introduced in response to issue https://github.com/pypa/pip/pull/3846).
nope:

```
$ pip install --ignore-requires-python --python-version 36 black
ERROR: When restricting platform and interpreter constraints using --python-version, --platform, --abi, or --implementation, either --no-deps must be set, or --only-binary=:all: must be set and --no-binary must not be set (or must be set to :none:).
```
I even reverted back to when it was introduced -- it didn't work then either:

```console
$ pip install git+https://github.com/pypa/pip@8df742e56db99c48f7ad85085501fe23456b419c
Collecting git+https://github.com/pypa/pip@8df742e56db99c48f7ad85085501fe23456b419c
  Cloning https://github.com/pypa/pip (to revision 8df742e56db99c48f7ad85085501fe23456b419c) to ./pip-req-build-mdzrw938
Building wheels for collected packages: pip
  Building wheel for pip (setup.py) ... done
  Stored in directory: /tmp/pip-ephem-wheel-cache-3htnnj3r/wheels/f4/06/5d/1652f21a0ecf6bed88b63647ec859e0384f0f07fcae05c57f3
Successfully built pip
Installing collected packages: pip
  Found existing installation: pip 19.0.3
    Uninstalling pip-19.0.3:
      Successfully uninstalled pip-19.0.3
Successfully installed pip-8.2.0.dev0
$ pip install --ignore-requires-python black
Collecting black
  Cache entry deserialization failed, entry ignored
  Could not find a version that satisfies the requirement black (from versions: )
No matching distribution found for black
You are using pip version 8.2.0.dev0, however version 19.0.3 is available.
You should consider upgrading via the 'pip install --upgrade pip' command.
```
The ignore-requires option wasn’t meant to be used for the purpose you’re trying to use it. I was wondering if another option could help though.
my reading of #3846 especially these comments seems to indicate it _is_ intended for this:

https://github.com/pypa/pip/pull/3846#issuecomment-232652134

https://github.com/pypa/pip/pull/3846#issuecomment-233173644

https://github.com/pypa/pip/pull/3846/commits/2df0ea9a269067786d35c748dd6f2c379b495323


The `--python-version` / abi / etc. parameters did not even exist at the time, my reading is that this argument was intended as an escape hatch for pip refusing to install incompatible `requires_python` (what else could it be for?)
> ERROR: When restricting platform and interpreter constraints using --python-version, --platform, --abi, or --implementation, either --no-deps must be set, or --only-binary=:all: must be set and --no-binary must not be set (or must be set to :none:).

When you're trying `--python-version`, can you also try adding `--only-binary=:all:` like the error message says?


> (what else could it be for?)

When installing a package, Python performs a check of the `Requires-Python` metadata prior to allowing it: https://github.com/pypa/pip/blob/ac9010e87c5a672f335feb796dbe1270019a5f63/src/pip/_internal/resolve.py#L298-L304

The `--ignore-requires-python` option is an escape hatch to suppress that check.

In your case, it's rejecting the package before even getting to that point (before it's even downloaded), so the command option isn't coming into play. The `--python-version` and related options are for controlling whether a package is eligible for download.

Okay, it looks like there is a second application of `check_requires_python()` that isn't taking `ignore_requires_python` into account: https://github.com/pypa/pip/blob/ac9010e87c5a672f335feb796dbe1270019a5f63/src/pip/_internal/index.py#L852-L863 

PS - the most important part of the log messages in your OP are getting hidden by default because GitHub doesn't wrap the long lines when using the fixed-width formatting:

> ... (requires-python:>=3.6) is incompatible with the python version in use. Acceptable python versions are: >=3.6

I didn't see that until now.

(Note that the wheels will still get rejected without using —python-version.)
😆 I'm glad you finally took the time to look instead of assuming I'm wrong

I've been following closely the `--python-version` / platform / abi / etc. options, they are a non-solution until the `--target` requirement is lifted: https://github.com/pypa/pip/issues/5453#issuecomment-416012640
Out of curiosity, what does it mean to pass `--ignore-requires-python` without `--python-version`? That the Python… does not have a version? That seems a bit pointless in this case. I would expect these two to be mutually exclusive: if `--python-version` is passed, the value is used to check against `Requires-Python` (both in metadata and on index), and if `--ignore-requires-python` is passed, checks against `Requires-Python` are disabled altogether (so all links are collected on the index).
FWIW, `--ignore-requires-python` was added (and still has the expected effect) for escape hatching this kind of case:
```
$ docker run -ti --rm python:3.4 bash
root@b30693b8f33e:/# pip install https://files.pythonhosted.org/packages/54/85/0bef63668fb170888c1a2970ec897d4528d6072f32dee27653381a332642/Django-2.2-py3-none-any.whl
DEPRECATION: Python 3.4 support has been deprecated. pip 19.1 will be the last one supporting it. Please upgrade your Python as Python 3.4 won't be maintained after March 2019 (cf PEP 429).
Collecting Django==2.2 from https://files.pythonhosted.org/packages/54/85/0bef63668fb170888c1a2970ec897d4528d6072f32dee27653381a332642/Django-2.2-py3-none-any.whl
  Downloading https://files.pythonhosted.org/packages/54/85/0bef63668fb170888c1a2970ec897d4528d6072f32dee27653381a332642/Django-2.2-py3-none-any.whl (7.4MB)
    100% |████████████████████████████████| 7.5MB 3.6MB/s 
Django requires Python '>=3.5' but the running Python is 3.4.10
You are using pip version 19.0.3, however version 19.1 is available.
You should consider upgrading via the 'pip install --upgrade pip' command.
root@b30693b8f33e:/# echo $?
1
root@b30693b8f33e:/# pip install https://files.pythonhosted.org/packages/54/85/0bef63668fb170888c1a2970ec897d4528d6072f32dee27653381a332642/Django-2.2-py3-none-any.whl --ignore-requires-python
DEPRECATION: Python 3.4 support has been deprecated. pip 19.1 will be the last one supporting it. Please upgrade your Python as Python 3.4 won't be maintained after March 2019 (cf PEP 429).
Collecting Django==2.2 from https://files.pythonhosted.org/packages/54/85/0bef63668fb170888c1a2970ec897d4528d6072f32dee27653381a332642/Django-2.2-py3-none-any.whl
  Using cached https://files.pythonhosted.org/packages/54/85/0bef63668fb170888c1a2970ec897d4528d6072f32dee27653381a332642/Django-2.2-py3-none-any.whl
Django requires Python '>=3.5' but the running Python is 3.4.10
Collecting sqlparse (from Django==2.2)
  Downloading https://files.pythonhosted.org/packages/ef/53/900f7d2a54557c6a37886585a91336520e5539e3ae2423ff1102daf4f3a7/sqlparse-0.3.0-py2.py3-none-any.whl
Collecting pytz (from Django==2.2)
  Downloading https://files.pythonhosted.org/packages/3d/73/fe30c2daaaa0713420d0382b16fbb761409f532c56bdcc514bf7b6262bb6/pytz-2019.1-py2.py3-none-any.whl (510kB)
    100% |████████████████████████████████| 512kB 17.0MB/s 
Installing collected packages: sqlparse, pytz, Django
Successfully installed Django-2.2 pytz-2019.1 sqlparse-0.3.0
You are using pip version 19.0.3, however version 19.1 is available.
You should consider upgrading via the 'pip install --upgrade pip' command.
root@b30693b8f33e:/# echo $?
0
```

It might still be interesting to also use it in `check_requires_python()` though.
I'm ok with this being closed as "works as intended" though the option should probably be deprecated and/or removed if it has no effect
Are you able to get the install to work by passing something for `--python-version`? My understanding is that `--ignore-requires-python` has a slightly different purpose (introduced in response to issue https://github.com/pypa/pip/pull/3846).
nope:

```
$ pip install --ignore-requires-python --python-version 36 black
ERROR: When restricting platform and interpreter constraints using --python-version, --platform, --abi, or --implementation, either --no-deps must be set, or --only-binary=:all: must be set and --no-binary must not be set (or must be set to :none:).
```
I even reverted back to when it was introduced -- it didn't work then either:

```console
$ pip install git+https://github.com/pypa/pip@8df742e56db99c48f7ad85085501fe23456b419c
Collecting git+https://github.com/pypa/pip@8df742e56db99c48f7ad85085501fe23456b419c
  Cloning https://github.com/pypa/pip (to revision 8df742e56db99c48f7ad85085501fe23456b419c) to ./pip-req-build-mdzrw938
Building wheels for collected packages: pip
  Building wheel for pip (setup.py) ... done
  Stored in directory: /tmp/pip-ephem-wheel-cache-3htnnj3r/wheels/f4/06/5d/1652f21a0ecf6bed88b63647ec859e0384f0f07fcae05c57f3
Successfully built pip
Installing collected packages: pip
  Found existing installation: pip 19.0.3
    Uninstalling pip-19.0.3:
      Successfully uninstalled pip-19.0.3
Successfully installed pip-8.2.0.dev0
$ pip install --ignore-requires-python black
Collecting black
  Cache entry deserialization failed, entry ignored
  Could not find a version that satisfies the requirement black (from versions: )
No matching distribution found for black
You are using pip version 8.2.0.dev0, however version 19.0.3 is available.
You should consider upgrading via the 'pip install --upgrade pip' command.
```
The ignore-requires option wasn’t meant to be used for the purpose you’re trying to use it. I was wondering if another option could help though.
my reading of #3846 especially these comments seems to indicate it _is_ intended for this:

https://github.com/pypa/pip/pull/3846#issuecomment-232652134

https://github.com/pypa/pip/pull/3846#issuecomment-233173644

https://github.com/pypa/pip/pull/3846/commits/2df0ea9a269067786d35c748dd6f2c379b495323


The `--python-version` / abi / etc. parameters did not even exist at the time, my reading is that this argument was intended as an escape hatch for pip refusing to install incompatible `requires_python` (what else could it be for?)
> ERROR: When restricting platform and interpreter constraints using --python-version, --platform, --abi, or --implementation, either --no-deps must be set, or --only-binary=:all: must be set and --no-binary must not be set (or must be set to :none:).

When you're trying `--python-version`, can you also try adding `--only-binary=:all:` like the error message says?


> (what else could it be for?)

When installing a package, Python performs a check of the `Requires-Python` metadata prior to allowing it: https://github.com/pypa/pip/blob/ac9010e87c5a672f335feb796dbe1270019a5f63/src/pip/_internal/resolve.py#L298-L304

The `--ignore-requires-python` option is an escape hatch to suppress that check.

In your case, it's rejecting the package before even getting to that point (before it's even downloaded), so the command option isn't coming into play. The `--python-version` and related options are for controlling whether a package is eligible for download.

Okay, it looks like there is a second application of `check_requires_python()` that isn't taking `ignore_requires_python` into account: https://github.com/pypa/pip/blob/ac9010e87c5a672f335feb796dbe1270019a5f63/src/pip/_internal/index.py#L852-L863 

PS - the most important part of the log messages in your OP are getting hidden by default because GitHub doesn't wrap the long lines when using the fixed-width formatting:

> ... (requires-python:>=3.6) is incompatible with the python version in use. Acceptable python versions are: >=3.6

I didn't see that until now.

(Note that the wheels will still get rejected without using —python-version.)
😆 I'm glad you finally took the time to look instead of assuming I'm wrong

I've been following closely the `--python-version` / platform / abi / etc. options, they are a non-solution until the `--target` requirement is lifted: https://github.com/pypa/pip/issues/5453#issuecomment-416012640
Out of curiosity, what does it mean to pass `--ignore-requires-python` without `--python-version`? That the Python… does not have a version? That seems a bit pointless in this case. I would expect these two to be mutually exclusive: if `--python-version` is passed, the value is used to check against `Requires-Python` (both in metadata and on index), and if `--ignore-requires-python` is passed, checks against `Requires-Python` are disabled altogether (so all links are collected on the index).
FWIW, `--ignore-requires-python` was added (and still has the expected effect) for escape hatching this kind of case:
```
$ docker run -ti --rm python:3.4 bash
root@b30693b8f33e:/# pip install https://files.pythonhosted.org/packages/54/85/0bef63668fb170888c1a2970ec897d4528d6072f32dee27653381a332642/Django-2.2-py3-none-any.whl
DEPRECATION: Python 3.4 support has been deprecated. pip 19.1 will be the last one supporting it. Please upgrade your Python as Python 3.4 won't be maintained after March 2019 (cf PEP 429).
Collecting Django==2.2 from https://files.pythonhosted.org/packages/54/85/0bef63668fb170888c1a2970ec897d4528d6072f32dee27653381a332642/Django-2.2-py3-none-any.whl
  Downloading https://files.pythonhosted.org/packages/54/85/0bef63668fb170888c1a2970ec897d4528d6072f32dee27653381a332642/Django-2.2-py3-none-any.whl (7.4MB)
    100% |████████████████████████████████| 7.5MB 3.6MB/s 
Django requires Python '>=3.5' but the running Python is 3.4.10
You are using pip version 19.0.3, however version 19.1 is available.
You should consider upgrading via the 'pip install --upgrade pip' command.
root@b30693b8f33e:/# echo $?
1
root@b30693b8f33e:/# pip install https://files.pythonhosted.org/packages/54/85/0bef63668fb170888c1a2970ec897d4528d6072f32dee27653381a332642/Django-2.2-py3-none-any.whl --ignore-requires-python
DEPRECATION: Python 3.4 support has been deprecated. pip 19.1 will be the last one supporting it. Please upgrade your Python as Python 3.4 won't be maintained after March 2019 (cf PEP 429).
Collecting Django==2.2 from https://files.pythonhosted.org/packages/54/85/0bef63668fb170888c1a2970ec897d4528d6072f32dee27653381a332642/Django-2.2-py3-none-any.whl
  Using cached https://files.pythonhosted.org/packages/54/85/0bef63668fb170888c1a2970ec897d4528d6072f32dee27653381a332642/Django-2.2-py3-none-any.whl
Django requires Python '>=3.5' but the running Python is 3.4.10
Collecting sqlparse (from Django==2.2)
  Downloading https://files.pythonhosted.org/packages/ef/53/900f7d2a54557c6a37886585a91336520e5539e3ae2423ff1102daf4f3a7/sqlparse-0.3.0-py2.py3-none-any.whl
Collecting pytz (from Django==2.2)
  Downloading https://files.pythonhosted.org/packages/3d/73/fe30c2daaaa0713420d0382b16fbb761409f532c56bdcc514bf7b6262bb6/pytz-2019.1-py2.py3-none-any.whl (510kB)
    100% |████████████████████████████████| 512kB 17.0MB/s 
Installing collected packages: sqlparse, pytz, Django
Successfully installed Django-2.2 pytz-2019.1 sqlparse-0.3.0
You are using pip version 19.0.3, however version 19.1 is available.
You should consider upgrading via the 'pip install --upgrade pip' command.
root@b30693b8f33e:/# echo $?
0
```

It might still be interesting to also use it in `check_requires_python()` though.

Resolving patch:
diff --git a/src/pip/_internal/cli/base_command.py b/src/pip/_internal/cli/base_command.py
--- a/src/pip/_internal/cli/base_command.py
+++ b/src/pip/_internal/cli/base_command.py
@@ -326,11 +326,15 @@ def _build_package_finder(
         platform=None,         # type: Optional[str]
         python_versions=None,  # type: Optional[List[str]]
         abi=None,              # type: Optional[str]
-        implementation=None    # type: Optional[str]
+        implementation=None,   # type: Optional[str]
+        ignore_requires_python=None,  # type: Optional[bool]
     ):
         # type: (...) -> PackageFinder
         """
         Create a package finder appropriate to this requirement command.
+
+        :param ignore_requires_python: Whether to ignore incompatible
+            "Requires-Python" values in links. Defaults to False.
         """
         index_urls = [options.index_url] + options.extra_index_urls
         if options.no_index:
@@ -352,4 +356,5 @@ def _build_package_finder(
             abi=abi,
             implementation=implementation,
             prefer_binary=options.prefer_binary,
+            ignore_requires_python=ignore_requires_python,
         )
diff --git a/src/pip/_internal/commands/install.py b/src/pip/_internal/commands/install.py
--- a/src/pip/_internal/commands/install.py
+++ b/src/pip/_internal/commands/install.py
@@ -297,6 +297,7 @@ def run(self, options, args):
                 python_versions=python_versions,
                 abi=options.abi,
                 implementation=options.implementation,
+                ignore_requires_python=options.ignore_requires_python,
             )
             build_delete = (not (options.no_clean or options.build_dir))
             wheel_cache = WheelCache(options.cache_dir, options.format_control)
diff --git a/src/pip/_internal/index.py b/src/pip/_internal/index.py
--- a/src/pip/_internal/index.py
+++ b/src/pip/_internal/index.py
@@ -256,6 +256,49 @@ def _get_html_page(link, session=None):
     return None
 
 
+def _check_link_requires_python(
+    link,  # type: Link
+    version_info,  # type: Tuple[int, ...]
+    ignore_requires_python=False,  # type: bool
+):
+    # type: (...) -> bool
+    """
+    Return whether the given Python version is compatible with a link's
+    "Requires-Python" value.
+
+    :param version_info: The Python version to use to check, as a 3-tuple
+        of ints (major-minor-micro).
+    :param ignore_requires_python: Whether to ignore the "Requires-Python"
+        value if the given Python version isn't compatible.
+    """
+    try:
+        support_this_python = check_requires_python(
+            link.requires_python, version_info=version_info,
+        )
+    except specifiers.InvalidSpecifier:
+        logger.debug(
+            "Ignoring invalid Requires-Python (%r) for link: %s",
+            link.requires_python, link,
+        )
+    else:
+        if not support_this_python:
+            version = '.'.join(map(str, version_info))
+            if not ignore_requires_python:
+                logger.debug(
+                    'Link requires a different Python (%s not in: %r): %s',
+                    version, link.requires_python, link,
+                )
+                return False
+
+            logger.debug(
+                'Ignoring failed Requires-Python check (%s not in: %r) '
+                'for link: %s',
+                version, link.requires_python, link,
+            )
+
+    return True
+
+
 class CandidateEvaluator(object):
 
     """
@@ -269,6 +312,7 @@ def __init__(
         prefer_binary=False,   # type: bool
         allow_all_prereleases=False,  # type: bool
         py_version_info=None,  # type: Optional[Tuple[int, ...]]
+        ignore_requires_python=None,  # type: Optional[bool]
     ):
         # type: (...) -> None
         """
@@ -277,12 +321,17 @@ def __init__(
             representing a major-minor-micro version, to use to check both
             the Python version embedded in the filename and the package's
             "Requires-Python" metadata. Defaults to `sys.version_info[:3]`.
+        :param ignore_requires_python: Whether to ignore incompatible
+            "Requires-Python" values in links. Defaults to False.
         """
         if py_version_info is None:
             py_version_info = sys.version_info[:3]
+        if ignore_requires_python is None:
+            ignore_requires_python = False
 
         py_version = '.'.join(map(str, py_version_info[:2]))
 
+        self._ignore_requires_python = ignore_requires_python
         self._prefer_binary = prefer_binary
         self._py_version = py_version
         self._py_version_info = py_version_info
@@ -354,23 +403,15 @@ def evaluate_link(self, link, search):
             py_version = match.group(1)
             if py_version != self._py_version:
                 return (False, 'Python version is incorrect')
-        try:
-            support_this_python = check_requires_python(
-                link.requires_python, version_info=self._py_version_info,
-            )
-        except specifiers.InvalidSpecifier:
-            logger.debug("Package %s has an invalid Requires-Python entry: %s",
-                         link.filename, link.requires_python)
-        else:
-            if not support_this_python:
-                logger.debug(
-                    "The package %s is incompatible with the python "
-                    "version in use. Acceptable python versions are: %s",
-                    link, link.requires_python,
-                )
-                # Return None for the reason text to suppress calling
-                # _log_skipped_link().
-                return (False, None)
+
+        supports_python = _check_link_requires_python(
+            link, version_info=self._py_version_info,
+            ignore_requires_python=self._ignore_requires_python,
+        )
+        if not supports_python:
+            # Return None for the reason text to suppress calling
+            # _log_skipped_link().
+            return (False, None)
 
         logger.debug('Found link %s, version: %s', link, version)
 
@@ -558,7 +599,8 @@ def create(
         versions=None,  # type: Optional[List[str]]
         abi=None,  # type: Optional[str]
         implementation=None,  # type: Optional[str]
-        prefer_binary=False  # type: bool
+        prefer_binary=False,  # type: bool
+        ignore_requires_python=None,  # type: Optional[bool]
     ):
         # type: (...) -> PackageFinder
         """Create a PackageFinder.
@@ -582,6 +624,8 @@ def create(
             to pep425tags.py in the get_supported() method.
         :param prefer_binary: Whether to prefer an old, but valid, binary
             dist over a new source dist.
+        :param ignore_requires_python: Whether to ignore incompatible
+            "Requires-Python" values in links. Defaults to False.
         """
         if session is None:
             raise TypeError(
@@ -617,6 +661,7 @@ def create(
         candidate_evaluator = CandidateEvaluator(
             valid_tags=valid_tags, prefer_binary=prefer_binary,
             allow_all_prereleases=allow_all_prereleases,
+            ignore_requires_python=ignore_requires_python,
         )
 
         # If we don't have TLS enabled, then WARN if anyplace we're looking


Test patch:
diff --git a/tests/unit/test_index.py b/tests/unit/test_index.py
--- a/tests/unit/test_index.py
+++ b/tests/unit/test_index.py
@@ -8,11 +8,78 @@
 
 from pip._internal.download import PipSession
 from pip._internal.index import (
-    CandidateEvaluator, Link, PackageFinder, _clean_link, _determine_base_url,
+    CandidateEvaluator, Link, PackageFinder, Search,
+    _check_link_requires_python, _clean_link, _determine_base_url,
     _egg_info_matches, _find_name_version_sep, _get_html_page,
 )
 
 
+@pytest.mark.parametrize('requires_python, expected', [
+    ('== 3.6.4', False),
+    ('== 3.6.5', True),
+    # Test an invalid Requires-Python value.
+    ('invalid', True),
+])
+def test_check_link_requires_python(requires_python, expected):
+    version_info = (3, 6, 5)
+    link = Link('https://example.com', requires_python=requires_python)
+    actual = _check_link_requires_python(link, version_info)
+    assert actual == expected
+
+
+def check_caplog(caplog, expected_level, expected_message):
+    assert len(caplog.records) == 1
+    record = caplog.records[0]
+    assert record.levelname == expected_level
+    assert record.message == expected_message
+
+
+@pytest.mark.parametrize('ignore_requires_python, expected', [
+    (None, (
+        False, 'DEBUG',
+        "Link requires a different Python (3.6.5 not in: '== 3.6.4'): "
+        "https://example.com"
+    )),
+    (True, (
+        True, 'DEBUG',
+        "Ignoring failed Requires-Python check (3.6.5 not in: '== 3.6.4') "
+        "for link: https://example.com"
+    )),
+])
+def test_check_link_requires_python__incompatible_python(
+    caplog, ignore_requires_python, expected,
+):
+    """
+    Test an incompatible Python.
+    """
+    expected_return, expected_level, expected_message = expected
+    link = Link('https://example.com', requires_python='== 3.6.4')
+    caplog.set_level(logging.DEBUG)
+    actual = _check_link_requires_python(
+        link, version_info=(3, 6, 5),
+        ignore_requires_python=ignore_requires_python,
+    )
+    assert actual == expected_return
+
+    check_caplog(caplog, expected_level, expected_message)
+
+
+def test_check_link_requires_python__invalid_requires(caplog):
+    """
+    Test the log message for an invalid Requires-Python.
+    """
+    link = Link('https://example.com', requires_python='invalid')
+    caplog.set_level(logging.DEBUG)
+    actual = _check_link_requires_python(link, version_info=(3, 6, 5))
+    assert actual
+
+    expected_message = (
+        "Ignoring invalid Requires-Python ('invalid') for link: "
+        "https://example.com"
+    )
+    check_caplog(caplog, 'DEBUG', expected_message)
+
+
 class TestCandidateEvaluator:
 
     @pytest.mark.parametrize("version_info, expected", [
@@ -37,6 +104,32 @@ def test_init__py_version_default(self):
         index = sys.version.find('.', 2)
         assert evaluator._py_version == sys.version[:index]
 
+    @pytest.mark.parametrize(
+        'py_version_info,ignore_requires_python,expected', [
+            ((3, 6, 5), None, (True, '1.12')),
+            # Test an incompatible Python.
+            ((3, 6, 4), None, (False, None)),
+            # Test an incompatible Python with ignore_requires_python=True.
+            ((3, 6, 4), True, (True, '1.12')),
+        ],
+    )
+    def test_evaluate_link(
+        self, py_version_info, ignore_requires_python, expected,
+    ):
+        link = Link(
+            'https://example.com/#egg=twine-1.12',
+            requires_python='== 3.6.5',
+        )
+        search = Search(
+            supplied='twine', canonical='twine', formats=['source'],
+        )
+        evaluator = CandidateEvaluator(
+            [], py_version_info=py_version_info,
+            ignore_requires_python=ignore_requires_python,
+        )
+        actual = evaluator.evaluate_link(link, search=search)
+        assert actual == expected
+
 
 def test_sort_locations_file_expand_dir(data):
     """
diff --git a/tests/unit/test_packaging.py b/tests/unit/test_packaging.py
new file mode 100644
--- /dev/null
+++ b/tests/unit/test_packaging.py
@@ -0,0 +1,22 @@
+import pytest
+from pip._vendor.packaging import specifiers
+
+from pip._internal.utils.packaging import check_requires_python
+
+
+@pytest.mark.parametrize('version_info, requires_python, expected', [
+    ((3, 6, 5), '== 3.6.4', False),
+    ((3, 6, 5), '== 3.6.5', True),
+    ((3, 6, 5), None, True),
+])
+def test_check_requires_python(version_info, requires_python, expected):
+    actual = check_requires_python(requires_python, version_info)
+    assert actual == expected
+
+
+def test_check_requires_python__invalid():
+    """
+    Test an invalid Requires-Python value.
+    """
+    with pytest.raises(specifiers.InvalidSpecifier):
+        check_requires_python('invalid', (3, 6, 5))