Exemplo n.º 1
0
    def test_single_language_with_multiple_targets(self) -> None:
        addresses = [Address.parse(":t1"), Address.parse(":t2")]

        def get_stderr(*, per_target_caching: bool) -> str:
            stderr = self.run_fmt_rule(
                language_target_collection_types=[FortranTargets],
                targets=[
                    self.make_target_with_origin(addr) for addr in addresses
                ],
                result_digest=self.fortran_digest,
                per_target_caching=per_target_caching,
            )
            self.assert_workspace_modified(fortran_formatted=True,
                                           smalltalk_formatted=False)
            return stderr

        assert get_stderr(per_target_caching=False) == dedent(f"""\
            𐄂 FortranFormatter made changes.
            {FortranTargets.stdout(addresses)}
            """)
        assert get_stderr(per_target_caching=True) == dedent(f"""\
            𐄂 FortranFormatter made changes.
            {FortranTargets.stdout([addresses[0]])}

            𐄂 FortranFormatter made changes.
            {FortranTargets.stdout([addresses[1]])}
            """)
Exemplo n.º 2
0
    def test_summary(self) -> None:
        """Test that we render the summary correctly.

        This tests that we:
        * Merge multiple results belonging to the same linter (`--per-file-caching`).
        * Decide correctly between skipped, failed, and succeeded.
        """
        good_address = Address.parse(":good")
        bad_address = Address.parse(":bad")

        def assert_expected(*, per_file_caching: bool) -> None:
            exit_code, stderr = self.run_lint_rule(
                lint_request_types=[
                    ConditionallySucceedsRequest,
                    FailingRequest,
                    SkippedRequest,
                    SuccessfulRequest,
                ],
                targets=[self.make_target(good_address), self.make_target(bad_address)],
                per_file_caching=per_file_caching,
            )
            assert exit_code == FailingRequest.exit_code([bad_address])
            assert stderr == dedent(
                """\

                𐄂 ConditionallySucceedsLinter failed.
                𐄂 FailingLinter failed.
                - SkippedLinter skipped.
                ✓ SuccessfulLinter succeeded.
                """
            )

        assert_expected(per_file_caching=False)
        assert_expected(per_file_caching=True)
Exemplo n.º 3
0
    def test_summary(self) -> None:
        good_address = Address.parse(":good")
        bad_address = Address.parse(":bad")
        exit_code, stderr = self.run_typecheck_rule(
            request_types=[
                ConditionallySucceedsRequest,
                FailingRequest,
                SkippedRequest,
                SuccessfulRequest,
            ],
            targets=[
                self.make_target(good_address),
                self.make_target(bad_address),
            ],
        )
        assert exit_code == FailingRequest.exit_code([bad_address])
        assert stderr == dedent(
            """\

            𐄂 ConditionallySucceedsTypechecker failed.
            𐄂 FailingTypechecker failed.
            - SkippedTypechecker skipped.
            ✓ SuccessfulTypechecker succeeded.
            """
        )
Exemplo n.º 4
0
def test_filter_by_target_type() -> None:
    class Fortran(Target):
        alias = "fortran"
        core_fields = ()

    class Smalltalk(Target):
        alias = "smalltalk"
        core_fields = ()

    fortran_targets = [
        Fortran({}, address=Address.parse(addr)) for addr in (":f1", ":f2")
    ]
    smalltalk_targets = [
        Smalltalk({}, address=Address.parse(addr)) for addr in (":s1", ":s2")
    ]
    targets = [*fortran_targets, *smalltalk_targets]

    assert run_goal(targets, target_type=["fortran"]).strip() == "//:f1\n//:f2"
    assert run_goal(targets,
                    target_type=["+smalltalk"]).strip() == "//:s1\n//:s2"
    assert run_goal(targets,
                    target_type=["-smalltalk"]).strip() == "//:f1\n//:f2"
    # The comma is inside the string, so these are ORed.
    assert run_goal(targets, target_type=["fortran,smalltalk"]) == dedent("""\
        //:f1
        //:f2
        //:s1
        //:s2
        """)

    # A target can only have one type, so this output should be empty.
    assert run_goal(targets, target_type=["fortran", "smalltalk"]) == ""

    with pytest.raises(UnrecognizedTargetTypeException):
        run_goal(targets, target_type=["invalid"])
