Exemple #1
0
async def determine_go_mod_info(request: GoModInfoRequest, ) -> GoModInfo:
    if isinstance(request.source, Address):
        wrapped_target = await Get(
            WrappedTarget,
            WrappedTargetRequest(request.source,
                                 description_of_origin="<go mod info rule>"),
        )
        sources_field = wrapped_target.target[GoModSourcesField]
    else:
        sources_field = request.source
    go_mod_path = sources_field.go_mod_path
    go_mod_dir = os.path.dirname(go_mod_path)

    # Get the `go.mod` (and `go.sum`) and strip so the file has no directory prefix.
    hydrated_sources = await Get(HydratedSources,
                                 HydrateSourcesRequest(sources_field))
    sources_digest = hydrated_sources.snapshot.digest

    mod_json = await Get(
        ProcessResult,
        GoSdkProcess(
            command=("mod", "edit", "-json"),
            input_digest=sources_digest,
            working_dir=go_mod_dir,
            description=f"Parse {go_mod_path}",
        ),
    )
    module_metadata = json.loads(mod_json.stdout)
    return GoModInfo(
        import_path=module_metadata["Module"]["Path"],
        digest=sources_digest,
        mod_path=go_mod_path,
        minimum_go_version=module_metadata.get("Go"),
    )
Exemple #2
0
async def find_apache_thrift_python_requirement(
    request: InjectApacheThriftPythonDependencies,
    thrift_python: ThriftPythonSubsystem,
    python_setup: PythonSetup,
    # TODO(#12946): Make this a lazy Get once possible.
    module_mapping: ThirdPartyPythonModuleMapping,
) -> InjectedDependencies:
    if not thrift_python.infer_runtime_dependency:
        return InjectedDependencies()

    wrapped_tgt = await Get(
        WrappedTarget,
        WrappedTargetRequest(
            request.dependencies_field.address, description_of_origin="<infallible>"
        ),
    )
    resolve = wrapped_tgt.target.get(PythonResolveField).normalized_value(python_setup)

    addr = find_python_runtime_library_or_raise_error(
        module_mapping,
        request.dependencies_field.address,
        "thrift",
        resolve=resolve,
        resolves_enabled=python_setup.enable_resolves,
        recommended_requirement_name="thrift",
        recommended_requirement_url="https://pypi.org/project/thrift/",
        disable_inference_option=f"[{thrift_python.options_scope}].infer_runtime_dependency",
    )
    return InjectedDependencies([addr])
Exemple #3
0
async def run(
    run_subsystem: RunSubsystem,
    global_options: GlobalOptions,
    workspace: Workspace,
    build_root: BuildRoot,
    complete_env: CompleteEnvironment,
) -> Run:
    targets_to_valid_field_sets = await Get(
        TargetRootsToFieldSets,
        TargetRootsToFieldSetsRequest(
            RunFieldSet,
            goal_description="the `run` goal",
            no_applicable_targets_behavior=NoApplicableTargetsBehavior.error,
            expect_single_field_set=True,
        ),
    )
    field_set = targets_to_valid_field_sets.field_sets[0]
    request = await Get(RunRequest, RunFieldSet, field_set)
    wrapped_target = await Get(
        WrappedTarget,
        WrappedTargetRequest(field_set.address,
                             description_of_origin="<infallible>"))
    restartable = wrapped_target.target.get(RestartableField).value
    # Cleanup is the default, so we want to preserve the chroot if either option is off.
    cleanup = run_subsystem.cleanup and global_options.process_cleanup

    with temporary_dir(root_dir=global_options.pants_workdir,
                       cleanup=cleanup) as tmpdir:
        if not cleanup:
            logger.info(f"Preserving running binary chroot {tmpdir}")
        workspace.write_digest(
            request.digest,
            path_prefix=PurePath(tmpdir).relative_to(
                build_root.path).as_posix(),
            # We don't want to influence whether the InteractiveProcess is able to restart. Because
            # we're writing into a temp directory, we can safely mark this side_effecting=False.
            side_effecting=False,
        )

        args = (arg.format(chroot=tmpdir) for arg in request.args)
        env = {
            **complete_env,
            **{
                k: v.format(chroot=tmpdir)
                for k, v in request.extra_env.items()
            }
        }
        result = await Effect(
            InteractiveProcessResult,
            InteractiveProcess(
                argv=(*args, *run_subsystem.args),
                env=env,
                run_in_workspace=True,
                restartable=restartable,
            ),
        )
        exit_code = result.exit_code

    return Run(exit_code)
Exemple #4
0
async def resolve_unexpanded_targets(
        addresses: Addresses) -> UnexpandedTargets:
    wrapped_targets = await MultiGet(
        Get(WrappedTarget,
            WrappedTargetRequest(a, description_of_origin="TODO(#14468)"))
        for a in addresses)
    return UnexpandedTargets(wrapped_target.target
                             for wrapped_target in wrapped_targets)
