def test_parse_local_spec(self): spec_path, target_name = parse_spec(':c') self.assertEqual(spec_path, '') self.assertEqual(target_name, 'c') spec_path, target_name = parse_spec(':c', relative_to='here') self.assertEqual(spec_path, 'here') self.assertEqual(target_name, 'c')
def test_parse_absolute_spec(self): spec_path, target_name = parse_spec('//a/b/c') self.assertEqual(spec_path, 'a/b/c') self.assertEqual(target_name, 'c') spec_path, target_name = parse_spec('//a/b/c:c') self.assertEqual(spec_path, 'a/b/c') self.assertEqual(target_name, 'c') spec_path, target_name = parse_spec('//:c') self.assertEqual(spec_path, '') self.assertEqual(target_name, 'c')
def test_parse_spec(self): spec_path, target_name = parse_spec('a/b/c') self.assertEqual(spec_path, 'a/b/c') self.assertEqual(target_name, 'c') spec_path, target_name = parse_spec('a/b/c:c') self.assertEqual(spec_path, 'a/b/c') self.assertEqual(target_name, 'c') spec_path, target_name = parse_spec('a/b/c', relative_to='here') # no effect - we have a path self.assertEqual(spec_path, 'a/b/c') self.assertEqual(target_name, 'c')
def test_parse_spec(self): spec_path, target_name = parse_spec('a/b/c/') self.assertEqual(spec_path, 'a/b/c') self.assertEqual(target_name, 'c') spec_path, target_name = parse_spec('a/b/c') self.assertEqual(spec_path, 'a/b/c') self.assertEqual(target_name, 'c') spec_path, target_name = parse_spec('a/b/c:foo') self.assertEqual(spec_path, 'a/b/c') self.assertEqual(target_name, 'foo')
def dep_address_iter(): for dep_spec in self.dependencies: dep_spec_path, dep_target_name = parse_spec(dep_spec, relative_to=self.build_file.spec_path) dep_build_file = spec_path_to_build_file(self.build_file.root_dir, dep_spec_path) dep_address = BuildFileAddress(dep_build_file, dep_target_name) yield dep_address
def _parse_spec(self, spec): def normalize_spec_path(path): path = os.path.join(self._root_dir, path.lstrip('//')) normalized = os.path.relpath(os.path.realpath(path), self._root_dir) if normalized == '.': normalized = '' return normalized if spec.endswith('::'): spec_path = spec[:-len('::')] spec_dir = normalize_spec_path(spec_path) for build_file in BuildFile.scan_buildfiles(self._root_dir, spec_dir): self._build_file_parser.parse_build_file(build_file) for address in self._build_file_parser.addresses_by_build_file[build_file]: yield address elif spec.endswith(':'): spec_path = spec[:-len(':')] spec_dir = normalize_spec_path(spec_path) for build_file in BuildFile(self._root_dir, spec_dir).family(): self._build_file_parser.parse_build_file(build_file) for address in self._build_file_parser.addresses_by_build_file[build_file]: yield address else: spec_parts = spec.rsplit(':', 1) spec_parts[0] = normalize_spec_path(spec_parts[0]) spec_path, target_name = parse_spec(':'.join(spec_parts)) build_file = BuildFile(self._root_dir, spec_path) yield BuildFileAddress(build_file, target_name)
def dep_address_iter(): for dep_spec in self.dependencies: dep_spec_path, dep_target_name = parse_spec( dep_spec, relative_to=self.build_file.spec_path) dep_build_file = BuildFileCache.spec_path_to_build_file( self.build_file.root_dir, dep_spec_path) dep_address = BuildFileAddress(dep_build_file, dep_target_name) yield dep_address
def inject_spec_closure_into_build_graph(self, spec, build_graph, addresses_already_closed=None): spec_path, target_name = parse_spec(spec) self._inject_spec_closure_into_build_graph(spec_path, target_name, build_graph, addresses_already_closed)
def parse_spec(self, spec, relative_to=None, context=None): try: return parse_spec(spec, relative_to=relative_to) except ValueError as e: if context: msg = ('Invalid spec {spec} found while ' 'parsing {context}: {exc}').format(spec=spec, context=context, exc=e) else: msg = 'Invalid spec {spec}: {exc}'.format(spec=spec, exc=e) raise self.InvalidTargetException(msg)
def inject_address_closure_into_build_graph(self, address, build_graph, addresses_already_closed=None): addresses_already_closed = addresses_already_closed or set() if address in addresses_already_closed: return self._populate_target_proxy_transitive_closure_for_address(address) target_proxy = self._target_proxy_by_address[address] if not build_graph.contains_address(address): addresses_already_closed.add(address) for dep_address in target_proxy.dependency_addresses: self.inject_address_closure_into_build_graph( dep_address, build_graph, addresses_already_closed) target = target_proxy.to_target(build_graph) build_graph.inject_target( target, dependencies=target_proxy.dependency_addresses) for traversable_spec in target.traversable_dependency_specs: spec_path, target_name = parse_spec( traversable_spec, relative_to=address.spec_path) self._inject_spec_closure_into_build_graph( spec_path, target_name, build_graph, addresses_already_closed) traversable_spec_target = build_graph.get_target( SyntheticAddress(spec_path, target_name)) if traversable_spec_target not in target.dependencies: build_graph.inject_dependency( dependent=target.address, dependency=traversable_spec_target.address) target.mark_transitive_invalidation_hash_dirty() for traversable_spec in target.traversable_specs: spec_path, target_name = parse_spec( traversable_spec, relative_to=address.spec_path) self._inject_spec_closure_into_build_graph( spec_path, target_name, build_graph, addresses_already_closed) target.mark_transitive_invalidation_hash_dirty()
def _parse_spec(self, spec): def normalize_spec_path(path): is_abs = not path.startswith('//') and os.path.isabs(path) if is_abs: path = os.path.realpath(path) if os.path.commonprefix([self._root_dir, path ]) != self._root_dir: raise self.BadSpecError( 'Absolute address path {0} does not share build root {1}' .format(path, self._root_dir)) else: if path.startswith('//'): path = path[2:] path = os.path.join(self._root_dir, path) normalized = os.path.relpath(path, self._root_dir) if normalized == '.': normalized = '' return normalized if spec.endswith('::'): addresses = set() spec_path = spec[:-len('::')] spec_dir = normalize_spec_path(spec_path) if not os.path.isdir(os.path.join(self._root_dir, spec_dir)): raise self.BadSpecError( 'Can only recursive glob directories and {0} is not a valid dir' .format(spec_dir)) try: for build_file in BuildFile.scan_buildfiles( self._root_dir, spec_dir): addresses.update( self._address_mapper.addresses_in_spec_path( build_file.spec_path)) return addresses except (BuildFile.BuildFileError, AddressLookupError) as e: raise self.BadSpecError(e) elif spec.endswith(':'): spec_path = spec[:-len(':')] spec_dir = normalize_spec_path(spec_path) try: return set( self._address_mapper.addresses_in_spec_path(spec_dir)) except AddressLookupError as e: raise self.BadSpecError(e) else: spec_parts = spec.rsplit(':', 1) spec_parts[0] = normalize_spec_path(spec_parts[0]) spec_path, target_name = parse_spec(':'.join(spec_parts)) try: build_file = BuildFile.from_cache(self._root_dir, spec_path) return set([BuildFileAddress(build_file, target_name)]) except BuildFile.BuildFileError as e: raise self.BadSpecError(e)
def inject_spec_closure_into_build_graph(self, spec, build_graph, addresses_already_closed=None): addresses_already_closed = addresses_already_closed or set() spec_path, target_name = parse_spec(spec) build_file = BuildFileCache.spec_path_to_build_file( self._root_dir, spec_path) address = BuildFileAddress(build_file, target_name) self.inject_address_closure_into_build_graph(address, build_graph, addresses_already_closed)
def inject_address_closure_into_build_graph(self, address, build_graph, addresses_already_closed=None): addresses_already_closed = addresses_already_closed or set() if address in addresses_already_closed: return self._populate_target_proxy_transitive_closure_for_address(address) target_proxy = self._target_proxy_by_address[address] if not build_graph.contains_address(address): addresses_already_closed.add(address) for dep_address in target_proxy.dependency_addresses: self.inject_address_closure_into_build_graph(dep_address, build_graph, addresses_already_closed) target = target_proxy.to_target(build_graph) build_graph.inject_target(target, dependencies=target_proxy.dependency_addresses) for traversable_spec in target.traversable_dependency_specs: spec_path, target_name = parse_spec(traversable_spec, relative_to=address.spec_path) self._inject_spec_closure_into_build_graph(spec_path, target_name, build_graph, addresses_already_closed) traversable_spec_target = build_graph.get_target(SyntheticAddress(spec_path, target_name)) if traversable_spec_target not in target.dependencies: build_graph.inject_dependency(dependent=target.address, dependency=traversable_spec_target.address) target.mark_transitive_invalidation_hash_dirty() for traversable_spec in target.traversable_specs: spec_path, target_name = parse_spec(traversable_spec, relative_to=address.spec_path) self._inject_spec_closure_into_build_graph(spec_path, target_name, build_graph, addresses_already_closed) target.mark_transitive_invalidation_hash_dirty()
def spec_to_address(self, spec, relative_to=''): """A helper method for mapping a spec to the correct BuildFileAddress. :param spec: a spec to lookup in the map. :raises AddressLookupError: if the BUILD file cannot be found in the path specified by the spec :returns a new BuildFileAddress instanace """ spec_path, name = parse_spec(spec, relative_to=relative_to) try: build_file = BuildFile.from_cache(self.root_dir, spec_path) except BuildFile.BuildFileError as e: raise self.InvalidBuildFileReference('{message}\n when translating spec {spec}' .format(message=e, spec=spec)) return BuildFileAddress(build_file, name)
def _parse_spec(self, spec): def normalize_spec_path(path): is_abs = not path.startswith('//') and os.path.isabs(path) if is_abs: path = os.path.realpath(path) if os.path.commonprefix([self._root_dir, path]) != self._root_dir: raise self.BadSpecError('Absolute spec path {0} does not share build root {1}' .format(path, self._root_dir)) else: if path.startswith('//'): path = path[2:] path = os.path.join(self._root_dir, path) normalized = os.path.relpath(path, self._root_dir) if normalized == '.': normalized = '' return normalized if spec.endswith('::'): addresses = set() spec_path = spec[:-len('::')] spec_dir = normalize_spec_path(spec_path) if not os.path.isdir(os.path.join(self._root_dir, spec_dir)): raise self.BadSpecError('Can only recursive glob directories and {0} is not a valid dir' .format(spec_dir)) try: for build_file in BuildFile.scan_buildfiles(self._root_dir, spec_dir): addresses.update(self._address_mapper.addresses_in_spec_path(build_file.spec_path)) return addresses except (IOError, BuildFile.MissingBuildFileError, AddressLookupError) as e: raise self.BadSpecError(e) elif spec.endswith(':'): spec_path = spec[:-len(':')] spec_dir = normalize_spec_path(spec_path) try: return set(self._address_mapper.addresses_in_spec_path(spec_dir)) except (IOError, BuildFile.MissingBuildFileError, AddressLookupError) as e: raise self.BadSpecError(e) else: spec_parts = spec.rsplit(':', 1) spec_parts[0] = normalize_spec_path(spec_parts[0]) spec_path, target_name = parse_spec(':'.join(spec_parts)) try: build_file = BuildFile.from_cache(self._root_dir, spec_path) return set([BuildFileAddress(build_file, target_name)]) except (IOError, BuildFile.MissingBuildFileError) as e: raise self.BadSpecError(e)
def spec_to_address(self, spec, relative_to=''): """A helper method for mapping a spec to the correct address. :param string spec: A spec to lookup in the map. :param string relative_to: Path the spec might be relative to :raises :class:`pants.base.address_lookup_error.AddressLookupError` If the BUILD file cannot be found in the path specified by the spec. :returns: A new Address instance. :rtype: :class:`pants.base.address.Address` """ spec_path, name = parse_spec(spec, relative_to=relative_to) try: self.from_cache(self.root_dir, spec_path) except BuildFile.BuildFileError as e: raise self.InvalidBuildFileReference('{message}\n when translating spec {spec}' .format(message=e, spec=spec)) return Address(spec_path, name)
def spec_to_address(self, spec, relative_to=''): """A helper method for mapping a spec to the correct address. :param string spec: A spec to lookup in the map. :param string relative_to: Path the spec might be relative to :raises :class:`pants.base.address_lookup_error.AddressLookupError` If the BUILD file cannot be found in the path specified by the spec. :returns: A new Address instance. :rtype: :class:`pants.base.address.Address` """ spec_path, name = parse_spec(spec, relative_to=relative_to) try: self.from_cache(self.root_dir, spec_path) except BuildFile.BuildFileError as e: raise self.InvalidBuildFileReference( '{message}\n when translating spec {spec}'.format(message=e, spec=spec)) return Address(spec_path, name)
def parse_addresses(self, spec): if spec.endswith('::'): spec_rel_dir = self._get_dir(spec[:-len('::')]) spec_dir = os.path.join(self._root_dir, spec_rel_dir) for build_file in BuildFile.scan_buildfiles(self._root_dir, spec_dir): self._build_file_parser.parse_build_file(build_file) for address in self._build_file_parser.addresses_by_build_file[build_file]: yield address elif spec.endswith(':'): spec_rel_dir = self._get_dir(spec[:-len(':')]) spec_dir = os.path.join(self._root_dir, spec_rel_dir) for build_file in BuildFile(self._root_dir, spec_dir).family(): self._build_file_parser.parse_build_file(build_file) for address in self._build_file_parser.addresses_by_build_file[build_file]: yield address else: spec_path, target_name = parse_spec(spec) build_file = BuildFile(self._root_dir, spec_path) yield BuildFileAddress(build_file, target_name)
def inject_graph(self, root_spec, graph_dict): """Given a root spec, injects relevant targets from the graph represented by graph_dict. graph_dict should contain address specs, keyed by sources with lists of value destinations. Each created target will be a simple `target` alias. Returns the parsed Address for the root_spec. """ for src, targets in graph_dict.items(): src_path, src_name = parse_spec(src) if not src_path: # The target is located in the root. src_path = '.' self.add_to_build_file( '{}/BUILD'.format(src_path), '''target(name='{}', dependencies=[{}])\n'''.format( src_name, "'{}'".format("','".join(targets)) if targets else '')) root_address = SyntheticAddress.parse(root_spec) self.build_graph.inject_address_closure(root_address) return root_address
def parse_addresses(self, spec): if spec.endswith('::'): spec_rel_dir = self._get_dir(spec[:-len('::')]) spec_dir = os.path.join(self._root_dir, spec_rel_dir) for build_file in BuildFile.scan_buildfiles( self._root_dir, spec_dir): self._build_file_parser.parse_build_file(build_file) for address in self._build_file_parser.addresses_by_build_file[ build_file]: yield address elif spec.endswith(':'): spec_rel_dir = self._get_dir(spec[:-len(':')]) spec_dir = os.path.join(self._root_dir, spec_rel_dir) for build_file in BuildFile(self._root_dir, spec_dir).family(): self._build_file_parser.parse_build_file(build_file) for address in self._build_file_parser.addresses_by_build_file[ build_file]: yield address else: spec_path, target_name = parse_spec(spec) build_file = BuildFile(self._root_dir, spec_path) yield BuildFileAddress(build_file, target_name)
def inject_graph(self, root_spec, graph_dict): """Given a root spec, injects relevant targets from the graph represented by graph_dict. graph_dict should contain address specs, keyed by sources with lists of value destinations. Each created target will be a simple `target` alias. Returns the parsed Address for the root_spec. """ for src, targets in graph_dict.items(): src_path, src_name = parse_spec(src) if not src_path: # The target is located in the root. src_path = '.' self.add_to_build_file( '{}/BUILD'.format(src_path), '''target(name='{}', dependencies=[{}])\n'''.format( src_name, "'{}'".format("','".join(targets)) if targets else '' ) ) root_address = SyntheticAddress.parse(root_spec) self.build_graph.inject_address_closure(root_address) return root_address
def __init__(self, run_tracker, root_dir, parser, argv): Command.__init__(self, run_tracker, root_dir, parser, argv) self.target = None self.extra_targets = [] self.extra_requirements = [] self.config = Config.load() interpreters = self.options.interpreters or [b''] self.interpreter_cache = PythonInterpreterCache(self.config, logger=self.debug) self.interpreter_cache.setup(filters=interpreters) interpreters = self.interpreter_cache.select_interpreter( list(self.interpreter_cache.matches(interpreters))) if len(interpreters) != 1: self.error('Unable to detect suitable interpreter.') self.interpreter = interpreters[0] for req in self.options.extra_requirements: self.extra_requirements.append(PythonRequirement(req, use_2to3=True)) # We parse each arg in the context of the cli usage: # ./pants command (options) [spec] (build args) # ./pants command (options) [spec]... -- (build args) # Our command token and our options are parsed out so we see args of the form: # [spec] (build args) # [spec]... -- (build args) binaries = [] for k in range(len(self.args)): arg = self.args.pop(0) if arg == '--': break def not_a_target(debug_msg): self.debug('Not a target, assuming option: %s.' % e) # We failed to parse the arg as a target or else it was in valid address format but did not # correspond to a real target. Assume this is the 1st of the build args and terminate # processing args for target addresses. self.args.insert(0, arg) target = None try: print(root_dir, arg) # import pdb; pdb.set_trace() self.build_file_parser.inject_spec_closure_into_build_graph(arg, self.build_graph) spec_path, target_name = parse_spec(arg) build_file = BuildFile(root_dir, spec_path) address = BuildFileAddress(build_file, target_name) target = self.build_graph.get_target(address) if target is None: not_a_target(debug_msg='Unrecognized target') break except Exception as e: not_a_target(debug_msg=e) break if isinstance(target, PythonBinary): binaries.append(target) else: self.extra_targets.append(target) if len(binaries) == 0: # treat as a chroot pass elif len(binaries) == 1: # We found a binary and are done, the rest of the args get passed to it self.target = binaries[0] else: self.error('Can only process 1 binary target, %s contains %d:\n\t%s' % ( arg, len(binaries), '\n\t'.join(str(binary.address) for binary in binaries) )) if self.target is None: if not self.extra_targets: self.error('No valid target specified!') self.target = self.extra_targets.pop(0)
def inject_spec_closure_into_build_graph(self, spec, build_graph, addresses_already_closed=None): addresses_already_closed = addresses_already_closed or set() spec_path, target_name = parse_spec(spec) build_file = BuildFileCache.spec_path_to_build_file(self._root_dir, spec_path) address = BuildFileAddress(build_file, target_name) self.inject_address_closure_into_build_graph(address, build_graph, addresses_already_closed)
def do_test_bad_spec(self, spec): with self.assertRaises(ValueError): parse_spec(spec)
def __init__(self, run_tracker, root_dir, parser, argv, build_file_parser, build_graph): Command.__init__(self, run_tracker, root_dir, parser, argv, build_file_parser, build_graph) self.binary = None self.targets = [] self.extra_requirements = [] self.config = Config.load() interpreters = self.options.interpreters or [b''] self.interpreter_cache = PythonInterpreterCache(self.config, logger=self.debug) self.interpreter_cache.setup(filters=interpreters) interpreters = self.interpreter_cache.select_interpreter( list(self.interpreter_cache.matches(interpreters))) if len(interpreters) != 1: self.error('Unable to detect suitable interpreter.') self.interpreter = interpreters[0] for req in self.options.extra_requirements: self.extra_requirements.append( PythonRequirement(req, use_2to3=True)) # We parse each arg in the context of the cli usage: # ./pants command (options) [spec] (build args) # ./pants command (options) [spec]... -- (build args) # Our command token and our options are parsed out so we see args of the form: # [spec] (build args) # [spec]... -- (build args) for k in range(len(self.args)): arg = self.args.pop(0) if arg == '--': break def not_a_target(debug_msg): self.debug('Not a target, assuming option: %s.' % debug_msg) # We failed to parse the arg as a target or else it was in valid address format but did not # correspond to a real target. Assume this is the 1st of the build args and terminate # processing args for target addresses. self.args.insert(0, arg) try: print(root_dir, arg) self.build_file_parser.inject_spec_closure_into_build_graph( arg, self.build_graph) spec_path, target_name = parse_spec(arg) build_file = BuildFile(root_dir, spec_path) address = BuildFileAddress(build_file, target_name) target = self.build_graph.get_target(address) if target is None: not_a_target(debug_msg='Unrecognized target') break except Exception as e: not_a_target(debug_msg=e) break if isinstance(target, PythonBinary): if self.binary: self.error( 'Can only process 1 binary target. Found %s and %s.' % (self.binary, target)) else: self.binary = target self.targets.append(target) if not self.targets: self.error('No valid targets specified!')
def __init__(self, spec): spec_path, target_name = parse_spec(spec) super(AnotherTarget, self).__init__(target_name, Address.parse(spec), None)
def _parse_spec(self, spec, fail_fast=False): def normalize_spec_path(path): is_abs = not path.startswith('//') and os.path.isabs(path) if is_abs: path = os.path.realpath(path) if os.path.commonprefix([self._root_dir, path]) != self._root_dir: raise self.BadSpecError('Absolute address path {0} does not share build root {1}' .format(path, self._root_dir)) else: if path.startswith('//'): path = path[2:] path = os.path.join(self._root_dir, path) normalized = os.path.relpath(path, self._root_dir) if normalized == '.': normalized = '' return normalized errored_out = [] if spec.endswith('::'): addresses = set() spec_path = spec[:-len('::')] spec_dir = normalize_spec_path(spec_path) try: build_files = self._address_mapper.scan_buildfiles(self._root_dir, spec_dir, spec_excludes=self._spec_excludes) except (BuildFile.BuildFileError, AddressLookupError) as e: raise self.BadSpecError(e) for build_file in build_files: try: # This attempts to filter out broken BUILD files before we parse them. if self._not_excluded_spec(build_file.spec_path): addresses.update(self._address_mapper.addresses_in_spec_path(build_file.spec_path)) except (BuildFile.BuildFileError, AddressLookupError) as e: if fail_fast: raise self.BadSpecError(e) errored_out.append('--------------------') errored_out.append(traceback.format_exc()) errored_out.append('Exception message: {0}'.format(e)) if errored_out: error_msg = '\n'.join(errored_out + ["Invalid BUILD files for [{0}]".format(spec)]) raise self.BadSpecError(error_msg) return addresses elif spec.endswith(':'): spec_path = spec[:-len(':')] spec_dir = normalize_spec_path(spec_path) try: return set(self._address_mapper.addresses_in_spec_path(spec_dir)) except AddressLookupError as e: raise self.BadSpecError(e) else: spec_parts = spec.rsplit(':', 1) spec_parts[0] = normalize_spec_path(spec_parts[0]) spec_path, target_name = parse_spec(':'.join(spec_parts)) try: self._address_mapper.from_cache(self._root_dir, spec_path) except BuildFile.BuildFileError as e: raise self.BadSpecError(e) return {Address(spec_path, target_name)}
def __init__(self, spec): spec_path, target_name = parse_spec(spec) super(NotTestTarget, self).__init__(target_name, SyntheticAddress.parse(spec), None)
def __init__(self, *args, **kwargs): super(Py, self).__init__(*args, **kwargs) self.binary = None self.targets = [] self.extra_requirements = [] self.config = Config.from_cache() interpreters = self.old_options.interpreters or [b''] self.interpreter_cache = PythonInterpreterCache(self.config, logger=self.debug) self.interpreter_cache.setup(filters=interpreters) interpreters = self.interpreter_cache.select_interpreter( list(self.interpreter_cache.matches(interpreters))) if len(interpreters) != 1: self.error('Unable to detect suitable interpreter.') self.interpreter = interpreters[0] for req in self.old_options.extra_requirements: self.extra_requirements.append(PythonRequirement(req, use_2to3=True)) # We parse each arg in the context of the cli usage: # ./pants command (options) [spec] (build args) # ./pants command (options) [spec]... -- (build args) # Our command token and our options are parsed out so we see args of the form: # [spec] (build args) # [spec]... -- (build args) for k in range(len(self.args)): arg = self.args.pop(0) if arg == '--': break def not_a_target(debug_msg): self.debug('Not a target, assuming option: %s.' % debug_msg) # We failed to parse the arg as a target or else it was in valid address format but did not # correspond to a real target. Assume this is the 1st of the build args and terminate # processing args for target addresses. self.args.insert(0, arg) try: print(self.root_dir, arg, file=sys.stderr) self.build_graph.inject_spec_closure(arg) spec_path, target_name = parse_spec(arg) build_file = BuildFile.from_cache(self.root_dir, spec_path) address = BuildFileAddress(build_file, target_name) target = self.build_graph.get_target(address) if target is None: not_a_target(debug_msg='Unrecognized target') break except Exception as e: not_a_target(debug_msg=e) break if isinstance(target, PythonBinary): if self.binary: self.error('Can only process 1 binary target. Found %s and %s.' % (self.binary, target)) else: self.binary = target self.targets.append(target) if not self.targets: self.error('No valid targets specified!')
def spec_to_address(self, spec, relative_to=''): """A helper method for mapping a spec to the correct BuildFileAddress.""" spec_path, name = parse_spec(spec, relative_to=relative_to) build_file = BuildFile.from_cache(self.root_dir, spec_path) return BuildFileAddress(build_file, name)
def _parse_spec(self, spec, fail_fast=False): def normalize_spec_path(path): is_abs = not path.startswith('//') and os.path.isabs(path) if is_abs: path = os.path.realpath(path) if os.path.commonprefix([self._root_dir, path ]) != self._root_dir: raise self.BadSpecError( 'Absolute address path {0} does not share build root {1}' .format(path, self._root_dir)) else: if path.startswith('//'): path = path[2:] path = os.path.join(self._root_dir, path) normalized = os.path.relpath(path, self._root_dir) if normalized == '.': normalized = '' return normalized errored_out = [] if spec.endswith('::'): addresses = set() spec_path = spec[:-len('::')] spec_dir = normalize_spec_path(spec_path) try: build_files = self._address_mapper.scan_buildfiles( self._root_dir, spec_dir, spec_excludes=self._spec_excludes) except (BuildFile.BuildFileError, AddressLookupError) as e: raise self.BadSpecError(e) for build_file in build_files: try: # This attempts to filter out broken BUILD files before we parse them. if self._not_excluded_spec(build_file.spec_path): addresses.update( self._address_mapper.addresses_in_spec_path( build_file.spec_path)) except (BuildFile.BuildFileError, AddressLookupError) as e: if fail_fast: raise self.BadSpecError(e) errored_out.append('--------------------') errored_out.append(traceback.format_exc()) errored_out.append('Exception message: {0}'.format(e)) if errored_out: error_msg = '\n'.join( errored_out + ["Invalid BUILD files for [{0}]".format(spec)]) raise self.BadSpecError(error_msg) return addresses elif spec.endswith(':'): spec_path = spec[:-len(':')] spec_dir = normalize_spec_path(spec_path) try: return set( self._address_mapper.addresses_in_spec_path(spec_dir)) except AddressLookupError as e: raise self.BadSpecError(e) else: spec_parts = spec.rsplit(':', 1) spec_parts[0] = normalize_spec_path(spec_parts[0]) spec_path, target_name = parse_spec(':'.join(spec_parts)) try: self._address_mapper.from_cache(self._root_dir, spec_path) except BuildFile.BuildFileError as e: raise self.BadSpecError(e) return {Address(spec_path, target_name)}
def _parse_spec(self, spec, fail_fast=False): def normalize_spec_path(path): is_abs = not path.startswith('//') and os.path.isabs(path) if is_abs: path = os.path.realpath(path) if os.path.commonprefix([self._root_dir, path]) != self._root_dir: raise self.BadSpecError('Absolute address path {0} does not share build root {1}' .format(path, self._root_dir)) else: if path.startswith('//'): path = path[2:] path = os.path.join(self._root_dir, path) normalized = os.path.relpath(path, self._root_dir) if normalized == '.': normalized = '' return normalized errored_out = [] if spec.endswith('::'): addresses = set() spec_path = spec[:-len('::')] spec_dir = normalize_spec_path(spec_path) if not os.path.isdir(os.path.join(self._root_dir, spec_dir)): raise self.BadSpecError('Can only recursive glob directories and {0} is not a valid dir' .format(spec_dir)) try: build_files = BuildFile.scan_buildfiles(self._root_dir, spec_dir) except (BuildFile.BuildFileError, AddressLookupError) as e: raise self.BadSpecError(e) for build_file in build_files: try: addresses.update(self._address_mapper.addresses_in_spec_path(build_file.spec_path)) except (BuildFile.BuildFileError, AddressLookupError) as e: if fail_fast: raise self.BadSpecError(e) errored_out.append('Exception message: {0}'.format(e.message)) if errored_out: error_msg = '\n'.join(errored_out + ["Invalid BUILD files for [{0}]".format(spec)]) raise self.BadSpecError(error_msg) return addresses elif spec.endswith(':'): spec_path = spec[:-len(':')] spec_dir = normalize_spec_path(spec_path) try: return set(self._address_mapper.addresses_in_spec_path(spec_dir)) except AddressLookupError as e: raise self.BadSpecError(e) else: spec_parts = spec.rsplit(':', 1) spec_parts[0] = normalize_spec_path(spec_parts[0]) spec_path, target_name = parse_spec(':'.join(spec_parts)) try: build_file = BuildFile.from_cache(self._root_dir, spec_path) return set([BuildFileAddress(build_file, target_name)]) except BuildFile.BuildFileError as e: raise self.BadSpecError(e)