def get_subset(self, address: Address, consumer: Target) -> Target: """Find the Target with the given Address, or with fields matching the given consumer.""" # Check for exact matches. instance = self.get(address) if instance is not None: return instance def remaining_fields_match(candidate: Target) -> bool: """Returns true if all Fields absent from the candidate's Address match the consumer.""" unspecified_param_field_names = { key for key in candidate.address.parameters.keys() if key not in address.parameters } return all( consumer.has_field(field_type) and consumer[field_type] == field_value for field_type, field_value in candidate.field_values.items() if field_type.alias in unspecified_param_field_names) for parametrization in self: # If the given Address is a subset-match of the parametrization's original Target # (meaning that the user specified an un-parameterized generator Address), then we # need to match against one of the generated Targets instead (because a parametrized # generator does not keep its Fields). if (parametrization.original_target and address.is_parametrized_subset_of( parametrization.original_target.address) and parametrization.parametrization and remaining_fields_match( next(iter(parametrization.parametrization.values())))): return parametrization.original_target # Else, see whether any of the generated targets match. for candidate in parametrization.parametrization.values(): if address.is_parametrized_subset_of( candidate.address) and remaining_fields_match( candidate): return candidate raise ValueError( f"The explicit dependency `{address}` of the target at `{consumer.address}` does " "not provide enough address parameters to identify which parametrization of the " "dependency target should be used.\n" f"Target `{address.maybe_convert_to_target_generator()}` can be addressed as:\n" f"{bullet_list(str(t.address) for t in self.all)}")
def get_all_superset_targets(self, address: Address) -> Iterator[Address]: """Yield the input address itself, or any parameterized addresses which are a superset of the input address. For example, an input address `dir:tgt` may yield `(dir:tgt@k=v1, dir:tgt@k=v2)`. If no targets are a match, will yield nothing. """ # Check for exact matches. if self.get(address) is not None: yield address return for parametrization in self: if parametrization.original_target is not None and address.is_parametrized_subset_of( parametrization.original_target.address): yield parametrization.original_target.address for parametrized_tgt in parametrization.parametrization.values(): if address.is_parametrized_subset_of(parametrized_tgt.address): yield parametrized_tgt.address