Exemple #5
0
async def parse_dockerfile(request: DockerfileInfoRequest) -> DockerfileInfo:
    wrapped_target = await Get(
        WrappedTarget,
        WrappedTargetRequest(request.address,
                             description_of_origin="<infallible>"))
    target = wrapped_target.target
    sources = await Get(
        HydratedSources,
        HydrateSourcesRequest(
            target.get(SourcesField),
            for_sources_types=(DockerImageSourceField, ),
            enable_codegen=True,
        ),
    )

    dockerfiles = sources.snapshot.files
    assert len(dockerfiles) == 1, (
        f"Internal error: Expected a single source file to Dockerfile parse request {request}, "
        f"got: {dockerfiles}.")

    result = await Get(
        ProcessResult,
        DockerfileParseRequest(
            sources.snapshot.digest,
            dockerfiles,
        ),
    )

    try:
        raw_output = result.stdout.decode("utf-8")
        outputs = json.loads(raw_output)
        assert len(outputs) == len(dockerfiles)
    except Exception as e:
        raise DockerfileInfoError(
            f"Unexpected failure to parse Dockerfiles: {', '.join(dockerfiles)}, "
            f"for the {request.address} target: {e}") from e

    info = outputs[0]
    try:
        return DockerfileInfo(
            address=request.address,
            digest=sources.snapshot.digest,
            source=info["source"],
            build_args=DockerBuildArgs.from_strings(
                *info["build_args"], duplicates_must_match=True),
            copy_source_paths=tuple(info["copy_source_paths"]),
            from_image_build_args=DockerBuildArgs.from_strings(
                *info["from_image_build_args"], duplicates_must_match=True),
            version_tags=tuple(info["version_tags"]),
        )
    except ValueError as e:
        raise DockerfileInfoError(
            f"Error while parsing {info['source']} for the {request.address} target: {e}"
        ) from e
Exemple #6
0
async def inject_pex_binary_entry_point_dependency(
    request: InjectPexBinaryEntryPointDependency,
    python_infer_subsystem: PythonInferSubsystem,
    python_setup: PythonSetup,
) -> InjectedDependencies:
    if not python_infer_subsystem.entry_points:
        return InjectedDependencies()
    original_tgt = await Get(
        WrappedTarget,
        WrappedTargetRequest(
            request.dependencies_field.address, description_of_origin="<infallible>"
        ),
    )
    entry_point_field = original_tgt.target.get(PexEntryPointField)
    if entry_point_field.value is None:
        return InjectedDependencies()

    explicitly_provided_deps, entry_point = await MultiGet(
        Get(ExplicitlyProvidedDependencies, DependenciesRequest(original_tgt.target[Dependencies])),
        Get(ResolvedPexEntryPoint, ResolvePexEntryPointRequest(entry_point_field)),
    )
    if entry_point.val is None:
        return InjectedDependencies()

    owners = await Get(
        PythonModuleOwners,
        PythonModuleOwnersRequest(
            entry_point.val.module,
            resolve=original_tgt.target[PythonResolveField].normalized_value(python_setup),
        ),
    )
    address = original_tgt.target.address
    explicitly_provided_deps.maybe_warn_of_ambiguous_dependency_inference(
        owners.ambiguous,
        address,
        # If the entry point was specified as a file, like `app.py`, we know the module must
        # live in the pex_binary's directory or subdirectory, so the owners must be ancestors.
        owners_must_be_ancestors=entry_point.file_name_used,
        import_reference="module",
        context=softwrap(
            f"""
            The pex_binary target {address} has the field
            `entry_point={repr(entry_point_field.value.spec)}`, which
            maps to the Python module `{entry_point.val.module}`
            """
        ),
    )
    maybe_disambiguated = explicitly_provided_deps.disambiguated(
        owners.ambiguous, owners_must_be_ancestors=entry_point.file_name_used
    )
    unambiguous_owners = owners.unambiguous or (
        (maybe_disambiguated,) if maybe_disambiguated else ()
    )
    return InjectedDependencies(unambiguous_owners)
Exemple #7
0
async def isolate_local_dist_wheels(
    dist_field_set: PythonDistributionFieldSet,
    bash: BashBinary,
    unzip_binary: UnzipBinary,
) -> LocalDistWheels:
    dist = await Get(BuiltPackage, PackageFieldSet, dist_field_set)
    wheels_snapshot = await Get(Snapshot, DigestSubset(dist.digest, PathGlobs(["**/*.whl"])))

    # A given local dist might build a wheel and an sdist (and maybe other artifacts -
    # we don't know what setup command was run...)
    # As long as there is a wheel, we can ignore the other artifacts.
    artifacts = {(a.relpath or "") for a in dist.artifacts}
    wheels = [wheel for wheel in wheels_snapshot.files if wheel in artifacts]

    if not wheels:
        tgt = await Get(
            WrappedTarget,
            WrappedTargetRequest(dist_field_set.address, description_of_origin="<infallible>"),
        )
        logger.warning(
            softwrap(
                f"""
                Encountered a dependency on the {tgt.target.alias} target at {dist_field_set.address},
                but this target does not produce a Python wheel artifact. Therefore this target's
                code will be used directly from sources, without a distribution being built,
                and any native extensions in it will not be built.

                See {doc_url('python-distributions')} for details on how to set up a
                {tgt.target.alias} target to produce a wheel.
                """
            )
        )

    wheels_listing_result = await Get(
        ProcessResult,
        Process(
            argv=[
                bash.path,
                "-c",
                f"""
                set -ex
                for f in {' '.join(shlex.quote(f) for f in wheels)}; do
                  {unzip_binary.path} -Z1 "$f"
                done
                """,
            ],
            input_digest=wheels_snapshot.digest,
            description=f"List contents of artifacts produced by {dist_field_set.address}",
        ),
    )
    provided_files = set(wheels_listing_result.stdout.decode().splitlines())

    return LocalDistWheels(tuple(wheels), wheels_snapshot.digest, frozenset(provided_files))
