Ejemplo n.º 1
0
def test_address_specs_filter_by_exclude_pattern(
        address_specs_rule_runner: RuleRunner) -> None:
    address_specs_rule_runner.set_options(
        ["--exclude-target-regexp=exclude_me.*"])
    address_specs_rule_runner.create_file("demo/f.txt")
    address_specs_rule_runner.add_to_build_file(
        "demo",
        dedent("""\
            mock_tgt(name="exclude_me", sources=["f.txt"])
            mock_tgt(name="not_me", sources=["f.txt"])
            """),
    )

    assert resolve_address_specs(
        address_specs_rule_runner,
        [SiblingAddresses("demo")]) == {Address("demo", target_name="not_me")}

    # The same filtering should work when given literal addresses, including file addresses.
    # The filtering will operate against the normalized Address.spec.
    literals_result = resolve_address_specs(
        address_specs_rule_runner,
        [
            AddressLiteralSpec("demo", "exclude_me"),
            AddressLiteralSpec("demo", "not_me"),
            AddressLiteralSpec("demo/f.txt", "exclude_me"),
            AddressLiteralSpec("demo/f.txt", "not_me"),
        ],
    )

    assert literals_result == {
        Address("demo", relative_file_path="f.txt", target_name="not_me"),
        Address("demo", target_name="not_me"),
    }
Ejemplo n.º 2
0
def test_raw_specs_without_file_owners_deduplication(
        rule_runner: RuleRunner) -> None:
    """When multiple specs cover the same address, we should deduplicate to one single Address."""
    rule_runner.write_files({
        "demo/f.txt":
        "",
        "demo/BUILD":
        dedent("""\
                file_generator(sources=['f.txt'])
                nonfile_generator(name="nonfile")
                """),
    })
    specs = [
        AddressLiteralSpec("demo"),
        DirLiteralSpec("demo"),
        DirGlobSpec("demo"),
        RecursiveGlobSpec("demo"),
        AncestorGlobSpec("demo"),
        AddressLiteralSpec("demo",
                           target_component="nonfile",
                           generated_component="gen"),
        AddressLiteralSpec("demo/f.txt"),
    ]
    assert resolve_raw_specs_without_file_owners(rule_runner, specs) == [
        Address("demo"),
        Address("demo", target_name="nonfile"),
        Address("demo", target_name="nonfile", generated_name="gen"),
        Address("demo", relative_file_path="f.txt"),
    ]
Ejemplo n.º 3
0
def test_address_specs_deduplication(
        address_specs_rule_runner: RuleRunner) -> None:
    """When multiple specs cover the same address, we should deduplicate to one single
    AddressWithOrigin.

    We should use the most specific origin spec possible, such as AddressLiteralSpec >
    SiblingAddresses.
    """
    address_specs_rule_runner.create_file("demo/f.txt")
    address_specs_rule_runner.add_to_build_file("demo",
                                                "mock_tgt(sources=['f.txt'])")
    # We also include a file address to ensure that that is included in the result.
    specs = [
        AddressLiteralSpec("demo", "demo"),
        AddressLiteralSpec("demo/f.txt", "demo"),
        SiblingAddresses("demo"),
        DescendantAddresses("demo"),
        AscendantAddresses("demo"),
    ]
    assert resolve_address_specs(address_specs_rule_runner, specs) == {
        AddressWithOrigin(Address("demo"), AddressLiteralSpec("demo", "demo")),
        AddressWithOrigin(
            Address("demo", relative_file_path="f.txt"),
            AddressLiteralSpec("demo/f.txt", "demo"),
        ),
    }
Ejemplo n.º 4
0
    def parse_spec(self, spec: str) -> Union[AddressSpec, FilesystemSpec]:
        """Parse the given spec into an `AddressSpec` or `FilesystemSpec` object.

        :raises: CmdLineSpecParser.BadSpecError if the address selector could not be parsed.
        """
        if spec.endswith("::"):
            spec_path = spec[:-len("::")]
            return DescendantAddresses(
                directory=self._normalize_spec_path(spec_path))
        if spec.endswith(":"):
            spec_path = spec[:-len(":")]
            return SiblingAddresses(
                directory=self._normalize_spec_path(spec_path))
        if ":" in spec:
            spec_parts = spec.rsplit(":", 1)
            spec_path = self._normalize_spec_path(spec_parts[0])
            return AddressLiteralSpec(path_component=spec_path,
                                      target_component=spec_parts[1])
        if spec.startswith("!"):
            return FilesystemIgnoreSpec(spec[1:])
        if "*" in spec:
            return FilesystemGlobSpec(spec)
        if PurePath(spec).suffix:
            return FilesystemLiteralSpec(self._normalize_spec_path(spec))
        spec_path = self._normalize_spec_path(spec)
        if Path(self._root_dir, spec_path).is_file():
            return FilesystemLiteralSpec(spec_path)
        # Else we apply address shorthand, i.e. `src/python/pants/util` ->
        # `src/python/pants/util:util`
        return AddressLiteralSpec(path_component=spec_path,
                                  target_component=PurePath(spec).name)
