Пример #1
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)
Пример #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"),
    ]
Пример #3
0
async def find_all_targets(_: AllTargetsRequest) -> AllTargets:
    tgts = await Get(
        Targets,
        RawSpecsWithoutFileOwners(
            recursive_globs=(RecursiveGlobSpec(""), ),
            description_of_origin="the `AllTargets` rule"),
    )
    return AllTargets(tgts)
Пример #4
0
def test_resolve_with_a_jar(rule_runner: RuleRunner) -> None:

    rule_runner.write_files({
        "BUILD":
        textwrap.dedent("""\
            jvm_artifact(
              name="jeremy",
              group="jeremy",
              artifact="jeremy",
              version="4.13.2",
              jar="jeremy.jar",
            )
            """),
        "jeremy.jar":
        "hello dave",
    })

    targets = rule_runner.request(Targets, [
        RawSpecs(recursive_globs=(RecursiveGlobSpec(""), ),
                 description_of_origin="tests")
    ])
    jeremy_target = targets[0]

    jar_field = jeremy_target[JvmArtifactJarSourceField]

    requirement = ArtifactRequirement(
        coordinate=Coordinate(
            group="jeremy",
            artifact="jeremy",
            version="4.13.2",
        ),
        jar=jar_field,
    )

    resolved_lockfile = rule_runner.request(
        CoursierResolvedLockfile,
        [ArtifactRequirements([requirement])],
    )

    coordinate = requirement.coordinate
    assert resolved_lockfile == CoursierResolvedLockfile(
        entries=(CoursierLockfileEntry(
            coord=Coordinate(group=coordinate.group,
                             artifact=coordinate.artifact,
                             version=coordinate.version),
            file_name=
            f"{coordinate.group}_{coordinate.artifact}_{coordinate.version}.jar",
            direct_dependencies=Coordinates([]),
            dependencies=Coordinates([]),
            file_digest=FileDigest(
                fingerprint=
                "55b9afa8d7776cd6c318eec51f506e9c7f66c247dcec343d4667f5f269714f86",
                serialized_bytes_length=10,
            ),
            pants_address=jar_field.address.spec,
        ), ))
Пример #5
0
def test_get_target_data(rule_runner: RuleRunner) -> None:
    rule_runner.write_files({
        "foo/BUILD":
        dedent("""\
            target(name="bar", dependencies=[":baz"])

            files(name="baz", sources=["*.txt"])
            """),
        "foo/a.txt":
        "",
        "foo/b.txt":
        "",
    })
    tds = rule_runner.request(
        TargetDatas,
        [
            RawSpecs(recursive_globs=(RecursiveGlobSpec("foo"), ),
                     description_of_origin="tests")
        ],
    )
    assert list(tds) == [
        TargetData(
            GenericTarget({"dependencies": [":baz"]},
                          Address("foo", target_name="bar")),
            None,
            ("foo/a.txt:baz", "foo/b.txt:baz"),
        ),
        TargetData(
            FilesGeneratorTarget({"sources": ["*.txt"]},
                                 Address("foo", target_name="baz")),
            ("foo/a.txt", "foo/b.txt"),
            ("foo/a.txt:baz", "foo/b.txt:baz"),
        ),
        TargetData(
            FileTarget({"source": "a.txt"},
                       Address("foo",
                               relative_file_path="a.txt",
                               target_name="baz")),
            ("foo/a.txt", ),
            (),
        ),
        TargetData(
            FileTarget({"source": "b.txt"},
                       Address("foo",
                               relative_file_path="b.txt",
                               target_name="baz")),
            ("foo/b.txt", ),
            (),
        ),
    ]
