Exemple #1
0
 def __init__(
     self,
     path: str,
     name: str,
     type_alias: str,
     triggering_sources: Iterable[str],
     owned_sources: Iterable[str],
     *,
     addressable: bool = True,
     kwargs: Mapping[str, str | int | bool | tuple[str, ...]] | None = None,
     comments: Iterable[str] = tuple(),
 ) -> None:
     self.path = path
     self.name = name
     self.type_alias = type_alias
     self.triggering_sources = tuple(triggering_sources)
     self.owned_sources = tuple(owned_sources)
     self.addressable = addressable
     self.kwargs = FrozenDict(kwargs or {})
     self.comments = tuple(comments)
Exemple #2
0
async def map_import_paths_to_packages(go_tgts: AllGoTargets) -> ImportPathToPackages:
    mapping: dict[str, list[Address]] = defaultdict(list)
    first_party_addresses = []
    first_party_gets = []
    for tgt in go_tgts:
        if tgt.has_field(GoImportPathField):
            import_path = tgt[GoImportPathField].value
            mapping[import_path].append(tgt.address)
        else:
            first_party_addresses.append(tgt.address)
            first_party_gets.append(
                Get(FirstPartyPkgImportPath, FirstPartyPkgImportPathRequest(tgt.address))
            )

    first_party_import_paths = await MultiGet(first_party_gets)
    for import_path_info, addr in zip(first_party_import_paths, first_party_addresses):
        mapping[import_path_info.import_path].append(addr)

    frozen_mapping = FrozenDict({ip: tuple(tgts) for ip, tgts in mapping.items()})
    return ImportPathToPackages(frozen_mapping)
async def map_addresses_to_dependees() -> AddressToDependees:
    # Get every target in the project so that we can iterate over them to find their dependencies.
    all_expanded_targets, all_explicit_targets = await MultiGet(
        Get(Targets, AddressSpecs([DescendantAddresses("")])),
        Get(UnexpandedTargets, AddressSpecs([DescendantAddresses("")])),
    )
    all_targets = {*all_expanded_targets, *all_explicit_targets}
    dependencies_per_target = await MultiGet(
        Get(Addresses, DependenciesRequest(tgt.get(Dependencies))) for tgt in all_targets
    )

    address_to_dependees = defaultdict(set)
    for tgt, dependencies in zip(all_targets, dependencies_per_target):
        for dependency in dependencies:
            address_to_dependees[dependency].add(tgt.address)
    return AddressToDependees(
        FrozenDict(
            {addr: FrozenOrderedSet(dependees) for addr, dependees in address_to_dependees.items()}
        )
    )
Exemple #4
0
 def assert_parsed(
     spec: str,
     *,
     path_component: str,
     target_component: str | None = None,
     parameters: dict[str, str] | None = None,
     generated_component: str | None = None,
     relative_to: str | None = None,
 ) -> None:
     ai = AddressInput.parse(spec, relative_to=relative_to)
     assert ai.path_component == path_component
     if target_component is None:
         assert ai.target_component is None
     else:
         assert ai.target_component == target_component
     assert ai.parameters == FrozenDict(parameters or {})
     if generated_component is None:
         assert ai.generated_component is None
     else:
         assert ai.generated_component == generated_component
Exemple #5
0
def test_first_party_modules_mapping() -> None:
    util_addr = Address("src/python/util", relative_file_path="strutil.py")
    test_addr = Address("tests/python/project_test",
                        relative_file_path="test.py")
    mapping = FirstPartyModuleToAddressMapping(
        FrozenDict({
            "util.strutil": (util_addr, ),
            "project_test.test": (test_addr, )
        }))
    assert mapping.addresses_for_module("util.strutil") == (util_addr, )
    assert mapping.addresses_for_module("util.strutil.ensure_text") == (
        util_addr, )
    assert not mapping.addresses_for_module("util")
    assert mapping.addresses_for_module("project_test.test") == (test_addr, )
    assert mapping.addresses_for_module("project_test.test.TestDemo") == (
        test_addr, )
    assert not mapping.addresses_for_module(
        "project_test.test.TestDemo.method")
    assert not mapping.addresses_for_module("project_test")
    assert not mapping.addresses_for_module("project.test")
