Exemplo n.º 1
0
    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)}")
Exemplo n.º 2
0
    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