async def addresses_from_address_specs( address_specs: AddressSpecs, global_options: GlobalOptions, specs_filter: AddressSpecsFilter) -> Addresses: matched_addresses: OrderedSet[Address] = OrderedSet() filtering_disabled = address_specs.filter_by_global_options is False # First convert all `AddressLiteralSpec`s. Some of the resulting addresses may be generated # addresses. This will raise an exception if any of the addresses are not valid. literal_addresses = await MultiGet( Get( Address, AddressInput(spec.path_component, spec.target_component, spec.generated_component), ) for spec in address_specs.literals) literal_target_adaptors = await MultiGet( Get(TargetAdaptor, Address, addr.maybe_convert_to_target_generator()) for addr in literal_addresses) # We convert to targets for the side effect of validating that any generated targets actually # belong to their target generator. await Get( UnexpandedTargets, Addresses(addr for addr in literal_addresses if addr.is_generated_target)) for literal_spec, addr, target_adaptor in zip(address_specs.literals, literal_addresses, literal_target_adaptors): if filtering_disabled or specs_filter.matches(addr, target_adaptor): matched_addresses.add(addr) # Then, convert all `AddressGlobSpecs`. Resolve all BUILD files covered by the specs, then # group by directory. paths = await Get( Paths, PathGlobs, address_specs.to_path_globs( build_patterns=global_options.options.build_patterns, build_ignore_patterns=global_options.options.build_ignore, ), ) dirnames = {os.path.dirname(f) for f in paths.files} address_families = await MultiGet( Get(AddressFamily, AddressFamilyDir(d)) for d in dirnames) address_family_by_directory = {af.namespace: af for af in address_families} for glob_spec in address_specs.globs: # These may raise ResolveError, depending on the type of spec. addr_families_for_spec = glob_spec.matching_address_families( address_family_by_directory) addr_target_pairs_for_spec = glob_spec.matching_addresses( addr_families_for_spec) matched_addresses.update( addr for (addr, tgt) in addr_target_pairs_for_spec # TODO(#11123): handle the edge case if a generated target's `tags` != its generator's. if filtering_disabled or specs_filter.matches(addr, tgt)) return Addresses(sorted(matched_addresses))
async def addresses_with_origins_from_address_specs( address_mapper: AddressMapper, address_specs: AddressSpecs) -> AddressesWithOrigins: """Given an AddressMapper and list of AddressSpecs, return matching AddressesWithOrigins. :raises: :class:`ResolveError` if there were no matching AddressFamilies or no targets were matched. """ # Snapshot all BUILD files covered by the AddressSpecs, then group by directory. snapshot = await Get( Snapshot, PathGlobs, address_specs.to_path_globs( build_patterns=address_mapper.build_patterns, build_ignore_patterns=address_mapper.build_ignore_patterns, ), ) dirnames = {os.path.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[Address] = OrderedSet() addr_to_origin: Dict[Address, AddressSpec] = {} for address_spec in address_specs: # These may raise ResolveError, depending on the type of spec. addr_families_for_spec = address_spec.matching_address_families( address_family_by_directory) addr_target_pairs_for_spec = address_spec.matching_addresses( addr_families_for_spec) if isinstance(address_spec, SingleAddress) and not addr_target_pairs_for_spec: addr_family = assert_single_element(addr_families_for_spec) raise _did_you_mean_exception(addr_family, address_spec.name) for addr, _ in addr_target_pairs_for_spec: # A target might be covered by multiple specs, so we take the most specific one. addr_to_origin[addr] = AddressSpecs.more_specific( addr_to_origin.get(addr), address_spec) matched_addresses.update( addr for (addr, tgt) in addr_target_pairs_for_spec if (address_specs.filter_by_global_options is False or address_mapper.matches_filter_options(addr, tgt))) return AddressesWithOrigins( AddressWithOrigin(address=addr, origin=addr_to_origin[addr]) for addr in matched_addresses)
async def addresses_with_origins_from_address_specs( address_specs: AddressSpecs, global_options: GlobalOptions, specs_filter: AddressSpecsFilter ) -> AddressesWithOrigins: """Given an AddressMapper and list of AddressSpecs, return matching AddressesWithOrigins. :raises: :class:`ResolveError` if the provided specs fail to match targets, and those spec types expect to have matched something. """ matched_addresses: OrderedSet[Address] = OrderedSet() addr_to_origin: Dict[Address, AddressSpec] = {} filtering_disabled = address_specs.filter_by_global_options is False # First convert all `AddressLiteralSpec`s. Some of the resulting addresses may be file # addresses. This will raise an exception if any of the addresses are not valid. literal_addresses = await MultiGet( Get(Address, AddressInput(spec.path_component, spec.target_component)) for spec in address_specs.literals ) literal_target_adaptors = await MultiGet( Get(TargetAdaptor, Address, addr.maybe_convert_to_base_target()) for addr in literal_addresses ) # We convert to targets for the side effect of validating that any file addresses actually # belong to the specified base targets. await Get( UnexpandedTargets, Addresses(addr for addr in literal_addresses if not addr.is_base_target) ) for literal_spec, addr, target_adaptor in zip( address_specs.literals, literal_addresses, literal_target_adaptors ): addr_to_origin[addr] = literal_spec if filtering_disabled or specs_filter.matches(addr, target_adaptor): matched_addresses.add(addr) # Then, convert all `AddressGlobSpecs`. Snapshot all BUILD files covered by the specs, then # group by directory. snapshot = await Get( Snapshot, PathGlobs, address_specs.to_path_globs( build_patterns=global_options.options.build_patterns, build_ignore_patterns=global_options.options.build_ignore, ), ) dirnames = {os.path.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} for glob_spec in address_specs.globs: # These may raise ResolveError, depending on the type of spec. addr_families_for_spec = glob_spec.matching_address_families(address_family_by_directory) addr_target_pairs_for_spec = glob_spec.matching_addresses(addr_families_for_spec) for addr, _ in addr_target_pairs_for_spec: # A target might be covered by multiple specs, so we take the most specific one. addr_to_origin[addr] = AddressSpecs.more_specific(addr_to_origin.get(addr), glob_spec) matched_addresses.update( addr for (addr, tgt) in addr_target_pairs_for_spec if filtering_disabled or specs_filter.matches(addr, tgt) ) return AddressesWithOrigins( AddressWithOrigin(address=addr, origin=addr_to_origin[addr]) for addr in matched_addresses )