Пример #6
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
Пример #7
0
    def run(enable_resolves: bool) -> ExportResults:
        rule_runner.set_options(
            [
                f"--python-interpreter-constraints=['=={current_interpreter}']",
                "--python-resolves={'a': 'lock.txt', 'b': 'lock.txt'}",
                f"--python-enable-resolves={enable_resolves}",
                # Turn off lockfile validation to make the test simpler.
                "--python-invalid-lockfile-behavior=ignore",
            ],
            env_inherit={"PATH", "PYENV_ROOT"},
        )
        targets = rule_runner.request(
            Targets,
            [
                RawSpecs(recursive_globs=(RecursiveGlobSpec("src/foo"), ),
                         description_of_origin="tests")
            ],
        )
        all_results = rule_runner.request(ExportResults,
                                          [ExportVenvsRequest(targets)])

        for result in all_results:
            assert len(result.post_processing_cmds) == 2

            ppc0 = result.post_processing_cmds[0]
            assert ppc0.argv[1:] == (
                # The first arg is the full path to the python interpreter, which we
                # don't easily know here, so we ignore it in this comparison.
                os.path.join("{digest_root}", ".", "pex"),
                os.path.join("{digest_root}", "requirements.pex"),
                "venv",
                "--pip",
                "--collisions-ok",
                "--remove=all",
                f"{{digest_root}}/{current_interpreter}",
            )
            assert ppc0.extra_env == FrozenDict({"PEX_MODULE": "pex.tools"})

            ppc1 = result.post_processing_cmds[1]
            assert ppc1.argv == (
                "rm",
                "-f",
                os.path.join("{digest_root}", ".", "pex"),
            )
            assert ppc1.extra_env == FrozenDict()

        return all_results
Пример #8
0
def test_filtered_targets(rule_runner: RuleRunner) -> None:
    rule_runner.write_files({
        "addr_specs/f1.txt":
        "",
        "addr_specs/f2.txt":
        "",
        "addr_specs/BUILD":
        dedent("""\
                file_generator(
                    sources=["*.txt"],
                    tags=["a"],
                    overrides={"f2.txt": {"tags": ["b"]}},
                )
                nonfile_generator(name="nonfile", tags=["b"])

                target(name='t', tags=["a"])
                """),
        "fs_specs/f1.txt":
        "",
        "fs_specs/f2.txt":
        "",
        "fs_specs/BUILD":
        dedent("""\
                file_generator(
                    sources=["*.txt"],
                    tags=["a"],
                    overrides={"f2.txt": {"tags": ["b"]}},
                )

                target(name='t', sources=["f1.txt"], tags=["a"])
                """),
    })
    specs = RawSpecs(
        recursive_globs=(RecursiveGlobSpec("addr_specs"), ),
        file_globs=(FileGlobSpec("fs_specs/*.txt"), ),
        filter_by_global_options=True,
        description_of_origin="tests",
    )

    def check(tags_option: str | None, expected: set[Address]) -> None:
        if tags_option:
            rule_runner.set_options([f"--tag={tags_option}"])
        addresses = rule_runner.request(Addresses, [specs])
        result = rule_runner.request(FilteredTargets, [addresses])
        assert {t.address for t in result} == expected

    addr_f1 = Address("addr_specs", relative_file_path="f1.txt")
    addr_f2 = Address("addr_specs", relative_file_path="f2.txt")
    addr_gen = Address("addr_specs",
                       target_name="nonfile",
                       generated_name="gen")
    addr_direct = Address("addr_specs", target_name="t")

    fs_f1 = Address("fs_specs", relative_file_path="f1.txt")
    fs_f2 = Address("fs_specs", relative_file_path="f2.txt")
    fs_direct = Address("fs_specs", target_name="t")

    all_a_tags = {addr_f1, addr_direct, fs_f1, fs_direct}
    all_b_tags = {addr_gen, addr_f2, fs_f2}

    check(None, {*all_a_tags, *all_b_tags})
    check("a", all_a_tags)
    check("b", all_b_tags)
    check("-a", all_b_tags)
    check("-b", all_a_tags)
