コード例 #1
0
def test_configuration() -> None:
    class UnrelatedField(StringField):
        alias = "unrelated_field"
        default = "default"
        value: str

    class UnrelatedTarget(Target):
        alias = "unrelated_target"
        core_fields = (UnrelatedField, )

    class NoFieldsTarget(Target):
        alias = "no_fields_target"
        core_fields = ()

    @dataclass(frozen=True)
    class FortranConfiguration(Configuration):
        required_fields = (FortranSources, )

        sources: FortranSources
        unrelated_field: UnrelatedField

    @dataclass(frozen=True)
    class UnrelatedFieldConfiguration(ConfigurationWithOrigin):
        required_fields = ()

        unrelated_field: UnrelatedField

    fortran_addr = Address.parse(":fortran")
    fortran_tgt = FortranTarget({}, address=fortran_addr)
    unrelated_addr = Address.parse(":unrelated")
    unrelated_tgt = UnrelatedTarget({UnrelatedField.alias: "configured"},
                                    address=unrelated_addr)
    no_fields_addr = Address.parse(":no_fields")
    no_fields_tgt = NoFieldsTarget({}, address=no_fields_addr)

    assert FortranConfiguration.is_valid(fortran_tgt) is True
    assert FortranConfiguration.is_valid(unrelated_tgt) is False
    assert FortranConfiguration.is_valid(no_fields_tgt) is False
    # When no fields are required, every target is valid.
    for tgt in [fortran_tgt, unrelated_tgt, no_fields_tgt]:
        assert UnrelatedFieldConfiguration.is_valid(tgt) is True

    valid_fortran_config = FortranConfiguration.create(fortran_tgt)
    assert valid_fortran_config.address == fortran_addr
    assert valid_fortran_config.unrelated_field.value == UnrelatedField.default
    with pytest.raises(KeyError):
        FortranConfiguration.create(unrelated_tgt)

    origin = FilesystemLiteralSpec("f.txt")
    assert (UnrelatedFieldConfiguration.create(
        TargetWithOrigin(fortran_tgt, origin)).origin == origin)
    assert (UnrelatedFieldConfiguration.create(
        TargetWithOrigin(unrelated_tgt,
                         origin)).unrelated_field.value == "configured")
    assert (UnrelatedFieldConfiguration.create(
        TargetWithOrigin(
            no_fields_tgt,
            origin)).unrelated_field.value == UnrelatedField.default)
コード例 #2
0
 def make_target_with_origin(
     self,
     source_files: List[FileContent],
     *,
     name: str = "target",
     interpreter_constraints: Optional[str] = None,
     origin: Optional[OriginSpec] = None,
     dependencies: Optional[List[Address]] = None,
 ) -> TargetWithOrigin:
     for source_file in source_files:
         self.create_file(source_file.path, source_file.content.decode())
     source_globs = [
         PurePath(source_file.path).name for source_file in source_files
     ]
     self.create_library(path=self.source_root,
                         target_type=PythonLibrary.alias,
                         name=name,
                         sources=source_globs)
     # We must re-write the files because `create_library` will have over-written the content.
     for source_file in source_files:
         self.create_file(source_file.path, source_file.content.decode())
     target = PythonLibrary(
         {
             Sources.alias: source_globs,
             Dependencies.alias: dependencies,
             PythonInterpreterCompatibility.alias: interpreter_constraints,
         },
         address=Address(self.source_root, name),
     )
     if origin is None:
         origin = SingleAddress(directory=self.source_root, name=name)
     return TargetWithOrigin(target, origin)
コード例 #3
0
 def make_target_with_origin(address: Optional[Address] = None) -> TargetWithOrigin:
     if address is None:
         address = Address.parse(":tests")
     return TargetWithOrigin(
         MockTarget({}, address=address),
         origin=SingleAddress(directory=address.spec_path, name=address.target_name),
     )