Ejemplo n.º 5
0
def test_address_specs_do_not_exist(
        address_specs_rule_runner: RuleRunner) -> None:
    address_specs_rule_runner.write_files({
        "real/f.txt": "",
        "real/BUILD": "mock_tgt(sources=['f.txt'])",
        "empty/BUILD": "# empty"
    })

    def assert_resolve_error(specs: Iterable[AddressSpec], *,
                             expected: str) -> None:
        with pytest.raises(ExecutionError) as exc:
            resolve_address_specs(address_specs_rule_runner, specs)
        assert expected in str(exc.value)

    # Literal addresses require both a BUILD file to exist and for a target to be resolved.
    assert_resolve_error([AddressLiteralSpec("fake", "tgt")],
                         expected="'fake' does not exist on disk")
    assert_resolve_error(
        [AddressLiteralSpec("fake/f.txt", "tgt")],
        expected="'fake/f.txt' does not exist on disk",
    )
    did_you_mean = ResolveError.did_you_mean(bad_name="fake_tgt",
                                             known_names=["real"],
                                             namespace="real")
    assert_resolve_error([AddressLiteralSpec("real", "fake_tgt")],
                         expected=str(did_you_mean))
    assert_resolve_error([AddressLiteralSpec("real/f.txt", "fake_tgt")],
                         expected=str(did_you_mean))

    # SiblingAddresses requires the BUILD file to exist and at least one match.
    assert_resolve_error(
        [SiblingAddresses("fake")],
        expected=
        ("'fake' does not contain any BUILD files, but 'fake:' expected matching targets "
         "there."),
    )
    assert_resolve_error(
        [SiblingAddresses("empty")],
        expected="Address spec 'empty:' does not match any targets",
    )

    # MaybeEmptySiblingAddresses does not require a BUILD file to exist nor any matches.
    assert not resolve_address_specs(address_specs_rule_runner,
                                     [MaybeEmptySiblingAddresses("fake")])
    assert not resolve_address_specs(address_specs_rule_runner,
                                     [MaybeEmptySiblingAddresses("empty")])

    # DescendantAddresses requires at least one match, even if BUILD files exist.
    assert_resolve_error(
        [DescendantAddresses("fake"),
         DescendantAddresses("empty")],
        expected="Address spec 'fake::' does not match any targets",
    )

    # AscendantAddresses does not require any matches or BUILD files.
    assert not resolve_address_specs(
        address_specs_rule_runner,
        [AscendantAddresses("fake"),
         AscendantAddresses("empty")])
Ejemplo n.º 6
0
def test_address_specs_do_not_exist(
        address_specs_rule_runner: RuleRunner) -> None:
    address_specs_rule_runner.write_files({
        "real/f.txt": "",
        "real/BUILD": "mock_tgt(sources=['f.txt'])",
        "empty/BUILD": "# empty"
    })

    def assert_resolve_error(specs: Iterable[AddressSpec], *,
                             expected: str) -> None:
        with engine_error(contains=expected):
            resolve_address_specs(address_specs_rule_runner, specs)

    # Literal addresses require for the relevant BUILD file to exist and for the target to be
    # resolved.
    assert_resolve_error([AddressLiteralSpec("fake", "tgt")],
                         expected="'fake' does not exist on disk")
    assert_resolve_error(
        [AddressLiteralSpec("fake/f.txt", "tgt")],
        expected="'fake/f.txt' does not exist on disk",
    )
    did_you_mean = ResolveError.did_you_mean(bad_name="fake_tgt",
                                             known_names=["real"],
                                             namespace="real")
    assert_resolve_error([AddressLiteralSpec("real", "fake_tgt")],
                         expected=str(did_you_mean))
    assert_resolve_error([AddressLiteralSpec("real/f.txt", "fake_tgt")],
                         expected=str(did_you_mean))

    # SiblingAddresses requires at least one match.
    assert_resolve_error(
        [SiblingAddresses("fake")],
        expected="No targets found for the address glob `fake:`",
    )
    assert_resolve_error(
        [SiblingAddresses("empty")],
        expected="No targets found for the address glob `empty:`")

    # MaybeEmptySiblingAddresses does not require any matches.
    assert not resolve_address_specs(address_specs_rule_runner,
                                     [MaybeEmptySiblingAddresses("fake")])
    assert not resolve_address_specs(address_specs_rule_runner,
                                     [MaybeEmptySiblingAddresses("empty")])

    # DescendantAddresses requires at least one match.
    assert_resolve_error(
        [DescendantAddresses("fake"),
         DescendantAddresses("empty")],
        expected=
        "No targets found for these address globs: ['empty::', 'fake::']",
    )

    # AscendantAddresses does not require any matches.
    assert not resolve_address_specs(
        address_specs_rule_runner,
        [AscendantAddresses("fake"),
         AscendantAddresses("empty")])
