Skip to content

Commit

Permalink
Record original requirements in PEX-INFO.
Browse files Browse the repository at this point in the history
Previously we recorded the post-resolve exact requirements of all
resolved distributions. This necessitated a good deal of work to recover
environment markers and still left out any top-level environment markers
specified in direct requirements / requirement files passed to Pex. Now
we record all requirements as we received them, only filling in project
name and version for local loose-source requirements in our resolve
post-processing. This saves time (~O(500ms) for medium to large PEX
builds) and fixes bugs.

Fixes pex-tool#899
  • Loading branch information
jsirois committed Jan 13, 2021
1 parent fd89f30 commit df79f35
Show file tree
Hide file tree
Showing 7 changed files with 233 additions and 218 deletions.
8 changes: 2 additions & 6 deletions pex/bin/pex.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@
import sys
import tempfile
from argparse import Action, ArgumentDefaultsHelpFormatter, ArgumentParser, ArgumentTypeError
from shlex import shlex
from textwrap import TextWrapper

from pex import pex_warnings
Expand Down Expand Up @@ -935,12 +934,9 @@ def to_python_interpreter(full_path_or_basename):
)

for resolved_dist in resolveds:
log(
" %s -> %s" % (resolved_dist.requirement, resolved_dist.distribution),
V=options.verbosity,
)
pex_builder.add_distribution(resolved_dist.distribution)
pex_builder.add_requirement(resolved_dist.requirement)
if resolved_dist.direct_requirement:
pex_builder.add_requirement(resolved_dist.direct_requirement)
except Unsatisfiable as e:
die(str(e))

Expand Down
17 changes: 10 additions & 7 deletions pex/environment.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@

from pex import dist_metadata, pex_builder, pex_warnings
from pex.bootstrap import Bootstrap
from pex.common import atomic_directory, die, open_zip
from pex.common import atomic_directory, open_zip
from pex.inherit_path import InheritPath
from pex.interpreter import PythonInterpreter
from pex.orderedset import OrderedSet
Expand Down Expand Up @@ -84,6 +84,10 @@ def create(
return cls(requirement=requirement, required_by=required_by)


class ResolveError(Exception):
"""Indicates an error resolving requirements for a PEX."""


class PEXEnvironment(object):
class _CachingZipImporter(object):
class _CachingLoader(object):
Expand Down Expand Up @@ -434,12 +438,11 @@ def _root_requirements_iter(self, reqs):
for key, requirements in reqs_by_key.items():
ranked_dists = self._available_ranked_dists_by_key.get(key)
if ranked_dists is None:
# This can only happen in a multi-platform PEX where the original requirement had
# an environment marker and this environment does not satisfy that marker.
TRACER.log(
"A distribution for {} will not be resolved in this environment.".format(key)
# We've winnowed down reqs_by_key to just those requirements whose environment
# markers apply; so, we should always have an available distribution.
raise ResolveError(
"A distribution for {} could not be resolved in this environment.".format(key)
)
continue
candidates = [
(ranked_dist, requirement)
for requirement in requirements
Expand Down Expand Up @@ -519,7 +522,7 @@ def _resolve(self, reqs):
)
)

die(
raise ResolveError(
"Failed to execute PEX file. Needed {platform} compatible dependencies for:\n"
"{items}".format(platform=self._interpreter.platform, items="\n".join(items))
)
Expand Down
7 changes: 5 additions & 2 deletions pex/requirements.py
Original file line number Diff line number Diff line change
Expand Up @@ -303,10 +303,13 @@ def parse_requirement_from_dist(
"Failed to find a project name and version from the given wheel path: "
"{wheel}".format(wheel=dist)
)
project_name_and_specifier = ProjectNameAndSpecifier.from_project_name_and_version(
project_name_and_version
)
return parse_requirement_from_project_name_and_specifier(
project_name_and_version.project_name,
project_name_and_specifier.project_name,
extras=extras,
specifier=SpecifierSet("=={}".format(project_name_and_version.version)),
specifier=project_name_and_specifier.specifier,
marker=marker,
)

Expand Down
Loading

0 comments on commit df79f35

Please sign in to comment.