def _expand_goals_and_specs(self): goals = self.options.goals specs = self.options.target_specs fail_fast = self.options.for_global_scope().fail_fast for goal in goals: if self.address_mapper.from_cache(get_buildroot(), goal, must_exist=False).file_exists(): logger.warning(" Command-line argument '{0}' is ambiguous and was assumed to be " "a goal. If this is incorrect, disambiguate it with ./{0}.".format(goal)) if self.options.print_help_if_requested(): sys.exit(0) self.requested_goals = goals with self.run_tracker.new_workunit(name='setup', labels=[WorkUnit.SETUP]): spec_parser = CmdLineSpecParser(self.root_dir, self.address_mapper, spec_excludes=self.spec_excludes, exclude_target_regexps=self.global_options.exclude_target_regexp) with self.run_tracker.new_workunit(name='parse', labels=[WorkUnit.SETUP]): def filter_for_tag(tag): return lambda target: tag in map(str, target.tags) tag_filter = wrap_filters(create_filters(self.global_options.tag, filter_for_tag)) for spec in specs: for address in spec_parser.parse_addresses(spec, fail_fast): self.build_graph.inject_address_closure(address) tgt = self.build_graph.get_target(address) if tag_filter(tgt): self.targets.append(tgt) self.goals = [Goal.by_name(goal) for goal in goals]
def test_wrap_filters(self): divides_by_6 = wrap_filters(create_filters(['2', '3'], self._divides_by)) self.assertFalse(divides_by_6(2)) self.assertFalse(divides_by_6(3)) self.assertTrue(divides_by_6(6)) self.assertFalse(divides_by_6(9)) self.assertTrue(divides_by_6(12))
def _target_tag_matches(self): def filter_for_tag(tag): return lambda t: tag in [ str(t_tag) for t_tag in t.kwargs().get("tags", []) ] return wrap_filters(create_filters(self.tags, filter_for_tag))
def console_output(self, _): wrapped_filter = wrap_filters(self._filters) filtered = set() for target in self.context.target_roots: if target not in filtered: filtered.add(target) if wrapped_filter(target): yield target.address.spec
def test_wrap_filters(self): divides_by_6 = wrap_filters( create_filters(['2', '3'], self._divides_by)) self.assertFalse(divides_by_6(2)) self.assertFalse(divides_by_6(3)) self.assertTrue(divides_by_6(6)) self.assertFalse(divides_by_6(9)) self.assertTrue(divides_by_6(12))
def _target_tag_matches(self): def filter_for_tag(tag): def filter_target(tgt): # `tags` can sometimes be explicitly set to `None`. We convert that to an empty list # with `or`. tags = tgt.kwargs().get("tags", []) or [] return tag in [str(t_tag) for t_tag in tags] return filter_target return wrap_filters(create_filters(self.tags, filter_for_tag))
def _expand_specs(self, specs, fail_fast): """Populate the BuildGraph and target list from a set of input specs.""" with self._run_tracker.new_workunit(name='parse', labels=[WorkUnitLabel.SETUP]): def filter_for_tag(tag): return lambda target: tag in map(str, target.tags) tag_filter = wrap_filters(create_filters(self._tag, filter_for_tag)) for spec in specs: for address in self._spec_parser.parse_addresses(spec, fail_fast): self._build_graph.inject_address_closure(address) target = self._build_graph.get_target(address) if tag_filter(target): self._targets.append(target)
def _roots_to_targets(self, target_roots): """Populate the BuildGraph and target list from a set of input TargetRoots.""" with self._run_tracker.new_workunit(name='parse', labels=[WorkUnitLabel.SETUP]): def filter_for_tag(tag): return lambda target: tag in map(str, target.tags) tag_filter = wrap_filters(create_filters(self._tag, filter_for_tag)) def generate_targets(): for address in self._build_graph.inject_roots_closure(target_roots, self._fail_fast): target = self._build_graph.get_target(address) if tag_filter(target): yield target return list(generate_targets())
def _expand_specs(self, spec_strs, fail_fast): """Populate the BuildGraph and target list from a set of input specs.""" with self._run_tracker.new_workunit(name='parse', labels=[WorkUnitLabel.SETUP]): def filter_for_tag(tag): return lambda target: tag in map(str, target.tags) tag_filter = wrap_filters(create_filters(self._tag, filter_for_tag)) # Parse all specs into unique Spec objects. spec_parser = CmdLineSpecParser(self._root_dir) specs = OrderedSet() for spec_str in spec_strs: specs.add(spec_parser.parse_spec(spec_str)) # Then scan them to generate unique Addresses. for address in self._build_graph.inject_specs_closure(specs, fail_fast): target = self._build_graph.get_target(address) if tag_filter(target): self._targets.append(target)
def _expand_specs(self, spec_strs, fail_fast): """Populate the BuildGraph and target list from a set of input specs.""" with self._run_tracker.new_workunit(name='parse', labels=[WorkUnitLabel.SETUP]): def filter_for_tag(tag): return lambda target: tag in map(str, target.tags) tag_filter = wrap_filters(create_filters(self._tag, filter_for_tag)) # Parse all specs into unique Spec objects. spec_parser = CmdLineSpecParser(self._root_dir) specs = OrderedSet() for spec_str in spec_strs: specs.add(spec_parser.parse_spec(spec_str)) # Then scan them to generate unique Addresses. for address in self._address_mapper.scan_specs(specs, fail_fast, self._spec_excludes): self._build_graph.inject_address_closure(address) target = self._build_graph.get_target(address) if tag_filter(target): self._targets.append(target)
def addresses_from_address_families(address_mapper, specs): """Given an AddressMapper and list of Specs, return matching BuildFileAddresses. Raises a AddressLookupError if: - there were no matching AddressFamilies, or - the Spec matches no addresses for SingleAddresses. """ # Capture a Snapshot covering all paths for these Specs, then group by directory. snapshot = yield Get(Snapshot, PathGlobs, _spec_to_globs(address_mapper, specs)) dirnames = set(dirname(f.stat.path) for f in snapshot.files) address_families = yield [Get(AddressFamily, Dir(d)) for d in dirnames] # NB: `@memoized` does not work on local functions. def by_directory(): if by_directory.cached is None: by_directory.cached = {af.namespace: af for af in address_families} return by_directory.cached by_directory.cached = None def raise_empty_address_family(spec): raise ResolveError('Path "{}" does not contain any BUILD files.'.format(spec.directory)) def exclude_address(spec): if specs.exclude_patterns: return any(p.search(spec) is not None for p in specs.exclude_patterns_memo()) return False def filter_for_tag(tag): return lambda t: tag in map(str, t.kwargs().get("tags", [])) include_target = wrap_filters(create_filters(specs.tags if specs.tags else '', filter_for_tag)) addresses = [] included = set() def include(address_families, predicate=None): matched = False for af in address_families: for (a, t) in af.addressables.items(): if (predicate is None or predicate(a)): if include_target(t) and (not exclude_address(a.spec)): matched = True if a not in included: addresses.append(a) included.add(a) return matched for spec in specs.dependencies: if type(spec) is DescendantAddresses: matched = include( af for af in address_families if fast_relpath_optional(af.namespace, spec.directory) is not None ) if not matched: raise AddressLookupError( 'Spec {} does not match any targets.'.format(spec)) elif type(spec) is SiblingAddresses: address_family = by_directory().get(spec.directory) if not address_family: raise_empty_address_family(spec) include([address_family]) elif type(spec) is SingleAddress: address_family = by_directory().get(spec.directory) if not address_family: raise_empty_address_family(spec) # spec.name here is generally the root node specified on commandline. equality here implies # a root node i.e. node specified on commandline. if not include([address_family], predicate=lambda a: a.target_name == spec.name): if len(addresses) == 0: _raise_did_you_mean(address_family, spec.name) elif type(spec) is AscendantAddresses: include( af for af in address_families if fast_relpath_optional(spec.directory, af.namespace) is not None ) else: raise ValueError('Unrecognized Spec type: {}'.format(spec)) yield BuildFileAddresses(addresses)
def _target_tag_matches(self): def filter_for_tag(tag): return lambda t: tag in [str(t_tag) for t_tag in t.kwargs().get("tags", [])] return wrap_filters(create_filters(self.tags, filter_for_tag))
def addresses_from_address_families(address_mapper, specs): """Given an AddressMapper and list of Specs, return matching BuildFileAddresses. Raises a AddressLookupError if: - there were no matching AddressFamilies, or - the Spec matches no addresses for SingleAddresses. """ # Capture a Snapshot covering all paths for these Specs, then group by directory. snapshot = yield Get(Snapshot, PathGlobs, _spec_to_globs(address_mapper, specs)) dirnames = set(dirname(f.stat.path) for f in snapshot.files) address_families = yield [Get(AddressFamily, Dir(d)) for d in dirnames] # NB: `@memoized` does not work on local functions. def by_directory(): if by_directory.cached is None: by_directory.cached = {af.namespace: af for af in address_families} return by_directory.cached by_directory.cached = None def raise_empty_address_family(spec): raise ResolveError('Path "{}" does not contain any BUILD files.'.format(spec.directory)) def exclude_address(spec): if specs.exclude_patterns: return any(p.search(spec) is not None for p in specs.exclude_patterns_memo()) return False def filter_for_tag(tag): return lambda t: tag in [str(t_tag) for t_tag in t.kwargs().get("tags", [])] include_target = wrap_filters(create_filters(specs.tags if specs.tags else '', filter_for_tag)) addresses = [] included = set() def include(address_families, predicate=None): matched = False for af in address_families: for (a, t) in af.addressables.items(): if (predicate is None or predicate(a)): if include_target(t) and (not exclude_address(a.spec)): matched = True if a not in included: addresses.append(a) included.add(a) return matched for spec in specs.dependencies: if type(spec) is DescendantAddresses: matched = include( af for af in address_families if fast_relpath_optional(af.namespace, spec.directory) is not None ) if not matched: raise AddressLookupError( 'Spec {} does not match any targets.'.format(spec)) elif type(spec) is SiblingAddresses: address_family = by_directory().get(spec.directory) if not address_family: raise_empty_address_family(spec) include([address_family]) elif type(spec) is SingleAddress: address_family = by_directory().get(spec.directory) if not address_family: raise_empty_address_family(spec) # spec.name here is generally the root node specified on commandline. equality here implies # a root node i.e. node specified on commandline. if not include([address_family], predicate=lambda a: a.target_name == spec.name): if len(addresses) == 0: _raise_did_you_mean(address_family, spec.name) elif type(spec) is AscendantAddresses: include( af for af in address_families if fast_relpath_optional(spec.directory, af.namespace) is not None ) else: raise ValueError('Unrecognized Spec type: {}'.format(spec)) yield BuildFileAddresses(addresses)