async def provenanced_addresses_from_address_families( address_mapper: AddressMapper, address_specs: AddressSpecs, ) -> ProvenancedBuildFileAddresses: """Given an AddressMapper and list of AddressSpecs, return matching ProvenancedBuildFileAddresses. :raises: :class:`ResolveError` if: - there were no matching AddressFamilies, or - the AddressSpec matches no addresses for SingleAddresses. :raises: :class:`AddressLookupError` if no targets are matched for non-SingleAddress specs. """ # Capture a Snapshot covering all paths for these AddressSpecs, then group by directory. snapshot = await Get[Snapshot](PathGlobs, _address_spec_to_globs( address_mapper, address_specs)) dirnames = {dirname(f) for f in snapshot.files} address_families = await MultiGet(Get[AddressFamily](Dir(d)) for d in dirnames) address_family_by_directory = {af.namespace: af for af in address_families} matched_addresses = OrderedSet() addr_to_provenance: Dict[BuildFileAddress, AddressSpec] = {} for address_spec in address_specs: # NB: if an address spec is provided which expands to some number of targets, but those targets # match --exclude-target-regexp, we do NOT fail! This is why we wait to apply the tag and # exclude patterns until we gather all the targets the address spec would have matched # without them. try: addr_families_for_spec = address_spec.matching_address_families( address_family_by_directory) except AddressSpec.AddressFamilyResolutionError as e: raise ResolveError(e) from e try: all_addr_tgt_pairs = address_spec.address_target_pairs_from_address_families( addr_families_for_spec) for addr, _ in all_addr_tgt_pairs: # A target might be covered by multiple specs, so we take the most specific one. addr_to_provenance[addr] = more_specific( addr_to_provenance.get(addr), address_spec) except AddressSpec.AddressResolutionError as e: raise AddressLookupError(e) from e except SingleAddress._SingleAddressResolutionError as e: _raise_did_you_mean(e.single_address_family, e.name, source=e) matched_addresses.update( addr for (addr, tgt) in all_addr_tgt_pairs if address_specs.matcher.matches_target_address_pair(addr, tgt)) # NB: This may be empty, as the result of filtering by tag and exclude patterns! return ProvenancedBuildFileAddresses( tuple( ProvenancedBuildFileAddress(build_file_address=addr, provenance=addr_to_provenance[addr]) for addr in matched_addresses))
def test_more_specific(): single_address = SingleAddress(directory="foo/bar", name="baz") sibling_addresses = SiblingAddresses(directory="foo/bar") ascendant_addresses = AscendantAddresses(directory="foo/bar") descendant_addresses = DescendantAddresses(directory="foo/bar") assert single_address == more_specific(single_address, None) assert single_address == more_specific(single_address, sibling_addresses) assert single_address == more_specific(single_address, ascendant_addresses) assert single_address == more_specific(single_address, descendant_addresses) assert single_address == more_specific(None, single_address) assert single_address == more_specific(sibling_addresses, single_address) assert single_address == more_specific(ascendant_addresses, single_address) assert single_address == more_specific(descendant_addresses, single_address) assert sibling_addresses == more_specific(sibling_addresses, None) assert sibling_addresses == more_specific(sibling_addresses, ascendant_addresses) assert sibling_addresses == more_specific(sibling_addresses, descendant_addresses) assert sibling_addresses == more_specific(None, sibling_addresses) assert sibling_addresses == more_specific(ascendant_addresses, sibling_addresses) assert sibling_addresses == more_specific(descendant_addresses, sibling_addresses) assert ascendant_addresses == more_specific(ascendant_addresses, None) assert ascendant_addresses == more_specific(ascendant_addresses, descendant_addresses) assert ascendant_addresses == more_specific(None, ascendant_addresses) assert ascendant_addresses == more_specific(descendant_addresses, ascendant_addresses) assert descendant_addresses == more_specific(descendant_addresses, None) assert descendant_addresses == more_specific(None, descendant_addresses)