Ejemplo n.º 7
0
def test_raw_specs_without_file_owners_do_not_exist(
        rule_runner: RuleRunner) -> None:
    rule_runner.write_files({
        "real/f.txt": "",
        "real/BUILD": "target(sources=['f.txt'])",
        "empty/BUILD": "# empty"
    })

    def assert_resolve_error(spec: Spec, *, expected: str) -> None:
        with engine_error(contains=expected):
            resolve_raw_specs_without_file_owners(rule_runner, [spec])

    def assert_does_not_error(spec: Spec,
                              *,
                              ignore_nonexistent: bool = False) -> None:
        assert not resolve_raw_specs_without_file_owners(
            rule_runner, [spec], ignore_nonexistent=ignore_nonexistent)

    # Literal addresses require for the target to be resolved.
    assert_resolve_error(AddressLiteralSpec("fake", "tgt"),
                         expected="'fake' does not exist on disk")
    assert_resolve_error(
        AddressLiteralSpec("fake/f.txt", "tgt"),
        expected="'fake/f.txt' does not exist on disk",
    )
    did_you_mean = ResolveError.did_you_mean(bad_name="fake_tgt",
                                             known_names=["real"],
                                             namespace="real")
    assert_resolve_error(AddressLiteralSpec("real", "fake_tgt"),
                         expected=str(did_you_mean))
    assert_resolve_error(AddressLiteralSpec("real/f.txt", "fake_tgt"),
                         expected=str(did_you_mean))

    assert_resolve_error(DirGlobSpec("fake"),
                         expected='Unmatched glob from tests: "fake/*"')
    assert_does_not_error(DirGlobSpec("empty"))
    assert_does_not_error(DirGlobSpec("fake"), ignore_nonexistent=True)

    assert_resolve_error(DirLiteralSpec("fake"),
                         expected='Unmatched glob from tests: "fake/*"')
    assert_does_not_error(DirLiteralSpec("empty"))
    assert_does_not_error(DirLiteralSpec("fake"), ignore_nonexistent=True)

    assert_resolve_error(RecursiveGlobSpec("fake"),
                         expected='Unmatched glob from tests: "fake/**"')
    assert_does_not_error(RecursiveGlobSpec("empty"))
    assert_does_not_error(RecursiveGlobSpec("fake"), ignore_nonexistent=True)

    assert_resolve_error(AncestorGlobSpec("fake"),
                         expected='Unmatched glob from tests: "fake/*"')
    assert_does_not_error(AncestorGlobSpec("empty"))
    assert_does_not_error(AncestorGlobSpec("fake"), ignore_nonexistent=True)
Ejemplo n.º 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),
    )
Ejemplo n.º 9
0
    def parse_spec(self, spec: str) -> AddressSpec | FilesystemSpec:
        """Parse the given spec into an `AddressSpec` or `FilesystemSpec` object.

        :raises: CmdLineSpecParser.BadSpecError if the address selector could not be parsed.
        """
        if spec.endswith("::"):
            spec_path = spec[:-len("::")]
            return DescendantAddresses(
                directory=self._normalize_spec_path(spec_path))
        if spec.endswith(":"):
            spec_path = spec[:-len(":")]
            return SiblingAddresses(
                directory=self._normalize_spec_path(spec_path))
        if ":" in spec or "#" in spec:
            tgt_parts = spec.split(":", maxsplit=1)
            path_component = tgt_parts[0]
            if len(tgt_parts) == 1:
                target_component = None
                generated_parts = path_component.split("#", maxsplit=1)
                if len(generated_parts) == 1:
                    generated_component = None
                else:
                    path_component, generated_component = generated_parts
            else:
                generated_parts = tgt_parts[1].split("#", maxsplit=1)
                if len(generated_parts) == 1:
                    target_component = generated_parts[0]
                    generated_component = None
                else:
                    target_component, generated_component = generated_parts
            return AddressLiteralSpec(
                path_component=self._normalize_spec_path(path_component),
                target_component=target_component,
                generated_component=generated_component,
            )
        if spec.startswith("!"):
            return FilesystemIgnoreSpec(spec[1:])
        if "*" in spec:
            return FilesystemGlobSpec(spec)
        if PurePath(spec).suffix:
            return FilesystemLiteralSpec(self._normalize_spec_path(spec))
        spec_path = self._normalize_spec_path(spec)
        if Path(self._root_dir, spec_path).is_file():
            return FilesystemLiteralSpec(spec_path)
        # Else we apply address shorthand, i.e. `src/python/pants/util` ->
        # `src/python/pants/util:util`
        return AddressLiteralSpec(spec_path, None, None)
Ejemplo n.º 10
0
    def test_address_specs_do_not_exist(self) -> None:
        self.create_file("real/f.txt")
        self.add_to_build_file("real", "mock_tgt(sources=['f.txt'])")
        self.add_to_build_file("empty", "# empty")

        def assert_resolve_error(specs: Iterable[AddressSpec], *,
                                 expected: str) -> None:
            with pytest.raises(ExecutionError) as exc:
                self.resolve_address_specs(specs)
            assert expected in str(exc.value)

        # Literal addresses require both a BUILD file to exist and for a target to be resolved.
        assert_resolve_error([AddressLiteralSpec("fake", "tgt")],
                             expected="'fake' does not exist on disk")
        assert_resolve_error(
            [AddressLiteralSpec("fake/f.txt", "tgt")],
            expected="'fake/f.txt' does not exist on disk",
        )
        did_you_mean = ResolveError.did_you_mean(bad_name="fake_tgt",
                                                 known_names=["real"],
                                                 namespace="real")
        assert_resolve_error([AddressLiteralSpec("real", "fake_tgt")],
                             expected=str(did_you_mean))
        assert_resolve_error([AddressLiteralSpec("real/f.txt", "fake_tgt")],
                             expected=str(did_you_mean))

        # SiblingAddresses require the BUILD file to exist, but are okay if no targets are resolved.
        assert_resolve_error(
            [SiblingAddresses("fake")],
            expected=
            ("'fake' does not contain any BUILD files, but 'fake:' expected matching targets "
             "there."),
        )
        assert not self.resolve_address_specs([SiblingAddresses("empty")])

        # DescendantAddresses requires at least one match, even if BUILD files exist.
        assert_resolve_error(
            [DescendantAddresses("fake"),
             DescendantAddresses("empty")],
            expected="Address spec 'fake::' does not match any targets",
        )

        # AscendantAddresses does not require any matches or BUILD files.
        assert not self.resolve_address_specs(
            [AscendantAddresses("fake"),
             AscendantAddresses("empty")])