コード例 #4
0
 def run_pytest(
     self,
     *,
     passthrough_args: Optional[str] = None,
     origin: Optional[OriginSpec] = None,
 ) -> TestResult:
     args = [
         "--backend-packages2=pants.backend.python",
         # pin to lower versions so that we can run Python 2 tests
         "--pytest-version=pytest>=4.6.6,<4.7",
         "--pytest-pytest-plugins=['zipp==1.0.0']",
     ]
     if passthrough_args:
         args.append(f"--pytest-args='{passthrough_args}'")
     options_bootstrapper = create_options_bootstrapper(args=args)
     address = Address(self.source_root, "target")
     if origin is None:
         origin = SingleAddress(directory=address.spec_path,
                                name=address.target_name)
     tgt = PythonTests({}, address=address)
     params = Params(
         PythonTestConfiguration.create(TargetWithOrigin(tgt, origin)),
         options_bootstrapper)
     test_result = self.request_single_product(TestResult, params)
     debug_request = self.request_single_product(TestDebugRequest, params)
     debug_result = InteractiveRunner(
         self.scheduler).run_local_interactive_process(debug_request.ipr)
     if test_result.status == Status.SUCCESS:
         assert debug_result.process_exit_code == 0
     else:
         assert debug_result.process_exit_code != 0
     return test_result
コード例 #5
0
 def make_target_with_origin(
     self,
     source_files: List[FileContent],
     *,
     package: Optional[str] = None,
     name: str = "target",
 ) -> TargetWithOrigin:
     if not package:
         package = self.package
     for source_file in source_files:
         self.create_file(source_file.path, source_file.content.decode())
     source_globs = [
         PurePath(source_file.path).name for source_file in source_files
     ]
     self.add_to_build_file(
         f"{package}",
         dedent(f"""\
             python_library(
                 name={repr(name)},
                 sources={source_globs},
             )
             """),
     )
     target = self.request_single_product(
         WrappedTarget, Address(package, target_name=name)).target
     origin = SingleAddress(directory=package, name=name)
     return TargetWithOrigin(target, origin)
コード例 #6
0
 def make_target_with_origin(
     self,
     source_files: List[FileContent],
     *,
     name: str = "target",
     interpreter_constraints: Optional[str] = None,
     origin: Optional[OriginSpec] = None,
     dependencies: Optional[List[Address]] = None,
 ) -> TargetWithOrigin:
     for source_file in source_files:
         self.create_file(source_file.path, source_file.content.decode())
     source_globs = [
         PurePath(source_file.path).name for source_file in source_files
     ]
     self.add_to_build_file(
         self.source_root,
         f"python_library(name='{name}', sources={source_globs})\n")
     target = PythonLibrary(
         {
             Sources.alias: source_globs,
             Dependencies.alias: dependencies,
             PythonInterpreterCompatibility.alias: interpreter_constraints,
         },
         address=Address(self.source_root, name),
     )
     if origin is None:
         origin = SingleAddress(directory=self.source_root, name=name)
     return TargetWithOrigin(target, origin)
コード例 #7
0
 def make_target_with_origin(
     self,
     source_files: List[FileContent],
     *,
     name: str = "target",
     interpreter_constraints: Optional[str] = None,
     origin: Optional[OriginSpec] = None,
     dependencies: Optional[List[Address]] = None,
 ) -> TargetWithOrigin:
     for source_file in source_files:
         self.create_file(source_file.path, source_file.content.decode())
     source_globs = [PurePath(source_file.path).name for source_file in source_files]
     self.add_to_build_file(
         self.source_root,
         dedent(
             f"""\
             python_library(
                 name={repr(name)},
                 sources={source_globs},
                 dependencies={[str(dep) for dep in dependencies or ()]},
                 compatibility={repr(interpreter_constraints)},
             )
             """
         ),
     )
     target = self.request_single_product(WrappedTarget, Address(self.source_root, name)).target
     if origin is None:
         origin = SingleAddress(directory=self.source_root, name=name)
     return TargetWithOrigin(target, origin)