Exemple #6
0
    def __init__(
        self,
        argv: Iterable[str],
        *,
        env: Optional[Mapping[str, str]] = None,
        input_digest: Digest = EMPTY_DIGEST,
        run_in_workspace: bool = False,
    ) -> None:
        """Request to run a subprocess in the foreground, similar to subprocess.run().

        Unlike `Process`, the result will not be cached.

        To run the process, request `InteractiveRunner` in a `@goal_rule`, then use
        `interactive_runner.run()`.
        """
        self.argv = tuple(argv)
        self.env = FrozenDict(env or {})
        self.input_digest = input_digest
        self.run_in_workspace = run_in_workspace
        self.__post_init__()
Exemple #7
0
    def perform_test(extra_targets: list[str], dym: str) -> None:

        parser = Parser(
            target_type_aliases=["tgt", *extra_targets],
            object_aliases=BuildFileAliases(
                objects={"obj": 0},
                context_aware_object_factories={"caof": lambda parse_context: lambda _: None},
            ),
        )
        prelude_symbols = BuildFilePreludeSymbols(FrozenDict({"prelude": 0}))
        fmt_extra_sym = str(extra_targets)[1:-1] + (", ") if len(extra_targets) != 0 else ""
        with pytest.raises(ParseError) as exc:
            parser.parse("dir/BUILD", "fake", prelude_symbols)
        assert str(exc.value) == (
            f"Name 'fake' is not defined.\n\n{dym}"
            "If you expect to see more symbols activated in the below list,"
            f" refer to {docs_url('enabling-backends')} for all available"
            " backends to activate.\n\n"
            f"All registered symbols: ['caof', {fmt_extra_sym}'obj', 'prelude', 'tgt']"
        )
Exemple #8
0
class ModuleMappingField(DictStringToStringSequenceField):
    alias = "module_mapping"
    help = softwrap(f"""
        A mapping of requirement names to a list of the modules they provide.

        For example, `{{"ansicolors": ["colors"]}}`.

        Any unspecified requirements will use a default. See the
        `{PythonRequirementModulesField.alias}` field from the `{PythonRequirementTarget.alias}`
        target for more information.
        """)
    value: FrozenDict[str, tuple[str, ...]]
    default: ClassVar[FrozenDict[str, tuple[str, ...]]] = FrozenDict()

    @classmethod
    def compute_value(  # type: ignore[override]
            cls, raw_value: Dict[str, Iterable[str]],
            address: Address) -> FrozenDict[str, Tuple[str, ...]]:
        value_or_default = super().compute_value(raw_value, address)
        return normalize_module_mapping(value_or_default)
Exemple #9
0
def test_group_field_sets_by_constraints() -> None:
    py2_fs = MockFieldSet.create_for_test(Address("", target_name="py2"),
                                          ">=2.7,<3")
    py3_fs = [
        MockFieldSet.create_for_test(Address("", target_name="py3"),
                                     "==3.6.*"),
        MockFieldSet.create_for_test(Address("", target_name="py3_second"),
                                     "==3.6.*"),
    ]
    no_constraints_fs = MockFieldSet.create_for_test(
        Address("", target_name="no_constraints"), None)
    assert PexInterpreterConstraints.group_field_sets_by_constraints(
        [py2_fs, *py3_fs, no_constraints_fs],
        python_setup=create_subsystem(PythonSetup, interpreter_constraints=[]),
    ) == FrozenDict({
        PexInterpreterConstraints(): (no_constraints_fs, ),
        PexInterpreterConstraints(["CPython>=2.7,<3"]): (py2_fs, ),
        PexInterpreterConstraints(["CPython==3.6.*"]):
        tuple(py3_fs),
    })