Ejemplo n.º 11
0
def address_literal(
    directory: str,
    name: str | None = None,
    generated: str | None = None,
    parameters: dict[str, str] | None = None,
) -> AddressLiteralSpec:
    return AddressLiteralSpec(
        directory, name, generated,
        FrozenDict(sorted(parameters.items()) if parameters else ()))
Ejemplo n.º 12
0
def calculate_specs(
    options_bootstrapper: OptionsBootstrapper,
    options: Options,
    session: SchedulerSession,
    *,
    build_root: Optional[str] = None,
) -> Specs:
    """Determine the specs for a given Pants run."""
    build_root = build_root or get_buildroot()
    specs = SpecsParser(build_root).parse_specs(options.specs)
    changed_options = ChangedOptions.from_options(options.for_scope("changed"))

    logger.debug("specs are: %s", specs)
    logger.debug("changed_options are: %s", changed_options)

    if specs.provided and changed_options.provided:
        changed_name = "--changed-since" if changed_options.since else "--changed-diffspec"
        if specs.filesystem_specs and specs.address_specs:
            specs_description = "target and file arguments"
        elif specs.filesystem_specs:
            specs_description = "file arguments"
        else:
            specs_description = "target arguments"
        raise InvalidSpecConstraint(
            f"You used `{changed_name}` at the same time as using {specs_description}. Please "
            "use only one.")

    if not changed_options.provided:
        return specs

    git = get_git()
    if not git:
        raise InvalidSpecConstraint(
            "The `--changed-*` options are only available if Git is used for the repository."
        )
    changed_request = ChangedRequest(
        sources=tuple(changed_options.changed_files(git)),
        dependees=changed_options.dependees,
    )
    (changed_addresses, ) = session.product_request(
        ChangedAddresses, [Params(changed_request, options_bootstrapper)])
    logger.debug("changed addresses: %s", changed_addresses)

    address_specs = []
    for address in cast(ChangedAddresses, changed_addresses):
        address_input = AddressInput.parse(address.spec)
        address_specs.append(
            AddressLiteralSpec(
                path_component=address_input.path_component,
                # NB: AddressInput.target_component may be None, but AddressLiteralSpec expects a
                # string.
                target_component=address_input.target_component
                or address.target_name,
            ))
    return Specs(AddressSpecs(address_specs, filter_by_global_options=True),
                 FilesystemSpecs([]))
Ejemplo n.º 13
0
def test_strip_address_origin() -> None:
    addr = Address.parse("//:demo")
    result = run_rule_with_mocks(
        strip_address_origins,
        rule_args=[
            AddressesWithOrigins(
                [AddressWithOrigin(addr, AddressLiteralSpec("", "demo"))])
        ],
    )
    assert list(result) == [addr]
Ejemplo n.º 14
0
def test_address_specs_deduplication(address_specs_rule_runner: RuleRunner) -> None:
    """When multiple specs cover the same address, we should deduplicate to one single Address."""
    address_specs_rule_runner.write_files(
        {"demo/f.txt": "", "demo/BUILD": "generator(sources=['f.txt'])"}
    )
    specs = [
        AddressLiteralSpec("demo"),
        SiblingAddresses("demo"),
        DescendantAddresses("demo"),
        AscendantAddresses("demo"),
        # We also include targets generated from `demo` to ensure that the final result has both
        # the generator and its generated targets.
        AddressLiteralSpec("demo", None, "f.txt"),
        AddressLiteralSpec("demo/f.txt"),
    ]
    assert resolve_address_specs(address_specs_rule_runner, specs) == {
        Address("demo"),
        Address("demo", generated_name="f.txt"),
        Address("demo", relative_file_path="f.txt"),
    }
