Skip to content

Commit

Permalink
Add interpreter constraints rule
Browse files Browse the repository at this point in the history
  • Loading branch information
gshuflin committed Oct 1, 2019
1 parent de968b8 commit 8af08d8
Show file tree
Hide file tree
Showing 5 changed files with 63 additions and 21 deletions.
2 changes: 2 additions & 0 deletions src/python/pants/backend/python/register.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
from pants.backend.python.rules import (
download_pex_bin,
inject_init,
interpreter_constraints,
pex,
python_run_binary,
python_test_runner,
Expand Down Expand Up @@ -99,6 +100,7 @@ def rules():
return (
download_pex_bin.rules() +
inject_init.rules() +
interpreter_constraints.rules() +
python_test_runner.rules() +
python_run_binary.rules() +
python_native_code_rules() +
Expand Down
42 changes: 42 additions & 0 deletions src/python/pants/backend/python/rules/interpreter_constraints.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
# Copyright 2019 Pants project contributors (see CONTRIBUTORS.md).
# Licensed under the Apache License, Version 2.0 (see LICENSE).

from dataclasses import dataclass
from typing import FrozenSet, List, Tuple

from pants.backend.python.subsystems.python_setup import PythonSetup
from pants.engine.legacy.structs import PythonTargetAdaptor
from pants.engine.rules import RootRule, rule


@dataclass(frozen=True)
class BuildConstraintsForAdaptors:
adaptors: Tuple[PythonTargetAdaptor]


@dataclass(frozen=True)
class PexInterpreterContraints:
constraint_set: FrozenSet[str] = frozenset()

def generate_pex_arg_list(self) -> List[str]:
args = []
for constraint in self.constraint_set:
args.extend(["--interpreter-constraint", constraint])
return args


@rule
def handle_constraints(build_constraints_for_adaptors: BuildConstraintsForAdaptors, python_setup: PythonSetup) -> PexInterpreterContraints:
interpreter_constraints = frozenset(
[constraint
for target_adaptor in build_constraints_for_adaptors.adaptors
for constraint in python_setup.compatibility_or_constraints(
getattr(target_adaptor, 'compatibility', None)
)]
)

yield PexInterpreterContraints(constraint_set=interpreter_constraints)


def rules():
return [handle_constraints, RootRule(BuildConstraintsForAdaptors)]
9 changes: 4 additions & 5 deletions src/python/pants/backend/python/rules/pex.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@

from pants.backend.python.rules.download_pex_bin import DownloadedPexBin
from pants.backend.python.rules.hermetic_pex import HermeticPex
from pants.backend.python.rules.interpreter_constraints import PexInterpreterContraints
from pants.backend.python.subsystems.python_native_code import PexBuildEnvironment
from pants.backend.python.subsystems.python_setup import PythonSetup
from pants.backend.python.subsystems.subprocess_environment import SubprocessEncodingEnvironment
Expand All @@ -31,7 +32,7 @@ class CreatePex:
"""Represents a generic request to create a PEX from its inputs."""
output_filename: str
requirements: Tuple[str] = ()
interpreter_constraints: Tuple[str] = ()
interpreter_constraints: PexInterpreterContraints = PexInterpreterContraints()
entry_point: Optional[str] = None
input_files_digest: Optional[Digest] = None

Expand All @@ -57,9 +58,7 @@ def create_pex(
"""Returns a PEX with the given requirements, optional entry point, and optional
interpreter constraints."""

interpreter_constraint_args = []
for constraint in request.interpreter_constraints:
interpreter_constraint_args.extend(["--interpreter-constraint", constraint])
interpreter_constraint_args = request.interpreter_constraints.generate_pex_arg_list()

argv = ["--output-file", request.output_filename]
if request.entry_point is not None:
Expand Down Expand Up @@ -118,7 +117,7 @@ class RunnablePex:
# necessarily the interpreter that PEX will use to execute the generated .pex file.
@rule
def pex_execute_request(
runnable_pex: RunnablePex,
runnable_pex: RunnablePex, #TODO if this rule is a Pex the rule graph blows up wtf?
subprocess_encoding_environment: SubprocessEncodingEnvironment,
python_setup: PythonSetup
) -> ExecuteProcessRequest:
Expand Down
16 changes: 8 additions & 8 deletions src/python/pants/backend/python/rules/python_run_binary.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,10 @@
# Licensed under the Apache License, Version 2.0 (see LICENSE).

from pants.backend.python.rules.inject_init import InjectedInitDigest
from pants.backend.python.rules.interpreter_constraints import (
BuildConstraintsForAdaptors,
PexInterpreterContraints,
)
from pants.backend.python.rules.pex import CreatePex, RunnablePex
from pants.backend.python.subsystems.python_setup import PythonSetup
from pants.backend.python.targets.python_binary import PythonBinary
Expand All @@ -25,13 +29,9 @@ def run_python_binary(python_binary_target: PythonBinaryAdaptor,
all_targets = transitive_hydrated_targets.closure
all_target_adaptors = [t.adaptor for t in all_targets]

interpreter_constraints = {
constraint
for target_adaptor in all_target_adaptors
for constraint in python_setup.compatibility_or_constraints(
getattr(target_adaptor, 'compatibility', None)
)
}

interpreter_constraints = yield Get(PexInterpreterContraints,
BuildConstraintsForAdaptors(adaptors=tuple(all_target_adaptors)))

source_root_stripped_sources = yield [
Get(SourceRootStrippedSources, HydratedTarget, target_adaptor)
Expand Down Expand Up @@ -74,7 +74,7 @@ def run_python_binary(python_binary_target: PythonBinaryAdaptor,
create_requirements_pex = CreatePex(
output_filename=output_thirdparty_requirements_pex_filename,
requirements=tuple(sorted(all_requirements)),
interpreter_constraints=tuple(sorted(interpreter_constraints)),
interpreter_constraints=interpreter_constraints,
entry_point=entry_point,
input_files_digest=merged_input_files,
)
Expand Down
15 changes: 7 additions & 8 deletions src/python/pants/backend/python/rules/python_test_runner.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,10 @@
# Licensed under the Apache License, Version 2.0 (see LICENSE).

from pants.backend.python.rules.inject_init import InjectedInitDigest
from pants.backend.python.rules.interpreter_constraints import (
BuildConstraintsForAdaptors,
PexInterpreterContraints,
)
from pants.backend.python.rules.pex import CreatePex, Pex
from pants.backend.python.subsystems.pytest import PyTest
from pants.backend.python.subsystems.python_setup import PythonSetup
Expand Down Expand Up @@ -33,13 +37,8 @@ def run_python_test(
)
all_targets = transitive_hydrated_targets.closure

interpreter_constraints = {
constraint
for target_adaptor in all_targets
for constraint in python_setup.compatibility_or_constraints(
getattr(target_adaptor, 'compatibility', None)
)
}
interpreter_constraints = yield Get(PexInterpreterContraints,
BuildConstraintsForAdaptors(adaptors=tuple(all_targets)))

# Produce a pex containing pytest and all transitive 3rdparty requirements.
output_pytest_requirements_pex_filename = 'pytest-with-requirements.pex'
Expand All @@ -58,7 +57,7 @@ def run_python_test(
Pex, CreatePex(
output_filename=output_pytest_requirements_pex_filename,
requirements=tuple(sorted(all_requirements)),
interpreter_constraints=tuple(sorted(interpreter_constraints)),
interpreter_constraints=interpreter_constraints,
entry_point="pytest:main",
)
)
Expand Down

0 comments on commit 8af08d8

Please sign in to comment.