Repository: pypa/pip

Issue:
[2020-resolver] Fails if two versions with `; python_version` in constraints for the same package
**What did you want to do?**
I want to install a different version of a package depending on the Python version.

`constraints.txt`:
```
Django==3.0.9 ; python_version >= "3.6"
Django==2.2.15 ; python_version < "3.6"
```
```
$ python -m venv /tmp/venv
$ . /tmp/venv/bin/activate
$ pip install -U pip
$ pip install -U "pip @ https://github.com/pypa/pip/archive/master.zip"
$ pip install --use-feature 2020-resolver --constraint constraints.txt Django
```

**Output**

```
ERROR: Could not find a version that satisfies the requirement Django
ERROR: No matching distribution found for Django
```

**Additional information**

Tried with
 * Python 3.7.7
 * Python 3.8.2


Discussion:
Does this happen if it’s a requirements file (`-r`) instead of constraints? This would help locate the problem greatly. Thanks!
@uranusjr no, it works perfectly with `-r`.
To make sure my environment doesn't interfere with anything, I created a Docker setup to test this.

`/tmp/pip-issue-8724.sh`:
```bash
#!/bin/bash

cat >/constraints.txt <<EOF
Django==3.0.9 ; python_version >= "3.6"
Django==2.2.15 ; python_version < "3.6"
EOF

cd /opt/python
for PYTHON in *; do
    echo
    echo $PYTHON
    $PYTHON/bin/python -m venv /venv-$PYTHON
    . /venv-$PYTHON/bin/activate
    pip install -q -U pip
    pip install -q -U "pip @ https://github.com/pypa/pip/archive/master.zip"
    pip install --use-feature 2020-resolver --constraint /constraints.txt Django
done
```

Then run it in a manylinux container with Docker or Podman:
```
podman run \
  -v /tmp/pip-issue-8724.sh:/test.sh:Z \
  quay.io/pypa/manylinux2014_x86_64 \
  bash /test.sh
```

For me this outputs:
```
cp35-cp35m
Cache entry deserialization failed, entry ignored
ERROR: Could not find a version that satisfies the requirement Django
ERROR: No matching distribution found for Django

cp36-cp36m
ERROR: Could not find a version that satisfies the requirement Django
ERROR: No matching distribution found for Django

cp37-cp37m
ERROR: Could not find a version that satisfies the requirement Django
ERROR: No matching distribution found for Django

cp38-cp38
ERROR: Could not find a version that satisfies the requirement Django
ERROR: No matching distribution found for Django

cp39-cp39
ERROR: Could not find a version that satisfies the requirement Django
ERROR: No matching distribution found for Django
```
> @uranusjr no, it works perfectly with `-r`.

Thanks! I think I have an idea what’s going on; we’re likely not excluding lines based on the markers when we process the constraints file.

Resolving patch:
diff --git a/src/pip/_internal/resolution/resolvelib/resolver.py b/src/pip/_internal/resolution/resolvelib/resolver.py
--- a/src/pip/_internal/resolution/resolvelib/resolver.py
+++ b/src/pip/_internal/resolution/resolvelib/resolver.py
@@ -80,7 +80,8 @@ def resolve(self, root_reqs, check_supported_wheels):
                 problem = check_invalid_constraint_type(req)
                 if problem:
                     raise InstallationError(problem)
-
+                if not req.match_markers():
+                    continue
                 name = canonicalize_name(req.name)
                 if name in constraints:
                     constraints[name] = constraints[name] & req.specifier


Test patch:
diff --git a/tests/functional/test_new_resolver.py b/tests/functional/test_new_resolver.py
--- a/tests/functional/test_new_resolver.py
+++ b/tests/functional/test_new_resolver.py
@@ -1,6 +1,7 @@
 import json
 import os
 import sys
+import textwrap
 
 import pytest
 from pip._vendor.packaging.utils import canonicalize_name
@@ -729,6 +730,30 @@ def test_new_resolver_constraint_on_path(script):
     assert msg in result.stderr, str(result)
 
 
+def test_new_resolver_constraint_only_marker_match(script):
+    create_basic_wheel_for_package(script, "pkg", "1.0")
+    create_basic_wheel_for_package(script, "pkg", "2.0")
+    create_basic_wheel_for_package(script, "pkg", "3.0")
+
+    constrants_content = textwrap.dedent(
+        """
+        pkg==1.0; python_version == "{ver[0]}.{ver[1]}"  # Always satisfies.
+        pkg==2.0; python_version < "0"  # Never satisfies.
+        """
+    ).format(ver=sys.version_info)
+    constraints_txt = script.scratch_path / "constraints.txt"
+    constraints_txt.write_text(constrants_content)
+
+    script.pip(
+        "install", "--use-feature=2020-resolver",
+        "--no-cache-dir", "--no-index",
+        "-c", constraints_txt,
+        "--find-links", script.scratch_path,
+        "pkg",
+    )
+    assert_installed(script, pkg="1.0")
+
+
 def test_new_resolver_upgrade_needs_option(script):
     # Install pkg 1.0.0
     create_basic_wheel_for_package(script, "pkg", "1.0.0")