Ejemplo n.º 15
0
def test_address_specs_filter_by_tag(
        address_specs_rule_runner: RuleRunner) -> None:
    address_specs_rule_runner.set_options(["--tag=+integration"])
    address_specs_rule_runner.create_file("demo/f.txt")
    address_specs_rule_runner.add_to_build_file(
        "demo",
        dedent("""\
            mock_tgt(name="a", sources=["f.txt"])
            mock_tgt(name="b", sources=["f.txt"], tags=["integration"])
            mock_tgt(name="c", sources=["f.txt"], tags=["ignore"])
            """),
    )
    assert resolve_address_specs(
        address_specs_rule_runner,
        [SiblingAddresses("demo")]) == {Address("demo", target_name="b")}

    # The same filtering should work when given literal addresses, including file addresses.
    # For file addresses, we look up the `tags` field of the original BUILD target.
    literals_result = resolve_address_specs(
        address_specs_rule_runner,
        [
            AddressLiteralSpec("demo", "a"),
            AddressLiteralSpec("demo", "b"),
            AddressLiteralSpec("demo", "c"),
            AddressLiteralSpec("demo/f.txt", "a"),
            AddressLiteralSpec("demo/f.txt", "b"),
            AddressLiteralSpec("demo/f.txt", "c"),
        ],
    )
    assert literals_result == {
        Address("demo", relative_file_path="f.txt", target_name="b"),
        Address("demo", target_name="b"),
    }
Ejemplo n.º 16
0
def test_specs_to_dirs() -> None:
    assert specs_to_dirs(RawSpecs(description_of_origin="tests")) == ("", )
    assert specs_to_dirs(
        RawSpecs(address_literals=(AddressLiteralSpec("src/python/foo"), ),
                 description_of_origin="tests")) == ("src/python/foo", )
    assert specs_to_dirs(
        RawSpecs(dir_literals=(DirLiteralSpec("src/python/foo"), ),
                 description_of_origin="tests")) == ("src/python/foo", )
    assert specs_to_dirs(
        RawSpecs(
            address_literals=(
                AddressLiteralSpec("src/python/foo"),
                AddressLiteralSpec("src/python/bar"),
            ),
            description_of_origin="tests",
        )) == ("src/python/foo", "src/python/bar")

    with pytest.raises(ValueError):
        specs_to_dirs(
            RawSpecs(file_literals=(FileLiteralSpec("src/python/foo.py"), ),
                     description_of_origin="tests"))

    with pytest.raises(ValueError):
        specs_to_dirs(
            RawSpecs(
                address_literals=(AddressLiteralSpec("src/python/bar",
                                                     "tgt"), ),
                description_of_origin="tests",
            ))

    with pytest.raises(ValueError):
        specs_to_dirs(
            RawSpecs(
                address_literals=(AddressLiteralSpec(
                    "src/python/bar",
                    target_component=None,
                    generated_component="gen"), ),
                description_of_origin="tests",
            ))
Ejemplo n.º 17
0
def test_specs_to_dirs() -> None:
    assert specs_to_dirs(Specs(AddressSpecs([]),
                               FilesystemSpecs([]))) == ("", )
    assert specs_to_dirs(
        Specs(AddressSpecs([AddressLiteralSpec("src/python/foo")]),
              FilesystemSpecs([]))) == ("src/python/foo", )
    assert specs_to_dirs(
        Specs(AddressSpecs([]),
              FilesystemSpecs([DirLiteralSpec("src/python/foo")
                               ]))) == ("src/python/foo", )
    assert specs_to_dirs(
        Specs(
            AddressSpecs([
                AddressLiteralSpec("src/python/foo"),
                AddressLiteralSpec("src/python/bar")
            ]),
            FilesystemSpecs([]),
        )) == ("src/python/foo", "src/python/bar")

    with pytest.raises(ValueError):
        specs_to_dirs(
            Specs(AddressSpecs([]),
                  FilesystemSpecs([FileLiteralSpec("src/python/foo.py")])))

    with pytest.raises(ValueError):
        specs_to_dirs(
            Specs(AddressSpecs([AddressLiteralSpec("src/python/bar", "tgt")]),
                  FilesystemSpecs([])))

    with pytest.raises(ValueError):
        specs_to_dirs(
            Specs(
                AddressSpecs([
                    AddressLiteralSpec("src/python/bar",
                                       target_component=None,
                                       generated_component="gen")
                ]),
                FilesystemSpecs([]),
            ))
Ejemplo n.º 18
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)
Ejemplo n.º 19
0
    def parse_spec(self, spec: str) -> AddressSpec | FilesystemSpec:
        """Parse the given spec into an `AddressSpec` or `FilesystemSpec` object.

        :raises: CmdLineSpecParser.BadSpecError if the address selector could not be parsed.
        """
        if spec.endswith("::"):
            spec_path = spec[:-len("::")]
            return DescendantAddresses(
                directory=self._normalize_spec_path(spec_path))
        if spec.endswith(":"):
            spec_path = spec[:-len(":")]
            return SiblingAddresses(
                directory=self._normalize_spec_path(spec_path))
        if ":" in spec or "#" in spec:
            tgt_parts = spec.split(":", maxsplit=1)
            path_component = tgt_parts[0]
            if len(tgt_parts) == 1:
                target_component = None
                generated_parts = path_component.split("#", maxsplit=1)
                if len(generated_parts) == 1:
                    generated_component = None
                else:
                    path_component, generated_component = generated_parts
            else:
                generated_parts = tgt_parts[1].split("#", maxsplit=1)
                if len(generated_parts) == 1:
                    target_component = generated_parts[0]
                    generated_component = None
                else:
                    target_component, generated_component = generated_parts
            return AddressLiteralSpec(
                path_component=self._normalize_spec_path(path_component),
                target_component=target_component,
                generated_component=generated_component,
            )
        if spec.startswith("!"):
            return FileIgnoreSpec(spec[1:])
        if "*" in spec:
            return FileGlobSpec(spec)
        if PurePath(spec).suffix:
            return FileLiteralSpec(self._normalize_spec_path(spec))
        spec_path = self._normalize_spec_path(spec)
        if spec_path == ".":
            return DirLiteralSpec("")
        # Some paths that look like dirs can actually be files without extensions.
        if Path(self._root_dir, spec_path).is_file():
            return FileLiteralSpec(spec_path)
        return DirLiteralSpec(spec_path)