Exemplo n.º 5
0
 def assert_injected(deps_cls: Type[Dependencies], *, injected: List[str]) -> None:
     provided_addr = Address.parse("//:provided")
     deps_field = deps_cls([provided_addr], address=Address.parse("//:target"))
     result = self.request_single_product(Addresses, DependenciesRequest(deps_field))
     assert result == Addresses(
         sorted([provided_addr, *(Address.parse(addr) for addr in injected)])
     )
Exemplo n.º 6
0
    def test_multiple_targets_with_multiple_linters(self) -> None:
        good_address = Address.parse(":good")
        bad_address = Address.parse(":bad")

        def get_stdout(*, per_target_caching: bool) -> str:
            exit_code, stdout = self.run_lint_rule(
                config_collection_types=[
                    ConditionallySucceedsConfigurations,
                    SuccessfulConfigurations,
                ],
                targets=[
                    self.make_target_with_origin(good_address),
                    self.make_target_with_origin(bad_address),
                ],
                per_target_caching=per_target_caching,
            )
            assert exit_code == ConditionallySucceedsConfigurations.exit_code([bad_address])
            return stdout

        stdout = get_stdout(per_target_caching=False)
        assert stdout.splitlines() == [
            config_collection.stdout([good_address, bad_address])
            for config_collection in [ConditionallySucceedsConfigurations, SuccessfulConfigurations]
        ]

        stdout = get_stdout(per_target_caching=True)
        assert stdout.splitlines() == [
            config_collection.stdout([address])
            for config_collection in [ConditionallySucceedsConfigurations, SuccessfulConfigurations]
            for address in [good_address, bad_address]
        ]
Exemplo n.º 7
0
def test_get_field() -> None:
    extensions = ("FortranExt1",)
    tgt = FortranTarget({FortranExtensions.alias: extensions}, address=Address.parse(":lib"))

    assert tgt[FortranExtensions].value == extensions
    assert tgt.get(FortranExtensions).value == extensions
    assert tgt.get(FortranExtensions, default_raw_value=["FortranExt2"]).value == extensions

    # Default field value. This happens when the field is registered on the target type, but the
    # user does not explicitly set the field in the BUILD file.
    #
    # NB: `default_raw_value` is not used in this case - that parameter is solely used when
    # the field is not registered on the target type. To override the default field value, either
    # subclass the Field and create a new target, or, in your call site, interpret the result and
    # and apply your default.
    default_field_tgt = FortranTarget({}, address=Address.parse(":default"))
    assert default_field_tgt[FortranExtensions].value == ()
    assert default_field_tgt.get(FortranExtensions).value == ()
    assert default_field_tgt.get(FortranExtensions, default_raw_value=["FortranExt2"]).value == ()
    # Example of a call site applying its own default value instead of the field's default value.
    assert default_field_tgt[FortranExtensions].value or 123 == 123

    # Field is not registered on the target.
    with pytest.raises(KeyError) as exc:
        default_field_tgt[UnrelatedField]
    assert UnrelatedField.__name__ in str(exc)
    assert default_field_tgt.get(UnrelatedField).value == UnrelatedField.default
    assert default_field_tgt.get(
        UnrelatedField, default_raw_value=not UnrelatedField.default
    ).value == (not UnrelatedField.default)
Exemplo n.º 8
0
    def test_map_third_party_modules_to_addresses(self) -> None:
        self.add_to_build_file(
            "3rdparty/python",
            dedent("""\
                python_requirement_library(
                  name='ansicolors',
                  requirements=['ansicolors==1.21'],
                  module_mapping={'ansicolors': ['colors']},
                )

                python_requirement_library(
                  name='req1',
                  requirements=['req1', 'two_owners'],
                )

                python_requirement_library(
                  name='un_normalized',
                  requirements=['Un-Normalized-Project>3', 'two_owners'],
                )
                """),
        )
        result = self.request_single_product(
            ThirdPartyModuleToAddressMapping,
            Params(create_options_bootstrapper()))
        assert result.mapping == FrozenDict({
            "colors":
            Address.parse("3rdparty/python:ansicolors"),
            "req1":
            Address.parse("3rdparty/python:req1"),
            "un_normalized_project":
            Address.parse("3rdparty/python:un_normalized"),
        })
