def test_synthetic_forms(self): self.assertAddress('a/b', 'target', SyntheticAddress.parse('a/b:target')) self.assertAddress('a/b', 'b', SyntheticAddress.parse('a/b')) self.assertAddress('a/b', 'target', SyntheticAddress.parse(':target', 'a/b')) self.assertAddress('', 'target', SyntheticAddress.parse(':target'))
def test_derived_from_chain(self): context = self.context() # add concrete target build_file = self.add_to_build_file( 'y/BUILD', dedent(''' java_library( name='concrete', sources=['SourceA.scala'], ) ''')) concrete_address = BuildFileAddress(build_file, 'concrete') context.build_graph.inject_address_closure(concrete_address) concrete = context.build_graph.get_target(concrete_address) # add synthetic targets syn_one = context.add_new_target(SyntheticAddress('y', 'syn_one'), JavaLibrary, derived_from=concrete, sources=["SourceB.scala"]) syn_two = context.add_new_target(SyntheticAddress('y', 'syn_two'), JavaLibrary, derived_from=syn_one, sources=["SourceC.scala"]) # validate self.assertEquals(list(syn_two.derived_from_chain), [syn_one, concrete]) self.assertEquals(list(syn_one.derived_from_chain), [concrete]) self.assertEquals(list(concrete.derived_from_chain), [])
def _create_java_target(self, target, dependees): genfiles = [] for source in target.sources_relative_to_source_root(): path = os.path.join(target.target_base, source) genfiles.extend(calculate_genfiles(path, source).get('java', [])) spec_path = os.path.relpath(self.java_out, get_buildroot()) address = SyntheticAddress(spec_path, target.id) deps = OrderedSet(self.javadeps) import_jars = target.imports jars_tgt = self.context.add_new_target(SyntheticAddress(spec_path, target.id+str('-rjars')), JarLibrary, jars=import_jars, derived_from=target) # Add in the 'spec-rjars' target, which contains all the JarDependency targets passed in via the # imports parameter. Each of these jars is expected to contain .proto files bundled together # with their .class files. deps.add(jars_tgt) tgt = self.context.add_new_target(address, JavaLibrary, derived_from=target, sources=genfiles, provides=target.provides, dependencies=deps, excludes=target.payload.get_field_value('excludes')) for dependee in dependees: dependee.inject_dependency(tgt.address) return tgt
def test_no_targets(self): self.add_to_build_file('empty/BUILD', 'pass') with self.assertRaises(AddressLookupError): self.build_graph.inject_address_closure( SyntheticAddress.parse('empty')) with self.assertRaises(AddressLookupError): self.build_graph.inject_address_closure( SyntheticAddress.parse('empty:foo'))
def test_deferred_sources_payload_field(self): target = TestDeferredSourcesTarget( name='bar', address=SyntheticAddress.parse('//:bar'), build_graph=self.build_graph, deferred_sources_address=SyntheticAddress.parse('//:foo')) self.assertSequenceEqual([], list(target.traversable_specs)) self.assertSequenceEqual([':foo'], list(target.traversable_dependency_specs))
def test_target_invalid(self): self.add_to_build_file('a/BUILD', 'target(name="a")') with self.assertRaises(AddressLookupError): self.build_graph.inject_address_closure(SyntheticAddress.parse('a:nope')) self.add_to_build_file('b/BUILD', 'target(name="a")') with self.assertRaises(AddressLookupError): self.build_graph.inject_address_closure(SyntheticAddress.parse('b')) with self.assertRaises(AddressLookupError): self.build_graph.inject_address_closure(SyntheticAddress.parse('b:b'))
def test_inject_then_inject_closure(self): self.add_to_build_file( 'BUILD', 'target(name="a", ' ' dependencies=[' ' "other:b",' '])') self.add_to_build_file('other/BUILD', 'target(name="b")') self.build_graph.inject_address(SyntheticAddress.parse('//:a')) self.build_graph.inject_address_closure(SyntheticAddress.parse('//:a')) a = self.build_graph.get_target_from_spec('//:a') b = self.build_graph.get_target_from_spec('//other:b') self.assertIn(b, a.dependencies)
def _synthesize_resources_target(self): # Create an address for the synthetic target. spec = self.address.spec + '_synthetic_resources' synthetic_address = SyntheticAddress.parse(spec=spec) # For safety, ensure an address that's not used already, even though that's highly unlikely. while self._build_graph.contains_address(synthetic_address): spec += '_' synthetic_address = SyntheticAddress.parse(spec=spec) self._build_graph.inject_synthetic_target(synthetic_address, Resources, sources=self.payload.resources.source_paths, derived_from=self) return self._build_graph.get_target(synthetic_address)
def test_inject_then_inject_closure(self): self.add_to_build_file('BUILD', 'target(name="a", ' ' dependencies=[' ' "other:b",' '])') self.add_to_build_file('other/BUILD', 'target(name="b")') self.build_graph.inject_address(SyntheticAddress.parse('//:a')) self.build_graph.inject_address_closure(SyntheticAddress.parse('//:a')) a = self.build_graph.get_target_from_spec('//:a') b = self.build_graph.get_target_from_spec('//other:b') self.assertIn(b, a.dependencies)
def test_target_invalid(self): self.add_to_build_file('a/BUILD', 'target(name="a")') with self.assertRaises(AddressLookupError): self.build_graph.inject_address_closure( SyntheticAddress.parse('a:nope')) self.add_to_build_file('b/BUILD', 'target(name="a")') with self.assertRaises(AddressLookupError): self.build_graph.inject_address_closure( SyntheticAddress.parse('b')) with self.assertRaises(AddressLookupError): self.build_graph.inject_address_closure( SyntheticAddress.parse('b:b'))
def test_jar_dependencies(self): jar1 = JarDependency(org='testOrg1', name='testName1', rev='123') jar2 = JarDependency(org='testOrg2', name='testName2', rev='456') lib = JarLibrary(name='foo', address=SyntheticAddress.parse('//:foo'), build_graph=self.build_graph, jars=[jar1, jar2]) self.assertEquals((jar1, jar2), lib.jar_dependencies)
def resolve_spec(self, spec): """Converts a spec to an address and maps it using `resolve`""" try: address = SyntheticAddress.parse(spec) except ValueError as e: raise self.InvalidAddressError(e) return self.resolve(address)
def createtarget(self, lang, gentarget, dependees): predicates = self.genlangs() languages = predicates.keys() if not (lang in languages) or not (predicates[lang](gentarget)): raise TaskError('Invalid language "{lang}" for task {task}'.format( lang=lang, task=type(self).__name__)) to_generate = [] for source in gentarget.sources_relative_to_buildroot(): to_generate.extend( self._sources_to_be_generated(gentarget.package, source)) spec_path = os.path.join( os.path.relpath(self.workdir, get_buildroot()), 'gen-java') address = SyntheticAddress(spec_path=spec_path, target_name=gentarget.id) target = self.context.add_new_target( address, JavaLibrary, derived_from=gentarget, sources=to_generate, provides=gentarget.provides, dependencies=[], excludes=gentarget.payload.excludes) for dependee in dependees: dependee.inject_dependency(target.address) return target
def test_register_bad_target_alias(self): with self.assertRaises(TypeError): self.build_configuration.register_target_alias('fred', object()) target = Target('fred', SyntheticAddress.parse('a:b'), BuildGraph(address_mapper=None)) with self.assertRaises(TypeError): self.build_configuration.register_target_alias('fred', target)
def create_classes_jar_target(self, target, archive, jar_file): """Create a JarLibrary target containing the jar_file as a JarDependency. :param AndroidLibrary target: The new JarLibrary will be derived from this AndroidLibrary . :param string archive: Archive name as fetched by ivy, e.g. 'org.pantsbuild.example-1.0.aar'. :param string jar_file: Full path of the classes.jar contained within unpacked aar files. :return: new_target. :rtype::class:`pants.backend.jvm.targets.java_library.JarLibrary` """ # TODO(mateor) add another JarDependency for every jar under 'libs'. # Try to parse revision number. This is just to satisfy the spec, the rev is part of 'archive'. archive_version = os.path.splitext(archive)[0].rpartition('-')[-1] jar_url = 'file://{0}'.format(jar_file) jar_dep = JarDependency(org=target.id, name=archive, rev=archive_version, url=jar_url) address = SyntheticAddress(self.workdir, '{}-classes.jar'.format(archive)) new_target = self.context.add_new_target(address, JarLibrary, jars=[jar_dep], derived_from=target) return new_target
def __init__(self, name, build_file, build_file_source_lines, target_source_lines, target_interval, dependencies, dependencies_interval): """See BuildFileManipulator.load() for how to construct one as a user.""" self.name = name self.build_file = build_file self.target_address = BuildFileAddress(build_file, name) self._build_file_source_lines = build_file_source_lines self._target_source_lines = target_source_lines self._target_interval = target_interval self._dependencies_interval = dependencies_interval self._dependencies_by_address = {} for dep in dependencies: dep_address = SyntheticAddress.parse(dep.spec, relative_to=build_file.spec_path) if dep_address in self._dependencies_by_address: raise BuildTargetParseError('The address {dep_address} occurred multiple times in the ' 'dependency specs for target {name} in {build_file}. ' .format(dep_address=dep_address.spec, name=name, build_file=build_file)) self._dependencies_by_address[dep_address] = dep
def test_excludes(self): # TODO(Eric Ayers) There doesn't seem to be any way to set this field at the moment. lib = JarLibrary(name='foo', address=SyntheticAddress.parse('//:foo'), build_graph=self.build_graph, jars=[jar1]) self.assertEquals([], lib.excludes)
def create_python_library(self, relpath, name, source_contents_map=None, dependencies=(), provides=None): sources = ['__init__.py'] + source_contents_map.keys( ) if source_contents_map else None sources_strs = ["'{0}'".format(s) for s in sources] if sources else None self.create_file(relpath=self.build_path(relpath), contents=dedent(""" python_library( name='{name}', {sources_clause} dependencies=[ {dependencies} ], {provides_clause} ) """).format(name=name, sources_clause='sources=[{0}],'.format(','.join(sources_strs)) if sources_strs else '', dependencies=','.join(map(repr, dependencies)), provides_clause='provides={0},'.format(provides) if provides else '')) if source_contents_map: self.create_file(relpath=os.path.join(relpath, '__init__.py')) for source, contents in source_contents_map.items(): self.create_file(relpath=os.path.join(relpath, source), contents=contents) return self.target(SyntheticAddress(relpath, name).spec)
def test_target_insertion_middle(self): expected_build_string = dedent( """\ # This comment should stay target_type( name = 'target_top', dependencies = [ ':dep_a', ] ) target_type( name = 'target_middle', dependencies = [ ':dep_b', ':new_dep', ], ) # This comment should be okay target_type( name = 'target_bottom', ) # Also this one though it's weird""" ) build_file = self.add_to_build_file('BUILD', self.multi_target_build_string) multi_targ_bfm = BuildFileManipulator.load(build_file, 'target_middle', set(['target_type'])) multi_targ_bfm.add_dependency(SyntheticAddress.parse(':new_dep')) build_file_str = '\n'.join(multi_targ_bfm.build_file_lines()) self.assertEqual(build_file_str, expected_build_string)
def create_sources_field(self, sources, sources_rel_path, address=None): """Factory method to create a SourcesField appropriate for the type of the sources object. Note that this method is called before the call to Target.__init__ so don't expect fields to be populated! :return: a payload field object representing the sources parameter :rtype: SourcesField """ if isinstance(sources, Addresses): # Currently, this is only created by the result of from_target() which takes a single argument if len(sources.addresses) != 1: raise self.WrongNumberOfAddresses( "Expected a single address to from_target() as argument to {spec}" .format(spec=address.spec)) referenced_address = SyntheticAddress.parse(sources.addresses[0], relative_to=sources.rel_path) return DeferredSourcesField(ref_address=referenced_address) elif isinstance(sources, FilesetWithSpec): filespec = sources.filespec else: sources = sources or [] assert_list(sources) filespec = {'globs' : [os.path.join(sources_rel_path, src) for src in (sources or [])]} return SourcesField(sources=sources, sources_rel_path=sources_rel_path, filespec=filespec)
def imports(self): """Returns the set of JarDependencys to be included when compiling this target.""" if self._imports is None: import_jars = set() for spec in self.payload.raw_imports: if not isinstance(spec, six.string_types): raise self.ExpectedAddressError( "{address}: expected imports to contain string addresses, got {found_class}." .format(address=self.address.spec, found_class=spec.__class__.__name__)) address = SyntheticAddress.parse(spec, relative_to=self.address.spec_path) target = self._build_graph.get_target(address) if isinstance(target, JarLibrary): import_jars.update(target.jar_dependencies) elif target is None: # TODO(pl, zundel): Not sure if we can ever reach this case. An address that # can't be resolved is caught when resolving the build graph. raise self.PrematureImportPokeError( "Internal Error: {address}: Failed to resolve import '{spec}'".format( address=self.address.spec, spec=address.spec)) else: raise self.WrongTargetTypeError( "{address}: expected {spec} to be jar_library target type, got {found_class}" .format(address=self.address.spec, spec=address.spec, found_class=target.__class__.__name__)) self._imports = list(import_jars) return self._imports
def java_sources(self): for spec in self._java_sources_specs: address = SyntheticAddress.parse(spec, relative_to=self.address.spec_path) target = self._build_graph.get_target(address) if target is None: raise TargetDefinitionException(self, 'No such java target: %s' % spec) yield target
def create_sources_field(self, sources, sources_rel_path, address=None, key_arg=None): """Factory method to create a SourcesField appropriate for the type of the sources object. Note that this method is called before the call to Target.__init__ so don't expect fields to be populated! :return: a payload field object representing the sources parameter :rtype: SourcesField """ if isinstance(sources, Addresses): # Currently, this is only created by the result of from_target() which takes a single argument if len(sources.addresses) != 1: raise self.WrongNumberOfAddresses( "Expected a single address to from_target() as argument to {spec}" .format(spec=address.spec)) referenced_address = SyntheticAddress.parse(sources.addresses[0], relative_to=sources.rel_path) return DeferredSourcesField(ref_address=referenced_address) elif isinstance(sources, FilesetWithSpec): filespec = sources.filespec else: sources = sources or [] assert_list(sources, key_arg=key_arg) filespec = {'globs' : [os.path.join(sources_rel_path, src) for src in (sources or [])]} return SourcesField(sources=sources, sources_rel_path=sources_rel_path, filespec=filespec)
def _create_java_target(self, target, dependees): antlr_files_suffix = ["Lexer.java", "Parser.java"] if target.compiler == 'antlr4': antlr_files_suffix = ["BaseListener.java", "BaseVisitor.java", "Listener.java", "Visitor.java"] + antlr_files_suffix generated_sources = [] for source in target.sources_relative_to_source_root(): # Antlr enforces that generated sources are relative to the base filename, and that # each grammar filename must match the resulting grammar Lexer and Parser classes. source_base, source_ext = os.path.splitext(source) for suffix in antlr_files_suffix: generated_sources.append(source_base + suffix) deps = self._resolve_java_deps(target) syn_target_sourceroot = os.path.join(self._java_out(target), target.target_base) spec_path = os.path.relpath(syn_target_sourceroot, get_buildroot()) address = SyntheticAddress(spec_path=spec_path, target_name=target.id) tgt = self.context.add_new_target(address, JavaLibrary, dependencies=deps, derived_from=target, sources=generated_sources, provides=target.provides, excludes=target.excludes) for dependee in dependees: dependee.inject_dependency(tgt.address) return tgt
def test_transitive_closure_spec(self): with self.workspace('./BUILD', 'a/BUILD', 'a/b/BUILD') as root_dir: with open(os.path.join(root_dir, './BUILD'), 'w') as build: build.write( dedent(''' fake(name="foo", dependencies=[ 'a', ]) ''')) with open(os.path.join(root_dir, 'a/BUILD'), 'w') as build: build.write( dedent(''' fake(name="a", dependencies=[ 'a/b:bat', ]) ''')) with open(os.path.join(root_dir, 'a/b/BUILD'), 'w') as build: build.write(dedent(''' fake(name="bat") ''')) build_configuration = BuildConfiguration() build_configuration.register_target_alias('fake', Target) parser = BuildFileParser(build_configuration, root_dir=root_dir) build_graph = BuildGraph(self.address_mapper) parser.inject_spec_closure_into_build_graph(':foo', build_graph) self.assertEqual( len(build_graph.dependencies_of( SyntheticAddress.parse(':foo'))), 1)
def test_traversable_specs(self): self.add_to_build_file( 'BUILD', dedent(''' java_protobuf_library(name='foo', sources=[], imports=[':import_jars',], # Note: Should not be a part of traversable_specs dependencies=[ ':proto_dep', ] ) jar_library(name='import_jars', jars=[ jar(org='foo', name='bar', rev='123'), ], ) java_protobuf_library(name='proto_dep', sources=[], ) ''')) self.build_graph.inject_spec_closure('//:foo') target = self.build_graph.get_target(SyntheticAddress.parse('//:foo')) self.assertIsInstance(target, JavaProtobufLibrary) traversable_specs = [spec for spec in target.traversable_specs] self.assertSequenceEqual([':import_jars'], traversable_specs)
def assert_parsed_list(self, cmdline_spec_list, expected): def sort(addresses): return sorted(addresses, key=lambda address: address.spec) self.assertEqual( sort(SyntheticAddress.parse(addr) for addr in expected), sort(self.spec_parser.parse_addresses(cmdline_spec_list)))
def to_jar_dependencies(self, jar_library_specs): """Convenience method to resolve a list of specs to JarLibraries and return its jars attributes. Expects that the jar_libraries are declared relative to this target. :param Address relative_to: Address that references library_specs, for error messages :param library_specs: string specs to JavaLibrary targets. Note, this list should be returned by the caller's traversable_specs() implementation to make sure that the jar_dependency jars have been added to the build graph. :param build_graph: build graph instance used to search for specs :return: list of JarDependency instances represented by the library_specs """ jar_deps = set() for spec in jar_library_specs: if not isinstance(spec, six.string_types): raise self.ExpectedAddressError( "{address}: expected imports to contain string addresses, got {found_class}." .format(address=self.address.spec, found_class=type(spec).__name__)) address = SyntheticAddress.parse(spec, relative_to=self.address.spec_path) target = self._build_graph.get_target(address) if isinstance(target, JarLibrary): jar_deps.update(target.jar_dependencies) else: raise self.WrongTargetTypeError( "{address}: expected {spec} to be jar_library target type, got {found_class}" .format(address=self.address.spec, spec=address.spec, found_class=type(target).__name__)) return list(jar_deps)
def test_validation(self): target = Target(name='mybird', address=SyntheticAddress.parse('//:mybird'), build_graph=self.build_graph) # jars attribute must contain only JarLibrary instances with self.assertRaises(TargetDefinitionException): JarLibrary(name="test", jars=[target])
def test_ragel_gen(self): self.create_file(relpath='test_ragel_gen/atoi.rl', contents=ragel_file_contents) self.add_to_build_file('test_ragel_gen', dedent(""" java_ragel_library(name='atoi', sources=['atoi.rl'], dependencies=[] ) """)) task = prepare_task(RagelGen, build_graph=self.build_graph, targets=[self.target('test_ragel_gen:atoi')], build_file_parser=self.build_file_parser) task._ragel_binary = 'ragel' task.invalidate_for_files = lambda: [] task._java_out = self.task_outdir sources = [os.path.join(self.task_outdir, 'com/example/atoi/Parser.java')] try: saved_add_new_target = Context.add_new_target Context.add_new_target = MagicMock() task.execute() relative_task_outdir = os.path.relpath(self.task_outdir, get_buildroot()) spec = '{spec_path}:{name}'.format(spec_path=relative_task_outdir, name='test_ragel_gen.atoi') address = SyntheticAddress.parse(spec=spec) Context.add_new_target.assert_called_once_with(address, JavaRagelLibrary, sources=sources, excludes=OrderedSet(), dependencies=OrderedSet(), provides=None) finally: Context.add_new_target = saved_add_new_target
def test_target_insertion_middle(self): expected_build_string = dedent("""\ # This comment should stay target_type( name = 'target_top', dependencies = [ ':dep_a', ] ) target_type( name = 'target_middle', dependencies = [ ':dep_b', ':new_dep', ], ) # This comment should be okay target_type( name = 'target_bottom', ) # Also this one though it's weird""") build_file = self.add_to_build_file('BUILD', self.multi_target_build_string) multi_targ_bfm = BuildFileManipulator.load(build_file, 'target_middle', set(['target_type'])) multi_targ_bfm.add_dependency(SyntheticAddress.parse(':new_dep')) build_file_str = '\n'.join(multi_targ_bfm.build_file_lines()) self.assertEqual(build_file_str, expected_build_string)
def test_transitive_closure_spec(self): with self.workspace('./BUILD', 'a/BUILD', 'a/b/BUILD') as root_dir: with open(os.path.join(root_dir, './BUILD'), 'w') as build: build.write(dedent(''' fake(name="foo", dependencies=[ 'a', ]) ''')) with open(os.path.join(root_dir, 'a/BUILD'), 'w') as build: build.write(dedent(''' fake(name="a", dependencies=[ 'a/b:bat', ]) ''')) with open(os.path.join(root_dir, 'a/b/BUILD'), 'w') as build: build.write(dedent(''' fake(name="bat") ''')) build_configuration = BuildConfiguration() build_configuration.register_target_alias('fake', Target) parser = BuildFileParser(build_configuration, root_dir=root_dir) build_graph = BuildGraph(self.address_mapper) parser.inject_spec_closure_into_build_graph(':foo', build_graph) self.assertEqual(len(build_graph.dependencies_of(SyntheticAddress.parse(':foo'))), 1)
def test_transitive_closure_address(self): self.add_to_build_file( 'BUILD', dedent(''' target(name='foo', dependencies=[ 'a', ]) ''')) self.add_to_build_file( 'a/BUILD', dedent(''' target(name='a', dependencies=[ 'a/b:bat', ]) ''')) self.add_to_build_file( 'a/b/BUILD', dedent(''' target(name='bat') ''')) root_address = SyntheticAddress.parse('//:foo') self.build_graph.inject_address_closure(root_address) self.assertEqual( len( self.build_graph.transitive_subgraph_of_addresses( [root_address])), 3)
def traversable_specs(self): for spec in super(PythonTarget, self).traversable_specs: yield spec if self._provides: for spec in self._provides._binaries.values(): address = SyntheticAddress.parse(spec, relative_to=self.address.spec_path) yield address.spec
def test_synthetic_forms(self): self.assert_address('a/b', 'target', SyntheticAddress.parse('a/b:target')) self.assert_address('a/b', 'target', SyntheticAddress.parse('//a/b:target')) self.assert_address('a/b', 'b', SyntheticAddress.parse('a/b')) self.assert_address('a/b', 'b', SyntheticAddress.parse('//a/b')) self.assert_address('a/b', 'target', SyntheticAddress.parse(':target', relative_to='a/b')) self.assert_address('', 'target', SyntheticAddress.parse('//:target', relative_to='a/b')) self.assert_address('', 'target', SyntheticAddress.parse(':target')) self.assert_address('a/b', 'target', SyntheticAddress.parse(':target', relative_to='a/b'))
def test_simple_targets(self): simple_targets = dedent( """ target_type( name = 'no_deps', ) target_type( name = 'empty_deps', dependencies = [ ] ) target_type( name = 'empty_deps_inline', dependencies = [] ) """ ) build_file = self.add_to_build_file('BUILD', simple_targets) for no_deps_name in ['no_deps', 'empty_deps', 'empty_deps_inline']: no_deps = BuildFileManipulator.load(build_file, no_deps_name, set(['target_type'])) self.assertEqual(tuple(no_deps.dependency_lines()), tuple()) no_deps.add_dependency(SyntheticAddress.parse(':fake_dep')) self.assertEqual(tuple(no_deps.dependency_lines()), tuple([' dependencies = [', " ':fake_dep',", ' ],'])) no_deps.add_dependency(SyntheticAddress.parse(':b_fake_dep')) no_deps.add_dependency(SyntheticAddress.parse(':a_fake_dep')) self.assertEqual(tuple(no_deps.dependency_lines()), tuple([' dependencies = [', " ':a_fake_dep',", " ':b_fake_dep',", " ':fake_dep',", ' ],'])) self.assertEqual(tuple(no_deps.target_lines()), tuple(['target_type(', " name = '{0}',".format(no_deps_name), ' dependencies = [', " ':a_fake_dep',", " ':b_fake_dep',", " ':fake_dep',", ' ],', ')']))
def test_contains_address(self): a = SyntheticAddress.parse('a') self.assertFalse(self.build_graph.contains_address(a)) target = Target(name='a', address=a, build_graph=self.build_graph) self.build_graph.inject_target(target) self.assertTrue(self.build_graph.contains_address(a))
def test_targets_synthetic(self): a = self.make_target('a') b = self.make_target('b', dependencies=[a]) c = self.make_target('c', dependencies=[b]) d = self.make_target('d', dependencies=[c, a]) context = self.context(target_roots=[c]) self.assertEquals([c, b, a], context.targets()) syn_b = context.add_new_target(SyntheticAddress.parse('syn_b'), Target, derived_from=b) context.add_new_target(SyntheticAddress.parse('syn_d'), Target, derived_from=d) # We expect syn_b to be included now since it has been synthesized during this run from an # in-play target. self.assertEquals([c, b, a, syn_b], context.targets()) # And verify the predicate operates over both normal and synthetic targets. self.assertEquals([syn_b], context.targets(lambda t: t.derived_from != t)) self.assertEquals([c, b, a], context.targets(lambda t: t.derived_from == t))
def assert_parsed_list(self, cmdline_spec_list, expected): def sort(addresses): return sorted(addresses, key=lambda address: address.spec) self.assertEqual( sort(SyntheticAddress.parse(addr) for addr in expected), sort(self.spec_parser.parse_addresses(cmdline_spec_list)), )
def traversable_specs(self): for spec in super(PythonTarget, self).traversable_specs: yield spec if self._provides: for spec in self._provides._binaries.values(): address = SyntheticAddress.parse( spec, relative_to=self.address.spec_path) yield address.spec
def _get_target(spec, build_graph): try: address = SyntheticAddress(spec) except IOError as e: raise TaskError('Failed to parse address: %s: %s' % (address, e)) match = build_graph.get_target(address) if not match: raise TaskError('Invalid target address: %s' % address) return match
def create_target(files, deps, target_type): spec = '{spec_path}:{name}'.format(spec_path=outdir, name=gentarget.id) address = SyntheticAddress.parse(spec=spec) return self.context.add_new_target(address, target_type, sources=files, provides=gentarget.provides, dependencies=deps, excludes=gentarget.excludes)
def _get_target(spec, build_graph): try: address = SyntheticAddress.parse(spec) except IOError as e: raise TaskError('Failed to parse address: %s: %s' % (address, e)) match = build_graph.get_target(address) if not match: raise TaskError('Invalid target address: %s' % address) return match
def create_non_python_target(self, relpath, name): self.create_file(relpath=self.build_path(relpath), contents=dedent(""" jvm_target( name='{name}', ) """).format(name=name)) return self.target(SyntheticAddress(relpath, name).spec)
def create_target(files, deps): spec_path = os.path.join(self.combined_relpath, 'gen-py') spec = '{spec_path}:{name}'.format(spec_path=spec_path, name=target.id) address = SyntheticAddress.parse(spec=spec) return self.context.add_new_target(address, PythonLibrary, derived_from=target, sources=files, dependencies=deps)
def test_smoke(self): contents = dedent( """namespace java com.pants.example struct Example { 1: optional i64 number } """ ) self.create_file(relpath="test_smoke/a.thrift", contents=contents) self.add_to_build_file( "test_smoke", dedent( """ java_thrift_library(name='a', sources=['a.thrift'], dependencies=[], compiler='scrooge', language='scala', rpc_style='finagle' ) """ ), ) target = self.target("test_smoke:a") task = prepare_task( ScroogeGen, build_graph=self.build_graph, targets=[target], build_file_parser=self.build_file_parser ) with patch("pants.backend.codegen.tasks.scrooge_gen.calculate_services"): task._outdir = MagicMock() task._outdir.return_value = self.task_outdir task.gen = MagicMock() sources = [os.path.join(self.task_outdir, "com/pants/example/Example.scala")] task.gen.return_value = {"test_smoke/a.thrift": sources} try: saved_add_new_target = Context.add_new_target Context.add_new_target = MagicMock() task.execute() relative_task_outdir = os.path.relpath(self.task_outdir, get_buildroot()) spec = "{spec_path}:{name}".format(spec_path=relative_task_outdir, name="test_smoke.a") address = SyntheticAddress.parse(spec=spec) Context.add_new_target.assert_called_once_with( address, ScalaLibrary, sources=sources, excludes=OrderedSet(), dependencies=OrderedSet(), provides=None, derived_from=target, ) finally: Context.add_new_target = saved_add_new_target
def provides(self): if not self._provides: return None # TODO(pl): This is an awful hack for key, binary in self._provides._binaries.iteritems(): if isinstance(binary, Compatibility.string): address = SyntheticAddress.parse(binary, relative_to=self.address.spec_path) self._provides._binaries[key] = self._build_graph.get_target(address) return self._provides
def target(self, spec): """Resolves the given target address to a Target object. address: The BUILD target address to resolve. Returns the corresponding Target or else None if the address does not point to a defined Target. """ address = SyntheticAddress.parse(spec) self.build_graph.inject_address_closure(address) return self.build_graph.get_target(address)
def make_target(self, spec="", target_type=Target, dependencies=None, resources=None, derived_from=None, **kwargs): address = SyntheticAddress.parse(spec) target = target_type(name=address.target_name, address=address, build_graph=self.build_graph, **kwargs) dependencies = dependencies or [] dependencies.extend(resources or []) self.build_graph.inject_target( target, dependencies=[dep.address for dep in dependencies], derived_from=derived_from ) return target
def setUp(self): super(JavaWireLibraryTest, self).setUp() self.build_file_parser._build_configuration.register_target_alias('java_wire_library', JavaWireLibrary) self.add_to_build_file('BUILD', dedent(''' java_wire_library(name='foo', sources=[], service_writer='com.squareup.wire.RetrofitServiceWriter' )''')) self.build_graph.inject_spec_closure('//:foo') self.target = self.build_graph.get_target(SyntheticAddress.parse('//:foo'))
def provides(self): if not self.payload.provides: return None # TODO(pl): This is an awful hack if isinstance(self.payload.provides.repo, Compatibility.string): address = SyntheticAddress.parse(self.payload.provides.repo, relative_to=self.address.spec_path) repo_target = self._build_graph.get_target(address) self.payload.provides.repo = repo_target return self.payload.provides
def create_target(files, deps): spec_path = os.path.join(self.combined_relpath, 'gen-java') spec = '{spec_path}:{name}'.format(spec_path=spec_path, name=target.id) address = SyntheticAddress.parse(spec=spec) return self.context.add_new_target(address, JavaLibrary, derived_from=target, sources=files, provides=target.provides, dependencies=deps, excludes=target.payload.get_field_value('excludes'))