class UnionProductsTest(BaseTest): def setUp(self): super(UnionProductsTest, self).setUp() self.products = UnionProducts() def test_get_for_target(self): c = self.make_target('c') b = self.make_target('b', dependencies=[c]) a = self.make_target('a', dependencies=[b, c]) self.products.add_for_target(a, [1]) self.products.add_for_target(b, [2]) self.products.add_for_target(c, [3]) self.assertEquals(self.products.get_for_target(a), OrderedSet([1, 2, 3])) self.assertEquals(self.products.get_for_target(b), OrderedSet([2, 3])) self.assertEquals(self.products.get_for_target(c), OrderedSet([3])) self.assertEquals(self.products.get_for_target(a, transitive=False), OrderedSet([1])) self.assertEquals(self.products.get_for_target(b, transitive=False), OrderedSet([2])) self.assertEquals(self.products.get_for_target(c, transitive=False), OrderedSet([3])) def test_remove_for_target(self): c = self.make_target('c') b = self.make_target('b', dependencies=[c]) a = self.make_target('a', dependencies=[b, c]) self.products.add_for_target(a, [1]) self.products.add_for_target(b, [2]) self.products.add_for_target(c, [3]) self.products.remove_for_target(a, [1]) self.assertEquals(self.products.get_for_target(a), OrderedSet([2, 3])) self.assertEquals(self.products.get_for_target(b), OrderedSet([2, 3])) self.assertEquals(self.products.get_for_target(c), OrderedSet([3])) def test_empty_products(self): c = self.make_target('c') self.assertFalse(self.products.get_for_target(c)) def test_non_empty_products(self): c = self.make_target('c') self.products.add_for_target(c, [3]) self.assertTrue(self.products.get_for_target(c)) def test_target_for_product_existing_product(self): c = self.make_target('c') self.products.add_for_target(c, [3]) found_target = self.products.target_for_product(3) self.assertEqual(c, found_target) def test_target_for_product_nonexistent_product(self): c = self.make_target('c') self.products.add_for_target(c, [3]) found_target = self.products.target_for_product(1000) self.assertIsNone(found_target)
class UnionProductsTest(BaseTest): def setUp(self): super(UnionProductsTest, self).setUp() self.products = UnionProducts() def test_get_for_target(self): c = self.make_target("c") b = self.make_target("b", dependencies=[c]) a = self.make_target("a", dependencies=[b, c]) self.products.add_for_target(a, [1]) self.products.add_for_target(b, [2]) self.products.add_for_target(c, [3]) self.assertEquals(self.products.get_for_target(a), OrderedSet([1, 2, 3])) self.assertEquals(self.products.get_for_target(b), OrderedSet([2, 3])) self.assertEquals(self.products.get_for_target(c), OrderedSet([3])) self.assertEquals(self.products.get_for_target(a, transitive=False), OrderedSet([1])) self.assertEquals(self.products.get_for_target(b, transitive=False), OrderedSet([2])) self.assertEquals(self.products.get_for_target(c, transitive=False), OrderedSet([3])) def test_remove_for_target(self): c = self.make_target("c") b = self.make_target("b", dependencies=[c]) a = self.make_target("a", dependencies=[b, c]) self.products.add_for_target(a, [1]) self.products.add_for_target(b, [2]) self.products.add_for_target(c, [3]) self.products.remove_for_target(a, [1]) self.assertEquals(self.products.get_for_target(a), OrderedSet([2, 3])) self.assertEquals(self.products.get_for_target(b), OrderedSet([2, 3])) self.assertEquals(self.products.get_for_target(c), OrderedSet([3])) def test_empty_products(self): c = self.make_target("c") self.assertFalse(self.products.get_for_target(c)) def test_non_empty_products(self): c = self.make_target("c") self.products.add_for_target(c, [3]) self.assertTrue(self.products.get_for_target(c)) def test_target_for_product_existing_product(self): c = self.make_target("c") self.products.add_for_target(c, [3]) found_target = self.products.target_for_product(3) self.assertEqual(c, found_target) def test_target_for_product_nonexistent_product(self): c = self.make_target("c") self.products.add_for_target(c, [3]) found_target = self.products.target_for_product(1000) self.assertIsNone(found_target)
class UnionProductsTest(BaseTest): def setUp(self): super(UnionProductsTest, self).setUp() self.products = UnionProducts() def test_get_for_target(self): c = self.make_target('c') b = self.make_target('b', dependencies=[c]) a = self.make_target('a', dependencies=[b, c]) self.products.add_for_target(a, [1]) self.products.add_for_target(b, [2]) self.products.add_for_target(c, [3]) self.assertEquals(self.products.get_for_targets(a.closure(bfs=True)), OrderedSet([1, 2, 3])) self.assertEquals(self.products.get_for_targets(b.closure(bfs=True)), OrderedSet([2, 3])) self.assertEquals(self.products.get_for_targets(c.closure(bfs=True)), OrderedSet([3])) self.assertEquals(self.products.get_for_target(a), OrderedSet([1])) self.assertEquals(self.products.get_for_target(b), OrderedSet([2])) self.assertEquals(self.products.get_for_target(c), OrderedSet([3])) def test_get_product_target_mappings_for_targets(self): b = self.make_target('b') a = self.make_target('a', dependencies=[b]) self.products.add_for_target(a, [1, 3]) self.products.add_for_target(b, [2, 3]) self.assertEquals(self.products.get_for_targets(a.closure(bfs=True)), OrderedSet([1, 3, 2])) self.assertEquals(self.products.get_for_targets(b.closure(bfs=True)), OrderedSet([2, 3])) self.assertEquals(self.products.get_product_target_mappings_for_targets(a.closure(bfs=True)), [(1, a), (3, a), (2, b), (3, b)]) def test_copy(self): c = self.make_target('c') b = self.make_target('b', dependencies=[c]) a = self.make_target('a', dependencies=[b, c]) self.products.add_for_target(a, [1]) self.products.add_for_target(b, [2]) copied = self.products.copy() self.assertEquals(self.products.get_for_targets(a.closure(bfs=True)), OrderedSet([1, 2])) self.assertEquals(self.products.get_for_targets(b.closure(bfs=True)), OrderedSet([2])) self.assertEquals(copied.get_for_targets(a.closure(bfs=True)), OrderedSet([1, 2])) self.assertEquals(copied.get_for_targets(b.closure(bfs=True)), OrderedSet([2])) copied.add_for_target(c, [3]) self.assertEquals(self.products.get_for_targets(a.closure(bfs=True)), OrderedSet([1, 2])) self.assertEquals(self.products.get_for_targets(b.closure(bfs=True)), OrderedSet([2])) self.assertEquals(self.products.get_for_targets(c.closure(bfs=True)), OrderedSet()) self.assertEquals(copied.get_for_targets(a.closure(bfs=True)), OrderedSet([1, 2, 3])) self.assertEquals(copied.get_for_targets(b.closure(bfs=True)), OrderedSet([2, 3])) self.assertEquals(copied.get_for_targets(c.closure(bfs=True)), OrderedSet([3])) def test_remove_for_target(self): c = self.make_target('c') b = self.make_target('b', dependencies=[c]) a = self.make_target('a', dependencies=[b, c]) self.products.add_for_target(a, [1]) self.products.add_for_target(b, [2]) self.products.add_for_target(c, [3]) self.products.remove_for_target(a, [1]) self.assertEquals(self.products.get_for_targets(a.closure(bfs=True)), OrderedSet([2, 3])) self.assertEquals(self.products.get_for_targets(b.closure(bfs=True)), OrderedSet([2, 3])) self.assertEquals(self.products.get_for_targets(c.closure(bfs=True)), OrderedSet([3])) def test_empty_products(self): c = self.make_target('c') self.assertFalse(self.products.get_for_target(c)) def test_non_empty_products(self): c = self.make_target('c') self.products.add_for_target(c, [3]) self.assertTrue(self.products.get_for_target(c)) def test_target_for_product_existing_product(self): c = self.make_target('c') self.products.add_for_target(c, [3]) found_target = self.products.target_for_product(3) self.assertEqual(c, found_target) def test_target_for_product_nonexistent_product(self): c = self.make_target('c') self.products.add_for_target(c, [3]) found_target = self.products.target_for_product(1000) self.assertIsNone(found_target)
class ClasspathProducts(object): def __init__(self): self._classpaths = UnionProducts() self._exclude_patterns = UnionProducts() self._buildroot = get_buildroot() def add_for_targets(self, targets, classpath_elements): """Adds classpath elements to the products of all the provided targets.""" for target in targets: self.add_for_target(target, classpath_elements) def add_for_target(self, target, classpath_elements): """Adds classpath elements to the products of the provided target.""" self._validate_classpath_tuples(classpath_elements, target) self._classpaths.add_for_target(target, classpath_elements) def add_excludes_for_targets(self, targets): """Add excludes from the provided targets. Does not look up transitive excludes.""" for target in targets: self._add_excludes_for_target(target) def remove_for_target(self, target, classpath_elements): """Removes the given entries for the target""" self._classpaths.remove_for_target(target, classpath_elements) def get_for_target(self, target): """Gets the transitive classpath products for the given target, in order, respecting target excludes.""" return self.get_for_targets([target]) def get_for_targets(self, targets): """Gets the transitive classpath products for the given targets, in order, respecting target excludes.""" classpath_tuples = self._classpaths.get_for_targets(targets) filtered_classpath_tuples = self._filter_by_excludes( classpath_tuples, targets) return filtered_classpath_tuples def _filter_by_excludes(self, classpath_tuples, root_targets): exclude_patterns = self._exclude_patterns.get_for_targets(root_targets) filtered_classpath_tuples = filter( _not_excluded_filter(exclude_patterns), classpath_tuples) return filtered_classpath_tuples def _add_excludes_for_target(self, target): # TODO(nhoward): replace specific ivy based exclude filterings in the jar object refactor # creates strings from excludes that will match classpath entries generated by ivy # eg exclude(org='org.example', name='lib') => 'jars/org.example/lib' # exclude(org='org.example') => 'jars/org.example/' # The empty string was added to the end of the os.path.join list, so that the exclude pattern # always ends with a path separator. It's a short term fix so we don't match the following # 'jars/com.twitter.common/text' in '.../jars/com.twitter.common/text-lang-model/jars/text...' if target.is_exported: self._exclude_patterns.add_for_target(target, [ os.path.join('jars', target.provides.org, target.provides.name, '') ]) if isinstance(target, JvmTarget) and target.excludes: self._exclude_patterns.add_for_target(target, [ os.path.join('jars', e.org, e.name or '', '') for e in target.excludes ]) def _validate_classpath_tuples(self, classpath, target): """Validates that all files are located within the working copy, to simplify relativization.""" for classpath_tuple in classpath: self._validate_path_in_buildroot(classpath_tuple, target) def _validate_path_in_buildroot(self, classpath_tuple, target): conf, path = classpath_tuple if os.path.relpath(path, self._buildroot).startswith(os.pardir): raise TaskError( 'Classpath entry {} for target {} is located outside the buildroot.' .format(path, target.address.spec))
class ClasspathProducts(object): def __init__(self): self._classpaths = UnionProducts() self._excludes = UnionProducts() self._buildroot = get_buildroot() def add_for_targets(self, targets, classpath_elements): """Adds classpath path elements to the products of all the provided targets.""" for target in targets: self.add_for_target(target, classpath_elements) def add_for_target(self, target, classpath_elements): """Adds classpath path elements to the products of the provided target.""" self._add_elements_for_target( target, self._wrap_path_elements(classpath_elements)) def add_jars_for_targets(self, targets, conf, resolved_jars): """Adds jar classpath elements to the products of the provided targets in a way that works with excludes. """ classpath_entries = [] for jar in resolved_jars: if not jar.pants_path: raise TaskError("Jar: {!s} has no specified path.".format( jar.coordinate)) classpath_entries.append( (conf, ArtifactClasspathEntry(jar.coordinate, jar.pants_path))) for target in targets: self._add_elements_for_target(target, classpath_entries) def add_excludes_for_targets(self, targets): """Add excludes from the provided targets. Does not look up transitive excludes.""" for target in targets: self._add_excludes_for_target(target) def remove_for_target(self, target, classpath_elements): """Removes the given entries for the target""" self._classpaths.remove_for_target( target, self._wrap_path_elements(classpath_elements)) def get_for_target(self, target, transitive=True): """Gets the transitive classpath products for the given target, in order, respecting target excludes.""" return self.get_for_targets([target], transitive=transitive) def get_for_targets(self, targets, transitive=True): """Gets the transitive classpath products for the given targets, in order, respecting target excludes.""" classpath_tuples = self._classpaths.get_for_targets( targets, transitive) filtered_classpath_tuples = self._filter_by_excludes( classpath_tuples, targets, transitive) return [(classpath_tuple[0], classpath_tuple[1].path) for classpath_tuple in filtered_classpath_tuples] def _filter_by_excludes(self, classpath_tuples, root_targets, transitive): excludes = self._excludes.get_for_targets(root_targets, transitive=transitive) return filter(_not_excluded_filter(excludes), classpath_tuples) def _add_excludes_for_target(self, target): if target.is_exported: self._excludes.add_for_target( target, [Exclude(target.provides.org, target.provides.name)]) if isinstance(target, JvmTarget) and target.excludes: self._excludes.add_for_target(target, target.excludes) def _wrap_path_elements(self, classpath_elements): return [(element[0], ClasspathEntry(element[1])) for element in classpath_elements] def _add_elements_for_target(self, target, elements): self._validate_classpath_tuples(elements, target) self._classpaths.add_for_target(target, elements) def _validate_classpath_tuples(self, classpath, target): """Validates that all files are located within the working copy, to simplify relativization. :param classpath: The list of classpath tuples. Each tuple is a 2-tuple of ivy_conf and ClasspathEntry :param target: The target that the classpath tuple is being registered for :raises: `TaskError` when the path is outside the build root """ for classpath_tuple in classpath: conf, classpath_entry = classpath_tuple path = classpath_entry.path if os.path.relpath(path, self._buildroot).startswith(os.pardir): raise TaskError( 'Classpath entry {} for target {} is located outside the buildroot.' .format(path, target.address.spec))
class ClasspathProducts(object): def __init__(self): self._classpaths = UnionProducts() self._excludes = UnionProducts() self._buildroot = get_buildroot() def add_for_targets(self, targets, classpath_elements): """Adds classpath path elements to the products of all the provided targets.""" for target in targets: self.add_for_target(target, classpath_elements) def add_for_target(self, target, classpath_elements): """Adds classpath path elements to the products of the provided target.""" self._add_elements_for_target(target, self._wrap_path_elements(classpath_elements)) def add_jars_for_targets(self, targets, conf, resolved_jars): """Adds jar classpath elements to the products of the provided targets in a way that works with excludes. """ classpath_entries = [] for jar in resolved_jars: if not jar.pants_path: raise TaskError("Jar: {!s} has no specified path.".format(jar.coordinate)) classpath_entries.append((conf, ArtifactClasspathEntry(jar.coordinate, jar.pants_path))) for target in targets: self._add_elements_for_target(target, classpath_entries) def add_excludes_for_targets(self, targets): """Add excludes from the provided targets. Does not look up transitive excludes.""" for target in targets: self._add_excludes_for_target(target) def remove_for_target(self, target, classpath_elements): """Removes the given entries for the target""" self._classpaths.remove_for_target(target, self._wrap_path_elements(classpath_elements)) def get_for_target(self, target, transitive=True): """Gets the transitive classpath products for the given target, in order, respecting target excludes.""" return self.get_for_targets([target], transitive=transitive) def get_for_targets(self, targets, transitive=True): """Gets the transitive classpath products for the given targets, in order, respecting target excludes.""" classpath_tuples = self._classpaths.get_for_targets(targets, transitive) filtered_classpath_tuples = self._filter_by_excludes(classpath_tuples, targets, transitive) return [(classpath_tuple[0], classpath_tuple[1].path) for classpath_tuple in filtered_classpath_tuples] def _filter_by_excludes(self, classpath_tuples, root_targets, transitive): excludes = self._excludes.get_for_targets(root_targets, transitive=transitive) return filter(_not_excluded_filter(excludes), classpath_tuples) def _add_excludes_for_target(self, target): if target.is_exported: self._excludes.add_for_target(target, [Exclude(target.provides.org, target.provides.name)]) if isinstance(target, JvmTarget) and target.excludes: self._excludes.add_for_target(target, target.excludes) def _wrap_path_elements(self, classpath_elements): return [(element[0], ClasspathEntry(element[1])) for element in classpath_elements] def _add_elements_for_target(self, target, elements): self._validate_classpath_tuples(elements, target) self._classpaths.add_for_target(target, elements) def _validate_classpath_tuples(self, classpath, target): """Validates that all files are located within the working copy, to simplify relativization. :param classpath: The list of classpath tuples. Each tuple is a 2-tuple of ivy_conf and ClasspathEntry :param target: The target that the classpath tuple is being registered for :raises: `TaskError` when the path is outside the build root """ for classpath_tuple in classpath: conf, classpath_entry = classpath_tuple path = classpath_entry.path if os.path.relpath(path, self._buildroot).startswith(os.pardir): raise TaskError( 'Classpath entry {} for target {} is located outside the buildroot.' .format(path, target.address.spec))
class ClasspathProducts(object): def __init__(self): self._classpaths = UnionProducts() self._exclude_patterns = UnionProducts() self._buildroot = get_buildroot() def add_for_targets(self, targets, classpath_elements): """Adds classpath elements to the products of all the provided targets.""" for target in targets: self.add_for_target(target, classpath_elements) def add_for_target(self, target, classpath_elements): """Adds classpath elements to the products of the provided target.""" self._validate_classpath_tuples(classpath_elements, target) self._classpaths.add_for_target(target, classpath_elements) def add_excludes_for_targets(self, targets): """Add excludes from the provided targets. Does not look up transitive excludes.""" for target in targets: self._add_excludes_for_target(target) def remove_for_target(self, target, classpath_elements): """Removes the given entries for the target""" self._classpaths.remove_for_target(target, classpath_elements) def get_for_target(self, target): """Gets the transitive classpath products for the given target, in order, respecting target excludes.""" return self.get_for_targets([target]) def get_for_targets(self, targets): """Gets the transitive classpath products for the given targets, in order, respecting target excludes.""" classpath_tuples = self._classpaths.get_for_targets(targets) filtered_classpath_tuples = self._filter_by_excludes(classpath_tuples, targets) return filtered_classpath_tuples def _filter_by_excludes(self, classpath_tuples, root_targets): exclude_patterns = self._exclude_patterns.get_for_targets(root_targets) filtered_classpath_tuples = filter(_not_excluded_filter(exclude_patterns), classpath_tuples) return filtered_classpath_tuples def _add_excludes_for_target(self, target): # TODO(nhoward): replace specific ivy based exclude filterings in the jar object refactor # creates strings from excludes that will match classpath entries generated by ivy # eg exclude(org='org.example', name='lib') => 'jars/org.example/lib' # exclude(org='org.example') => 'jars/org.example/' # The empty string was added to the end of the os.path.join list, so that the exclude pattern # always ends with a path separator. It's a short term fix so we don't match the following # 'jars/com.twitter.common/text' in '.../jars/com.twitter.common/text-lang-model/jars/text...' if target.is_exported: self._exclude_patterns.add_for_target(target, [os.path.join('jars', target.provides.org, target.provides.name, '')]) if isinstance(target, JvmTarget) and target.excludes: self._exclude_patterns.add_for_target(target, [os.path.join('jars', e.org, e.name or '', '') for e in target.excludes]) def _validate_classpath_tuples(self, classpath, target): """Validates that all files are located within the working copy, to simplify relativization.""" for classpath_tuple in classpath: self._validate_path_in_buildroot(classpath_tuple, target) def _validate_path_in_buildroot(self, classpath_tuple, target): conf, path = classpath_tuple if os.path.relpath(path, self._buildroot).startswith(os.pardir): raise TaskError( 'Classpath entry {} for target {} is located outside the buildroot.' .format(path, target.address.spec))