Exemple #8
0
async def inject_lambda_handler_dependency(
    request: InjectPythonLambdaHandlerDependency,
    python_infer_subsystem: PythonInferSubsystem,
    python_setup: PythonSetup,
) -> InjectedDependencies:
    if not python_infer_subsystem.entry_points:
        return InjectedDependencies()
    original_tgt = await Get(
        WrappedTarget,
        WrappedTargetRequest(
            request.dependencies_field.address, description_of_origin="<infallible>"
        ),
    )
    explicitly_provided_deps, handler = await MultiGet(
        Get(ExplicitlyProvidedDependencies, DependenciesRequest(original_tgt.target[Dependencies])),
        Get(
            ResolvedPythonAwsHandler,
            ResolvePythonAwsHandlerRequest(original_tgt.target[PythonAwsLambdaHandlerField]),
        ),
    )
    module, _, _func = handler.val.partition(":")
    owners = await Get(
        PythonModuleOwners,
        PythonModuleOwnersRequest(
            module, resolve=original_tgt.target[PythonResolveField].normalized_value(python_setup)
        ),
    )
    address = original_tgt.target.address
    explicitly_provided_deps.maybe_warn_of_ambiguous_dependency_inference(
        owners.ambiguous,
        address,
        # If the handler was specified as a file, like `app.py`, we know the module must
        # live in the python_awslambda's directory or subdirectory, so the owners must be ancestors.
        owners_must_be_ancestors=handler.file_name_used,
        import_reference="module",
        context=softwrap(
            f"""
            The python_awslambda target {address} has the field
            `handler={repr(original_tgt.target[PythonAwsLambdaHandlerField].value)}`,
            which maps to the Python module `{module}`"
            """
        ),
    )
    maybe_disambiguated = explicitly_provided_deps.disambiguated(
        owners.ambiguous, owners_must_be_ancestors=handler.file_name_used
    )
    unambiguous_owners = owners.unambiguous or (
        (maybe_disambiguated,) if maybe_disambiguated else ()
    )
    return InjectedDependencies(unambiguous_owners)
Exemple #9
0
    def get_target(self, address: Address) -> Target:
        """Find the target for a given address.

        This requires that the target actually exists, i.e. that you set up its BUILD file.

        :API: public
        """
        return self.request(
            WrappedTarget,
            [
                WrappedTargetRequest(
                    address, description_of_origin="RuleRunner.get_target()")
            ],
        ).target
Exemple #10
0
async def inject_go_binary_main_dependency(
    request: InjectGoBinaryMainDependencyRequest,
) -> InjectedDependencies:
    wrapped_tgt = await Get(
        WrappedTarget,
        WrappedTargetRequest(
            request.dependencies_field.address, description_of_origin="<infallible>"
        ),
    )
    main_pkg = await Get(
        GoBinaryMainPackage,
        GoBinaryMainPackageRequest(wrapped_tgt.target[GoBinaryMainPackageField]),
    )
    return InjectedDependencies([main_pkg.address])
Exemple #11
0
async def run_shell_command_request(
        shell_command: RunShellCommand) -> RunRequest:
    wrapped_tgt = await Get(
        WrappedTarget,
        WrappedTargetRequest(shell_command.address,
                             description_of_origin="<infallible>"),
    )
    process = await Get(Process,
                        ShellCommandProcessRequest(wrapped_tgt.target))
    return RunRequest(
        digest=process.input_digest,
        args=process.argv,
        extra_env=process.env,
    )
Exemple #12
0
async def run_all_setup_plugins(
        request: AllPytestPluginSetupsRequest,
        union_membership: UnionMembership) -> AllPytestPluginSetups:
    wrapped_tgt = await Get(
        WrappedTarget,
        WrappedTargetRequest(request.address,
                             description_of_origin="<infallible>"))
    applicable_setup_request_types = tuple(
        request for request in union_membership.get(PytestPluginSetupRequest)
        if request.is_applicable(wrapped_tgt.target))
    setups = await MultiGet(
        Get(PytestPluginSetup, PytestPluginSetupRequest,
            request(wrapped_tgt.target))  # type: ignore[misc, abstract]
        for request in applicable_setup_request_types)
    return AllPytestPluginSetups(setups)
