Skip to content

Commit

Permalink
Respect env markers when checking resolves.
Browse files Browse the repository at this point in the history
Previously we failed to do this and would erroneously fail resolves as
a result.

Fixes pex-tool#851
  • Loading branch information
jsirois committed Jan 23, 2020
1 parent aa6a843 commit 9c0d818
Show file tree
Hide file tree
Showing 2 changed files with 32 additions and 9 deletions.
15 changes: 15 additions & 0 deletions pex/distribution_target.py
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,21 @@ def get_interpreter(self):
def get_platform(self):
return self._platform or Platform.current()

def requirement_applies(self, requirement):
"""Determines if the given requirement applies to this distribution target.
:param requirement: The requirement to evaluate.
:type requirement: :class:`pex.third_party.pkg_resources.Requirement`
:rtype: bool
"""
if not requirement.marker:
return True

if self._interpreter is None:
return True

return requirement.marker.evaluate(self._interpreter.identity.env_markers)

@property
def id(self):
"""A unique id for a resolve target suitable as a path name component.
Expand Down
26 changes: 17 additions & 9 deletions pex/resolver.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,13 +33,15 @@ class Unsatisfiable(Exception):
pass


class ResolvedDistribution(namedtuple('ResolvedDistribution', ['requirement', 'distribution'])):
"""A requirement and the resolved distribution that satisfies it."""
class ResolvedDistribution(namedtuple('ResolvedDistribution',
['target', 'requirement', 'distribution'])):
"""A distribution target, requirement and the resolved distribution that satisfies them both."""

def __new__(cls, requirement, distribution):
def __new__(cls, target, requirement, distribution):
assert isinstance(target, DistributionTarget)
assert isinstance(requirement, Requirement)
assert isinstance(distribution, Distribution)
return super(ResolvedDistribution, cls).__new__(cls, requirement, distribution)
return super(ResolvedDistribution, cls).__new__(cls, target, requirement, distribution)


class DistributionRequirements(object):
Expand Down Expand Up @@ -565,6 +567,7 @@ def add_requirements_requests(install_result):
for distribution in requirements_request.distributions:
resolved_distributions.add(
ResolvedDistribution(
target=requirements_request.target,
requirement=distribution_requirements.to_requirement(distribution),
distribution=distribution
)
Expand All @@ -575,21 +578,26 @@ def add_requirements_requests(install_result):
return resolved_distributions

def _check_resolve(self, resolved_distributions):
dist_by_key = OrderedDict(
(resolved_distribution.requirement.key, resolved_distribution.distribution)
resolved_distribution_by_key = OrderedDict(
(resolved_distribution.requirement.key, resolved_distribution)
for resolved_distribution in resolved_distributions
)

unsatisfied = []
for dist in dist_by_key.values():
for resolved_distribution in resolved_distribution_by_key.values():
dist = resolved_distribution.distribution
target = resolved_distribution.target
for requirement in dist.requires():
resolved_dist = dist_by_key.get(requirement.key)
if not target.requirement_applies(requirement):
continue

resolved_dist = resolved_distribution_by_key.get(requirement.key)
if not resolved_dist or resolved_dist not in requirement:
unsatisfied.append(
'{dist} requires {requirement} but {resolved_dist} was resolved'.format(
dist=dist.as_requirement(),
requirement=requirement,
resolved_dist=resolved_dist.as_requirement() if resolved_dist else None
resolved_dist=resolved_dist.distribution.as_requirement() if resolved_dist else None
)
)

Expand Down

0 comments on commit 9c0d818

Please sign in to comment.