Exemple #1
0
def test_address_input_from_dir() -> None:
    assert AddressInput(
        "a", description_of_origin="tests").dir_to_address() == Address("a")
    assert AddressInput(
        "a", target_component="b",
        description_of_origin="tests").dir_to_address() == Address(
            "a", target_name="b")
    assert AddressInput(
        "a",
        target_component="b",
        generated_component="gen",
        description_of_origin="tests").dir_to_address() == Address(
            "a", target_name="b", generated_name="gen")
Exemple #2
0
 def address_input(self) -> AddressInput:
     if not self.uri.startswith("pants:"):
         raise ValueError(
             f"Unknown URI scheme for BSP BuildTargetIdentifier. Expected scheme `pants`, but URI was: {self.uri}"
         )
     raw_addr = self.uri[len("pants:") :]
     return AddressInput.parse(raw_addr)
Exemple #3
0
 def parse(spec, relative_to):
     return AddressInput.parse(
         spec,
         relative_to=relative_to,
         subproject_roots=["subprojectA", "path/to/subprojectB"],
         description_of_origin="tests",
     )
Exemple #4
0
async def parse_global_scalac_plugins(scalac_plugins: Scalac) -> _LoadedGlobalScalacPlugins:
    targets = await MultiGet(
        Get(WrappedTarget, AddressInput, AddressInput.parse(ai))
        for ai in scalac_plugins.plugins_global
    )

    artifact_address_inputs = []
    names = []
    invalid_targets = []
    for wrapped_target in targets:
        target = wrapped_target.target
        if target.has_field(ScalacPluginArtifactField):
            artifact_address_inputs.append(cast(str, target[ScalacPluginArtifactField].value))
            names.append(_plugin_name(target))
        else:
            invalid_targets.append(target)

    if invalid_targets:
        raise ValueError(
            f"The `[{Scalac.options_scope}].plugins_global` option accepts only "
            f"`{ScalacPluginTarget.alias}` targets, but got:\n\n"
            f"{bullet_list(type(t).alias for t in invalid_targets)}"
        )

    return _LoadedGlobalScalacPlugins(
        names=tuple(names), artifact_address_inputs=tuple(artifact_address_inputs)
    )