Exemple #13
0
async def inject_dependencies(
    request: InjectPythonProtobufDependencies,
    python_protobuf: PythonProtobufSubsystem,
    python_setup: PythonSetup,
    # TODO(#12946): Make this a lazy Get once possible.
    module_mapping: ThirdPartyPythonModuleMapping,
) -> InjectedDependencies:
    if not python_protobuf.infer_runtime_dependency:
        return InjectedDependencies()

    wrapped_tgt = await Get(
        WrappedTarget,
        WrappedTargetRequest(request.dependencies_field.address,
                             description_of_origin="<infallible>"),
    )
    tgt = wrapped_tgt.target
    resolve = tgt.get(PythonResolveField).normalized_value(python_setup)

    result = [
        find_python_runtime_library_or_raise_error(
            module_mapping,
            request.dependencies_field.address,
            "google.protobuf",
            resolve=resolve,
            resolves_enabled=python_setup.enable_resolves,
            recommended_requirement_name="protobuf",
            recommended_requirement_url="https://pypi.org/project/protobuf/",
            disable_inference_option=
            f"[{python_protobuf.options_scope}].infer_runtime_dependency",
        )
    ]

    if tgt.get(ProtobufGrpcToggleField).value:
        result.append(
            find_python_runtime_library_or_raise_error(
                module_mapping,
                request.dependencies_field.address,
                # Note that the library is called `grpcio`, but the module is `grpc`.
                "grpc",
                resolve=resolve,
                resolves_enabled=python_setup.enable_resolves,
                recommended_requirement_name="grpcio",
                recommended_requirement_url="https://pypi.org/project/grpcio/",
                disable_inference_option=
                f"[{python_protobuf.options_scope}].infer_runtime_dependency",
            ))

    return InjectedDependencies(result)
Exemple #14
0
async def infer_scala_dependencies_via_source_analysis(
    request: InferScalaSourceDependencies,
    scala_infer_subsystem: ScalaInferSubsystem,
    jvm: JvmSubsystem,
    symbol_mapping: SymbolMapping,
) -> InferredDependencies:
    if not scala_infer_subsystem.imports:
        return InferredDependencies([])

    address = request.sources_field.address
    wrapped_tgt = await Get(
        WrappedTarget,
        WrappedTargetRequest(address, description_of_origin="<infallible>"))
    tgt = wrapped_tgt.target
    explicitly_provided_deps, analysis = await MultiGet(
        Get(ExplicitlyProvidedDependencies,
            DependenciesRequest(tgt[Dependencies])),
        Get(ScalaSourceDependencyAnalysis,
            SourceFilesRequest([request.sources_field])),
    )

    symbols: OrderedSet[str] = OrderedSet()
    if scala_infer_subsystem.imports:
        symbols.update(analysis.all_imports())
    if scala_infer_subsystem.consumed_types:
        symbols.update(analysis.fully_qualified_consumed_symbols())

    resolve = tgt[JvmResolveField].normalized_value(jvm)

    dependencies: OrderedSet[Address] = OrderedSet()
    for symbol in symbols:
        for matches in symbol_mapping.addresses_for_symbol(symbol,
                                                           resolve).values():
            explicitly_provided_deps.maybe_warn_of_ambiguous_dependency_inference(
                matches,
                address,
                import_reference="type",
                context=f"The target {address} imports `{symbol}`",
            )

            maybe_disambiguated = explicitly_provided_deps.disambiguated(
                matches)
            if maybe_disambiguated:
                dependencies.add(maybe_disambiguated)

    return InferredDependencies(dependencies)
Exemple #15
0
async def infer_python_init_dependencies(
    request: InferInitDependencies,
    python_infer_subsystem: PythonInferSubsystem,
    python_setup: PythonSetup,
) -> InferredDependencies:
    if (
        not python_infer_subsystem.options.is_default("inits") and not python_infer_subsystem.inits
    ) or python_infer_subsystem.init_files is InitFilesInference.never:
        return InferredDependencies([])

    ignore_empty_files = (
        python_infer_subsystem.options.is_default("inits")
        and python_infer_subsystem.init_files is InitFilesInference.content_only
    )
    fp = request.sources_field.file_path
    assert fp is not None
    init_files = await Get(
        AncestorFiles,
        AncestorFilesRequest(
            input_files=(fp,),
            requested=("__init__.py", "__init__.pyi"),
            ignore_empty_files=ignore_empty_files,
        ),
    )
    owners = await MultiGet(Get(Owners, OwnersRequest((f,))) for f in init_files.snapshot.files)

    original_tgt, owner_tgts = await MultiGet(
        Get(
            WrappedTarget,
            WrappedTargetRequest(
                request.sources_field.address, description_of_origin="<infallible>"
            ),
        ),
        Get(Targets, Addresses(itertools.chain.from_iterable(owners))),
    )
    resolve = original_tgt.target[PythonResolveField].normalized_value(python_setup)
    python_owners = [
        tgt.address
        for tgt in owner_tgts
        if (
            tgt.has_field(PythonSourceField)
            and tgt[PythonResolveField].normalized_value(python_setup) == resolve
        )
    ]
    return InferredDependencies(python_owners)