コード例 #8
0
def make_target_with_origin(address: Optional[Address] = None) -> TargetWithOrigin:
    if address is None:
        address = Address("", target_name="tests")
    return TargetWithOrigin(
        MockTarget({}, address=address),
        origin=AddressLiteralSpec(address.spec_path, address.target_name),
    )
コード例 #9
0
async def resolve_targets_with_origins(
    addresses_with_origins: AddressesWithOrigins, ) -> TargetsWithOrigins:
    # TODO: See `resolve_targets`.
    targets_with_origins = await MultiGet(
        Get(TargetWithOrigin, AddressWithOrigin, address_with_origin)
        for address_with_origin in addresses_with_origins)
    # Split out and expand any base targets.
    # TODO: Should recursively expand alias targets here as well.
    other_targets_with_origins = []
    base_targets_with_origins = []
    for to in targets_with_origins:
        if to.target.address.is_base_target:
            base_targets_with_origins.append(to)
        else:
            other_targets_with_origins.append(to)

    base_targets_subtargets = await MultiGet(
        Get(Subtargets, Address, to.target.address)
        for to in base_targets_with_origins)
    # Zip the subtargets back to the base targets and replace them while maintaining origins.
    # NB: If a target had no subtargets, we use the base.
    expanded_targets_with_origins = set(other_targets_with_origins)
    expanded_targets_with_origins.update(
        TargetWithOrigin(target, bto.origin) for bto, subtargets in zip(
            base_targets_with_origins, base_targets_subtargets)
        for target in (
            subtargets.subtargets if subtargets.subtargets else [bto.target]))
    return TargetsWithOrigins(expanded_targets_with_origins)
コード例 #10
0
 def make_target_with_origin(
     self, source_files: List[FileContent], *, origin: Optional[OriginSpec] = None,
 ) -> TargetWithOrigin:
     for source_file in source_files:
         self.create_file(f"{source_file.path}", source_file.content.decode())
     target = PythonLibrary({}, address=Address.parse(":target"))
     if origin is None:
         origin = SingleAddress(directory="", name="target")
     return TargetWithOrigin(target, origin)
コード例 #11
0
 def make_target_with_origin(
         address: Optional[Address] = None,
         *,
         target_cls: Type[Target] = FortranTarget) -> TargetWithOrigin:
     if address is None:
         address = Address.parse(":tests")
     return TargetWithOrigin(
         target_cls({}, address=address),
         origin=SingleAddress(directory=address.spec_path,
                              name=address.target_name),
     )
コード例 #12
0
    def single_target_run(
        self,
        *,
        console: MockConsole,
        program_text: bytes,
        address_spec: str,
    ) -> Run:
        workspace = Workspace(self.scheduler)
        interactive_runner = InteractiveRunner(self.scheduler)

        class TestBinaryConfiguration(BinaryConfiguration):
            required_fields = ()

        class TestBinaryTarget(Target):
            alias = "binary"
            core_fields = ()

        address = Address.parse(address_spec)
        origin = SingleAddress(address.spec_path, address.target_name)
        res = run_rule(
            run,
            rule_args=[
                console,
                workspace,
                interactive_runner,
                BuildRoot(),
                TargetsWithOrigins([
                    TargetWithOrigin(
                        target=TestBinaryTarget(unhydrated_values={},
                                                address=address),
                        origin=origin,
                    )
                ]),
                create_goal_subsystem(RunOptions, args=[]),
                create_subsystem(GlobalOptions,
                                 pants_workdir=self.pants_workdir),
                UnionMembership(union_rules={
                    BinaryConfiguration:
                    OrderedSet([TestBinaryConfiguration])
                }),
                RegisteredTargetTypes.create([TestBinaryTarget]),
            ],
            mock_gets=[
                MockGet(
                    product_type=CreatedBinary,
                    subject_type=TestBinaryConfiguration,
                    mock=lambda _: self.create_mock_binary(program_text),
                ),
            ],
        )
        return cast(Run, res)