Exemplo n.º 9
0
def test_add_custom_fields() -> None:
    class CustomField(BoolField):
        alias: ClassVar = "custom_field"
        default: ClassVar = False

    union_membership = UnionMembership({FortranTarget.PluginField: [CustomField]})
    tgt_values = {CustomField.alias: True}
    tgt = FortranTarget(
        tgt_values, address=Address.parse(":lib"), union_membership=union_membership
    )

    assert tgt.field_types == (FortranExtensions, FortranSources, CustomField)
    assert tgt.core_fields == (FortranExtensions, FortranSources)
    assert tgt.plugin_fields == (CustomField,)
    assert tgt.has_field(CustomField) is True

    assert FortranTarget.class_field_types(union_membership=union_membership) == (
        FortranExtensions,
        FortranSources,
        CustomField,
    )
    assert FortranTarget.class_has_field(CustomField, union_membership=union_membership) is True

    assert tgt[CustomField].value is True

    default_tgt = FortranTarget(
        {}, address=Address.parse(":default"), union_membership=union_membership
    )
    assert default_tgt[CustomField].value is False
Exemplo n.º 10
0
    def test_dependency_inference(self) -> None:
        self.add_to_build_file(
            "",
            dedent("""\
                smalltalk(name='inferred1')
                smalltalk(name='inferred2')
                smalltalk(name='inferred3')
                smalltalk(name='provided')
                """),
        )
        self.create_file("demo/f1.st", "//:inferred1\n//:inferred2\n")
        self.create_file("demo/f2.st", "//:inferred3\n")
        self.add_to_build_file(
            "demo",
            "smalltalk(sources=['*.st'], dependencies=['//:provided'])")

        deps_field = Dependencies([Address.parse("//:provided")],
                                  address=Address.parse("demo"))
        result = self.request_single_product(
            Addresses,
            Params(
                DependenciesRequest(deps_field),
                create_options_bootstrapper(args=["--dependency-inference"]),
            ),
        )
        assert result == Addresses(
            sorted(
                Address.parse(addr) for addr in [
                    "//:inferred1", "//:inferred2", "//:inferred3",
                    "//:provided"
                ]))
Exemplo n.º 11
0
 def test_map_first_party_modules_to_addresses(self) -> None:
     options_bootstrapper = create_options_bootstrapper(args=[
         "--source-root-patterns=['src/python', 'tests/python', 'build-support']"
     ])
     util_addr = Address.parse("src/python/project/util")
     self.create_files("src/python/project/util",
                       ["dirutil.py", "tarutil.py"])
     self.add_to_build_file("src/python/project/util", "python_library()")
     # A module with two owners should not be resolved.
     self.create_file("src/python/two_owners.py")
     self.add_to_build_file("src/python", "python_library()")
     self.create_file("build-support/two_owners.py")
     self.add_to_build_file("build-support", "python_library()")
     # A package module
     self.create_file("tests/python/project_test/demo_test/__init__.py")
     self.add_to_build_file("tests/python/project_test/demo_test",
                            "python_library()")
     result = self.request_single_product(FirstPartyModuleToAddressMapping,
                                          options_bootstrapper)
     assert result.mapping == FrozenDict({
         "project.util.dirutil":
         util_addr,
         "project.util.tarutil":
         util_addr,
         "project_test.demo_test":
         Address.parse("tests/python/project_test/demo_test"),
     })
Exemplo n.º 12
0
 def test_timeout_validation(self) -> None:
     with pytest.raises(InvalidFieldException):
         PythonTestsTimeout(-100, address=Address.parse(":tests"))
     with pytest.raises(InvalidFieldException):
         PythonTestsTimeout(0, address=Address.parse(":tests"))
     assert PythonTestsTimeout(5,
                               address=Address.parse(":tests")).value == 5
