Repository: pex-tool/pex

Issue:
Pex resolver fails to evaluate markers when post-processing resolves to identify which dists satisfy direct requirements.
For example:
```
$ python2.7 -mpex "flake8>=3.7.9,<3.9" "setuptools<45; python_full_version == '2.7.*'" "setuptools; python_version > '2.7'" -e flake8 -o flake8.pex
Traceback (most recent call last):
  File "/usr/lib/python2.7/runpy.py", line 174, in _run_module_as_main
    "__main__", fname, loader, pkg_name)
  File "/usr/lib/python2.7/runpy.py", line 72, in _run_code
    exec code in run_globals
  File "/home/jsirois/dev/pantsbuild/jsirois-pex/pex/__main__.py", line 8, in <module>
    __name__ == "__main__" and pex.main()
  File "pex/bin/pex.py", line 1068, in main
    pex_builder = build_pex(options.requirements, options, cache=ENV.PEX_ROOT)
  File "pex/bin/pex.py", line 964, in build_pex
    ignore_errors=options.ignore_errors,
  File "pex/resolver.py", line 1111, in resolve_multi
    ignore_errors=ignore_errors, workspace=workspace, max_parallel_jobs=max_parallel_jobs
  File "pex/resolver.py", line 788, in install_distributions
    for index, direct_req in enumerate(direct_reqs)
AssertionError: More than one direct requirement is satisfied by setuptools 44.1.1:
0. setuptools<45; python_full_version == "2.7.*"
1. setuptools; python_version > "2.7"
This should never happen since Pip fails when more than one requirement for a given project name key is supplied and applies for a given target interpreter environment.
```

This was seen over in Pants here: https://github.com/pantsbuild/pants/blob/305964500ebb45c1caa8ccdb7fbd75b0ebe646f1/src/python/pants/backend/python/lint/flake8/subsystem.py#L15-L18


Discussion:

Resolving patch:
diff --git a/pex/resolver.py b/pex/resolver.py
--- a/pex/resolver.py
+++ b/pex/resolver.py
@@ -773,7 +773,9 @@ def add_installation(install_result):
             direct_reqs = [
                 req
                 for req in direct_requirements_by_key.get(distribution.key, ())
-                if req and distribution in req
+                if req
+                and distribution in req
+                and installed_distribution.target.requirement_applies(req)
             ]
             if len(direct_reqs) > 1:
                 raise AssertionError(


Test patch:
diff --git a/tests/test_resolver.py b/tests/test_resolver.py
--- a/tests/test_resolver.py
+++ b/tests/test_resolver.py
@@ -534,6 +534,27 @@ def test_resolve_arbitrary_equality_issues_940():
     assert requirement.marker is None
 
 
+def test_resolve_overlapping_requirements_discriminated_by_markers_issues_1196(py27):
+    # type: (PythonInterpreter) -> None
+    resolved_distributions = resolve_multi(
+        requirements=[
+            "setuptools<45; python_full_version == '2.7.*'",
+            "setuptools; python_version > '2.7'",
+        ],
+        interpreters=[py27],
+    )
+    assert 1 == len(resolved_distributions)
+    resolved_distribution = resolved_distributions[0]
+    assert (
+        Requirement.parse("setuptools<45; python_full_version == '2.7.*'")
+        == resolved_distribution.direct_requirement
+    )
+    assert (
+        Requirement.parse("setuptools==44.1.1")
+        == resolved_distribution.distribution.as_requirement()
+    )
+
+
 def create_pex_repository(
     interpreters=None,  # type: Optional[Iterable[PythonInterpreter]]
     platforms=None,  # type: Optional[Iterable[Platform]]