def classpath(self, targets, classpath_prefix=None, classpath_product=None): """Builds a transitive classpath for the given targets. Optionally includes a classpath prefix or building from a non-default classpath product. :param targets: the targets for which to build the transitive classpath. :param classpath_prefix: optional additional entries to prepend to the classpath. :param classpath_product: an optional ClasspathProduct from which to build the classpath. if not specified, the runtime_classpath will be used. :return: a list of classpath strings. """ classpath = list(classpath_prefix) if classpath_prefix else [] classpath_product = classpath_product or self.context.products.get_data( 'runtime_classpath') closure = BuildGraph.closure(targets, bfs=True) classpath_for_targets = ClasspathUtil.classpath( closure, classpath_product, self.confs) classpath.extend(classpath_for_targets) return classpath
def test_closure_bfs(self): root = self.inject_graph( 'a', { 'a': ['b', 'c'], 'b': ['d', 'e'], 'c': ['f', 'g'], 'd': ['h', 'i'], 'e': ['j', 'k'], 'f': ['l', 'm'], 'g': ['n', 'o'], 'h': [], 'i': [], 'j': [], 'k': [], 'l': [], 'm': [], 'n': [], 'o': [], }) bfs_closure = BuildGraph.closure([self.build_graph.get_target(root)], bfs=True) self.assertEquals( [t.address.target_name for t in bfs_closure], [ str(six.unichr(x)) for x in six.moves.xrange(ord('a'), ord('o') + 1) ], )
def test_closure_bfs(self): root = self.inject_graph( "a", { "a": ["b", "c"], "b": ["d", "e"], "c": ["f", "g"], "d": ["h", "i"], "e": ["j", "k"], "f": ["l", "m"], "g": ["n", "o"], "h": [], "i": [], "j": [], "k": [], "l": [], "m": [], "n": [], "o": [], }, ) bfs_closure = BuildGraph.closure([self.build_graph.get_target(root)], bfs=True) self.assertEqual( [t.address.target_name for t in bfs_closure], [chr(x) for x in range(ord("a"), ord("o") + 1)], )
def _compute_classpath(runtime_classpath, targets): closure = BuildGraph.closure( targets, bfs=True, include_scopes=Scopes.JVM_RUNTIME_SCOPES, respect_intransitive=True ) classpath_for_targets = ClasspathUtil.classpath(closure, runtime_classpath) return classpath_for_targets
def classpath(self, targets, classpath_prefix=None, classpath_product=None, exclude_scopes=None, include_scopes=None): """Builds a transitive classpath for the given targets. Optionally includes a classpath prefix or building from a non-default classpath product. :param targets: the targets for which to build the transitive classpath. :param classpath_prefix: optional additional entries to prepend to the classpath. :param classpath_product: an optional ClasspathProduct from which to build the classpath. if not specified, the runtime_classpath will be used. :param :class:`pants.build_graph.target_scopes.Scope` exclude_scopes: Exclude targets which have at least one of these scopes on the classpath. :param :class:`pants.build_graph.target_scopes.Scope` include_scopes: Only include targets which have at least one of these scopes on the classpath. Defaults to Scopes.JVM_RUNTIME_SCOPES. :return: a list of classpath strings. """ include_scopes = Scopes.JVM_RUNTIME_SCOPES if include_scopes is None else include_scopes classpath_product = classpath_product or self.context.products.get_data('runtime_classpath') closure = BuildGraph.closure(targets, bfs=True, include_scopes=include_scopes, exclude_scopes=exclude_scopes, respect_intransitive=True) classpath_for_targets = ClasspathUtil.classpath(closure, classpath_product, self.confs) classpath = list(classpath_prefix or ()) classpath.extend(classpath_for_targets) return classpath
def _filter_by_excludes(self, classpath_target_tuples, root_targets): # Excludes are always applied transitively, so regardless of whether a transitive # set of targets was included here, their closure must be included. closure = BuildGraph.closure(root_targets, bfs=True) excludes = self._excludes.get_for_targets(closure) return [target_tuple for target_tuple in classpath_target_tuples if _not_excluded_filter(excludes)(target_tuple)]
def _filter_by_excludes(self, classpath_target_tuples, root_targets): # Excludes are always applied transitively, so regardless of whether a transitive # set of targets was included here, their closure must be included. closure = BuildGraph.closure(root_targets, bfs=True) excludes = self._excludes.get_for_targets(closure) return [target_tuple for target_tuple in classpath_target_tuples if _not_excluded_filter(excludes)(target_tuple)]
def test_closure_bfs(self): root = self.inject_graph('a', { 'a': ['b', 'c'], 'b': ['d', 'e'], 'c': ['f', 'g'], 'd': ['h', 'i'], 'e': ['j', 'k'], 'f': ['l', 'm'], 'g': ['n', 'o'], 'h': [], 'i': [], 'j': [], 'k': [], 'l': [], 'm': [], 'n': [], 'o': [], }) bfs_closure = BuildGraph.closure([self.build_graph.get_target(root)], bfs=True) self.assertEquals( [t.address.target_name for t in bfs_closure], [str(six.unichr(x)) for x in six.moves.xrange(ord('a'), ord('o') + 1)], )
def test_closure(self): self.assertEqual(OrderedSet(), BuildGraph.closure([])) a = self.make_target("a") self.assertEqual(OrderedSet([a]), BuildGraph.closure([a])) b = self.make_target("b", dependencies=[a]) self.assertEqual(OrderedSet([b, a]), BuildGraph.closure([b])) c = self.make_target("c", dependencies=[b]) self.assertEqual(OrderedSet([c, b, a]), BuildGraph.closure([c])) d = self.make_target("d", dependencies=[a, c]) self.assertEqual(OrderedSet([d, a, c, b]), BuildGraph.closure([d])) def d_gen(): yield d self.assertEqual(OrderedSet([d, a, c, b]), BuildGraph.closure(d_gen())) empty_gen = iter(()) self.assertEqual(OrderedSet([]), BuildGraph.closure(empty_gen))
def classpath(self, targets, classpath_prefix=None, classpath_product=None): """Builds a transitive classpath for the given targets. Optionally includes a classpath prefix or building from a non-default classpath product. :param targets: the targets for which to build the transitive classpath. :param classpath_prefix: optional additional entries to prepend to the classpath. :param classpath_product: an optional ClasspathProduct from which to build the classpath. if not specified, the runtime_classpath will be used. :return: a list of classpath strings. """ classpath = list(classpath_prefix) if classpath_prefix else [] classpath_product = classpath_product or self.context.products.get_data('runtime_classpath') closure = BuildGraph.closure(targets, bfs=True) classpath_for_targets = ClasspathUtil.classpath(closure, classpath_product, self.confs) classpath.extend(classpath_for_targets) return classpath
def test_closure(self): self.assertEquals([], BuildGraph.closure([])) a = self.make_target('a') self.assertEquals([a], BuildGraph.closure([a])) b = self.make_target('b', dependencies=[a]) self.assertEquals([b, a], BuildGraph.closure([b])) c = self.make_target('c', dependencies=[b]) self.assertEquals([c, b, a], BuildGraph.closure([c])) d = self.make_target('d', dependencies=[a, c]) self.assertEquals([d, a, c, b], BuildGraph.closure([d])) def d_gen(): yield d self.assertEquals([d, a, c, b], BuildGraph.closure(d_gen())) def empty_gen(): return yield self.assertEquals([], BuildGraph.closure(empty_gen()))
def test_closure(self): self.assertEquals([], BuildGraph.closure([])) a = self.make_target('a') self.assertEquals([a], BuildGraph.closure([a])) b = self.make_target('b', dependencies=[a]) self.assertEquals([b, a], BuildGraph.closure([b])) c = self.make_target('c', dependencies=[b]) self.assertEquals([c, b, a], BuildGraph.closure([c])) d = self.make_target('d', dependencies=[a, c]) self.assertEquals([d, a, c, b], BuildGraph.closure([d])) def d_gen(): yield d self.assertEquals([d, a, c, b], BuildGraph.closure(d_gen())) def empty_gen(): return yield self.assertEquals([], BuildGraph.closure(empty_gen()))
def test_closure(self): self.assertEqual([], BuildGraph.closure([])) a = self.make_target('a') self.assertEqual([a], BuildGraph.closure([a])) b = self.make_target('b', dependencies=[a]) self.assertEqual([b, a], BuildGraph.closure([b])) c = self.make_target('c', dependencies=[b]) self.assertEqual([c, b, a], BuildGraph.closure([c])) d = self.make_target('d', dependencies=[a, c]) self.assertEqual([d, a, c, b], BuildGraph.closure([d])) def d_gen(): yield d self.assertEqual([d, a, c, b], BuildGraph.closure(d_gen())) def empty_gen(): return yield # type: ignore[misc] # MyPy complains that this is not reachable self.assertEqual([], BuildGraph.closure(empty_gen()))
def instrument(self, output_dir): for datafile in self._iter_datafiles(output_dir): os.unlink(datafile) self._canonical_datafile = os.path.join(output_dir, '{}.canonical'.format(self._DATAFILE_NAME)) # It's conceivable we'll be executing a test that has no source file dependencies; ie: we'll # never generate a canonical coverage datafile below. Create an empty one here to allow the # test run to proceeed normally. touch(self._canonical_datafile) # Setup an instrumentation classpath based on the existing runtime classpath. runtime_classpath = self._context.products.get_data('runtime_classpath') instrumentation_classpath = self._context.products.safe_create_data('instrument_classpath', runtime_classpath.copy) self.initialize_instrument_classpath(output_dir, self._settings, self._targets, instrumentation_classpath) cobertura_cp = self._settings.tool_classpath('cobertura-instrument') files_to_instrument = [] for target in self._targets: if Cobertura.is_coverage_target(target): paths = instrumentation_classpath.get_for_target(target) for (name, path) in paths: files_to_instrument.append(path) if len(files_to_instrument) > 0: unique_files = list(set(files_to_instrument)) relativize_paths(unique_files, self._settings.workdir) args = [ '--basedir', self._settings.workdir, '--datafile', self._canonical_datafile, ] if self._include_user_classpath: closure = BuildGraph.closure(self._targets, bfs=True, include_scopes=Scopes.JVM_TEST_SCOPES, respect_intransitive=True) aux_classpath = safe_classpath( ClasspathUtil.classpath(closure, runtime_classpath), synthetic_jar_dir=None) args.append('--auxClasspath') args.extend(aux_classpath) # apply class incl/excl filters if len(self._include_classes) > 0: for pattern in self._include_classes: args += ["--includeClasses", pattern] else: args += ["--includeClasses", '.*'] # default to instrumenting all classes for pattern in self._exclude_classes: args += ["--excludeClasses", pattern] with temporary_file() as tmp_file: tmp_file.write("\n".join(unique_files)) tmp_file.flush() args += ["--listOfFilesToInstrument", tmp_file.name] main = 'net.sourceforge.cobertura.instrument.InstrumentMain' self._settings.log.debug( "executing cobertura instrumentation with the following args: {}".format(args)) result = self._execute_java(classpath=cobertura_cp, main=main, jvm_options=self._settings.coverage_jvm_options, args=args, workunit_factory=self._context.new_workunit, workunit_name='cobertura-instrument') if result != 0: raise TaskError("java {0} ... exited non-zero ({1})" " 'failed to instrument'".format(main, result))
def instrument(self, output_dir): for datafile in self._iter_datafiles(output_dir): os.unlink(datafile) self._canonical_datafile = os.path.join( output_dir, '{}.canonical'.format(self._DATAFILE_NAME)) # It's conceivable we'll be executing a test that has no source file dependencies; ie: we'll # never generate a canonical coverage datafile below. Create an empty one here to allow the # test run to proceeed normally. touch(self._canonical_datafile) # Setup an instrumentation classpath based on the existing runtime classpath. runtime_classpath = self._context.products.get_data( 'runtime_classpath') instrumentation_classpath = self._context.products.safe_create_data( 'instrument_classpath', runtime_classpath.copy) self.initialize_instrument_classpath(output_dir, self._settings, self._targets, instrumentation_classpath) cobertura_cp = self._settings.tool_classpath('cobertura-instrument') files_to_instrument = [] for target in self._targets: if Cobertura.is_coverage_target(target): paths = instrumentation_classpath.get_for_target(target) for (name, path) in paths: files_to_instrument.append(path) if len(files_to_instrument) > 0: unique_files = list(set(files_to_instrument)) relativize_paths(unique_files, self._settings.workdir) args = [ '--basedir', self._settings.workdir, '--datafile', self._canonical_datafile, ] if self._include_user_classpath: closure = BuildGraph.closure( self._targets, bfs=True, include_scopes=Scopes.JVM_TEST_SCOPES, respect_intransitive=True) aux_classpath = safe_classpath(ClasspathUtil.classpath( closure, runtime_classpath), synthetic_jar_dir=None) args.append('--auxClasspath') args.extend(aux_classpath) # apply class incl/excl filters if len(self._include_classes) > 0: for pattern in self._include_classes: args += ["--includeClasses", pattern] else: args += ["--includeClasses", '.*'] # default to instrumenting all classes for pattern in self._exclude_classes: args += ["--excludeClasses", pattern] with temporary_file(binary_mode=False) as tmp_file: tmp_file.write("\n".join(unique_files)) tmp_file.flush() args += ["--listOfFilesToInstrument", tmp_file.name] main = 'net.sourceforge.cobertura.instrument.InstrumentMain' self._settings.log.debug( "executing cobertura instrumentation with the following args: {}" .format(args)) result = self._execute_java( classpath=cobertura_cp, main=main, jvm_options=self._settings.coverage_jvm_options, args=args, workunit_factory=self._context.new_workunit, workunit_name='cobertura-instrument') if result != 0: raise TaskError("java {0} ... exited non-zero ({1})" " 'failed to instrument'".format( main, result))