Commit 1cdd9408 authored by Steve Kowalik's avatar Steve Kowalik

Restore evaluating environment markers in WorkingSet

Correctly deal with parsed requirements that include extras as a
marker inside WorkingSet that are populated from METADATA inside
wheels, like we get from pip>=7.

This partially reverts commit 04d10ff0.

Closes: #523
parent 9803058d
......@@ -791,6 +791,8 @@ class WorkingSet(object):
# key -> dist
best = {}
to_activate = []
# Map requirement to the extras that require it
extra_req_mapping = {}
# Mapping of requirement to set of distributions that required it;
# useful for reporting info about conflicts.
......@@ -804,9 +806,14 @@ class WorkingSet(object):
continue
# If the req has a marker, evaluate it -- skipping the req if
# it evaluates to False.
# https://github.com/pypa/setuptools/issues/523
_issue_523_bypass = True
if not _issue_523_bypass and req.marker and not req.marker.evaluate():
if req.marker:
result = []
if req in extra_req_mapping:
for extra in extra_req_mapping[req] or ['']:
result.append(req.marker.evaluate({'extra': extra}))
else:
result.append(req.marker.evaluate())
if not any(result):
continue
dist = best.get(req.key)
if dist is None:
......@@ -840,6 +847,7 @@ class WorkingSet(object):
# Register the new requirements needed by req
for new_requirement in new_requirements:
required_by[new_requirement].add(req.project_name)
extra_req_mapping[new_requirement] = req.extras
processed[req] = True
......
......@@ -171,16 +171,85 @@ class TestDistro:
msg = 'Foo 0.9 is installed but Foo==1.2 is required'
assert vc.value.report() == msg
@pytest.mark.xfail(reason="Functionality disabled; see #523")
def test_environment_markers(self):
"""
Environment markers are evaluated at resolution time.
"""
def test_environment_marker_evaluation_negative(self):
"""Environment markers are evaluated at resolution time."""
ad = pkg_resources.Environment([])
ws = WorkingSet([])
res = ws.resolve(parse_requirements("Foo;python_version<'2'"), ad)
assert list(res) == []
def test_environment_marker_evaluation_positive(self):
ad = pkg_resources.Environment([])
ws = WorkingSet([])
Foo = Distribution.from_filename("/foo_dir/Foo-1.2.dist-info")
ad.add(Foo)
res = ws.resolve(parse_requirements("Foo;python_version>='2'"), ad)
assert list(res) == [Foo]
def test_marker_evaluation_with_extras(self):
"""Extras are also evaluated as markers at resolution time."""
ad = pkg_resources.Environment([])
ws = WorkingSet([])
# Metadata needs to be native strings due to cStringIO behaviour in
# 2.6, so use str().
Foo = Distribution.from_filename(
"/foo_dir/Foo-1.2.dist-info",
metadata=Metadata(("METADATA", str("Provides-Extra: baz\n"
"Requires-Dist: quux; extra=='baz'")))
)
ad.add(Foo)
assert list(ws.resolve(parse_requirements("Foo"), ad)) == [Foo]
quux = Distribution.from_filename("/foo_dir/quux-1.0.dist-info")
ad.add(quux)
res = list(ws.resolve(parse_requirements("Foo[baz]"), ad))
assert res == [Foo,quux]
def test_marker_evaluation_with_multiple_extras(self):
ad = pkg_resources.Environment([])
ws = WorkingSet([])
# Metadata needs to be native strings due to cStringIO behaviour in
# 2.6, so use str().
Foo = Distribution.from_filename(
"/foo_dir/Foo-1.2.dist-info",
metadata=Metadata(("METADATA", str("Provides-Extra: baz\n"
"Requires-Dist: quux; extra=='baz'\n"
"Provides-Extra: bar\n"
"Requires-Dist: fred; extra=='bar'\n")))
)
ad.add(Foo)
quux = Distribution.from_filename("/foo_dir/quux-1.0.dist-info")
ad.add(quux)
fred = Distribution.from_filename("/foo_dir/fred-0.1.dist-info")
ad.add(fred)
res = list(ws.resolve(parse_requirements("Foo[baz,bar]"), ad))
assert sorted(res) == [fred,quux,Foo]
def test_marker_evaluation_with_extras_loop(self):
ad = pkg_resources.Environment([])
ws = WorkingSet([])
# Metadata needs to be native strings due to cStringIO behaviour in
# 2.6, so use str().
a = Distribution.from_filename(
"/foo_dir/a-0.2.dist-info",
metadata=Metadata(("METADATA", str("Requires-Dist: c[a]")))
)
b = Distribution.from_filename(
"/foo_dir/b-0.3.dist-info",
metadata=Metadata(("METADATA", str("Requires-Dist: c[b]")))
)
c = Distribution.from_filename(
"/foo_dir/c-1.0.dist-info",
metadata=Metadata(("METADATA", str("Provides-Extra: a\n"
"Requires-Dist: b;extra=='a'\n"
"Provides-Extra: b\n"
"Requires-Dist: foo;extra=='b'")))
)
foo = Distribution.from_filename("/foo_dir/foo-0.1.dist-info")
for dist in (a, b, c, foo):
ad.add(dist)
res = list(ws.resolve(parse_requirements("a"), ad))
assert res == [a, c, b, foo]
def testDistroDependsOptions(self):
d = self.distRequires("""
Twisted>=1.5
......
......@@ -104,7 +104,6 @@ class TestEggInfo(object):
'setup.py': setup_script,
})
@pytest.mark.xfail(reason="Functionality disabled; see #523")
def test_install_requires_with_markers(self, tmpdir_cwd, env):
self._setup_script_with_requires(
"""install_requires=["barbazquux;python_version<'2'"],""")
......@@ -115,14 +114,12 @@ class TestEggInfo(object):
requires_txt).read().split('\n')
assert glob.glob(os.path.join(env.paths['lib'], 'barbazquux*')) == []
@pytest.mark.xfail(reason="Functionality disabled; see #523")
def test_setup_requires_with_markers(self, tmpdir_cwd, env):
self._setup_script_with_requires(
"""setup_requires=["barbazquux;python_version<'2'"],""")
self._run_install_command(tmpdir_cwd, env)
assert glob.glob(os.path.join(env.paths['lib'], 'barbazquux*')) == []
@pytest.mark.xfail(reason="Functionality disabled; see #523")
def test_tests_require_with_markers(self, tmpdir_cwd, env):
self._setup_script_with_requires(
"""tests_require=["barbazquux;python_version<'2'"],""")
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment