def test_filesystem_specs(self) -> None: # Literal file arg. sources_field1_all_sources = SOURCES1.source_file_absolute_paths sources_field1_slice = slice(0, 1) sources_field1 = self.mock_sources_field_with_origin( SOURCES1, origin=FilesystemLiteralSpec(sources_field1_all_sources[0])) # Glob file arg that matches the entire `sources`. sources_field2_all_sources = SOURCES2.source_file_absolute_paths sources_field2_slice = slice(0, len(sources_field2_all_sources)) sources_field2_origin = FilesystemResolvedGlobSpec( f"{SOURCES2.source_root}/*.py", files=tuple(sources_field2_all_sources)) sources_field2 = self.mock_sources_field_with_origin( SOURCES2, origin=sources_field2_origin) # Glob file arg that only matches a subset of the `sources` _and_ includes resolved # files not owned by the target. sources_field3_all_sources = SOURCES3.source_file_absolute_paths sources_field3_slice = slice(0, 1) sources_field3_origin = FilesystemResolvedGlobSpec( f"{SOURCES3.source_root}/*.java", files=tuple( PurePath(SOURCES3.source_root, name).as_posix() for name in [SOURCES3.source_files[0], "other_target.java", "j.tmp.java"]), ) sources_field3 = self.mock_sources_field_with_origin( SOURCES3, origin=sources_field3_origin) def assert_file_args_resolved( sources_field_with_origin: Tuple[SourcesField, OriginSpec], all_sources: List[str], expected_slice: slice, ) -> None: assert self.get_all_source_files([sources_field_with_origin ]) == all_sources assert (self.get_specified_source_files( [sources_field_with_origin]) == all_sources[expected_slice]) assert_file_args_resolved(sources_field1, sources_field1_all_sources, sources_field1_slice) assert_file_args_resolved(sources_field2, sources_field2_all_sources, sources_field2_slice) assert_file_args_resolved(sources_field3, sources_field3_all_sources, sources_field3_slice) combined_sources_fields = [ sources_field1, sources_field2, sources_field3 ] assert self.get_all_source_files(combined_sources_fields) == sorted([ *sources_field1_all_sources, *sources_field2_all_sources, *sources_field3_all_sources ]) assert self.get_specified_source_files( combined_sources_fields) == sorted([ *sources_field1_all_sources[sources_field1_slice], *sources_field2_all_sources[sources_field2_slice], *sources_field3_all_sources[sources_field3_slice], ])
def test_filesystem_specs(self) -> None: # Literal file arg. target1_all_sources = self.SOURCES1.source_file_absolute_paths target1_slice = slice(0, 1) target1 = self.mock_target(self.SOURCES1, origin=FilesystemLiteralSpec( target1_all_sources[0])) # Glob file arg that matches the entire target's `sources`. target2_all_sources = self.SOURCES2.source_file_absolute_paths target2_slice = slice(0, len(target2_all_sources)) target2_origin = FilesystemResolvedGlobSpec( f"{self.SOURCES2.source_root}/*.py", files=tuple(target2_all_sources)) target2 = self.mock_target(self.SOURCES2, origin=target2_origin) # Glob file arg that only matches a subset of the target's `sources` _and_ includes resolved # files not owned by the target. target3_all_sources = self.SOURCES3.source_file_absolute_paths target3_slice = slice(0, 1) target3_origin = FilesystemResolvedGlobSpec( f"{self.SOURCES3.source_root}/*.java", files=tuple( PurePath(self.SOURCES3.source_root, name).as_posix() for name in [ self.SOURCES3.source_files[0], "other_target.java", "j.tmp.java" ]), ) target3 = self.mock_target(self.SOURCES3, origin=target3_origin) def assert_file_args_resolved(target: TargetAdaptorWithOrigin, all_sources: List[str], expected_slice: slice) -> None: assert self.get_all_source_files([target]) == all_sources assert self.get_specified_source_files( [target]) == all_sources[expected_slice] assert_file_args_resolved(target1, target1_all_sources, target1_slice) assert_file_args_resolved(target2, target2_all_sources, target2_slice) assert_file_args_resolved(target3, target3_all_sources, target3_slice) combined_targets = [target1, target2, target3] assert self.get_all_source_files(combined_targets) == sorted( [*target1_all_sources, *target2_all_sources, *target3_all_sources]) assert self.get_specified_source_files(combined_targets) == sorted([ *target1_all_sources[target1_slice], *target2_all_sources[target2_slice], *target3_all_sources[target3_slice], ])
async def addresses_with_origins_from_filesystem_specs( filesystem_specs: FilesystemSpecs, global_options: GlobalOptions, ) -> AddressesWithOrigins: """Find the owner(s) for each FilesystemSpec while preserving the original FilesystemSpec those owners come from. This will merge FilesystemSpecs that come from the same owning target into a single FilesystemMergedSpec. """ pathglobs_per_include = ( filesystem_specs.path_globs_for_spec( spec, global_options.options.owners_not_found_behavior.to_glob_match_error_behavior(), ) for spec in filesystem_specs.includes ) snapshot_per_include = await MultiGet( Get[Snapshot](PathGlobs, pg) for pg in pathglobs_per_include ) owners_per_include = await MultiGet( Get[Owners](OwnersRequest(sources=snapshot.files)) for snapshot in snapshot_per_include ) addresses_to_specs: DefaultDict[ Address, List[Union[FilesystemLiteralSpec, FilesystemResolvedGlobSpec]] ] = defaultdict(list) for spec, snapshot, owners in zip( filesystem_specs.includes, snapshot_per_include, owners_per_include ): if ( global_options.options.owners_not_found_behavior != OwnersNotFoundBehavior.ignore and isinstance(spec, FilesystemLiteralSpec) and not owners.addresses ): file_path = PurePath(spec.to_spec_string()) msg = ( f"No owning targets could be found for the file `{file_path}`.\n\nPlease check " f"that there is a BUILD file in `{file_path.parent}` with a target whose `sources` field " f"includes `{file_path}`. See https://pants.readme.io/docs/targets for more " "information on target definitions.\n" "If you would like to ignore un-owned files, please pass `--owners-not-found-behavior=ignore`." ) if global_options.options.owners_not_found_behavior == OwnersNotFoundBehavior.warn: logger.warning(msg) else: raise ResolveError(msg) # We preserve what literal files any globs resolved to. This allows downstream goals to be # more precise in which files they operate on. origin: Union[FilesystemLiteralSpec, FilesystemResolvedGlobSpec] = ( spec if isinstance(spec, FilesystemLiteralSpec) else FilesystemResolvedGlobSpec(glob=spec.glob, files=snapshot.files) ) for address in owners.addresses: addresses_to_specs[address].append(origin) return AddressesWithOrigins( AddressWithOrigin( address, specs[0] if len(specs) == 1 else FilesystemMergedSpec.create(specs) ) for address, specs in addresses_to_specs.items() )