Exemple #10
0
class TypeStubsModuleMappingField(DictStringToStringSequenceField):
    alias = "type_stubs_module_mapping"
    help = (
        "A mapping of type-stub requirement names to a list of the modules they provide.\n\n"
        'For example, `{"types-requests": ["requests"]}`.\n\n'
        "If the requirement is not specified _and_ it starts with `types-` or `stubs-`, or ends "
        "with `-types` or `-stubs`, the requirement will be treated as a type stub for the "
        'corresponding module, e.g. "types-request" has the module "requests". Otherwise, '
        "the requirement is treated like a normal dependency (see the field "
        f"{ModuleMappingField.alias}).\n\n"
        "This is used to infer dependencies for type stubs.")
    value: FrozenDict[str, tuple[str, ...]]
    default: ClassVar[FrozenDict[str, tuple[str, ...]]] = FrozenDict()

    @classmethod
    def compute_value(  # type: ignore[override]
            cls, raw_value: Dict[str, Iterable[str]],
            address: Address) -> FrozenDict[str, Tuple[str, ...]]:
        value_or_default = super().compute_value(raw_value, address)
        return normalize_module_mapping(value_or_default)
Exemple #11
0
 def test_empty(self) -> None:
     """Test that parsing an empty BUILD file results in an empty AddressFamily."""
     address_mapper = AddressMapper(parser=JsonParser(TEST_TABLE), prelude_glob_patterns=())
     af = run_rule(
         parse_address_family,
         rule_args=[address_mapper, BuildFilePreludeSymbols(FrozenDict()), Dir("/dev/null")],
         mock_gets=[
             MockGet(
                 product_type=Snapshot,
                 subject_type=PathGlobs,
                 mock=lambda _: Snapshot(Digest("abc", 10), ("/dev/null/BUILD",), ()),
             ),
             MockGet(
                 product_type=FilesContent,
                 subject_type=Digest,
                 mock=lambda _: FilesContent([FileContent(path="/dev/null/BUILD", content=b"")]),
             ),
         ],
     )
     self.assertEqual(len(af.objects_by_name), 0)
Exemple #12
0
class TypeStubsModuleMappingField(DictStringToStringSequenceField):
    alias = "type_stubs_module_mapping"
    help = softwrap(f"""
        A mapping of type-stub requirement names to a list of the modules they provide.

        For example, `{{"types-requests": ["requests"]}}`.

        If the requirement is not specified _and_ its name looks like a type stub, Pants will
        use a default. See the `{PythonRequirementTypeStubModulesField.alias}` field from the
        `{PythonRequirementTarget.alias}` target for more information.
        """)
    value: FrozenDict[str, tuple[str, ...]]
    default: ClassVar[FrozenDict[str, tuple[str, ...]]] = FrozenDict()

    @classmethod
    def compute_value(  # type: ignore[override]
            cls, raw_value: Dict[str, Iterable[str]],
            address: Address) -> FrozenDict[str, Tuple[str, ...]]:
        value_or_default = super().compute_value(raw_value, address)
        return normalize_module_mapping(value_or_default)
Exemple #13
0
    def target_types_by_alias(
            self) -> FrozenDict[str, FrozenSet[Type[Target]]]:
        """Returns a mapping from target alias to the target types produced for that alias.

        Normally there is 1 target type per alias, but macros can expand a single alias to several
        target types.

        :API: public

        :rtype: dict
        """
        target_types_by_alias = defaultdict(list)
        for alias, target_type in self.target_types.items():
            target_types_by_alias[alias].append(target_type)
        for alias, target_macro_factory in self.target_macro_factories.items():
            target_types_by_alias[alias].extend(
                target_macro_factory.target_types)
        return FrozenDict(
            (alias, frozenset(target_types))
            for alias, target_types in target_types_by_alias.items())