Exemplo n.º 13
0
    def test_multiple_languages_with_single_targets(self) -> None:
        fortran_address = Address.parse(":fortran")
        smalltalk_address = Address.parse(":smalltalk")

        def assert_expected(*, per_target_caching: bool) -> None:
            stdout = self.run_fmt_rule(
                language_target_collection_types=[
                    FortranTargets, SmalltalkTargets
                ],
                targets=[
                    self.make_target_with_origin(fortran_address,
                                                 target_cls=FortranTarget),
                    self.make_target_with_origin(smalltalk_address,
                                                 target_cls=SmalltalkTarget),
                ],
                result_digest=self.merged_digest,
                per_target_caching=per_target_caching,
            )
            assert stdout.splitlines() == [
                FortranTargets.stdout([fortran_address]),
                SmalltalkTargets.stdout([smalltalk_address]),
            ]
            self.assert_workspace_modified(fortran_formatted=True,
                                           smalltalk_formatted=True)

        assert_expected(per_target_caching=False)
        assert_expected(per_target_caching=True)
Exemplo n.º 14
0
    def test_multiple_languages_with_single_targets(self) -> None:
        fortran_address = Address.parse(":fortran")
        smalltalk_address = Address.parse(":smalltalk")

        def assert_expected(*, per_target_caching: bool) -> None:
            stderr = self.run_fmt_rule(
                language_target_collection_types=[FortranTargets, SmalltalkTargets],
                targets=[
                    self.make_target(fortran_address, target_cls=FortranTarget),
                    self.make_target(smalltalk_address, target_cls=SmalltalkTarget),
                ],
                result_digest=self.merged_digest,
                per_target_caching=per_target_caching,
            )
            assert stderr == dedent(
                f"""\
                𐄂 FortranFormatter made changes.
                {FortranTargets.stdout([fortran_address])}

                𐄂 SmalltalkFormatter made changes.
                {SmalltalkTargets.stdout([smalltalk_address])}
                """
            )
            self.assert_workspace_modified(fortran_formatted=True, smalltalk_formatted=True)

        assert_expected(per_target_caching=False)
        assert_expected(per_target_caching=True)
Exemplo n.º 15
0
    def test_multiple_targets_with_one_linter(self) -> None:
        good_address = Address.parse(":good")
        bad_address = Address.parse(":bad")

        def get_stderr(*, per_target_caching: bool) -> str:
            exit_code, stderr = self.run_lint_rule(
                lint_request_types=[ConditionallySucceedsRequest],
                targets=[self.make_target(good_address), self.make_target(bad_address),],
                per_target_caching=per_target_caching,
            )
            assert exit_code == ConditionallySucceedsRequest.exit_code([bad_address])
            return stderr

        assert get_stderr(per_target_caching=False) == dedent(
            f"""\
            𐄂 ConditionallySucceedsLinter failed.
            {ConditionallySucceedsRequest.stdout([good_address, bad_address])}
            """
        )

        assert get_stderr(per_target_caching=True) == dedent(
            f"""\
            ✓ ConditionallySucceedsLinter succeeded.
            {ConditionallySucceedsRequest.stdout([good_address])}

            𐄂 ConditionallySucceedsLinter failed.
            {ConditionallySucceedsRequest.stdout([bad_address])}
            """
        )
Exemplo n.º 16
0
def test_list_provides() -> None:
    sample_artifact = PythonArtifact(name="project.demo", version="0.0.0.1")
    targets = [
        MockTarget({ProvidesField.alias: sample_artifact}, address=Address.parse(":provided")),
        MockTarget({}, address=Address.parse(":not_provided")),
    ]
    stdout, _ = run_goal(targets, show_provides=True)
    assert stdout.strip() == f"//:provided {sample_artifact}"
Exemplo n.º 17
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)
Exemplo n.º 18
0
 def test_multiple_debug_targets_fail(self) -> None:
     with pytest.raises(ResolveError):
         self.run_test_rule(
             config=SuccessfulConfiguration,
             targets=[
                 self.make_target_with_origin(Address.parse(":t1")),
                 self.make_target_with_origin(Address.parse(":t2")),
             ],
             debug=True,
         )
