def __init__(self, address=None, sources=None, resources=None, # Old-style resources (file list, Fileset). resource_targets=None, # New-style resources (Resources target specs). provides=None, compatibility=None, **kwargs): payload = PythonPayload(sources_rel_path=address.spec_path, sources=sources or [], resources=resources) super(PythonTarget, self).__init__(address=address, payload=payload, **kwargs) self._resource_target_specs = resource_targets self.add_labels('python') self._synthetic_resources_target = None if provides and not isinstance(provides, PythonArtifact): raise TargetDefinitionException(self, "Target must provide a valid pants setup_py object. Received a '%s' object instead." % provides.__class__.__name__) self._provides = provides self._compatibility = maybe_list(compatibility or ()) # Check that the compatibility requirements are well-formed. for req in self._compatibility: try: PythonIdentity.parse_requirement(req) except ValueError as e: raise TargetDefinitionException(self, str(e))
def __init__(self, address=None, payload=None, sources=None, resources=None, # Old-style resources (file list, Fileset). resource_targets=None, # New-style resources (Resources target specs). provides=None, compatibility=None, **kwargs): """ :param dependencies: Other targets that this target depends on. These dependencies may be ``python_library``-like targets (``python_library``, ``python_thrift_library``, ``python_antlr_library`` and so forth) or ``python_requirement_library`` targets. :type dependencies: List of target specs :param sources: Files to "include". Paths are relative to the BUILD file's directory. :type sources: ``Fileset`` or list of strings :param resources: non-Python resources, e.g. templates, keys, other data (it is recommended that your application uses the pkgutil package to access these resources in a .zip-module friendly way.) :param provides: The `setup_py <#setup_py>`_ to publish that represents this target outside the repo. :param compatibility: either a string or list of strings that represents interpreter compatibility for this target, using the Requirement-style format, e.g. ``'CPython>=3', or just ['>=2.7','<3']`` for requirements agnostic to interpreter class. """ self.address = address payload = payload or Payload() payload.add_fields({ 'sources': self.create_sources_field(sources, address.spec_path, key_arg='sources'), 'resources': self.create_sources_field(resources, address.spec_path, key_arg='resources'), 'provides': provides, 'compatibility': PrimitiveField(maybe_list(compatibility or ())), }) super(PythonTarget, self).__init__(address=address, payload=payload, **kwargs) self._resource_target_specs = resource_targets self.add_labels('python') self._synthetic_resources_target = None if provides and not isinstance(provides, PythonArtifact): raise TargetDefinitionException(self, "Target must provide a valid pants setup_py object. Received a '{}' object instead.".format( provides.__class__.__name__)) self._provides = provides # Check that the compatibility requirements are well-formed. for req in self.payload.compatibility: try: PythonIdentity.parse_requirement(req) except ValueError as e: raise TargetDefinitionException(self, str(e))
def __init__(self, address=None, payload=None, sources=None, resources=None, # Old-style resources (file list, Fileset). resource_targets=None, # New-style resources (Resources target specs). provides=None, compatibility=None, **kwargs): """ :param dependencies: Other targets that this target depends on. These dependencies may be ``python_library``-like targets (``python_library``, ``python_thrift_library``, ``python_antlr_library`` and so forth) or ``python_requirement_library`` targets. :type dependencies: List of target specs :param sources: Files to "include". Paths are relative to the BUILD file's directory. :type sources: ``Fileset`` or list of strings :param resources: non-Python resources, e.g. templates, keys, other data (it is recommended that your application uses the pkgutil package to access these resources in a .zip-module friendly way.) :param provides: The `setup_py <#setup_py>`_ to publish that represents this target outside the repo. :param compatibility: either a string or list of strings that represents interpreter compatibility for this target, using the Requirement-style format, e.g. ``'CPython>=3', or just ['>=2.7','<3']`` for requirements agnostic to interpreter class. """ self.address = address payload = payload or Payload() payload.add_fields({ 'sources': self.create_sources_field(sources, address.spec_path, key_arg='sources'), 'resources': self.create_sources_field(resources, address.spec_path, key_arg='resources'), 'provides': provides, 'compatibility': PrimitiveField(maybe_list(compatibility or ())), }) super(PythonTarget, self).__init__(address=address, payload=payload, **kwargs) self._resource_target_specs = resource_targets self.add_labels('python') if provides and not isinstance(provides, PythonArtifact): raise TargetDefinitionException(self, "Target must provide a valid pants setup_py object. Received a '{}' object instead.".format( provides.__class__.__name__)) self._provides = provides # Check that the compatibility requirements are well-formed. for req in self.payload.compatibility: try: PythonIdentity.parse_requirement(req) except ValueError as e: raise TargetDefinitionException(self, str(e))
def __init__(self, address=None, payload=None, sources=None, provides=None, compatibility=None, **kwargs): """ :param dependencies: The addresses of targets that this target depends on. These dependencies may be ``python_library``-like targets (``python_library``, ``python_thrift_library``, ``python_antlr_library`` and so forth) or ``python_requirement_library`` targets. :type dependencies: list of strings :param sources: Files to "include". Paths are relative to the BUILD file's directory. :type sources: ``Fileset`` or list of strings :param provides: The `setup_py <#setup_py>`_ to publish that represents this target outside the repo. :param compatibility: either a string that represents interpreter compatibility for this target using the Requirement-style format, e.g. ``'CPython>=2.7,<3'`` (Select a CPython interpreter with version ``>=2.7`` AND version ``<3``) or a list of Requirement-style strings which will be OR'ed together. If the compatibility requirement is agnostic to interpreter class, using the example above, a Requirement-style compatibility constraint like '>=2.7,<3' (N.B.: not prefixed with CPython) can be used. """ self.address = address payload = payload or Payload() payload.add_fields({ 'sources': self.create_sources_field(sources, address.spec_path, key_arg='sources'), 'provides': provides, 'compatibility': PrimitiveField(maybe_list(compatibility or ())), }) super(PythonTarget, self).__init__(address=address, payload=payload, **kwargs) if provides and not isinstance(provides, PythonArtifact): raise TargetDefinitionException( self, "Target must provide a valid pants setup_py object. Received a '{}' object instead." .format(provides.__class__.__name__)) self._provides = provides # Check that the compatibility requirements are well-formed. for req in self.payload.compatibility: try: PythonIdentity.parse_requirement(req) except ValueError as e: raise TargetDefinitionException(self, str(e))
def validate_constraints(constraints): # TODO: add check to see if constraints are mutually exclusive (bad) so no time is wasted: # https://github.com/pantsbuild/pex/issues/432 for req in constraints: # Check that the compatibility requirements are well-formed. try: PythonIdentity.parse_requirement(req) except ValueError as e: die("Compatibility requirements are not formatted properly: %s" % str(e))
def validate_constraints(constraints): # TODO: add check to see if constraints are mutually exclusive (bad) so no time is wasted: # https://github.com/pantsbuild/pex/issues/432 for req in constraints: # Check that the compatibility requirements are well-formed. try: PythonIdentity.parse_requirement(req) except ValueError as e: die("Compatibility requirements are not formatted properly: %s" % str(e))
def __init__( self, address=None, sources=None, resources=None, # Old-style resources (file list, Fileset). resource_targets=None, # New-style resources (Resources target specs). provides=None, compatibility=None, **kwargs): """ :param dependencies: Other targets that this target depends on. These dependencies may be ``python_library``-like targets (``python_library``, ``python_thrift_library``, ``python_antlr_library`` and so forth) or ``python_requirement_library`` targets. :type dependencies: List of target specs :param resources: non-Python resources, e.g. templates, keys, other data (it is recommended that your application uses the pkgutil package to access these resources in a .zip-module friendly way.) :param provides: The :ref:`setup_py <bdict_setup_py>` to publish that represents this target outside the repo. :param compatibility: either a string or list of strings that represents interpreter compatibility for this target, using the Requirement-style format, e.g. ``'CPython>=3', or just ['>=2.7','<3']`` for requirements agnostic to interpreter class. """ payload = PythonPayload(sources_rel_path=address.spec_path, sources=sources or [], resources=resources) super(PythonTarget, self).__init__(address=address, payload=payload, **kwargs) self._resource_target_specs = resource_targets self.add_labels('python') self._synthetic_resources_target = None if provides and not isinstance(provides, PythonArtifact): raise TargetDefinitionException( self, "Target must provide a valid pants setup_py object. Received a '%s' object instead." % provides.__class__.__name__) self._provides = provides self._compatibility = maybe_list(compatibility or ()) # Check that the compatibility requirements are well-formed. for req in self._compatibility: try: PythonIdentity.parse_requirement(req) except ValueError as e: raise TargetDefinitionException(self, str(e))
def __init__(self, address=None, payload=None, sources=None, provides=None, compatibility=None, **kwargs): """ :param dependencies: The addresses of targets that this target depends on. These dependencies may be ``python_library``-like targets (``python_library``, ``python_thrift_library``, ``python_antlr_library`` and so forth) or ``python_requirement_library`` targets. :type dependencies: list of strings :param sources: Files to "include". Paths are relative to the BUILD file's directory. :type sources: ``EagerFilesetWithSpec`` :param provides: The `setup_py <#setup_py>`_ to publish that represents this target outside the repo. :param compatibility: either a string that represents interpreter compatibility for this target using the Requirement-style format, e.g. ``'CPython>=2.7,<3'`` (Select a CPython interpreter with version ``>=2.7`` AND version ``<3``) or a list of Requirement-style strings which will be OR'ed together. If the compatibility requirement is agnostic to interpreter class, using the example above, a Requirement-style compatibility constraint like '>=2.7,<3' (N.B.: not prefixed with CPython) can be used. """ self.address = address payload = payload or Payload() payload.add_fields({ 'sources': self.create_sources_field(sources, address.spec_path, key_arg='sources'), 'provides': provides, 'compatibility': PrimitiveField(maybe_list(compatibility or ())), }) super(PythonTarget, self).__init__(address=address, payload=payload, **kwargs) if provides and not isinstance(provides, PythonArtifact): raise TargetDefinitionException(self, "Target must provide a valid pants setup_py object. Received a '{}' object instead.".format( provides.__class__.__name__)) self._provides = provides # Check that the compatibility requirements are well-formed. for req in self.payload.compatibility: try: PythonIdentity.parse_requirement(req) except ValueError as e: raise TargetDefinitionException(self, str(e))
def __init__(self, address=None, payload=None, sources=None, compatibility=None, setup_requires=None, **kwargs): """ :param address: The Address that maps to this Target in the BuildGraph. :type address: :class:`pants.build_graph.address.Address` :param payload: The configuration encapsulated by this target. Also in charge of most fingerprinting details. :type payload: :class:`pants.base.payload.Payload` :param sources: Files to "include". Paths are relative to the BUILD file's directory. :type sources: ``Fileset`` or list of strings. Must include setup.py. :param compatibility: either a string or list of strings that represents interpreter compatibility for this target, using the Requirement-style format, e.g. ``'CPython>=3', or just ['>=2.7','<3']`` for requirements agnostic to interpreter class. """ payload = payload or Payload() payload.add_fields({ 'sources': self.create_sources_field(sources, address.spec_path, key_arg='sources'), 'compatibility': PrimitiveField(maybe_list(compatibility or ())), 'setup_requires': PrimitiveField(maybe_list(setup_requires or ())) }) super(PythonDistribution, self).__init__(address=address, payload=payload, **kwargs) if not 'setup.py' in sources: raise TargetDefinitionException( self, 'A setup.py in the top-level directory relative to the target definition is required.' ) # Check that the compatibility requirements are well-formed. for req in self.payload.compatibility: try: PythonIdentity.parse_requirement(req) except ValueError as e: raise TargetDefinitionException(self, str(e))
def __init__(self, address=None, payload=None, sources=None, compatibility=None, setup_requires=None, **kwargs): """ :param address: The Address that maps to this Target in the BuildGraph. :type address: :class:`pants.build_graph.address.Address` :param payload: The configuration encapsulated by this target. Also in charge of most fingerprinting details. :type payload: :class:`pants.base.payload.Payload` :param sources: Files to "include". Paths are relative to the BUILD file's directory. :type sources: ``Fileset`` or list of strings. Must include setup.py. :param compatibility: either a string or list of strings that represents interpreter compatibility for this target, using the Requirement-style format, e.g. ``'CPython>=3', or just ['>=2.7','<3']`` for requirements agnostic to interpreter class. """ payload = payload or Payload() payload.add_fields({ 'sources': self.create_sources_field(sources, address.spec_path, key_arg='sources'), 'compatibility': PrimitiveField(maybe_list(compatibility or ())), 'setup_requires': PrimitiveField(maybe_list(setup_requires or ())) }) super(PythonDistribution, self).__init__(address=address, payload=payload, **kwargs) if not 'setup.py' in sources: raise TargetDefinitionException( self, 'A setup.py in the top-level directory relative to the target definition is required.' ) # Check that the compatibility requirements are well-formed. for req in self.payload.compatibility: try: PythonIdentity.parse_requirement(req) except ValueError as e: raise TargetDefinitionException(self, str(e))
def _extract_sdist( pex, # type: PEX dest_dir, # type: str ): # type: (...) -> None chroot = safe_mkdtemp() src = os.path.join(chroot, "src") safe_mkdir(src) excludes = ["__main__.py", "PEX-INFO"] if zipfile.is_zipfile(pex.path()): PEXEnvironment(pex.path()).explode_code(src, exclude=excludes) else: shutil.copytree(pex.path(), src, ignore=lambda _dir, _names: excludes) pex_info = pex.pex_info() name, _ = os.path.splitext(os.path.basename(pex.path())) version = "0.0.0+{}".format(pex_info.code_hash) zip_safe = pex_info.zip_safe py_modules = [os.path.splitext(f)[0] for f in os.listdir(src) if f.endswith(".py")] packages = [ os.path.relpath(os.path.join(root, d), src).replace(os.sep, ".") for root, dirs, _ in os.walk(src) for d in dirs ] install_requires = [str(req) for req in pex_info.requirements] python_requires = None if len(pex_info.interpreter_constraints) == 1: python_requires = str( PythonIdentity.parse_requirement(pex_info.interpreter_constraints[0]).specifier ) elif pex_info.interpreter_constraints: pex_warnings.warn( "Omitting `python_requires` for {name} sdist since {pex} has multiple " "interpreter constraints:\n{interpreter_constraints}".format( name=name, pex=os.path.normpath(pex.path()), interpreter_constraints="\n".join( "{index}.) {constraint}".format(index=index, constraint=constraint) for index, constraint in enumerate( pex_info.interpreter_constraints, start=1 ) ), ) ) entry_points = [] if pex_info.entry_point and ":" in pex_info.entry_point: entry_points = [(name, pex_info.entry_point)] with open(os.path.join(chroot, "setup.cfg"), "w") as fp: fp.write( dedent( """\ [metadata] name = {name} version = {version} [options] zip_safe = {zip_safe} {py_modules} {packages} package_dir = =src include_package_data = True {python_requires} {install_requires} [options.entry_points] {entry_points} """ ).format( name=name, version=version, zip_safe=zip_safe, py_modules=( "py_modules =\n {}".format("\n ".join(py_modules)) if py_modules else "" ), packages=( "packages = \n {}".format("\n ".join(packages)) if packages else "" ), install_requires=( "install_requires =\n {}".format("\n ".join(install_requires)) if install_requires else "" ), python_requires=( "python_requires = {}".format(python_requires) if python_requires else "" ), entry_points=( "console_scripts =\n {}".format( "\n ".join( "{} = {}".format(name, entry_point) for name, entry_point in entry_points ) ) if entry_points else "" ), ) ) with open(os.path.join(chroot, "MANIFEST.in"), "w") as fp: fp.write("recursive-include src *") with open(os.path.join(chroot, "setup.py"), "w") as fp: fp.write("import setuptools; setuptools.setup()") spawn_python_job( args=["setup.py", "sdist", "--dist-dir", dest_dir], interpreter=pex.interpreter, expose=["setuptools"], cwd=chroot, ).wait()