Exemple #16
0
async def inject_apache_thrift_java_dependencies(
        request: InjectApacheThriftJavaDependencies,
        jvm: JvmSubsystem) -> InjectedDependencies:
    wrapped_target = await Get(
        WrappedTarget,
        WrappedTargetRequest(request.dependencies_field.address,
                             description_of_origin="<infallible>"),
    )
    target = wrapped_target.target

    if not target.has_field(JvmResolveField):
        return InjectedDependencies()
    resolve = target[JvmResolveField].normalized_value(jvm)

    dependencies_info = await Get(
        ApacheThriftJavaRuntimeForResolve,
        ApacheThriftJavaRuntimeForResolveRequest(resolve))
    return InjectedDependencies(dependencies_info.addresses)
Exemple #17
0
async def inject_scala_library_dependency(
    request: InjectScalaLibraryDependencyRequest,
    jvm: JvmSubsystem,
) -> InjectedDependencies:
    wrapped_target = await Get(
        WrappedTarget,
        WrappedTargetRequest(request.dependencies_field.address,
                             description_of_origin="<infallible>"),
    )
    target = wrapped_target.target

    if not target.has_field(JvmResolveField):
        return InjectedDependencies()
    resolve = target[JvmResolveField].normalized_value(jvm)

    scala_library_target_info = await Get(
        ScalaRuntimeForResolve, ScalaRuntimeForResolveRequest(resolve))
    return InjectedDependencies(scala_library_target_info.addresses)
Exemple #18
0
async def _determine_literal_addresses_from_raw_specs(
        literal_specs: tuple[AddressLiteralSpec, ...], *,
        description_of_origin: str) -> tuple[WrappedTarget, ...]:
    literal_addresses = await MultiGet(
        Get(
            Address,
            AddressInput(
                spec.path_component,
                spec.target_component,
                generated_component=spec.generated_component,
                parameters=spec.parameters,
                description_of_origin=description_of_origin,
            ),
        ) for spec in literal_specs)

    # We replace references to parametrized target templates with all their created targets. For
    # example:
    #  - dir:tgt -> (dir:tgt@k=v1, dir:tgt@k=v2)
    #  - dir:tgt@k=v -> (dir:tgt@k=v,another=a, dir:tgt@k=v,another=b), but not anything
    #       where @k=v is not true.
    literal_parametrizations = await MultiGet(
        Get(
            _TargetParametrizations,
            _TargetParametrizationsRequest(
                address.maybe_convert_to_target_generator(),
                description_of_origin=description_of_origin,
            ),
        ) for address in literal_addresses)

    # Note that if the address is not in the _TargetParametrizations, we must fall back to that
    # address's value. This will allow us to error that the address is invalid.
    all_candidate_addresses = itertools.chain.from_iterable(
        list(params.get_all_superset_targets(address)) or [address] for
        address, params in zip(literal_addresses, literal_parametrizations))

    # We eagerly call the `WrappedTarget` rule because it will validate that every final address
    # actually exists, such as with generated target addresses.
    return await MultiGet(
        Get(
            WrappedTarget,
            WrappedTargetRequest(addr,
                                 description_of_origin=description_of_origin))
        for addr in all_candidate_addresses)
Exemple #19
0
async def inject_kotlin_junit_dependency(
    request: InjectKotlinJunitTestDependencyRequest,
    jvm: JvmSubsystem,
) -> InjectedDependencies:
    wrapped_target = await Get(
        WrappedTarget,
        WrappedTargetRequest(request.dependencies_field.address,
                             description_of_origin="<infallible>"),
    )
    target = wrapped_target.target

    if not target.has_field(JvmResolveField):
        return InjectedDependencies()
    resolve = target[JvmResolveField].normalized_value(jvm)

    kotlin_junit_libraries = await Get(
        KotlinJunitLibrariesForResolve,
        KotlinJunitLibrariesForResolveRequest(resolve))
    return InjectedDependencies(kotlin_junit_libraries.addresses)
Exemple #20
0
async def validate_python_dependencies(
    request: PythonValidateDependenciesRequest,
    python_setup: PythonSetup,
) -> ValidatedDependencies:
    dependencies = await MultiGet(
        Get(
            WrappedTarget,
            WrappedTargetRequest(
                d, description_of_origin=f"the dependencies of {request.field_set.address}"
            ),
        )
        for d in request.dependencies
    )

    # Validate that the ICs for dependencies are all compatible with our own.
    target_ics = request.field_set.interpreter_constraints.value_or_global_default(python_setup)
    non_subset_items = []
    for dep in dependencies:
        if not dep.target.has_field(InterpreterConstraintsField):
            continue
        dep_ics = dep.target[InterpreterConstraintsField].value_or_global_default(python_setup)
        if not interpreter_constraints_contains(
            dep_ics, target_ics, python_setup.interpreter_universe
        ):
            non_subset_items.append(f"{dep_ics}: {dep.target.address}")

    if non_subset_items:
        raise InvalidFieldException(
            softwrap(
                f"""
            The target {request.field_set.address} has the `interpreter_constraints` {target_ics},
            which are not a subset of the `interpreter_constraints` of some of its dependencies:

            {bullet_list(sorted(non_subset_items))}

            To fix this, you should likely adjust {request.field_set.address}'s
            `interpreter_constraints` to match the narrowest range in the above list.
            """
            )
        )

    return ValidatedDependencies()