Exemple #5
0
def assert_address_input_parsed(spec: str,
                                *,
                                path_component: str,
                                target_component: Optional[str],
                                relative_to: Optional[str] = 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
Exemple #6
0
async def gather_coordinates_for_jvm_lockfile(
    request: GatherJvmCoordinatesRequest, ) -> ArtifactRequirements:
    # Separate `artifact_inputs` by whether the strings parse as an `Address` or not.
    requirements: set[ArtifactRequirement] = set()
    candidate_address_inputs: set[AddressInput] = set()
    bad_artifact_inputs = []
    for artifact_input in request.artifact_inputs:
        # Try parsing as a `Coordinate` first since otherwise `AddressInput.parse` will try to see if the
        # group name is a file on disk.
        if 2 <= artifact_input.count(":") <= 3:
            try:
                maybe_coord = Coordinate.from_coord_str(
                    artifact_input).as_requirement()
                requirements.add(maybe_coord)
                continue
            except Exception:
                pass

        try:
            address_input = AddressInput.parse(
                artifact_input,
                description_of_origin=f"the option `{request.option_name}`")
            candidate_address_inputs.add(address_input)
        except Exception:
            bad_artifact_inputs.append(artifact_input)

    if bad_artifact_inputs:
        raise ValueError(
            "The following values could not be parsed as an address nor as a JVM coordinate string. "
            f"The problematic inputs supplied to the `{request.option_name}` option were: "
            f"{', '.join(bad_artifact_inputs)}.")

    # Gather coordinates from the provided addresses.
    addresses = await MultiGet(
        Get(Address, AddressInput, ai) for ai in candidate_address_inputs)
    all_supplied_targets = await Get(Targets, Addresses(addresses))
    other_targets = []
    for tgt in all_supplied_targets:
        if JvmArtifactFieldSet.is_applicable(tgt):
            requirements.add(ArtifactRequirement.from_jvm_artifact_target(tgt))
        else:
            other_targets.append(tgt)

    if other_targets:
        raise ValueError(
            softwrap(f"""
                The following addresses reference targets that are not `jvm_artifact` targets.
                Please only supply the addresses of `jvm_artifact` for the `{request.option_name}`
                option. The problematic addresses are: {', '.join(str(tgt.address) for tgt in other_targets)}.
                """))

    return ArtifactRequirements(requirements)
Exemple #7
0
async def resolve_scala_plugins_for_target(
    request: ScalaPluginsForTargetRequest,
    all_scala_plugins: AllScalaPluginTargets,
    jvm: JvmSubsystem,
    scalac: Scalac,
) -> ScalaPluginTargetsForTarget:
    target = request.target
    resolve = request.resolve_name

    plugin_names = target.get(ScalaConsumedPluginNamesField).value
    if plugin_names is None:
        plugin_names_by_resolve = scalac.parsed_default_plugins()
        plugin_names = tuple(plugin_names_by_resolve.get(resolve, ()))

    candidate_plugins = []
    artifact_address_gets = []
    for plugin in all_scala_plugins:
        if _plugin_name(plugin) not in plugin_names:
            continue
        candidate_plugins.append(plugin)
        artifact_field = plugin[ScalacPluginArtifactField]
        address_input = AddressInput.parse(
            artifact_field.value,
            relative_to=target.address.spec_path,
            description_of_origin=
            (f"the `{artifact_field.alias}` field from the target {artifact_field.address}"
             ),
        )
        artifact_address_gets.append(Get(Address, AddressInput, address_input))

    artifact_addresses = await MultiGet(artifact_address_gets)
    candidate_artifacts = await Get(Targets, Addresses(artifact_addresses))

    plugins: dict[str, tuple[Target, Target]] = {
    }  # Maps plugin name to relevant JVM artifact
    for plugin, artifact in zip(candidate_plugins, candidate_artifacts):
        if artifact[JvmResolveField].normalized_value(jvm) != resolve:
            continue

        plugins[_plugin_name(plugin)] = (plugin, artifact)

    for plugin_name in plugin_names:
        if plugin_name not in plugins:
            raise Exception(
                f"Could not find Scala plugin `{plugin_name}` in resolve `{resolve}` "
                f"for target {request.target}")

    plugin_targets, artifact_targets = zip(
        *plugins.values()) if plugins else ((), ())
    return ScalaPluginTargetsForTarget(Targets(plugin_targets),
                                       Targets(artifact_targets))
Exemple #8
0
async def resolve_scala_plugins_for_target(
    request: ScalaPluginsForTargetRequest,
    all_scala_plugins: AllScalaPluginTargets,
    jvm: JvmSubsystem,
    scalac: Scalac,
) -> ScalaPluginTargetsForTarget:

    target = request.target
    resolve = request.resolve_name

    plugin_names = target.get(ScalaConsumedPluginNamesField).value
    if plugin_names is None:
        plugin_names_by_resolve = scalac.parsed_default_plugins()
        plugin_names = tuple(plugin_names_by_resolve.get(resolve, ()))

    candidate_plugins: list[Target] = []
    for plugin in all_scala_plugins:
        if _plugin_name(plugin) in plugin_names:
            candidate_plugins.append(plugin)

    artifact_address_inputs = (
        plugin[ScalacPluginArtifactField].value for plugin in candidate_plugins
    )

    artifact_addresses = await MultiGet(
        # `is not None` is solely to satiate mypy. artifact field is required.
        Get(Address, AddressInput, AddressInput.parse(ai))
        for ai in artifact_address_inputs
        if ai is not None
    )

    candidate_artifacts = await Get(Targets, Addresses(artifact_addresses))

    plugins: dict[str, tuple[Target, Target]] = {}  # Maps plugin name to relevant JVM artifact
    for plugin, artifact in zip(candidate_plugins, candidate_artifacts):
        if artifact[JvmResolveField].normalized_value(jvm) != resolve:
            continue

        plugins[_plugin_name(plugin)] = (plugin, artifact)

    for plugin_name in plugin_names:
        if plugin_name not in plugins:
            raise Exception(
                f"Could not find Scala plugin `{plugin_name}` in resolve `{resolve}` "
                f"for target {request.target}"
            )

    plugin_targets, artifact_targets = zip(*plugins.values()) if plugins else ((), ())
    return ScalaPluginTargetsForTarget(Targets(plugin_targets), Targets(artifact_targets))
Exemple #9
0
 def assert_parsed(spec: str,
                   *,
                   path_component: str,
                   target_component: 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
     if generated_component is None:
         assert ai.generated_component is None
     else:
         assert ai.generated_component == generated_component
Exemple #10
0
    assert Address(
        "dir",
        target_name="generator").create_generated("generated") == Address(
            "dir", target_name="generator", generated_name="generated")
    with pytest.raises(AssertionError):
        Address("", target_name="t",
                relative_file_path="f.ext").create_generated("gen")
    with pytest.raises(AssertionError):
        Address("", target_name="t",
                generated_name="gen").create_generated("gen")


@pytest.mark.parametrize(
    "addr,expected",
    [
        (Address("a/b/c"), AddressInput("a/b/c", target_component="c")),
        (Address("a/b/c", target_name="tgt"), AddressInput("a/b/c", "tgt")),
        (
            Address("a/b/c", target_name="tgt", generated_name="gen"),
            AddressInput("a/b/c", "tgt", generated_component="gen"),
        ),
        (
            Address("a/b/c", target_name="tgt", generated_name="dir/gen"),
            AddressInput("a/b/c", "tgt", generated_component="dir/gen"),
        ),
        (Address("a/b/c",
                 relative_file_path="f.txt"), AddressInput("a/b/c/f.txt")),
        (
            Address("a/b/c", relative_file_path="f.txt", target_name="tgt"),
            AddressInput("a/b/c/f.txt", "tgt"),
        ),
Exemple #11
0
def test_address_spec_to_address_input(addr: Address,
                                       expected: AddressInput) -> None:
    """Check that Address.spec <-> AddressInput.parse() is idempotent."""
    assert AddressInput.parse(addr.spec,
                              description_of_origin="tests") == expected
Exemple #12
0
def test_address_generated_name(spec: str) -> None:
    with pytest.raises(InvalidTargetName):
        AddressInput.parse(spec,
                           description_of_origin="tests").dir_to_address()
Exemple #13
0
def test_address_bad_wildcard(spec: str) -> None:
    with pytest.raises(UnsupportedWildcard):
        AddressInput.parse(spec,
                           description_of_origin="tests").dir_to_address()
Exemple #14
0
def test_address_bad_target_component(spec: str) -> None:
    with pytest.raises(InvalidTargetName):
        AddressInput.parse(spec,
                           description_of_origin="tests").dir_to_address()
Exemple #15
0
def test_address_input_parse(spec: str, expected: str) -> None:
    with pytest.raises(AddressParseException) as e:
        AddressInput.parse(spec, description_of_origin="tests")
    assert expected in str(e.value)
Exemple #16
0
def test_address_input_parse(spec: str, expected: str) -> None:
    with pytest.raises(AddressParseException) as e:
        AddressInput.parse(spec)
    assert expected in str(e.value)
Exemple #17
0
def test_address_bad_target_component(spec: str) -> None:
    with pytest.raises(InvalidTargetName):
        AddressInput.parse(spec).dir_to_address()
Exemple #18
0
def test_address_invalid_params(spec: str) -> None:
    with pytest.raises(InvalidParameters):
        AddressInput.parse(spec,
                           description_of_origin="tests").dir_to_address()