Exemple #14
0
def test_map_third_party_modules_to_addresses(rule_runner: RuleRunner) -> None:
    rule_runner.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'],
            )

            python_requirement_library(
              name='direct_references',
              requirements=[
                'pip@ git+https://github.com/pypa/pip.git', 'local_dist@ file:///path/to/dist.whl',
              ],
            )
            """),
    )
    result = rule_runner.request(ThirdPartyModuleToAddressMapping, [])
    assert result.mapping == FrozenDict({
        "colors":
        Address("3rdparty/python", target_name="ansicolors"),
        "local_dist":
        Address("3rdparty/python", target_name="direct_references"),
        "pip":
        Address("3rdparty/python", target_name="direct_references"),
        "req1":
        Address("3rdparty/python", target_name="req1"),
        "un_normalized_project":
        Address("3rdparty/python", target_name="un_normalized"),
    })
 def assert_pants_requirement(
     self,
     build_file_entry: str,
     *,
     expected_target_name: str,
     expected_dist: str = "pantsbuild.pants",
     expected_module: str = "pants",
 ) -> None:
     self.add_to_build_file("3rdparty/python", f"{build_file_entry}\n")
     target = self.request_single_product(
         WrappedTarget,
         Params(
             Address("3rdparty/python", target_name=expected_target_name),
             create_options_bootstrapper(),
         ),
     ).target
     assert isinstance(target, PythonRequirementLibrary)
     assert target[PythonRequirementsField].value == (
         Requirement.parse(f"{expected_dist}=={pants_version()}"), )
     assert target[ModuleMappingField].value == FrozenDict(
         {expected_dist: (expected_module, )})
Exemple #16
0
def test_docker_push_env(rule_runner: RuleRunner) -> None:
    rule_runner.set_options(
        ["--docker-env-vars=DOCKER_CONFIG"],
        env_inherit={"PATH", "PYENV_ROOT", "HOME"},
        env={"DOCKER_CONFIG": "/etc/docker/custom-config"},
    )
    result, docker = run_publish(rule_runner, Address("src/default"))
    assert len(result) == 1
    assert_publish(
        result[0],
        ("default/default:latest",),
        None,
        process_assertion(
            argv=(
                docker.path,
                "push",
                "default/default:latest",
            ),
            env=FrozenDict({"DOCKER_CONFIG": "/etc/docker/custom-config"}),
        ),
    )
Exemple #17
0
async def analyze_import_path_to_package_mapping(
) -> GoImportPathToPackageMapping:
    mapping: dict[str, list[Address]] = defaultdict(list)

    all_targets = await Get(Targets, AddressSpecs([DescendantAddresses("")]))
    for tgt in all_targets:
        if not tgt.has_field(GoImportPath):
            continue

        # Note: This will usually skip go_package targets since they need analysis to infer the import path
        # since there is no way in the engine to attach inferred values as fields.
        import_path = tgt[GoImportPath].value
        if not import_path:
            continue

        mapping[import_path].append(tgt.address)

    frozen_mapping = FrozenDict(
        {ip: tuple(tgts)
         for ip, tgts in mapping.items()})
    return GoImportPathToPackageMapping(mapping=frozen_mapping)
Exemple #18
0
def test_parse_address_family_empty() -> None:
    """Test that parsing an empty BUILD file results in an empty AddressFamily."""
    address_mapper = AddressMapper(parser=Parser(
        target_type_aliases=[], object_aliases=BuildFileAliases()))
    af = run_rule(
        parse_address_family,
        rule_args=[
            address_mapper,
            BuildFilePreludeSymbols(FrozenDict()),
            Dir("/dev/null")
        ],
        mock_gets=[
            MockGet(
                product_type=DigestContents,
                subject_type=PathGlobs,
                mock=lambda _: DigestContents(
                    [FileContent(path="/dev/null/BUILD", content=b"")]),
            ),
        ],
    )
    assert len(af.name_to_target_adaptors) == 0
Exemple #19
0
async def merge_first_party_module_mappings(
    union_membership: UnionMembership, ) -> FirstPartyPythonModuleMapping:
    all_mappings = await MultiGet(
        Get(
            FirstPartyPythonMappingImpl,
            FirstPartyPythonMappingImplMarker,
            marker_cls(),
        ) for marker_cls in union_membership.get(
            FirstPartyPythonMappingImplMarker))
    resolves_to_modules_to_providers: DefaultDict[ResolveName, DefaultDict[
        str, list[ModuleProvider]]] = defaultdict(lambda: defaultdict(list))
    for mapping_impl in all_mappings:
        for resolve, modules_to_providers in mapping_impl.items():
            for module, providers in modules_to_providers.items():
                resolves_to_modules_to_providers[resolve][module].extend(
                    providers)
    return FirstPartyPythonModuleMapping((
        resolve,
        FrozenDict((mod, tuple(sorted(providers)))
                   for mod, providers in sorted(mapping.items())),
    ) for resolve, mapping in sorted(resolves_to_modules_to_providers.items()))
Exemple #20
0
    def check_docker_proc(process: Process):
        assert process.argv == (
            "/dummy/docker",
            "build",
            "-t",
            "args1:1.2.3",
            "--build-arg",
            "INHERIT",
            "--build-arg",
            "VAR=value",
            "-f",
            "docker/test/Dockerfile",
            ".",
        )

        # Check that we pull in name only args via env.
        assert process.env == FrozenDict(
            {
                "INHERIT": "from Pants env",
            }
        )
Exemple #21
0
async def map_third_party_modules_to_addresses() -> ThirdPartyModuleToAddressMapping:
    all_targets = await Get(Targets, AddressSpecs([DescendantAddresses("")]))
    modules_to_addresses: Dict[str, Address] = {}
    modules_with_multiple_owners: Set[str] = set()
    for tgt in all_targets:
        if not tgt.has_field(PythonRequirementsField):
            continue
        module_map = tgt.get(ModuleMappingField).value or {}  # type: ignore[var-annotated]
        for python_req in tgt[PythonRequirementsField].value:
            modules = module_map.get(
                python_req.project_name, [python_req.project_name.lower().replace("-", "_")],
            )
            for module in modules:
                if module in modules_to_addresses:
                    modules_with_multiple_owners.add(module)
                else:
                    modules_to_addresses[module] = tgt.address
    # Remove modules with ambiguous owners.
    for module in modules_with_multiple_owners:
        modules_to_addresses.pop(module)
    return ThirdPartyModuleToAddressMapping(FrozenDict(sorted(modules_to_addresses.items())))
Exemple #22
0
async def map_first_party_modules_to_addresses(
) -> FirstPartyModuleToAddressMapping:
    all_expanded_targets = await Get(Targets,
                                     AddressSpecs([DescendantAddresses("")]))
    candidate_targets = tuple(tgt for tgt in all_expanded_targets
                              if tgt.has_field(PythonSources))
    stripped_sources_per_explicit_target = await MultiGet(
        Get(StrippedSourceFiles, SourceFilesRequest([tgt[PythonSources]]))
        for tgt in candidate_targets)

    modules_to_addresses: DefaultDict[str, List[Address]] = defaultdict(list)
    modules_with_multiple_implementations: Set[str] = set()
    for tgt, stripped_sources in zip(candidate_targets,
                                     stripped_sources_per_explicit_target):
        for stripped_f in stripped_sources.snapshot.files:
            module = PythonModule.create_from_stripped_path(
                PurePath(stripped_f)).module
            if module in modules_to_addresses:
                # We check if one of the targets is an implementation (.py file) and the other is a type stub (.pyi
                # file), which we allow. Otherwise, we have ambiguity.
                either_targets_are_type_stubs = len(
                    modules_to_addresses[module]) == 1 and (
                        tgt.address.filename.endswith(".pyi")
                        or modules_to_addresses[module][0].filename.endswith(
                            ".pyi"))
                if either_targets_are_type_stubs:
                    modules_to_addresses[module].append(tgt.address)
                else:
                    modules_with_multiple_implementations.add(module)
            else:
                modules_to_addresses[module].append(tgt.address)

    # Remove modules with ambiguous owners.
    for module in modules_with_multiple_implementations:
        modules_to_addresses.pop(module)
    return FirstPartyModuleToAddressMapping(
        FrozenDict({
            module: tuple(sorted(addresses))
            for module, addresses in sorted(modules_to_addresses.items())
        }))
 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']"
     ])
     # Two modules belonging to the same target. We should generate subtargets for each file.
     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, meaning that neither should 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. Because there's only one source file belonging to the target, we should
     # not generate subtargets.
     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":
         Address(
             "src/python/project/util",
             relative_file_path="dirutil.py",
             target_name="util",
         ),
         "project.util.tarutil":
         Address(
             "src/python/project/util",
             relative_file_path="tarutil.py",
             target_name="util",
         ),
         "project_test.demo_test":
         Address(
             "tests/python/project_test/demo_test",
             relative_file_path="__init__.py",
             target_name="demo_test",
         ),
     })
Exemple #24
0
    def get_subset(
        self, requested: Sequence[str], *, allowed: Optional[Sequence[str]] = None
    ) -> FrozenDict[str, str]:
        """Extract a subset of named env vars.

        Given a list of extra environment variable specifiers as strings, filter the contents of
        the pants environment to only those variables.

        Each variable can be specified either as a name or as a name=value pair.
        In the former case, the value for that name is taken from this env. In the latter
        case the specified value overrides the value in this env.

        If `allowed` is specified, the requested variable names must be in that list, or an error
        will be raised.
        """
        allowed_set = None if allowed is None else set(allowed)
        env_var_subset: Dict[str, str] = {}

        def check_and_set(name: str, value: Optional[str]):
            if allowed_set is not None and name not in allowed_set:
                raise ValueError(
                    f"{name} is not in the list of variable names that are allowed to be set. "
                    f"Must be one of {','.join(sorted(allowed_set))}."
                )
            if value is not None:
                env_var_subset[name] = value

        for env_var in requested:
            name_value_match = name_value_re.match(env_var)
            if name_value_match:
                check_and_set(name_value_match[1], name_value_match[2])
            elif shorthand_re.match(env_var):
                check_and_set(env_var, self.get(env_var))
            else:
                raise ValueError(
                    f"An invalid variable was requested via the --test-extra-env-var "
                    f"mechanism: {env_var}"
                )

        return FrozenDict(env_var_subset)
Exemple #25
0
async def map_first_party_modules_to_addresses() -> FirstPartyModuleToAddressMapping:
    all_expanded_targets = await Get(Targets, AddressSpecs([DescendantAddresses("")]))
    candidate_targets = tuple(tgt for tgt in all_expanded_targets if tgt.has_field(PythonSources))
    stripped_sources_per_explicit_target = await MultiGet(
        Get(StrippedSourceFiles, SourceFilesRequest([tgt[PythonSources]]))
        for tgt in candidate_targets
    )

    modules_to_addresses: Dict[str, Address] = {}
    modules_with_multiple_owners: Set[str] = set()
    for tgt, stripped_sources in zip(candidate_targets, stripped_sources_per_explicit_target):
        for stripped_f in stripped_sources.snapshot.files:
            module = PythonModule.create_from_stripped_path(PurePath(stripped_f)).module
            if module in modules_to_addresses:
                modules_with_multiple_owners.add(module)
            else:
                modules_to_addresses[module] = tgt.address

    # Remove modules with ambiguous owners.
    for module in modules_with_multiple_owners:
        modules_to_addresses.pop(module)
    return FirstPartyModuleToAddressMapping(FrozenDict(sorted(modules_to_addresses.items())))
Exemple #26
0
 def __init__(
     self,
     *,
     argv: Iterable[str],
     description: str,
     additional_input_digest: Optional[Digest] = None,
     extra_env: Optional[Mapping[str, str]] = None,
     output_files: Optional[Iterable[str]] = None,
     output_directories: Optional[Iterable[str]] = None,
     python: Optional[PythonExecutable] = None,
     level: LogLevel = LogLevel.INFO,
 ) -> None:
     self.argv = tuple(argv)
     self.description = description
     self.additional_input_digest = additional_input_digest
     self.extra_env = FrozenDict(extra_env) if extra_env else None
     self.output_files = tuple(output_files) if output_files else None
     self.output_directories = tuple(
         output_directories) if output_directories else None
     self.python = python
     self.level = level
     self.__post_init__()
Exemple #27
0
async def evalute_preludes(
        address_mapper: AddressMapper) -> BuildFilePreludeSymbols:
    snapshot = await Get[Snapshot](PathGlobs(
        address_mapper.prelude_glob_patterns,
        glob_match_error_behavior=GlobMatchErrorBehavior.ignore,
    ))
    prelude_files_content = await Get[FilesContent](Digest, snapshot.digest)
    values: Dict[str, Any] = {}
    for file_content in prelude_files_content:
        try:
            file_content_str = file_content.content.decode()
            content = compile(file_content_str, file_content.path, "exec")
            exec(content, values)
        except Exception as e:
            raise Exception(
                f"Error parsing prelude file {file_content.path}: {e}")
        error_on_imports(file_content_str, file_content.path)
    # __builtins__ is a dict, so isn't hashable, and can't be put in a FrozenDict.
    # Fortunately, we don't care about it - preludes should not be able to override builtins, so we just pop it out.
    # TODO: Give a nice error message if a prelude tries to set a expose a non-hashable value.
    values.pop("__builtins__", None)
    return BuildFilePreludeSymbols(FrozenDict(values))
Exemple #28
0
async def evaluate_preludes(global_options: GlobalOptions) -> BuildFilePreludeSymbols:
    prelude_digest_contents = await Get(
        DigestContents,
        PathGlobs(
            global_options.options.build_file_prelude_globs,
            glob_match_error_behavior=GlobMatchErrorBehavior.ignore,
        ),
    )
    values: Dict[str, Any] = {}
    for file_content in prelude_digest_contents:
        try:
            file_content_str = file_content.content.decode()
            content = compile(file_content_str, file_content.path, "exec")
            exec(content, values)
        except Exception as e:
            raise Exception(f"Error parsing prelude file {file_content.path}: {e}")
        error_on_imports(file_content_str, file_content.path)
    # __builtins__ is a dict, so isn't hashable, and can't be put in a FrozenDict.
    # Fortunately, we don't care about it - preludes should not be able to override builtins, so we just pop it out.
    # TODO: Give a nice error message if a prelude tries to set a expose a non-hashable value.
    values.pop("__builtins__", None)
    return BuildFilePreludeSymbols(FrozenDict(values))
Exemple #29
0
def test_issue_15111(rule_runner: RuleRunner) -> None:
    """Ensure we can handle when a single address implement multiple modules.

    This is currently only possible with third-party targets.
    """
    rule_runner.write_files({
        "BUILD":
        "python_requirement(name='req', requirements=['docopt', 'types-docopt'])"
    })
    rule_runner.set_options(["--python-enable-resolves"])
    result = rule_runner.request(ThirdPartyPythonModuleMapping, [])
    assert result == ThirdPartyPythonModuleMapping({
        "python-default":
        FrozenDict({
            "docopt": (
                ModuleProvider(Address("", target_name="req"),
                               ModuleProviderType.IMPL),
                ModuleProvider(Address("", target_name="req"),
                               ModuleProviderType.TYPE_STUB),
            ),
        })
    })
Exemple #30
0
def test_parse_address_family_empty() -> None:
    """Test that parsing an empty BUILD file results in an empty AddressFamily."""
    af = run_rule_with_mocks(
        parse_address_family,
        rule_args=[
            Parser(target_type_aliases=[], object_aliases=BuildFileAliases()),
            create_subsystem(GlobalOptions,
                             build_patterns=["BUILD"],
                             build_ignore=[]),
            BuildFilePreludeSymbols(FrozenDict()),
            AddressFamilyDir("/dev/null"),
        ],
        mock_gets=[
            MockGet(
                output_type=DigestContents,
                input_type=PathGlobs,
                mock=lambda _: DigestContents(
                    [FileContent(path="/dev/null/BUILD", content=b"")]),
            ),
        ],
    )
    assert len(af.name_to_target_adaptors) == 0