Ejemplo n.º 20
0
def test_address_specs_more_specific() -> None:
    literal_addr = AddressLiteralSpec(path_component="foo/bar",
                                      target_component="baz")
    sibling_addresses = SiblingAddresses(directory="foo/bar")
    ascendant_addresses = AscendantAddresses(directory="foo/bar")
    descendant_addresses = DescendantAddresses(directory="foo/bar")

    assert literal_addr == AddressSpecs.more_specific(literal_addr, None)
    assert literal_addr == AddressSpecs.more_specific(literal_addr,
                                                      sibling_addresses)
    assert literal_addr == AddressSpecs.more_specific(literal_addr,
                                                      ascendant_addresses)
    assert literal_addr == AddressSpecs.more_specific(literal_addr,
                                                      descendant_addresses)
    assert literal_addr == AddressSpecs.more_specific(None, literal_addr)
    assert literal_addr == AddressSpecs.more_specific(sibling_addresses,
                                                      literal_addr)
    assert literal_addr == AddressSpecs.more_specific(ascendant_addresses,
                                                      literal_addr)
    assert literal_addr == AddressSpecs.more_specific(descendant_addresses,
                                                      literal_addr)

    assert sibling_addresses == AddressSpecs.more_specific(
        sibling_addresses, None)
    assert sibling_addresses == AddressSpecs.more_specific(
        sibling_addresses, ascendant_addresses)
    assert sibling_addresses == AddressSpecs.more_specific(
        sibling_addresses, descendant_addresses)
    assert sibling_addresses == AddressSpecs.more_specific(
        None, sibling_addresses)
    assert sibling_addresses == AddressSpecs.more_specific(
        ascendant_addresses, sibling_addresses)
    assert sibling_addresses == AddressSpecs.more_specific(
        descendant_addresses, sibling_addresses)

    assert ascendant_addresses == AddressSpecs.more_specific(
        ascendant_addresses, None)
    assert ascendant_addresses == AddressSpecs.more_specific(
        ascendant_addresses, descendant_addresses)
    assert ascendant_addresses == AddressSpecs.more_specific(
        None, ascendant_addresses)
    assert ascendant_addresses == AddressSpecs.more_specific(
        descendant_addresses, ascendant_addresses)

    assert descendant_addresses == AddressSpecs.more_specific(
        descendant_addresses, None)
    assert descendant_addresses == AddressSpecs.more_specific(
        None, descendant_addresses)
Ejemplo n.º 21
0
    def test_address_specs_file_does_not_belong_to_target(self) -> None:
        """Even if a file's address file exists and target exist, we should validate that the file
        actually belongs to that target."""
        self.create_file("demo/f.txt")
        self.add_to_build_file(
            "demo",
            dedent("""\
                mock_tgt(name='owner', sources=['f.txt'])
                mock_tgt(name='not_owner')
                """),
        )

        with pytest.raises(ExecutionError) as exc:
            self.resolve_address_specs(
                [AddressLiteralSpec("demo/f.txt", "not_owner")])
        assert "does not match a file demo/f.txt" in str(exc.value)
Ejemplo n.º 22
0
    def parse_spec(self, spec: str) -> tuple[Spec, bool]:
        """Parse the given spec string and also return `true` if it's an ignore.

        :raises: CmdLineSpecParser.BadSpecError if the address selector could not be parsed.
        """
        is_ignore = False
        if spec.startswith("-"):
            is_ignore = True
            spec = spec[1:]

        (
            (
                path_component,
                target_component,
                generated_component,
                parameters,
            ),
            wildcard,
        ) = native_engine.address_spec_parse(spec)

        if wildcard == "::":
            return RecursiveGlobSpec(
                directory=self._normalize_spec_path(path_component)), is_ignore
        if wildcard == ":":
            return DirGlobSpec(
                directory=self._normalize_spec_path(path_component)), is_ignore
        if target_component or generated_component or parameters:
            return (
                AddressLiteralSpec(
                    path_component=self._normalize_spec_path(path_component),
                    target_component=target_component,
                    generated_component=generated_component,
                    parameters=FrozenDict(sorted(parameters)),
                ),
                is_ignore,
            )
        if "*" in path_component:
            return FileGlobSpec(spec), is_ignore
        if PurePath(spec).suffix:
            return FileLiteralSpec(self._normalize_spec_path(spec)), is_ignore
        spec_path = self._normalize_spec_path(spec)
        if spec_path == ".":
            return DirLiteralSpec(""), is_ignore
        # Some paths that look like dirs can actually be files without extensions.
        if Path(self._root_dir, spec_path).is_file():
            return FileLiteralSpec(spec_path), is_ignore
        return DirLiteralSpec(spec_path), is_ignore