Пример #9
0
def test_raw_specs_without_file_owners_parametrize(
    rule_runner: RuleRunner, ) -> None:
    rule_runner.write_files({
        "demo/f.txt":
        "",
        "demo/BUILD":
        dedent("""\
                file_generator(sources=['f.txt'], resolve=parametrize("a", "b"))
                nonfile_generator(name="nonfile", resolve=parametrize("a", "b"))
                target(sources=['f.txt'], name="not_gen", resolve=parametrize("a", "b"))
                """),
    })

    def assert_resolved(spec: Spec, expected: set[Address]) -> None:
        assert set(resolve_raw_specs_without_file_owners(rule_runner,
                                                         [spec])) == expected

    not_gen_resolve_a = Address("demo",
                                target_name="not_gen",
                                parameters={"resolve": "a"})
    not_gen_resolve_b = Address("demo",
                                target_name="not_gen",
                                parameters={"resolve": "b"})
    file_generator_resolve_a = {
        Address("demo",
                relative_file_path="f.txt",
                parameters={"resolve": "a"}),
        Address("demo", parameters={"resolve": "a"}),
    }
    file_generator_resolve_b = {
        Address("demo",
                relative_file_path="f.txt",
                parameters={"resolve": "b"}),
        Address("demo", parameters={"resolve": "b"}),
    }
    nonfile_generator_resolve_a = {
        Address("demo",
                target_name="nonfile",
                generated_name="gen",
                parameters={"resolve": "a"}),
        Address("demo", target_name="nonfile", parameters={"resolve": "a"}),
    }
    nonfile_generator_resolve_b = {
        Address("demo",
                target_name="nonfile",
                generated_name="gen",
                parameters={"resolve": "b"}),
        Address("demo", target_name="nonfile", parameters={"resolve": "b"}),
    }

    assert_resolved(
        RecursiveGlobSpec(""),
        {
            *file_generator_resolve_a,
            *file_generator_resolve_b,
            *nonfile_generator_resolve_a,
            *nonfile_generator_resolve_b,
            not_gen_resolve_a,
            not_gen_resolve_b,
        },
    )

    # A literal address for a parameterized target works as expected.
    assert_resolved(
        AddressLiteralSpec("demo",
                           target_component="not_gen",
                           parameters=FrozenDict({"resolve": "a"})),
        {not_gen_resolve_a},
    )
    assert_resolved(
        AddressLiteralSpec("demo/f.txt",
                           parameters=FrozenDict({"resolve": "a"})),
        {
            Address("demo",
                    relative_file_path="f.txt",
                    parameters={"resolve": "a"})
        },
    )
    assert_resolved(
        AddressLiteralSpec("demo",
                           "nonfile",
                           generated_component="gen",
                           parameters=FrozenDict({"resolve": "a"})),
        {
            Address("demo",
                    target_name="nonfile",
                    generated_name="gen",
                    parameters={"resolve": "a"})
        },
    )
    assert_resolved(
        # A direct reference to the parametrized target generator.
        AddressLiteralSpec("demo", parameters=FrozenDict({"resolve": "a"})),
        {Address("demo", parameters={"resolve": "a"})},
    )

    # A literal address for a parametrized template should be expanded with the matching targets.
    assert_resolved(
        AddressLiteralSpec("demo", target_component="not_gen"),
        {not_gen_resolve_a, not_gen_resolve_b},
    )

    # The above affordance plays nicely with target generation.
    assert_resolved(
        # Note that this returns references to the two target generators. Certain goals like
        # `test` may then later replace those with their generated targets.
        AddressLiteralSpec("demo"),
        {Address("demo", parameters={"resolve": r})
         for r in ("a", "b")},
    )
    assert_resolved(
        AddressLiteralSpec("demo", "nonfile", "gen"),
        {
            Address("demo",
                    target_name="nonfile",
                    generated_name="gen",
                    parameters={"resolve": r})
            for r in ("a", "b")
        },
    )
    assert_resolved(
        AddressLiteralSpec("demo/f.txt"),
        {
            Address(
                "demo", relative_file_path="f.txt", parameters={"resolve": r})
            for r in ("a", "b")
        },
    )

    # Error on invalid targets.
    def assert_errors(spec: AddressLiteralSpec) -> None:
        with engine_error(ValueError):
            resolve_raw_specs_without_file_owners(rule_runner, [spec])

    assert_errors(
        AddressLiteralSpec("demo", parameters=FrozenDict({"fake": "v"})))
    assert_errors(
        AddressLiteralSpec("demo", parameters=FrozenDict({"resolve": "fake"})))
