def test_binary_target_injected_into_minified_dependencies(self): with ParseContext.temp(): foo = python_library( name = 'foo', provides = setup_py( name = 'foo', version = '0.0.0', ).with_binaries( foo_binary = pants(':foo_bin') ) ) foo_bin = python_binary( name = 'foo_bin', entry_point = 'foo.bin.foo', dependencies = [ pants(':foo_bin_dep') ] ) foo_bin_dep = python_library( name = 'foo_bin_dep' ) assert SetupPy.minified_dependencies(foo) == OrderedSet([foo_bin, foo_bin_dep]) entry_points = dict(SetupPy.iter_entry_points(foo)) assert entry_points == {'foo_binary': 'foo.bin.foo'} with self.run_execute(foo, recursive=False) as setup_py_command: setup_py_command.run_one.assert_called_with(foo) with self.run_execute(foo, recursive=True) as setup_py_command: setup_py_command.run_one.assert_called_with(foo)
def test_validation(self): with ParseContext.temp("InternalTargetTest/test_validation"): InternalTarget(name="valid", dependencies=None) self.assertRaises(TargetDefinitionException, InternalTarget, name=1, dependencies=None) InternalTarget(name="valid2", dependencies=Target(name="mybird")) self.assertRaises(TargetDefinitionException, InternalTarget, name="valid3", dependencies=1)
def test_python_binary_with_entry_point_and_source(self): with ParseContext.temp('src'): assert 'blork' == PythonBinary( name = 'binary1', entry_point = 'blork', source='blork.py').entry_point assert 'blork:main' == PythonBinary( name = 'binary2', entry_point = 'blork:main', source='blork.py').entry_point assert 'bin.blork:main' == PythonBinary( name = 'binary3', entry_point = 'bin.blork:main', source='bin/blork.py').entry_point
def dump(self): self.debug('Building PythonBinary %s:' % self._target) targets = self.resolve([self._target] + self._extra_targets) for lib in targets['libraries'] | targets['binaries']: self._dump_library(lib) generated_reqs = OrderedSet() if targets['thrifts']: for thr in set(targets['thrifts']): if thr not in self.MEMOIZED_THRIFTS: self.MEMOIZED_THRIFTS[thr] = self._generate_thrift_requirement(thr) generated_reqs.add(self.MEMOIZED_THRIFTS[thr]) with ParseContext.temp(): # trick pants into letting us add this python requirement, otherwise we get # TargetDefinitionException: Error in target BUILD.temp:thrift: duplicate to # PythonRequirement(thrift) # # TODO(wickman) Instead of just blindly adding a PythonRequirement for thrift, we # should first detect if any explicit thrift requirements have been added and use # those. Only if they have not been supplied should we auto-inject it. generated_reqs.add(PythonRequirement('thrift', use_2to3=True, name='thrift-' + ''.join(random.sample('0123456789abcdef' * 8, 8)))) for antlr in targets['antlrs']: generated_reqs.add(self._generate_antlr_requirement(antlr)) targets['reqs'] |= generated_reqs reqs_to_build = OrderedSet() for req in targets['reqs']: if not req.should_build(self._interpreter.python, Platform.current()): self.debug('Skipping %s based upon version filter' % req) continue reqs_to_build.add(req) self._dump_requirement(req._requirement, False, req._repository) platforms = self._platforms if isinstance(self._target, PythonBinary): platforms = self._target.platforms distributions = resolve_multi( self._config, reqs_to_build, interpreter=self._interpreter, platforms=platforms) locations = set() for platform, dist_set in distributions.items(): for dist in dist_set: if dist.location not in locations: self._dump_distribution(dist) locations.add(dist.location) if len(targets['binaries']) > 1: print('WARNING: Target has multiple python_binary targets!', file=sys.stderr) return self._builder
def execute(self): if self.options.pex and self.options.ipython: self.error('Cannot specify both --pex and --ipython!') if self.options.entry_point and self.options.ipython: self.error('Cannot specify both --entry_point and --ipython!') if self.options.verbose: print('Build operating on target: %s %s' % (self.target, 'Extra targets: %s' % ' '.join(map(str, self.extra_targets)) if self.extra_targets else '')) builder = PEXBuilder(tempfile.mkdtemp(), interpreter=self.interpreter, pex_info=self.target.pexinfo if isinstance(self.target, PythonBinary) else None) if self.options.entry_point: builder.set_entry_point(self.options.entry_point) if self.options.ipython: if not self.config.has_section('python-ipython'): self.error('No python-ipython sections defined in your pants.ini!') builder.info.entry_point = self.config.get('python-ipython', 'entry_point') if builder.info.entry_point is None: self.error('Must specify entry_point for IPython in the python-ipython section ' 'of your pants.ini!') requirements = self.config.getlist('python-ipython', 'requirements', default=[]) with ParseContext.temp(): for requirement in requirements: self.extra_targets.append(PythonRequirement(requirement)) executor = PythonChroot( self.target, self.root_dir, builder=builder, interpreter=self.interpreter, extra_targets=self.extra_targets, conn_timeout=self.options.conn_timeout) executor.dump() if self.options.pex: pex_name = os.path.join(self.root_dir, 'dist', '%s.pex' % self.target.name) builder.build(pex_name) print('Wrote %s' % pex_name) return 0 else: builder.freeze() pex = PEX(builder.path(), interpreter=self.interpreter) po = pex.run(args=list(self.args), blocking=False) try: return po.wait() except KeyboardInterrupt: po.send_signal(signal.SIGINT) raise
def test_python_binary_with_entry_point_and_source_mismatch(self): with ParseContext.temp('src'): with pytest.raises(TargetDefinitionException): PythonBinary(name = 'binary1', entry_point = 'blork', source='hork.py') with pytest.raises(TargetDefinitionException): PythonBinary(name = 'binary2', entry_point = 'blork:main', source='hork.py') with pytest.raises(TargetDefinitionException): PythonBinary(name = 'binary3', entry_point = 'bin.blork', source='blork.py') with pytest.raises(TargetDefinitionException): PythonBinary(name = 'binary4', entry_point = 'bin.blork', source='bin.py')
def create_dependencies(depmap): target_map = {} with ParseContext.temp(): for name, deps in depmap.items(): target_map[name] = python_library( name=name, provides=setup_py(name=name, version='0.0.0'), dependencies=[pants(':%s' % dep) for dep in deps] ) return target_map
def __init__(self, name, dependencies=None, num_sources=0, exclusives=None): with ParseContext.temp(): InternalTarget.__init__(self, name, dependencies, exclusives=exclusives) TargetWithSources.__init__(self, name, exclusives=exclusives) self.num_sources = num_sources self.declared_exclusives = defaultdict(set) if exclusives is not None: for k in exclusives: self.declared_exclusives[k] = set([exclusives[k]]) self.exclusives = None
def generate_test_targets(cls): if cls.TESTING_TARGETS is None: with ParseContext.temp(): cls.TESTING_TARGETS = [ PythonRequirement('pytest'), PythonRequirement('pytest-cov'), PythonRequirement('coverage==3.6b1'), PythonRequirement('unittest2', version_filter=lambda py, pl: py.startswith('2')), PythonRequirement('unittest2py3k', version_filter=lambda py, pl: py.startswith('3')) ] return cls.TESTING_TARGETS
def test_validation(self): with ParseContext.temp(): repo = Repository(name="myRepo", url="myUrl", push_db="myPushDb") Artifact(org="testOrg", name="testName", repo=repo, description="Test") self.assertRaises(ValueError, Artifact, org=1, name="testName", repo=repo, description="Test") self.assertRaises(ValueError, Artifact, org="testOrg", name=1, repo=repo, description="Test") self.assertRaises(ValueError, Artifact, org="testOrg", name="testName", repo=1, description="Test") self.assertRaises(ValueError, Artifact, org="testOrg", name="testName", repo=repo, description=1)
def _generate_requirement(self, library, builder_cls): library_key = self._key_generator.key_for_target(library) builder = builder_cls(library, self._root, self._config, '-' + library_key.hash[:8]) cache_dir = os.path.join(self._egg_cache_root, library_key.id) if self._build_invalidator.needs_update(library_key): sdist = builder.build(interpreter=self._interpreter) safe_mkdir(cache_dir) shutil.copy(sdist, os.path.join(cache_dir, os.path.basename(sdist))) self._build_invalidator.update(library_key) with ParseContext.temp(): return PythonRequirement(builder.requirement_string(), repository=cache_dir, use_2to3=True)
def test_validation(self): with ParseContext.temp('PythonTargetTest/test_validation'): # Adding a JVM Artifact as a provides on a PythonTarget doesn't make a lot of sense. This test # sets up that very scenario, and verifies that pants throws a TargetDefinitionException. self.assertRaises(TargetDefinitionException, PythonTarget, name="one", sources=[], provides=Artifact(org='com.twitter', name='one-jar', repo=Repository(name='internal', url=None, push_db=None, exclusives=None))) name = "test-with-PythonArtifact" pa = PythonArtifact(name='foo', version='1.0', description='foo') # This test verifies that adding a 'setup_py' provides to a PythonTarget is okay. self.assertEquals(PythonTarget(name=name, provides=pa, sources=[]).name, name) name = "test-with-none" # This test verifies that having no provides is okay. self.assertEquals(PythonTarget(name=name, provides=None, sources=[]).name, name)
def test_binary_cycle(self): with ParseContext.temp(): foo = python_library( name = 'foo', provides = setup_py( name = 'foo', version = '0.0.0', ).with_binaries( foo_binary = pants(':foo_bin') ) ) foo_bin = python_binary( name = 'foo_bin', entry_point = 'foo.bin.foo', dependencies = [ pants(':foo') ] ) with pytest.raises(TargetDefinitionException): SetupPy.minified_dependencies(foo)
def test_binary_target_injected_into_minified_dependencies_with_provider(self): with ParseContext.temp(): bar = python_library( name = 'bar', provides = setup_py( name = 'bar', version = '0.0.0', ).with_binaries( bar_binary = pants(':bar_bin') ) ) bar_bin = python_binary( name = 'bar_bin', entry_point = 'bar.bin.bar', dependencies = [ pants(':bar_bin_dep') ] ) bar_bin_dep = python_library( name = 'bar_bin_dep', provides = setup_py( name = 'bar_bin_dep', version = '0.0.0', ) ) assert SetupPy.minified_dependencies(bar) == OrderedSet([bar_bin, bar_bin_dep]) entry_points = dict(SetupPy.iter_entry_points(bar)) assert entry_points == {'bar_binary': 'bar.bin.bar'} with self.run_execute(bar, recursive=False) as setup_py_command: setup_py_command.run_one.assert_called_with(bar) with self.run_execute(bar, recursive=True) as setup_py_command: setup_py_command.run_one.assert_has_calls([ call(bar), call(bar_bin_dep) ], any_order=True)
def of(cls, target): with ParseContext.temp(): return cls(target.name, dependencies=[target])
def union(cls, targets, name=None): name = name or (cls.synthetic_name(targets) + '-union') with ParseContext.temp(): return cls(name, dependencies=targets)
def resolve(self, spec): """Returns an iterator over the target(s) the given address points to.""" with ParseContext.temp(): return Pants(spec).resolve()
def _create_new_target(self, target_base, target_type, *args, **kwargs): if not os.path.exists(target_base): os.makedirs(target_base) SourceRoot.register(target_base, target_type) with ParseContext.temp(target_base): return target_type(*args, **kwargs)
def test_validation(self): with ParseContext.temp('TargetTest/test_validation'): self.assertRaises(TargetDefinitionException, Target, name=None) name = "test" self.assertEquals(Target(name=name).name, name)
def test_no_dependencies(self): with pytest.raises(TargetDefinitionException): with ParseContext.temp(): JarLibrary("test-jar-library-with-empty-dependencies", None)
def test_empty_dependencies(self): with ParseContext.temp(): JarLibrary("test-jar-library-with-empty-dependencies", [])
def test_validation(self): basedir = "PantsTargetTest/test_validation" with ParseContext.temp(basedir): self.assertRaises(TargetDefinitionException, Pants, spec="fake") self.assertRaises(TargetDefinitionException, Pants, spec="%s:fake" % basedir)
def test_validation(self): with ParseContext.temp('JarLibraryTest/test_validation'): target = Target(name='mybird') JarLibrary(name="test", dependencies=target) self.assertRaises(TargetDefinitionException, JarLibrary, name="test1", dependencies=None)
def test_python_binary_with_entry_point_no_source(self): with ParseContext.temp('src'): assert PythonBinary(name = 'binary', entry_point = 'blork').entry_point == 'blork'
def test_python_binary_with_source_no_entry_point(self): with ParseContext.temp('src'): assert PythonBinary(name = 'binary1', source = 'blork.py').entry_point == 'blork' assert PythonBinary(name = 'binary2', source = 'bin/blork.py').entry_point == 'bin.blork'
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.config = Config.load() self.interpreter_cache = PythonInterpreterCache(self.config, logger=self.debug) self.interpreter_cache.setup() interpreters = self.interpreter_cache.select_interpreter( list(self.interpreter_cache.matches([self.options.interpreter] if self.options.interpreter else [b'']))) if len(interpreters) != 1: self.error('Unable to detect suitable interpreter.') self.interpreter = interpreters[0] for req in self.options.extra_requirements: with ParseContext.temp(): self.extra_targets.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: address = Address.parse(root_dir, arg) target = Target.get(address) if target is None: not_a_target(debug_msg='Unrecognized target') break except Exception as e: not_a_target(debug_msg=e) break for resolved in filter(lambda t: t.is_concrete, target.resolve()): if isinstance(resolved, PythonBinary): binaries.append(resolved) else: self.extra_targets.append(resolved) 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 test_python_binary_must_have_some_entry_point(self): with ParseContext.temp('src'): with pytest.raises(TargetDefinitionException): PythonBinary(name = 'binary')