Exemplo n.º 19
0
 def test_coverage(self) -> None:
     addr1 = Address.parse(":t1")
     addr2 = Address.parse(":t2")
     exit_code, stderr = self.run_test_rule(
         field_set=SuccessfulFieldSet,
         targets=[self.make_target_with_origin(addr1), self.make_target_with_origin(addr2)],
         use_coverage=True,
     )
     assert exit_code == 0
     assert stderr.strip().endswith(f"Ran coverage on {addr1.spec}, {addr2.spec}")
Exemplo n.º 20
0
    def test_infer_python_dependencies(self) -> None:
        options_bootstrapper = create_options_bootstrapper(
            args=["--source-root-patterns=src/python"]
        )
        self.add_to_build_file(
            "3rdparty/python",
            dedent(
                """\
                python_requirement_library(
                  name='Django',
                  requirements=[python_requirement('Django==1.21')],
                )
                """
            ),
        )

        self.create_file("src/python/no_owner/f.py")
        self.add_to_build_file("src/python/no_owner", "python_library()")

        self.create_file("src/python/util/dep.py")
        self.add_to_build_file("src/python/util", "python_library()")

        self.create_file(
            "src/python/app.py",
            dedent(
                """\
                import django

                from util.dep import Demo
                from util import dep
                """
            ),
        )
        self.create_file(
            "src/python/f2.py",
            dedent(
                """\
                import typing
                # Import from another file in the same target.
                from app import main
                """
            ),
        )
        self.add_to_build_file("src/python", "python_library()")

        tgt = self.request_single_product(WrappedTarget, Address.parse("src/python")).target
        result = self.request_single_product(
            InferredDependencies,
            Params(InferPythonDependencies(tgt[PythonSources]), options_bootstrapper),
        )
        assert result == InferredDependencies(
            [Address.parse("3rdparty/python:Django"), Address.parse("src/python/util")]
        )
Exemplo n.º 21
0
def test_generate_subtarget() -> None:
    class MockTarget(Target):
        alias = "mock_target"
        core_fields = (Dependencies, Tags, Sources)

    # When the target already only has a single source, the result should be the same, except for a
    # different address.
    single_source_tgt = MockTarget(
        {Sources.alias: ["demo.f95"], Tags.alias: ["demo"]},
        address=Address.parse("src/fortran:demo"),
    )
    expected_single_source_address = Address(
        "src/fortran", relative_file_path="demo.f95", target_name="demo"
    )
    assert generate_subtarget(
        single_source_tgt, full_file_name="src/fortran/demo.f95"
    ) == MockTarget(
        {Sources.alias: ["demo.f95"], Tags.alias: ["demo"]}, address=expected_single_source_address
    )
    assert (
        generate_subtarget_address(single_source_tgt.address, full_file_name="src/fortran/demo.f95")
        == expected_single_source_address
    )

    subdir_tgt = MockTarget(
        {Sources.alias: ["demo.f95", "subdir/demo.f95"]}, address=Address.parse("src/fortran:demo")
    )
    expected_subdir_address = Address(
        "src/fortran", relative_file_path="subdir/demo.f95", target_name="demo"
    )
    assert generate_subtarget(
        subdir_tgt, full_file_name="src/fortran/subdir/demo.f95"
    ) == MockTarget({Sources.alias: ["subdir/demo.f95"]}, address=expected_subdir_address)
    assert (
        generate_subtarget_address(subdir_tgt.address, full_file_name="src/fortran/subdir/demo.f95")
        == expected_subdir_address
    )

    # The full_file_name must match the filespec of the base target's Sources field.
    with pytest.raises(ValueError) as exc:
        generate_subtarget(single_source_tgt, full_file_name="src/fortran/fake_file.f95")
    assert "does not match a file src/fortran/fake_file.f95" in str(exc.value)

    class MissingFieldsTarget(Target):
        alias = "missing_fields_tgt"
        core_fields = (Tags,)

    missing_fields_tgt = MissingFieldsTarget(
        {Tags.alias: ["demo"]}, address=Address("", target_name="missing_fields")
    )
    with pytest.raises(ValueError) as exc:
        generate_subtarget(missing_fields_tgt, full_file_name="fake.txt")
    assert "does not have both a `dependencies` and `sources` field" in str(exc.value)
