-
-
Notifications
You must be signed in to change notification settings - Fork 652
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
9 changed files
with
254 additions
and
25 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
42 changes: 42 additions & 0 deletions
42
src/python/pants/backend/python/rules/interpreter_constraints.py
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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)] |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
96 changes: 96 additions & 0 deletions
96
src/python/pants/backend/python/rules/python_create_binary.py
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,96 @@ | ||
# Copyright 2019 Pants project contributors (see CONTRIBUTORS.md). | ||
# 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.python_setup import PythonSetup | ||
from pants.backend.python.targets.python_binary import PythonBinary | ||
from pants.engine.fs import Digest, DirectoriesToMerge | ||
from pants.engine.isolated_process import ExecuteProcessRequest, FallibleExecuteProcessResult | ||
from pants.engine.legacy.graph import BuildFileAddresses, HydratedTarget, TransitiveHydratedTargets | ||
from pants.engine.legacy.structs import PythonBinaryAdaptor | ||
from pants.engine.rules import UnionRule, rule | ||
from pants.engine.selectors import Get | ||
from pants.rules.core.binary import BinaryTarget, CreatedBinary | ||
from pants.rules.core.strip_source_root import SourceRootStrippedSources | ||
|
||
|
||
@rule | ||
def create_python_binary(python_binary_adaptor: PythonBinaryAdaptor, | ||
python_setup: PythonSetup) -> Pex: | ||
transitive_hydrated_targets = yield Get( | ||
TransitiveHydratedTargets, BuildFileAddresses((python_binary_adaptor.address,)) | ||
) | ||
all_targets = transitive_hydrated_targets.closure | ||
all_target_adaptors = [t.adaptor for t in all_targets] | ||
|
||
|
||
interpreter_constraints = yield Get(PexInterpreterContraints, | ||
BuildConstraintsForAdaptors(adaptors=tuple(all_target_adaptors))) | ||
|
||
source_root_stripped_sources = yield [ | ||
Get(SourceRootStrippedSources, HydratedTarget, target_adaptor) | ||
for target_adaptor in all_targets | ||
] | ||
|
||
#TODO This way of calculating the entry point works but is a bit hackish. | ||
entry_point = None | ||
if hasattr(python_binary_adaptor, 'entry_point'): | ||
entry_point = python_binary_adaptor.entry_point | ||
else: | ||
sources_snapshot = python_binary_adaptor.sources.snapshot | ||
if len(sources_snapshot.files) == 1: | ||
target = transitive_hydrated_targets.roots[0] | ||
output = yield Get(SourceRootStrippedSources, HydratedTarget, target) | ||
root_filename = output.snapshot.files[0] | ||
entry_point = PythonBinary.translate_source_path_to_py_module_specifier(root_filename) | ||
|
||
stripped_sources_digests = [stripped_sources.snapshot.directory_digest for stripped_sources in source_root_stripped_sources] | ||
sources_digest = yield Get(Digest, DirectoriesToMerge(directories=tuple(stripped_sources_digests))) | ||
inits_digest = yield Get(InjectedInitDigest, Digest, sources_digest) | ||
all_input_digests = [sources_digest, inits_digest.directory_digest] | ||
merged_input_files = yield Get(Digest, DirectoriesToMerge, DirectoriesToMerge(directories=tuple(all_input_digests))) | ||
|
||
#TODO This chunk of code should be made into an @rule and used both here and in | ||
# python_test_runner.py. | ||
# Produce a pex containing pytest and all transitive 3rdparty requirements. | ||
all_target_requirements = [] | ||
for maybe_python_req_lib in all_target_adaptors: | ||
# This is a python_requirement()-like target. | ||
if hasattr(maybe_python_req_lib, 'requirement'): | ||
all_target_requirements.append(str(maybe_python_req_lib.requirement)) | ||
# This is a python_requirement_library()-like target. | ||
if hasattr(maybe_python_req_lib, 'requirements'): | ||
for py_req in maybe_python_req_lib.requirements: | ||
all_target_requirements.append(str(py_req.requirement)) | ||
|
||
output_filename = f"{python_binary_adaptor.address.target_name}.pex" | ||
|
||
all_requirements = all_target_requirements | ||
create_requirements_pex = CreatePex( | ||
output_filename=output_filename, | ||
requirements=tuple(sorted(all_requirements)), | ||
interpreter_constraints=interpreter_constraints, | ||
entry_point=entry_point, | ||
input_files_digest=merged_input_files, | ||
) | ||
|
||
pex = yield Get(Pex, CreatePex, create_requirements_pex) | ||
yield pex | ||
|
||
|
||
@rule | ||
def pex_to_created_binary(pex: Pex) -> CreatedBinary: | ||
yield CreatedBinary(_inner=pex) | ||
|
||
|
||
def rules(): | ||
return [ | ||
UnionRule(BinaryTarget, PythonBinaryAdaptor), | ||
pex_to_created_binary, | ||
create_python_binary, | ||
] |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,68 @@ | ||
# 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 Any | ||
|
||
from pants.backend.python.rules.pex import Pex | ||
from pants.build_graph.address import Address | ||
from pants.engine.addressable import BuildFileAddresses | ||
from pants.engine.console import Console | ||
from pants.engine.fs import DirectoryToMaterialize, Workspace | ||
from pants.engine.goal import Goal, LineOriented | ||
from pants.engine.legacy.graph import HydratedTarget | ||
from pants.engine.legacy.structs import PythonBinaryAdaptor | ||
from pants.engine.rules import console_rule, optionable_rule, rule, union | ||
from pants.engine.selectors import Get | ||
|
||
|
||
@dataclass(frozen=True) | ||
class Binary(LineOriented, Goal): | ||
name = 'binary' | ||
|
||
|
||
@union | ||
@dataclass(frozen=True) | ||
class BinaryTarget: | ||
pass | ||
|
||
|
||
@union | ||
@dataclass(frozen=True) | ||
class CreatedBinary: | ||
_inner: Any | ||
|
||
def write_to_dist(self, print_stdout: Any, workspace: Workspace) -> None: | ||
if isinstance(self._inner, Pex): | ||
dtm = DirectoryToMaterialize( | ||
path = 'dist/', | ||
directory_digest = self._inner.directory_digest, | ||
) | ||
output = workspace.materialize_directories((dtm,)) | ||
for path in output.dependencies[0].output_paths: | ||
print_stdout(f"Wrote {path}") | ||
else: | ||
raise ValueError(f"CreatedBinary should not contain a value of type: {type(self._inner)}") | ||
|
||
|
||
@console_rule | ||
def create_binary(addresses: BuildFileAddresses, console: Console, workspace: Workspace, options: Binary.Options) -> Binary: | ||
with Binary.line_oriented(options, console) as (print_stdout, print_stderr): | ||
print_stdout("Generating binaries in `dist/`") | ||
binaries = yield [Get(CreatedBinary, Address, address.to_address()) for address in addresses] | ||
for binary in binaries: | ||
binary.write_to_dist(print_stdout, workspace) | ||
yield Binary(exit_code=0) | ||
|
||
|
||
@rule | ||
def coordinator_of_binaries(target: HydratedTarget) -> CreatedBinary: | ||
binary = yield Get(CreatedBinary, BinaryTarget, target.adaptor) | ||
yield binary | ||
|
||
|
||
def rules(): | ||
return [ | ||
create_binary, | ||
coordinator_of_binaries, | ||
] |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.