def _parse_addresses(self, spec): if spec.endswith('::'): dir = self._get_dir(spec[:-len('::')]) for buildfile in BuildFile.scan_buildfiles(self._root_dir, os.path.join(self._root_dir, dir)): for address in Target.get_all_addresses(buildfile): yield address elif spec.endswith(':'): dir = self._get_dir(spec[:-len(':')]) for address in Target.get_all_addresses(BuildFile(self._root_dir, dir)): yield address else: yield Address.parse(self._root_dir, spec)
def parse_jarcoordinate(coordinate): components = coordinate.split('#', 1) if len(components) == 2: org, name = components return org, name else: try: address = Address.parse(get_buildroot(), coordinate) try: target = Target.get(address) if not target: siblings = Target.get_all_addresses( address.buildfile) prompt = 'did you mean' if len( siblings ) == 1 else 'maybe you meant one of these' raise TaskError('%s => %s?:\n %s' % (address, prompt, '\n '.join( str(a) for a in siblings))) if not target.is_exported: raise TaskError('%s is not an exported target' % coordinate) return target.provides.org, target.provides.name except (ImportError, SyntaxError, TypeError): raise TaskError('Failed to parse %s' % address.buildfile.relpath) except IOError: raise TaskError('No BUILD file could be found at %s' % coordinate)
def parse_jarcoordinate(coordinate): components = coordinate.split('#', 1) if len(components) == 2: org, name = components return org, name else: try: # TODO(Eric Ayers) This code is suspect. Target.get() is a very old method and almost certainly broken. # Refactor to use methods from BuildGraph or BuildFileAddressMapper address = Address.parse(get_buildroot(), coordinate) target = Target.get(address) if not target: siblings = Target.get_all_addresses(address.build_file) prompt = 'did you mean' if len( siblings) == 1 else 'maybe you meant one of these' raise TaskError('%s => %s?:\n %s' % (address, prompt, '\n '.join( str(a) for a in siblings))) if not target.is_exported: raise TaskError('%s is not an exported target' % coordinate) return target.provides.org, target.provides.name except (BuildFile.BuildFileError, BuildFileParser.BuildFileParserError, AddressLookupError) as e: raise TaskError( '{message}\n Problem with BUILD file at {coordinate}' .format(message=e, coordinate=coordinate))
def configure_target(target): if target not in analyzed: analyzed.add(target) self.has_scala = not self.skip_scala and (self.has_scala or is_scala(target)) if target.has_resources: resources_by_basedir = defaultdict(set) for resources in target.resources: resources_by_basedir[resources.target_base].update( resources.sources) for basedir, resources in resources_by_basedir.items(): self.resource_extensions.update( Project.extract_resource_extensions(resources)) configure_source_sets(basedir, resources, is_test=False) if target.sources: test = target.is_test self.has_tests = self.has_tests or test configure_source_sets(target.target_base, target.sources, is_test=test) # Other BUILD files may specify sources in the same directory as this target. Those BUILD # files might be in parent directories (globs('a/b/*.java')) or even children directories if # this target globs children as well. Gather all these candidate BUILD files to test for # sources they own that live in the directories this targets sources live in. target_dirset = find_source_basedirs(target) candidates = Target.get_all_addresses(target.address.buildfile) for ancestor in target.address.buildfile.ancestors(): candidates.update(Target.get_all_addresses(ancestor)) for sibling in target.address.buildfile.siblings(): candidates.update(Target.get_all_addresses(sibling)) for descendant in target.address.buildfile.descendants(): candidates.update(Target.get_all_addresses(descendant)) def is_sibling(target): return source_target( target) and target_dirset.intersection( find_source_basedirs(target)) return filter( is_sibling, [Target.get(a) for a in candidates if a != target.address])
def _addresses(self): if self.context.target_roots: for target in self.context.target_roots: yield target.address else: for buildfile in BuildFile.scan_buildfiles(self._root_dir): for address in Target.get_all_addresses(buildfile): yield address
def _find_targets(self): if len(self.context.target_roots) > 0: for target in self.context.target_roots: yield target else: for buildfile in BuildFile.scan_buildfiles(get_buildroot()): target_addresses = Target.get_all_addresses(buildfile) for target_address in target_addresses: yield Target.get(target_address)
def scan_addresses(root_dir, base_path=None): """Parses all targets available in BUILD files under base_path and returns their addresses. If no base_path is specified, root_dir is assumed to be the base_path""" addresses = OrderedSet() for buildfile in BuildFile.scan_buildfiles(root_dir, base_path): addresses.update(Target.get_all_addresses(buildfile)) return addresses
def scan_addresses(root_dir, base_path=None): """Parses all targets available in BUILD files under base_path and returns their addresses. If no base_path is specified, root_dir is assumed to be the base_path""" addresses = OrderedSet() for buildfile in BuildFile.scan_buildfiles(root_dir, base_path): addresses.update(Target.get_all_addresses(buildfile)) return addresses
def configure_target(target): if target not in analyzed: analyzed.add(target) self.has_scala = not self.skip_scala and (self.has_scala or is_scala(target)) if target.has_resources: resources_by_basedir = defaultdict(set) for resources in target.resources: resources_by_basedir[resources.target_base].update(resources.sources) for basedir, resources in resources_by_basedir.items(): self.resource_extensions.update(Project.extract_resource_extensions(resources)) configure_source_sets(basedir, resources, is_test=False) if target.sources: test = target.is_test self.has_tests = self.has_tests or test configure_source_sets(target.target_base, target.sources, is_test=test) # Other BUILD files may specify sources in the same directory as this target. Those BUILD # files might be in parent directories (globs('a/b/*.java')) or even children directories if # this target globs children as well. Gather all these candidate BUILD files to test for # sources they own that live in the directories this targets sources live in. target_dirset = find_source_basedirs(target) candidates = Target.get_all_addresses(target.address.buildfile) for ancestor in target.address.buildfile.ancestors(): candidates.update(Target.get_all_addresses(ancestor)) for sibling in target.address.buildfile.siblings(): candidates.update(Target.get_all_addresses(sibling)) for descendant in target.address.buildfile.descendants(): candidates.update(Target.get_all_addresses(descendant)) def is_sibling(target): return source_target(target) and target_dirset.intersection(find_source_basedirs(target)) return filter(is_sibling, [Target.get(a) for a in candidates if a != target.address])
def __init__(self, context): ConsoleTask.__init__(self, context) self._print_uptodate = context.options.check_deps_print_uptodate self.repos = context.config.getdict('jar-publish', 'repos') self._artifacts_to_targets = {} all_addresses = (address for buildfile in BuildFile.scan_buildfiles(get_buildroot()) for address in Target.get_all_addresses(buildfile)) for address in all_addresses: target = Target.get(address) if target.is_exported: provided_jar, _, _ = target.get_artifact_info() artifact = (provided_jar.org, provided_jar.name) if not artifact in self._artifacts_to_targets: self._artifacts_to_targets[artifact] = target
def _owning_targets(self, path): for build_file in self._candidate_owners(path): is_build_file = (build_file.full_path == os.path.join(get_buildroot(), path)) for address in Target.get_all_addresses(build_file): target = Target.get(address) # A synthesized target can never own permanent files on disk if target != target.derived_from: # TODO(John Sirois): tighten up the notion of targets written down in a BUILD by a user # vs. targets created by pants at runtime. continue if target and (is_build_file or ((target.has_sources() or target.has_resources) and self._owns(target, path))): yield target
def console_output(self, _): buildfiles = OrderedSet() if self._dependees_type: base_paths = OrderedSet() for dependees_type in self._dependees_type: try: # Try to do a fully qualified import 1st for filtering on custom types. from_list, module, type_name = dependees_type.rsplit('.', 2) __import__('%s.%s' % (from_list, module), fromlist=[from_list]) except (ImportError, ValueError): # Fall back on pants provided target types. if hasattr(pants.base.build_file_context, dependees_type): type_name = getattr(pants.base.build_file_context, dependees_type) else: raise TaskError('Invalid type name: %s' % dependees_type) # Find the SourceRoot for the given input type base_paths.update(SourceRoot.roots(type_name)) if not base_paths: raise TaskError('No SourceRoot set for any target type in %s.' % self._dependees_type + '\nPlease define a source root in BUILD file as:' + '\n\tsource_root(\'<src-folder>\', %s)' % ', '.join(self._dependees_type)) for base_path in base_paths: buildfiles.update(BuildFile.scan_buildfiles(get_buildroot(), base_path)) else: buildfiles = BuildFile.scan_buildfiles(get_buildroot()) dependees_by_target = defaultdict(set) for buildfile in buildfiles: for address in Target.get_all_addresses(buildfile): for target in Target.get(address).resolve(): # TODO(John Sirois): tighten up the notion of targets written down in a BUILD by a # user vs. targets created by pants at runtime. target = self.get_concrete_target(target) if hasattr(target, 'dependencies'): for dependencies in target.dependencies: for dependency in dependencies.resolve(): dependency = self.get_concrete_target(dependency) dependees_by_target[dependency].add(target) roots = set(self.context.target_roots) if self._closed: for root in roots: yield str(root.address) for dependant in self.get_dependants(dependees_by_target, roots): yield str(dependant.address)
def parse_jarcoordinate(coordinate): components = coordinate.split('#', 1) if len(components) == 2: org, name = components return org, name else: try: # TODO(Eric Ayers) This code is suspect. Target.get() is a very old method and almost certainly broken. # Refactor to use methods from BuildGraph or BuildFileAddressMapper address = Address.parse(get_buildroot(), coordinate) target = Target.get(address) if not target: siblings = Target.get_all_addresses(address.build_file) prompt = 'did you mean' if len(siblings) == 1 else 'maybe you meant one of these' raise TaskError('%s => %s?:\n %s' % (address, prompt, '\n '.join(str(a) for a in siblings))) if not target.is_exported: raise TaskError('%s is not an exported target' % coordinate) return target.provides.org, target.provides.name except (BuildFile.BuildFileError, BuildFileParser.BuildFileParserError, AddressLookupError) as e: raise TaskError('{message}\n Problem with BUILD file at {coordinate}' .format(message=e, coordinate=coordinate))
def parse_jarcoordinate(coordinate): components = coordinate.split('#', 1) if len(components) == 2: org, name = components return org, name else: try: address = Address.parse(get_buildroot(), coordinate) # TODO: This is broken. try: target = Target.get(address) if not target: siblings = Target.get_all_addresses(address.buildfile) prompt = 'did you mean' if len(siblings) == 1 else 'maybe you meant one of these' raise TaskError('%s => %s?:\n %s' % (address, prompt, '\n '.join(str(a) for a in siblings))) if not target.is_exported: raise TaskError('%s is not an exported target' % coordinate) return target.provides.org, target.provides.name except (ImportError, SyntaxError, TypeError): raise TaskError('Failed to parse %s' % address.buildfile.relpath) except IOError: raise TaskError('No BUILD file could be found at %s' % coordinate)
def setup_parser(self, parser, args): self.config = Config.load() add_global_options(parser) # We support attempting zero or more goals. Multiple goals must be delimited from further # options and non goal args with a '--'. The key permutations we need to support: # ./pants goal => goals # ./pants goal goals => goals # ./pants goal compile src/java/... => compile # ./pants goal compile -x src/java/... => compile # ./pants goal compile src/java/... -x => compile # ./pants goal compile run -- src/java/... => compile, run # ./pants goal compile run -- src/java/... -x => compile, run # ./pants goal compile run -- -x src/java/... => compile, run if not args: args.append('goals') if len(args) == 1 and args[0] in set(['-h', '--help', 'help']): def format_usage(usages): left_colwidth = 0 for left, right in usages: left_colwidth = max(left_colwidth, len(left)) lines = [] for left, right in usages: lines.append(' %s%s%s' % (left, ' ' * (left_colwidth - len(left) + 1), right)) return '\n'.join(lines) usages = [ ("%prog goal goals ([spec]...)", Phase('goals').description), ("%prog goal help [goal] ([spec]...)", Phase('help').description), ("%prog goal [goal] [spec]...", "Attempt goal against one or more targets."), ("%prog goal [goal] ([goal]...) -- [spec]...", "Attempts all the specified goals."), ] parser.set_usage("\n%s" % format_usage(usages)) parser.epilog = ("Either lists all installed goals, provides extra help for a goal or else " "attempts to achieve the specified goal for the listed targets.") parser.print_help() # Add some text that we can't put in the epilog, because that formats away newlines. print(textwrap.dedent(""" Note that target specs accept two special forms: [dir]: to include all targets in the specified directory [dir]:: to include all targets found recursively under the directory""")) sys.exit(0) else: goals, specs = Goal.parse_args(args) self.requested_goals = goals with self.run_tracker.new_workunit(name='setup', labels=[WorkUnit.SETUP]): # Bootstrap goals by loading any configured bootstrap BUILD files with self.check_errors('The following bootstrap_buildfiles cannot be loaded:') as error: with self.run_tracker.new_workunit(name='bootstrap', labels=[WorkUnit.SETUP]): for path in self.config.getlist('goals', 'bootstrap_buildfiles', default = []): try: buildfile = BuildFile(get_buildroot(), os.path.relpath(path, get_buildroot())) ParseContext(buildfile).parse() except (TypeError, ImportError, TaskError, GoalError): error(path, include_traceback=True) except (IOError, SyntaxError): error(path) # Now that we've parsed the bootstrap BUILD files, and know about the SCM system. self.run_tracker.run_info.add_scm_info() # Bootstrap user goals by loading any BUILD files implied by targets. spec_parser = SpecParser(self.root_dir) with self.check_errors('The following targets could not be loaded:') as error: with self.run_tracker.new_workunit(name='parse', labels=[WorkUnit.SETUP]): for spec in specs: try: for target, address in spec_parser.parse(spec): if target: self.targets.append(target) # Force early BUILD file loading if this target is an alias that expands # to others. unused = list(target.resolve()) else: siblings = Target.get_all_addresses(address.buildfile) prompt = 'did you mean' if len(siblings) == 1 else 'maybe you meant one of these' error('%s => %s?:\n %s' % (address, prompt, '\n '.join(str(a) for a in siblings))) except (TypeError, ImportError, TaskError, GoalError): error(spec, include_traceback=True) except (IOError, SyntaxError, TargetDefinitionException): error(spec) self.phases = [Phase(goal) for goal in goals] rcfiles = self.config.getdefault('rcfiles', type=list, default=['/etc/pantsrc', '~/.pants.rc']) if rcfiles: rcfile = RcFile(rcfiles, default_prepend=False, process_default=True) # Break down the goals specified on the command line to the full set that will be run so we # can apply default flags to inner goal nodes. Also break down goals by Task subclass and # register the task class hierarchy fully qualified names so we can apply defaults to # baseclasses. sections = OrderedSet() for phase in Engine.execution_order(self.phases): for goal in phase.goals(): sections.add(goal.name) for clazz in goal.task_type.mro(): if clazz == Task: break sections.add('%s.%s' % (clazz.__module__, clazz.__name__)) augmented_args = rcfile.apply_defaults(sections, args) if augmented_args != args: del args[:] args.extend(augmented_args) sys.stderr.write("(using pantsrc expansion: pants goal %s)\n" % ' '.join(augmented_args)) Phase.setup_parser(parser, args, self.phases)