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")
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)
def parse(spec, relative_to): return AddressInput.parse( spec, relative_to=relative_to, subproject_roots=["subprojectA", "path/to/subprojectB"], description_of_origin="tests", )
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) )
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
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)
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))
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))
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
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"), ),
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
def test_address_generated_name(spec: str) -> None: with pytest.raises(InvalidTargetName): AddressInput.parse(spec, description_of_origin="tests").dir_to_address()
def test_address_bad_wildcard(spec: str) -> None: with pytest.raises(UnsupportedWildcard): AddressInput.parse(spec, description_of_origin="tests").dir_to_address()
def test_address_bad_target_component(spec: str) -> None: with pytest.raises(InvalidTargetName): AddressInput.parse(spec, description_of_origin="tests").dir_to_address()
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)
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)
def test_address_bad_target_component(spec: str) -> None: with pytest.raises(InvalidTargetName): AddressInput.parse(spec).dir_to_address()
def test_address_invalid_params(spec: str) -> None: with pytest.raises(InvalidParameters): AddressInput.parse(spec, description_of_origin="tests").dir_to_address()