Ejemplo n.º 23
0
def test_address_specs_filter_by_tag(
        address_specs_rule_runner: RuleRunner) -> None:
    address_specs_rule_runner.set_options(["--tag=+integration"])
    address_specs_rule_runner.write_files({
        "demo/f.txt":
        "",
        "demo/BUILD":
        dedent("""\
                generator(name="a", sources=["f.txt"])
                generator(name="b", sources=["f.txt"], tags=["integration"])
                generator(name="c", sources=["f.txt"], tags=["ignore"])
                """),
    })
    assert resolve_address_specs(address_specs_rule_runner,
                                 [SiblingAddresses("demo")]) == {
                                     Address("demo", target_name="b"),
                                     Address("demo",
                                             target_name="b",
                                             relative_file_path="f.txt"),
                                     Address("demo",
                                             target_name="b",
                                             generated_name="f.txt"),
                                 }

    # The same filtering should work when given literal addresses, including generated targets and
    # file addresses.
    literals_result = resolve_address_specs(
        address_specs_rule_runner,
        [
            AddressLiteralSpec("demo", "a"),
            AddressLiteralSpec("demo", "b"),
            AddressLiteralSpec("demo", "c"),
            AddressLiteralSpec("demo/f.txt", "a"),
            AddressLiteralSpec("demo/f.txt", "b"),
            AddressLiteralSpec("demo", "a", "f.txt"),
            AddressLiteralSpec("demo", "b", "f.txt"),
            AddressLiteralSpec("demo", "c", "f.txt"),
        ],
    )
    assert literals_result == {
        Address("demo", target_name="b"),
        Address("demo", target_name="b", generated_name="f.txt"),
        Address("demo", target_name="b", relative_file_path="f.txt"),
    }
Ejemplo n.º 24
0
def test_address_specs_generated_target_does_not_belong_to_generator(
    address_specs_rule_runner: RuleRunner, ) -> None:
    address_specs_rule_runner.write_files({
        "demo/f.txt":
        "",
        "demo/BUILD":
        dedent("""\
                generator(name='owner', sources=['f.txt'])
                generator(name='not_owner')
                """),
    })

    with pytest.raises(ExecutionError) as exc:
        resolve_address_specs(address_specs_rule_runner,
                              [AddressLiteralSpec("demo/f.txt", "not_owner")])
    assert (
        f"The address `demo/f.txt:not_owner` is not generated by the `{MockTargetGenerator.alias}` "
        f"target `demo:not_owner`") in str(exc.value)
Ejemplo n.º 25
0
    def test_address_specs_filter_by_tag(self) -> None:
        self.create_file("demo/f.txt")
        self.add_to_build_file(
            "demo",
            dedent("""\
                mock_tgt(name="a", sources=["f.txt"])
                mock_tgt(name="b", sources=["f.txt"], tags=["integration"])
                mock_tgt(name="c", sources=["f.txt"], tags=["ignore"])
                """),
        )
        bootstrapper = create_options_bootstrapper(args=["--tag=+integration"])

        assert self.resolve_address_specs([SiblingAddresses("demo")],
                                          bootstrapper=bootstrapper) == {
                                              AddressWithOrigin(
                                                  Address("demo",
                                                          target_name="b"),
                                                  SiblingAddresses("demo"))
                                          }

        # The same filtering should work when given literal addresses, including file addresses.
        # For file addresses, we look up the `tags` field of the original base target.
        literals_result = self.resolve_address_specs(
            [
                AddressLiteralSpec("demo", "a"),
                AddressLiteralSpec("demo", "b"),
                AddressLiteralSpec("demo", "c"),
                AddressLiteralSpec("demo/f.txt", "a"),
                AddressLiteralSpec("demo/f.txt", "b"),
                AddressLiteralSpec("demo/f.txt", "c"),
            ],
            bootstrapper=bootstrapper,
        )
        assert literals_result == {
            AddressWithOrigin(
                Address("demo", relative_file_path="f.txt", target_name="b"),
                AddressLiteralSpec("demo/f.txt", "b"),
            ),
            AddressWithOrigin(Address("demo", target_name="b"),
                              AddressLiteralSpec("demo", "b")),
        }