Exemplo n.º 22
0
    def test_normal_resolution(self) -> None:
        self.add_to_build_file("src/smalltalk", "smalltalk()")
        addr = Address.parse("src/smalltalk")
        deps = Addresses([Address.parse("//:dep1"), Address.parse("//:dep2")])
        deps_field = Dependencies(deps, address=addr)
        assert self.request_single_product(Addresses, DependenciesRequest(deps_field)) == deps

        # Also test that we handle no dependencies.
        empty_deps_field = Dependencies(None, address=addr)
        assert self.request_single_product(
            Addresses, DependenciesRequest(empty_deps_field)
        ) == Addresses([])
Exemplo n.º 23
0
    def test_resolve_cache(self) -> None:
        scheduler = self.create_json()

        nonstrict_address = Address.parse("graph_test:nonstrict")
        nonstrict = self.resolve(scheduler, nonstrict_address)
        self.assertEqual(nonstrict, self.resolve(scheduler, nonstrict_address))

        # The already resolved `nonstrict` interior node should be re-used by `java1`.
        java1_address = Address.parse("graph_test:java1")
        java1 = self.resolve(scheduler, java1_address)
        self.assertEqual(nonstrict, java1.configurations[1])

        self.assertEqual(java1, self.resolve(scheduler, java1_address))
Exemplo n.º 24
0
def test_third_party_modules_mapping() -> None:
    colors_addr = Address.parse("//:ansicolors")
    pants_addr = Address.parse("//:pantsbuild")
    mapping = ThirdPartyModuleToAddressMapping(
        FrozenDict({
            "colors": colors_addr,
            "pants": pants_addr
        }))
    assert mapping.address_for_module("colors") == colors_addr
    assert mapping.address_for_module("colors.red") == colors_addr
    assert mapping.address_for_module("pants") == pants_addr
    assert mapping.address_for_module("pants.task") == pants_addr
    assert mapping.address_for_module("pants.task.task") == pants_addr
    assert mapping.address_for_module("pants.task.task.Task") == pants_addr
Exemplo n.º 25
0
def test_field_set() -> 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 FortranFieldSet(FieldSet):
        required_fields = (FortranSources,)

        sources: FortranSources
        unrelated_field: UnrelatedField

    @dataclass(frozen=True)
    class UnrelatedFieldSet(FieldSet):
        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 FortranFieldSet.is_applicable(fortran_tgt) is True
    assert FortranFieldSet.is_applicable(unrelated_tgt) is False
    assert FortranFieldSet.is_applicable(no_fields_tgt) is False
    # When no fields are required, every target is applicable.
    for tgt in [fortran_tgt, unrelated_tgt, no_fields_tgt]:
        assert UnrelatedFieldSet.is_applicable(tgt) is True

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

    assert UnrelatedFieldSet.create(unrelated_tgt).unrelated_field.value == "configured"
    assert UnrelatedFieldSet.create(no_fields_tgt).unrelated_field.value == UnrelatedField.default
Exemplo n.º 26
0
    def test_map_module_to_targets(self) -> None:
        options_bootstrapper = create_options_bootstrapper(args=[
            "--source-root-patterns=['source_root1', 'source_root2', '/']"
        ])
        # First check that we can map 3rd-party modules.
        self.add_to_build_file(
            "3rdparty/python",
            dedent("""\
                python_requirement_library(
                  name='ansicolors',
                  requirements=[python_requirement('ansicolors==1.21', modules=['colors'])],
                )
                """),
        )
        result = self.request_single_product(
            PythonModuleOwners,
            Params(PythonModule("colors.red"), options_bootstrapper))
        assert result == PythonModuleOwners(
            [Address.parse("3rdparty/python:ansicolors")])

        # We set up the same module in two source roots to confirm we properly handle source roots.
        # The first example uses a normal module path, whereas the second uses a package path.
        self.create_file("source_root1/project/app.py")
        self.add_to_build_file("source_root1/project", "python_library()")
        self.create_file("source_root2/project/app/__init__.py")
        self.add_to_build_file("source_root2/project/app", "python_library()")
        result = self.request_single_product(
            PythonModuleOwners,
            Params(PythonModule("project.app"), options_bootstrapper))
        assert result == PythonModuleOwners([
            Address.parse("source_root1/project"),
            Address.parse("source_root2/project/app")
        ])

        # Test a module with no owner (stdlib). This also sanity checks that we can handle when
        # there is no parent module.
        result = self.request_single_product(
            PythonModuleOwners,
            Params(PythonModule("typing"), options_bootstrapper))
        assert not result

        # Test a module with a single owner with a top-level source root of ".". Also confirm we
        # can handle when the module includes a symbol (like a class name) at the end.
        self.create_file("script.py")
        self.add_to_build_file("", "python_library(name='script')")
        result = self.request_single_product(
            PythonModuleOwners,
            Params(PythonModule("script.Demo"), options_bootstrapper))
        assert result == PythonModuleOwners([Address.parse("//:script")])