Exemple #21
0
async def inject_protobuf_java_runtime_dependency(
    request: InjectProtobufJavaRuntimeDependencyRequest,
    jvm: JvmSubsystem,
) -> InjectedDependencies:
    wrapped_target = await Get(
        WrappedTarget,
        WrappedTargetRequest(request.dependencies_field.address,
                             description_of_origin="<infallible>"),
    )
    target = wrapped_target.target

    if not target.has_field(JvmResolveField):
        return InjectedDependencies()
    resolve = target[JvmResolveField].normalized_value(jvm)

    protobuf_java_runtime_target_info = await Get(
        ProtobufJavaRuntimeForResolve,
        ProtobufJavaRuntimeForResolveRequest(resolve))

    return InjectedDependencies(protobuf_java_runtime_target_info.addresses)
Exemple #22
0
async def infer_shell_dependencies(
        request: InferShellDependencies, shell_mapping: ShellMapping,
        shell_setup: ShellSetup) -> InferredDependencies:
    if not shell_setup.dependency_inference:
        return InferredDependencies([])

    address = request.sources_field.address
    wrapped_tgt = await Get(
        WrappedTarget,
        WrappedTargetRequest(address, description_of_origin="<infallible>"))
    explicitly_provided_deps, hydrated_sources = await MultiGet(
        Get(ExplicitlyProvidedDependencies,
            DependenciesRequest(wrapped_tgt.target[Dependencies])),
        Get(HydratedSources, HydrateSourcesRequest(request.sources_field)),
    )
    assert len(hydrated_sources.snapshot.files) == 1

    detected_imports = await Get(
        ParsedShellImports,
        ParseShellImportsRequest(hydrated_sources.snapshot.digest,
                                 hydrated_sources.snapshot.files[0]),
    )
    result: OrderedSet[Address] = OrderedSet()
    for import_path in detected_imports:
        unambiguous = shell_mapping.mapping.get(import_path)
        ambiguous = shell_mapping.ambiguous_modules.get(import_path)
        if unambiguous:
            result.add(unambiguous)
        elif ambiguous:
            explicitly_provided_deps.maybe_warn_of_ambiguous_dependency_inference(
                ambiguous,
                address,
                import_reference="file",
                context=f"The target {address} sources `{import_path}`",
            )
            maybe_disambiguated = explicitly_provided_deps.disambiguated(
                ambiguous)
            if maybe_disambiguated:
                result.add(maybe_disambiguated)
    return InferredDependencies(sorted(result))
Exemple #23
0
async def infer_protobuf_dependencies(
    request: InferProtobufDependencies, protobuf_mapping: ProtobufMapping, protoc: Protoc
) -> InferredDependencies:
    if not protoc.dependency_inference:
        return InferredDependencies([])

    address = request.sources_field.address
    wrapped_tgt = await Get(
        WrappedTarget, WrappedTargetRequest(address, description_of_origin="<infallible>")
    )
    explicitly_provided_deps, hydrated_sources = await MultiGet(
        Get(ExplicitlyProvidedDependencies, DependenciesRequest(wrapped_tgt.target[Dependencies])),
        Get(HydratedSources, HydrateSourcesRequest(request.sources_field)),
    )
    digest_contents = await Get(DigestContents, Digest, hydrated_sources.snapshot.digest)
    assert len(digest_contents) == 1
    file_content = digest_contents[0]

    result: OrderedSet[Address] = OrderedSet()
    for import_path in parse_proto_imports(file_content.content.decode()):
        unambiguous = protobuf_mapping.mapping.get(import_path)
        ambiguous = protobuf_mapping.ambiguous_modules.get(import_path)
        if unambiguous:
            result.add(unambiguous)
        elif ambiguous:
            explicitly_provided_deps.maybe_warn_of_ambiguous_dependency_inference(
                ambiguous,
                address,
                import_reference="file",
                context=softwrap(
                    f"""
                    The target {address} imports `{import_path}` in the file
                    {file_content.path}
                    """
                ),
            )
            maybe_disambiguated = explicitly_provided_deps.disambiguated(ambiguous)
            if maybe_disambiguated:
                result.add(maybe_disambiguated)
    return InferredDependencies(sorted(result))