Ejemplo n.º 26
0
def test_raw_specs_without_file_owners_filter_by_exclude_pattern(
        rule_runner: RuleRunner) -> None:
    rule_runner.set_options(["--exclude-target-regexp=exclude_me.*"])
    rule_runner.write_files({
        "demo/f.txt":
        "",
        "demo/BUILD":
        dedent("""\
                file_generator(name="exclude_me_f", sources=["f.txt"])
                file_generator(name="not_me_f", sources=["f.txt"])

                nonfile_generator(name="exclude_me_nf")
                nonfile_generator(name="not_me_nf")
                """),
    })
    not_me_tgts = [
        Address("demo", target_name="not_me_f"),
        Address("demo", target_name="not_me_nf"),
        Address("demo", target_name="not_me_nf", generated_name="gen"),
        Address("demo", target_name="not_me_f", relative_file_path="f.txt"),
    ]

    assert resolve_raw_specs_without_file_owners(
        rule_runner, [DirGlobSpec("demo")]) == not_me_tgts

    # The same filtering should work when given literal addresses, including generated targets and
    # file addresses.
    literals_result = resolve_raw_specs_without_file_owners(
        rule_runner,
        [
            AddressLiteralSpec("demo", "exclude_me_f"),
            AddressLiteralSpec("demo", "exclude_me_nf"),
            AddressLiteralSpec("demo", "not_me_f"),
            AddressLiteralSpec("demo", "not_me_nf"),
            AddressLiteralSpec("demo", "exclude_me_nf", "gen"),
            AddressLiteralSpec("demo", "not_me_nf", "gen"),
            AddressLiteralSpec("demo/f.txt", "exclude_me_f"),
            AddressLiteralSpec("demo/f.txt", "not_me_f"),
        ],
    )
    assert literals_result == not_me_tgts
Ejemplo n.º 27
0
def test_raw_specs_without_file_owners_generated_target_does_not_belong_to_generator(
    rule_runner: RuleRunner, ) -> None:
    rule_runner.write_files({
        "demo/f.txt":
        "",
        "demo/other.txt":
        "",
        "demo/BUILD":
        dedent("""\
                file_generator(name='owner', sources=['f.txt'])
                file_generator(name='not_owner', sources=['other.txt'])
                """),
    })

    with pytest.raises(ExecutionError) as exc:
        resolve_raw_specs_without_file_owners(
            rule_runner, [AddressLiteralSpec("demo/f.txt", "not_owner")])
    assert (
        "The address `demo/f.txt:not_owner` was not generated by the target `demo:not_owner`"
    ) in str(exc.value)
Ejemplo n.º 28
0
def test_address_specs_filter_by_exclude_pattern(
        address_specs_rule_runner: RuleRunner) -> None:
    address_specs_rule_runner.set_options(
        ["--exclude-target-regexp=exclude_me.*"])
    address_specs_rule_runner.write_files({
        "demo/f.txt":
        "",
        "demo/BUILD":
        dedent("""\
                generator(name="exclude_me", sources=["f.txt"])
                generator(name="not_me", sources=["f.txt"])
                """),
    })

    assert resolve_address_specs(address_specs_rule_runner,
                                 [SiblingAddresses("demo")]) == {
                                     Address("demo", target_name="not_me"),
                                     Address("demo",
                                             target_name="not_me",
                                             relative_file_path="f.txt"),
                                     Address("demo",
                                             target_name="not_me",
                                             generated_name="f.txt"),
                                 }

    # The same filtering should work when given literal addresses, including generated targets and
    # file addresses.
    literals_result = resolve_address_specs(
        address_specs_rule_runner,
        [
            AddressLiteralSpec("demo", "exclude_me"),
            AddressLiteralSpec("demo", "not_me"),
            AddressLiteralSpec("demo", "exclude_me", "f.txt"),
            AddressLiteralSpec("demo", "not_me", "f.txt"),
            AddressLiteralSpec("demo/f.txt", "exclude_me"),
            AddressLiteralSpec("demo/f.txt", "not_me"),
        ],
    )

    assert literals_result == {
        Address("demo", target_name="not_me"),
        Address("demo", target_name="not_me", relative_file_path="f.txt"),
        Address("demo", target_name="not_me", generated_name="f.txt"),
    }
Ejemplo n.º 29
0
    def test_address_specs_filter_by_exclude_pattern(self) -> None:
        self.create_file("demo/f.txt")
        self.add_to_build_file(
            "demo",
            dedent("""\
                mock_tgt(name="exclude_me", sources=["f.txt"])
                mock_tgt(name="not_me", sources=["f.txt"])
                """),
        )
        bootstrapper = create_options_bootstrapper(
            args=["--exclude-target-regexp=exclude_me.*"])

        assert self.resolve_address_specs(
            [SiblingAddresses("demo")], bootstrapper=bootstrapper) == {
                AddressWithOrigin(Address("demo", target_name="not_me"),
                                  SiblingAddresses("demo"))
            }

        # The same filtering should work when given literal addresses, including file addresses.
        # The filtering will operate against the normalized Address.spec.
        literals_result = self.resolve_address_specs(
            [
                AddressLiteralSpec("demo", "exclude_me"),
                AddressLiteralSpec("demo", "not_me"),
                AddressLiteralSpec("demo/f.txt", "exclude_me"),
                AddressLiteralSpec("demo/f.txt", "not_me"),
            ],
            bootstrapper=bootstrapper,
        )

        assert literals_result == {
            AddressWithOrigin(
                Address("demo",
                        relative_file_path="f.txt",
                        target_name="not_me"),
                AddressLiteralSpec("demo/f.txt", "not_me"),
            ),
            AddressWithOrigin(Address("demo", target_name="not_me"),
                              AddressLiteralSpec("demo", "not_me")),
        }
Ejemplo n.º 30
0
def address_literal(directory: str,
                    name: str | None = None) -> AddressLiteralSpec:
    name = name if name is not None else os.path.basename(directory)
    return AddressLiteralSpec(directory, name)