コード例 #13
0
    def single_target_run(
        self,
        *,
        console: MockConsole,
        program_text: bytes,
        address_spec: str,
    ) -> Run:
        workspace = Workspace(self.scheduler)
        interactive_runner = InteractiveRunner(self.scheduler)

        class TestRunFieldSet(RunFieldSet):
            required_fields = ()

        class TestBinaryTarget(Target):
            alias = "binary"
            core_fields = ()

        address = Address.parse(address_spec)
        target = TestBinaryTarget({}, address=address)
        target_with_origin = TargetWithOrigin(
            target, AddressLiteralSpec(address.spec_path, address.target_name))
        field_set = TestRunFieldSet.create(target)

        res = run_rule_with_mocks(
            run,
            rule_args=[
                create_goal_subsystem(RunSubsystem, args=[]),
                create_subsystem(GlobalOptions,
                                 pants_workdir=self.pants_workdir),
                console,
                interactive_runner,
                workspace,
                BuildRoot(),
            ],
            mock_gets=[
                MockGet(
                    product_type=TargetsToValidFieldSets,
                    subject_type=TargetsToValidFieldSetsRequest,
                    mock=lambda _: TargetsToValidFieldSets(
                        {target_with_origin: [field_set]}),
                ),
                MockGet(
                    product_type=RunRequest,
                    subject_type=TestRunFieldSet,
                    mock=lambda _: self.create_mock_run_request(program_text),
                ),
            ],
        )
        return cast(Run, res)
コード例 #14
0
 def make_target_with_origin(
     self,
     source_files: List[FileContent],
     *,
     interpreter_constraints: Optional[str] = None,
     origin: Optional[OriginSpec] = None,
 ) -> TargetWithOrigin:
     for source_file in source_files:
         self.create_file(source_file.path, source_file.content.decode())
     target = PythonLibrary(
         {PythonInterpreterCompatibility.alias: interpreter_constraints},
         address=Address.parse(":target"),
     )
     if origin is None:
         origin = SingleAddress(directory="", name="target")
     return TargetWithOrigin(target, origin)
コード例 #15
0
 def run_black_and_isort(
     self, source_files: List[FileContent], *, name: str, extra_args: Optional[List[str]] = None
 ) -> LanguageFmtResults:
     for source_file in source_files:
         self.create_file(source_file.path, source_file.content.decode())
     target = PythonLibrary({}, address=Address.parse(f"test:{name}"))
     origin = SingleAddress(directory="test", name=name)
     targets = PythonFmtTargets(TargetsWithOrigins([TargetWithOrigin(target, origin)]))
     args = [
         "--backend-packages2=['pants.backend.python.lint.black', 'pants.backend.python.lint.isort']",
         *(extra_args or []),
     ]
     results = self.request_single_product(
         LanguageFmtResults, Params(targets, create_options_bootstrapper(args=args)),
     )
     return results
コード例 #16
0
    def single_target_run(
        self, *, console: MockConsole, program_text: bytes, address_spec: str,
    ) -> Run:
        workspace = Workspace(self.scheduler)
        interactive_runner = InteractiveRunner(self.scheduler)

        class TestBinaryConfiguration(BinaryConfiguration):
            required_fields = ()

        class TestBinaryTarget(Target):
            alias = "binary"
            core_fields = ()

        address = Address.parse(address_spec)
        target = TestBinaryTarget({}, address=address)
        target_with_origin = TargetWithOrigin(
            target, SingleAddress(address.spec_path, address.target_name)
        )
        config = TestBinaryConfiguration.create(target)

        res = run_rule(
            run,
            rule_args=[
                console,
                workspace,
                interactive_runner,
                BuildRoot(),
                create_goal_subsystem(RunOptions, args=[]),
                create_subsystem(GlobalOptions, pants_workdir=self.pants_workdir),
            ],
            mock_gets=[
                MockGet(
                    product_type=TargetsToValidConfigurations,
                    subject_type=TargetsToValidConfigurationsRequest,
                    mock=lambda _: TargetsToValidConfigurations({target_with_origin: [config]}),
                ),
                MockGet(
                    product_type=CreatedBinary,
                    subject_type=TestBinaryConfiguration,
                    mock=lambda _: self.create_mock_binary(program_text),
                ),
            ],
        )
        return cast(Run, res)