Exemple #24
0
async def infer_python_conftest_dependencies(
    request: InferConftestDependencies,
    python_infer_subsystem: PythonInferSubsystem,
    python_setup: PythonSetup,
) -> InferredDependencies:
    if not python_infer_subsystem.conftests:
        return InferredDependencies([])

    fp = request.sources_field.file_path
    assert fp is not None
    conftest_files = await Get(
        AncestorFiles,
        AncestorFilesRequest(input_files=(fp,), requested=("conftest.py",)),
    )
    owners = await MultiGet(
        # NB: Because conftest.py files effectively always have content, we require an
        # owning target.
        Get(Owners, OwnersRequest((f,), OwnersNotFoundBehavior.error))
        for f in conftest_files.snapshot.files
    )

    original_tgt, owner_tgts = await MultiGet(
        Get(
            WrappedTarget,
            WrappedTargetRequest(
                request.sources_field.address, description_of_origin="<infallible>"
            ),
        ),
        Get(Targets, Addresses(itertools.chain.from_iterable(owners))),
    )
    resolve = original_tgt.target[PythonResolveField].normalized_value(python_setup)
    python_owners = [
        tgt.address
        for tgt in owner_tgts
        if (
            tgt.has_field(PythonSourceField)
            and tgt[PythonResolveField].normalized_value(python_setup) == resolve
        )
    ]
    return InferredDependencies(python_owners)
Exemple #25
0
async def analyze_first_party_package(
        request: FirstPartyPkgAnalysisRequest,
        analyzer: PackageAnalyzerSetup) -> FallibleFirstPartyPkgAnalysis:
    wrapped_target, import_path_info, owning_go_mod = await MultiGet(
        Get(
            WrappedTarget,
            WrappedTargetRequest(
                request.address,
                description_of_origin="<first party pkg analysis>"),
        ),
        Get(FirstPartyPkgImportPath,
            FirstPartyPkgImportPathRequest(request.address)),
        Get(OwningGoMod, OwningGoModRequest(request.address)),
    )
    go_mod_info = await Get(GoModInfo, GoModInfoRequest(owning_go_mod.address))

    pkg_sources = await Get(
        HydratedSources,
        HydrateSourcesRequest(wrapped_target.target[GoPackageSourcesField]),
    )

    input_digest = await Get(
        Digest, MergeDigests([pkg_sources.snapshot.digest, analyzer.digest]))
    result = await Get(
        FallibleProcessResult,
        Process(
            (analyzer.path, request.address.spec_path or "."),
            input_digest=input_digest,
            description=f"Determine metadata for {request.address}",
            level=LogLevel.DEBUG,
            env={"CGO_ENABLED": "0"},
        ),
    )
    return FallibleFirstPartyPkgAnalysis.from_process_result(
        result,
        dir_path=request.address.spec_path,
        import_path=import_path_info.import_path,
        minimum_go_version=go_mod_info.minimum_go_version or "",
        description_of_source=f"first-party Go package `{request.address}`",
    )
Exemple #26
0
async def inject_go_third_party_package_dependencies(
    request: InjectGoThirdPartyPackageDependenciesRequest,
    std_lib_imports: GoStdLibImports,
    package_mapping: ImportPathToPackages,
) -> InjectedDependencies:
    addr = request.dependencies_field.address
    go_mod_address = addr.maybe_convert_to_target_generator()
    wrapped_target, go_mod_info = await MultiGet(
        Get(WrappedTarget, WrappedTargetRequest(addr, description_of_origin="<infallible>")),
        Get(GoModInfo, GoModInfoRequest(go_mod_address)),
    )
    tgt = wrapped_target.target
    pkg_info = await Get(
        ThirdPartyPkgAnalysis,
        ThirdPartyPkgAnalysisRequest(
            tgt[GoImportPathField].value, go_mod_info.digest, go_mod_info.mod_path
        ),
    )

    inferred_dependencies = []
    for import_path in pkg_info.imports:
        if import_path in std_lib_imports:
            continue

        candidate_packages = package_mapping.mapping.get(import_path, ())
        if len(candidate_packages) > 1:
            # TODO(#12761): Use ExplicitlyProvidedDependencies for disambiguation.
            logger.warning(
                f"Ambiguous mapping for import path {import_path} on packages at addresses: {candidate_packages}"
            )
        elif len(candidate_packages) == 1:
            inferred_dependencies.append(candidate_packages[0])
        else:
            logger.debug(
                f"Unable to infer dependency for import path '{import_path}' "
                f"in go_third_party_package at address '{addr}'."
            )

    return InjectedDependencies(inferred_dependencies)
Exemple #27
0
async def create_analyze_scala_source_request(
        scala_subsystem: ScalaSubsystem, jvm: JvmSubsystem, scalac: Scalac,
        request: SourceFilesRequest) -> AnalyzeScalaSourceRequest:
    address = request.sources_fields[0].address

    wrapped_tgt, source_files = await MultiGet(
        Get(
            WrappedTarget,
            WrappedTargetRequest(
                address,
                description_of_origin="<the Scala analyze request setup rule>"
            ),
        ),
        Get(SourceFiles, SourceFilesRequest, request),
    )

    tgt = wrapped_tgt.target
    resolve = tgt[JvmResolveField].normalized_value(jvm)
    scala_version = scala_subsystem.version_for_resolve(resolve)
    source3 = "-Xsource:3" in scalac.args

    return AnalyzeScalaSourceRequest(source_files, scala_version, source3)