Exemplo n.º 27
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),
     )
Exemplo n.º 28
0
def test_sequence_field() -> None:
    @dataclass(frozen=True)
    class CustomObject:
        pass

    class Example(SequenceField):
        alias = "example"
        expected_element_type = CustomObject
        expected_type_description = "an iterable of `CustomObject` instances"

        @classmethod
        def compute_value(
                cls, raw_value: Optional[Iterable[CustomObject]], *,
                address: Address) -> Optional[Tuple[CustomObject, ...]]:
            return super().compute_value(raw_value, address=address)

    addr = Address.parse(":example")

    def assert_flexible_constructor(raw_value: Iterable[CustomObject]) -> None:
        assert Example(raw_value, address=addr).value == tuple(raw_value)

    assert_flexible_constructor([CustomObject(), CustomObject()])
    assert_flexible_constructor((CustomObject(), CustomObject()))
    assert_flexible_constructor(OrderedSet([CustomObject(), CustomObject()]))

    # Must be given a sequence, not a single element.
    with pytest.raises(InvalidFieldTypeException) as exc:
        Example(CustomObject(), address=addr)
    assert Example.expected_type_description in str(exc.value)

    # All elements must be the expected type.
    with pytest.raises(InvalidFieldTypeException):
        Example([CustomObject(), 1, CustomObject()], address=addr)
Exemplo n.º 29
0
def test_dependencies_and_sources_fields_raw_value_sanitation() -> None:
    """Ensure that both Sources and Dependencies behave like a StringSequenceField does.

    Normally, we would use StringSequenceField. However, these are both AsyncFields, and
    StringSequenceField is a PrimitiveField, so we end up replicating that validation logic.
    """
    addr = Address.parse(":test")

    def assert_flexible_constructor(raw_value: Iterable[str]) -> None:
        assert Sources(raw_value,
                       address=addr).sanitized_raw_value == tuple(raw_value)
        assert Dependencies(
            raw_value, address=addr).sanitized_raw_value == tuple(raw_value)

    for v in [("f1.txt", "f2.txt"), ["f1.txt", "f2.txt"],
              OrderedSet(["f1.txt", "f2.txt"])]:
        assert_flexible_constructor(v)

    def assert_invalid_type(raw_value: Any) -> None:
        with pytest.raises(InvalidFieldTypeException):
            Sources(raw_value, address=addr)
        with pytest.raises(InvalidFieldTypeException):
            Dependencies(raw_value, address=addr)

    for v in [0, object(), "f1.txt"]:  # type: ignore[assignment]
        assert_invalid_type(v)
Exemplo n.º 30
0
def test_dict_string_to_string_sequence_field() -> None:
    class Example(DictStringToStringSequenceField):
        alias = "example"

    addr = Address.parse(":example")

    def assert_flexible_constructor(
            raw_value: Dict[str, Iterable[str]]) -> None:
        assert Example(raw_value, address=addr).value == FrozenDict(
            {k: tuple(v)
             for k, v in raw_value.items()})

    for v in [("hello", "world"), ["hello", "world"],
              OrderedSet(["hello", "world"])]:
        assert_flexible_constructor({"greeting": v})

    def assert_invalid_type(raw_value: Any) -> None:
        with pytest.raises(InvalidFieldTypeException):
            Example(raw_value, address=addr)

    for v in [  # type: ignore[assignment]
            0,
            object(),
            "hello",
        ["hello"],
        {
            "hello": "world"
        },
        {
            0: ["world"]
        },
    ]:
        assert_invalid_type(v)