コード例 #17
0
async def resolve_target_with_origin(
        address_with_origin: AddressWithOrigin) -> TargetWithOrigin:
    wrapped_target = await Get[WrappedTarget](Address,
                                              address_with_origin.address)
    return TargetWithOrigin(wrapped_target.target, address_with_origin.origin)
コード例 #18
0
    def test_find_valid_field_sets(self) -> None:
        origin = FilesystemLiteralSpec("f.txt")
        valid_tgt = FortranTarget({}, address=Address.parse(":valid"))
        valid_tgt_with_origin = TargetWithOrigin(valid_tgt, origin)
        invalid_tgt = self.InvalidTarget({}, address=Address.parse(":invalid"))
        invalid_tgt_with_origin = TargetWithOrigin(invalid_tgt, origin)

        def find_valid_field_sets(
            superclass: Type,
            targets_with_origins: Iterable[TargetWithOrigin],
            *,
            error_if_no_valid_targets: bool = False,
            expect_single_config: bool = False,
        ) -> TargetsToValidFieldSets:
            request = TargetsToValidFieldSetsRequest(
                superclass,
                goal_description="fake",
                error_if_no_valid_targets=error_if_no_valid_targets,
                expect_single_field_set=expect_single_config,
            )
            return self.request_single_product(
                TargetsToValidFieldSets, Params(request, TargetsWithOrigins(targets_with_origins),),
            )

        valid = find_valid_field_sets(
            self.FieldSetSuperclass, [valid_tgt_with_origin, invalid_tgt_with_origin]
        )
        assert valid.targets == (valid_tgt,)
        assert valid.targets_with_origins == (valid_tgt_with_origin,)
        assert valid.field_sets == (
            self.FieldSetSubclass1.create(valid_tgt),
            self.FieldSetSubclass2.create(valid_tgt),
        )

        with pytest.raises(ExecutionError) as exc:
            find_valid_field_sets(
                self.FieldSetSuperclass, [valid_tgt_with_origin], expect_single_config=True
            )
        assert AmbiguousImplementationsException.__name__ in str(exc.value)

        with pytest.raises(ExecutionError) as exc:
            find_valid_field_sets(
                self.FieldSetSuperclass,
                [
                    valid_tgt_with_origin,
                    TargetWithOrigin(FortranTarget({}, address=Address.parse(":valid2")), origin),
                ],
                expect_single_config=True,
            )
        assert TooManyTargetsException.__name__ in str(exc.value)

        no_valid_targets = find_valid_field_sets(self.FieldSetSuperclass, [invalid_tgt_with_origin])
        assert no_valid_targets.targets == ()
        assert no_valid_targets.targets_with_origins == ()
        assert no_valid_targets.field_sets == ()

        with pytest.raises(ExecutionError) as exc:
            find_valid_field_sets(
                self.FieldSetSuperclass, [invalid_tgt_with_origin], error_if_no_valid_targets=True
            )
        assert NoValidTargetsException.__name__ in str(exc.value)

        valid_with_origin = find_valid_field_sets(
            self.FieldSetSuperclassWithOrigin, [valid_tgt_with_origin, invalid_tgt_with_origin]
        )
        assert valid_with_origin.targets == (valid_tgt,)
        assert valid_with_origin.targets_with_origins == (valid_tgt_with_origin,)
        assert valid_with_origin.field_sets == (
            self.FieldSetSubclassWithOrigin.create(valid_tgt_with_origin),
        )