Exemple #28
0
async def inject_scala_plugin_dependencies(
    request: InjectScalaPluginDependenciesRequest, ) -> InjectedDependencies:
    """Adds dependencies on plugins for scala source files, so that they get included in the
    target's resolve."""

    wrapped_target = await Get(
        WrappedTarget,
        WrappedTargetRequest(request.dependencies_field.address,
                             description_of_origin="<infallible>"),
    )
    target = wrapped_target.target

    if not target.has_field(JvmResolveField):
        return InjectedDependencies()

    scala_plugins = await Get(
        ScalaPluginTargetsForTarget,
        ScalaPluginsForTargetWithoutResolveRequest(target))

    plugin_addresses = [target.address for target in scala_plugins.artifacts]

    return InjectedDependencies(plugin_addresses)
Exemple #29
0
async def infer_thrift_dependencies(
        request: InferThriftDependencies, thrift_mapping: ThriftMapping,
        thrift: ThriftSubsystem) -> InferredDependencies:
    if not thrift.dependency_inference:
        return InferredDependencies([])

    address = request.sources_field.address
    wrapped_tgt = await Get(
        WrappedTarget,
        WrappedTargetRequest(address, description_of_origin="<infallible>"))
    explicitly_provided_deps, parsed_thrift = await MultiGet(
        Get(ExplicitlyProvidedDependencies,
            DependenciesRequest(wrapped_tgt.target[Dependencies])),
        Get(ParsedThrift, ParsedThriftRequest(request.sources_field)),
    )

    result: OrderedSet[Address] = OrderedSet()
    for import_path in parsed_thrift.imports:
        unambiguous = thrift_mapping.mapping.get(import_path)
        ambiguous = thrift_mapping.ambiguous_modules.get(import_path)
        if unambiguous:
            result.add(unambiguous)
        elif ambiguous:
            explicitly_provided_deps.maybe_warn_of_ambiguous_dependency_inference(
                ambiguous,
                address,
                import_reference="file",
                context=softwrap(f"""
                    The target {address} imports `{import_path}` in the file
                    {wrapped_tgt.target[ThriftSourceField].file_path}
                    """),
            )
            maybe_disambiguated = explicitly_provided_deps.disambiguated(
                ambiguous)
            if maybe_disambiguated:
                result.add(maybe_disambiguated)
    return InferredDependencies(sorted(result))
Exemple #30
0
async def infer_python_dependencies_via_source(
    request: InferPythonImportDependencies,
    python_infer_subsystem: PythonInferSubsystem,
    python_setup: PythonSetup,
) -> InferredDependencies:
    if not python_infer_subsystem.imports and not python_infer_subsystem.assets:
        return InferredDependencies([])

    _wrapped_tgt = await Get(
        WrappedTarget,
        WrappedTargetRequest(request.sources_field.address, description_of_origin="<infallible>"),
    )
    tgt = _wrapped_tgt.target
    interpreter_constraints = InterpreterConstraints.create_from_targets([tgt], python_setup)
    if interpreter_constraints is None:
        # TODO: This would represent a target with a PythonSource field, but no
        # InterpreterConstraints field. #15400 would allow inference to require both
        # fields.
        return InferredDependencies([])
    parsed_dependencies = await Get(
        ParsedPythonDependencies,
        ParsePythonDependenciesRequest(
            cast(PythonSourceField, request.sources_field),
            interpreter_constraints,
            string_imports=python_infer_subsystem.string_imports,
            string_imports_min_dots=python_infer_subsystem.string_imports_min_dots,
            assets=python_infer_subsystem.assets,
            assets_min_slashes=python_infer_subsystem.assets_min_slashes,
        ),
    )

    inferred_deps: set[Address] = set()
    unowned_imports: set[str] = set()
    parsed_imports = parsed_dependencies.imports
    parsed_assets = parsed_dependencies.assets
    if not python_infer_subsystem.imports:
        parsed_imports = ParsedPythonImports([])

    explicitly_provided_deps = await Get(
        ExplicitlyProvidedDependencies, DependenciesRequest(tgt[Dependencies])
    )

    resolve = tgt[PythonResolveField].normalized_value(python_setup)

    if parsed_imports:
        import_deps, unowned_imports = _get_imports_info(
            address=tgt.address,
            owners_per_import=await MultiGet(
                Get(PythonModuleOwners, PythonModuleOwnersRequest(imported_module, resolve=resolve))
                for imported_module in parsed_imports
            ),
            parsed_imports=parsed_imports,
            explicitly_provided_deps=explicitly_provided_deps,
        )
        inferred_deps.update(import_deps)

    if parsed_assets:
        all_asset_targets = await Get(AllAssetTargets, AllAssetTargetsRequest())
        assets_by_path = await Get(AllAssetTargetsByPath, AllAssetTargets, all_asset_targets)
        inferred_deps.update(
            _get_inferred_asset_deps(
                tgt.address,
                request.sources_field.file_path,
                assets_by_path,
                parsed_assets,
                explicitly_provided_deps,
            )
        )

    _ = await _handle_unowned_imports(
        tgt.address,
        python_infer_subsystem.unowned_dependency_behavior,
        python_setup,
        unowned_imports,
        parsed_imports,
        resolve=resolve,
    )

    return InferredDependencies(sorted(inferred_deps))