def _internal_scan_specs(self, specs, fail_fast=True, missing_is_fatal=True): # TODO: This should really use `product_request`, but on the other hand, we need to # deprecate the entire `AddressMapper` interface anyway. See #4769. request = self._scheduler.execution_request([BuildFileAddresses], [Specs(tuple(specs))]) result = self._scheduler.execute(request) if result.error: raise self.BuildFileScanError(str(result.error)) (_, state), = result.root_products if isinstance(state, Throw): if isinstance(state.exc, (AddressLookupError, ResolveError)): if missing_is_fatal: raise self.BuildFileScanError( 'Spec `{}` does not match any targets.\n{}'.format( self._specs_string(specs), str(state.exc))) else: # NB: ignore Throws containing ResolveErrors because they are due to missing targets / files return set() else: raise self.BuildFileScanError(str(state.exc)) elif missing_is_fatal and not state.value.dependencies: raise self.BuildFileScanError( 'Spec `{}` does not match any targets.'.format( self._specs_string(specs))) return set(state.value.dependencies)
def scan_build_files(self, base_path): specs = (DescendantAddresses(base_path), ) build_files_collection, = self._scheduler.product_request( BuildFilesCollection, [Specs(specs)]) build_files_set = set() for build_files in build_files_collection.dependencies: build_files_set.update( f.path for f in build_files.files_content.dependencies) return build_files_set
def _inject_specs(self, subjects): """Injects targets into the graph for each of the given `Spec` objects. Yields the resulting addresses. """ logger.debug('Injecting specs to %s: %s', self, subjects) with self._resolve_context(): specs = tuple(subjects) thts, = self._scheduler.product_request(TransitiveHydratedTargets, [Specs(specs)]) self._index(thts.closure) for hydrated_target in thts.roots: yield hydrated_target.address
def iter_target_addresses_for_sources(self, sources): """Bulk, iterable form of `target_addresses_for_source`.""" # Walk up the buildroot looking for targets that would conceivably claim changed sources. sources_set = set(sources) specs = tuple(AscendantAddresses(directory=d) for d in self._unique_dirs_for_sources(sources_set)) # Uniqify all transitive hydrated targets. hydrated_target_to_address = {} hydrated_targets, = self._scheduler.product_request(HydratedTargets, [Specs(specs)]) for hydrated_target in hydrated_targets.dependencies: if hydrated_target not in hydrated_target_to_address: hydrated_target_to_address[hydrated_target] = hydrated_target.adaptor.address for hydrated_target, legacy_address in six.iteritems(hydrated_target_to_address): # Handle BUILD files. if (LegacyAddressMapper.any_is_declaring_file(legacy_address, sources_set) or self._owns_any_source(sources_set, hydrated_target)): yield legacy_address
def warm_product_graph(self, target_roots): """Warm the scheduler's `ProductGraph` with `TransitiveHydratedTargets` products. :param TargetRoots target_roots: The targets root of the request. """ logger.debug('warming target_roots for: %r', target_roots) if type(target_roots) is ChangedTargetRoots: subjects = [BuildFileAddresses(target_roots.addresses)] elif type(target_roots) is LiteralTargetRoots: subjects = [Specs(tuple(target_roots.specs))] else: raise ValueError( 'Unexpected TargetRoots type: `{}`.'.format(target_roots)) request = self.scheduler.execution_request([TransitiveHydratedTargets], subjects) result = self.scheduler.execute(request) if result.error: raise result.error
def iter_changed_target_addresses(self, changed_request): """Given a `ChangedRequest`, compute and yield all affected target addresses.""" changed_files = self.changed_files(changed_request.changes_since, changed_request.diffspec) logger.debug('changed files: %s', changed_files) if not changed_files: return changed_addresses = set( address for address in self._mapper.iter_target_addresses_for_sources( changed_files)) for address in changed_addresses: yield address if changed_request.include_dependees not in ('direct', 'transitive'): return # TODO: For dependee finding, we technically only need to parse all build files to collect target # dependencies. But in order to fully validate the graph and account for the fact that deleted # targets do not show up as changed roots, we use the `TransitiveHydratedTargets` product. # see https://github.com/pantsbuild/pants/issues/382 specs = (DescendantAddresses(''), ) adaptor_iter = (t.adaptor for targets in self._scheduler.product_request( TransitiveHydratedTargets, [Specs(specs)]) for t in targets.roots) graph = _DependentGraph.from_iterable( target_types_from_symbol_table(self._symbol_table), adaptor_iter) if changed_request.include_dependees == 'direct': for address in graph.dependents_of_addresses(changed_addresses): yield address elif changed_request.include_dependees == 'transitive': for address in graph.transitive_dependents_of_addresses( changed_addresses): yield address
def resolve(self, spec): uhs, = self.scheduler.product_request(UnhydratedStructs, [Specs(tuple([spec]))]) return uhs.dependencies
def parse_specs(self, *specs): return Specs(tuple( self.spec_parser.parse_spec(spec) for spec in specs))