Пример #10
0
def test_raw_specs_without_file_owners_literals_vs_globs(
        rule_runner: RuleRunner) -> None:
    rule_runner.write_files({
        "demo/BUILD":
        dedent("""\
                file_generator(sources=['**/*.txt'])
                nonfile_generator(name="nonfile")
                """),
        "demo/f1.txt":
        "",
        "demo/f2.txt":
        "",
        "demo/f[3].txt":
        "",
        "demo/subdir/f.txt":
        "",
        "demo/subdir/f.another_ext":
        "",
        "demo/subdir/BUILD":
        "target(name='another_ext', sources=['f.another_ext'])",
        "another_dir/BUILD":
        "target(sources=[])",
    })

    def assert_resolved(spec: Spec, expected: set[Address]) -> None:
        result = resolve_raw_specs_without_file_owners(rule_runner, [spec])
        assert set(result) == expected

    # Literals should be "one-in, one-out".
    assert_resolved(AddressLiteralSpec("demo"), {Address("demo")})
    assert_resolved(AddressLiteralSpec("demo/f1.txt"),
                    {Address("demo", relative_file_path="f1.txt")})
    assert_resolved(
        AddressLiteralSpec("demo",
                           target_component="nonfile",
                           generated_component="gen"),
        {Address("demo", target_name="nonfile", generated_name="gen")},
    )
    assert_resolved(
        AddressLiteralSpec("demo/subdir", target_component="another_ext"),
        {Address("demo/subdir", target_name="another_ext")},
    )

    demo_dir_generated_targets = {
        Address("demo", relative_file_path="f1.txt"),
        Address("demo", relative_file_path="f2.txt"),
        Address("demo", relative_file_path="f[[]3].txt"),
        Address("demo", target_name="nonfile", generated_name="gen"),
    }
    demo_subdir_generated_targets = {
        Address("demo", relative_file_path="subdir/f.txt"),
        Address("demo/subdir", target_name="another_ext"),
    }

    # `DirGlobSpec` matches all targets that "reside" in the directory, either because explicitly
    # declared there or generated into that dir.
    assert_resolved(
        # Note that this does not include `demo/subdir/f2.ext:../demo`, even though its target
        # generator matches.
        DirGlobSpec("demo"),
        {
            Address("demo"),
            Address("demo", target_name="nonfile"), *demo_dir_generated_targets
        },
    )
    assert_resolved(
        # Should include all generated targets that reside in `demo/subdir`, even though their
        # target generator is in an ancestor.
        DirGlobSpec("demo/subdir"),
        demo_subdir_generated_targets,
    )

    # `DirLiteralSpec` matches all targets that "reside" in the directory, but it filters out
    # target generators.
    assert_resolved(DirLiteralSpec("demo"), demo_dir_generated_targets)
    assert_resolved(DirLiteralSpec("demo/subdir"),
                    demo_subdir_generated_targets)

    all_tgts_in_demo = {
        Address("demo"),
        Address("demo", target_name="nonfile"),
        *demo_dir_generated_targets,
        *demo_subdir_generated_targets,
    }
    assert_resolved(RecursiveGlobSpec("demo"), all_tgts_in_demo)

    assert_resolved(AncestorGlobSpec("demo/subdir"), all_tgts_in_demo)
    assert_resolved(
        AncestorGlobSpec("demo"),
        {
            Address("demo"),
            Address("demo", target_name="nonfile"),
            Address("demo", target_name="nonfile", generated_name="gen"),
            Address("demo", relative_file_path="f1.txt"),
            Address("demo", relative_file_path="f2.txt"),
            Address("demo", relative_file_path="f[[]3].txt"),
        },
    )
Пример #11
0
def recursive_glob(directory: str) -> RecursiveGlobSpec:
    return RecursiveGlobSpec(directory)
Пример #12
0
def test_recursive_glob() -> None:
    spec = RecursiveGlobSpec("dir/subdir")
    assert spec.to_glob() == "dir/subdir/**"
    assert spec.matches_target_residence_dir("") is False
    assert spec.matches_target_residence_dir("dir") is False
    assert spec.matches_target_residence_dir("dir/subdir") is True
    assert spec.matches_target_residence_dir("dir/subdir/nested") is True
    assert spec.matches_target_residence_dir("dir/subdir/nested/again") is True
    assert spec.matches_target_residence_dir("another/subdir") is False
    assert_build_file_globs(
        RawSpecsWithoutFileOwners(recursive_globs=(spec,), description_of_origin="tests"),
        expected_build_globs={"BUILD", "dir/BUILD", "dir/subdir/BUILD", "dir/subdir/**/BUILD"},
        expected_validation_globs={"dir/subdir/**"},
    )

    spec = RecursiveGlobSpec("")
    assert spec.to_glob() == "**"
    assert spec.matches_target_residence_dir("") is True
    assert spec.matches_target_residence_dir("dir") is True
    assert spec.matches_target_residence_dir("another_dir") is True
    assert_build_file_globs(
        RawSpecsWithoutFileOwners(recursive_globs=(spec,), description_of_origin="tests"),
        expected_build_globs={"BUILD", "**/BUILD"},
        expected_validation_globs={"**"},
    )