def __init__(self, name, sources, resources=None, dependencies=None, provides=None, compatibility=None, exclusives=None): TargetWithSources.__init__(self, name, sources=sources, exclusives=exclusives) TargetWithDependencies.__init__(self, name, dependencies=dependencies, exclusives=exclusives) self.add_labels('python') self.resources = self._resolve_paths(resources) if resources else OrderedSet() 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 = compatibility or [''] for req in self.compatibility: try: PythonIdentity.parse_requirement(req) except ValueError as e: raise TargetDefinitionException(str(e))
def __init__(self, name, main=None, basename=None, source=None, resources=None, dependencies=None, excludes=None, deploy_excludes=None, configurations=None, exclusives=None): """ :param string name: The name of this target, which combined with this build file defines the target :class:`twitter.pants.base.address.Address`. :param string main: The name of the ``main`` class, e.g., ``'com.twitter.common.examples.pingpong.Main'``. This class may be present as the source of this target or depended-upon library. :param string basename: Base name for the generated ``.jar`` file, e.g., ``'pingpong'``. (By default, uses ``name`` param) :param string source: Name of one ``.java`` or ``.scala`` file (a good place for a ``main``). :param resources: List of ``resource``\s to include in bundle. :param dependencies: List of targets (probably ``java_library`` and ``scala_library`` targets) to "link" in. :param excludes: List of ``exclude``\s to filter this target's transitive dependencies against. :param deploy_excludes: List of ``excludes`` to apply at deploy time. If you, for example, deploy a java servlet that has one version of ``servlet.jar`` onto a Tomcat environment that provides another version, they might conflict. ``deploy_excludes`` gives you a way to build your code but exclude the conflicting ``jar`` when deploying. :param configurations: Ivy configurations to resolve for this target. This parameter is not intended for general use. :type configurations: tuple of strings """ super(JvmBinary, self).__init__(name=name, sources=[source] if source else None, dependencies=dependencies, excludes=excludes, configurations=configurations, exclusives=exclusives) if main and not isinstance(main, Compatibility.string): raise TargetDefinitionException( self, 'main must be a fully qualified classname') if source and not isinstance(source, Compatibility.string): raise TargetDefinitionException( self, 'source must be a single relative file path') self.main = main self.basename = basename or name self.resources = resources self.deploy_excludes = deploy_excludes or []
def __init__(self, spec, exclusives=None): """ :param string spec: target address. E.g., src/main/java/com/twitter/common/util/BUILD:util """ # it's critical the spec is parsed 1st, the results are needed elsewhere in constructor flow parse_context = ParseContext.locate() def parse_address(): if spec.startswith(':'): # the :[target] could be in a sibling BUILD - so parse using the canonical address pathish = "%s:%s" % (parse_context.buildfile.canonical_relpath, spec[1:]) return Address.parse(parse_context.buildfile.root_dir, pathish, False) else: return Address.parse(parse_context.buildfile.root_dir, spec, False) try: self.address = parse_address() except IOError as e: self.address = parse_context.buildfile.relpath raise TargetDefinitionException( self, '%s%s' % (self._DEFINITION_ERROR_MSG, e)) # We must disable the re-init check, because our funky __getattr__ breaks it. # We're not involved in any multiple inheritance, so it's OK to disable it here. super(Pants, self).__init__(self.address.target_name, reinit_check=False, exclusives=exclusives)
def __init__(self, name, binary, bundles, basename=None): """ :param string name: The name of this target, which combined with this build file defines the target :class:`twitter.pants.base.address.Address`. :param binary: The :class:`twitter.pants.targets.jvm_binary.JvmBinary`, or a :class:`twitter.pants.targets.pants_target.Pants` pointer to one. :param bundles: One or more :class:`twitter.pants.targets.jvm_binary.Bundle`'s describing "extra files" that should be included with this app (e.g.: config files, startup scripts). :param string basename: Name of this application, if different from the ``name``. Pants uses this in the ``bundle`` goal to name the distribution artifact. In most cases this parameter is not necessary. """ super(JvmApp, self).__init__(name, dependencies=[]) self._binaries = maybe_list( util.resolve(binary), expected_type=(Pants, JarLibrary, JvmBinary), raise_type=partial(TargetDefinitionException, self)) self._bundles = maybe_list(bundles, expected_type=Bundle, raise_type=partial( TargetDefinitionException, self)) if name == basename: raise TargetDefinitionException(self, 'basename must not equal name.') self.basename = basename or name self._resolved_binary = None self._resolved_bundles = []
def __init__(self, name, sources, resources=None, dependencies=None, provides=None, compatibility=None, exclusives=None): TargetWithSources.__init__(self, name, sources=sources, exclusives=exclusives) TargetWithDependencies.__init__(self, name, dependencies=dependencies, exclusives=exclusives) self.add_labels('python') self.resources = self._resolve_paths( resources) if resources else OrderedSet() self.provides = provides self.compatibility = compatibility or [''] for req in self.compatibility: try: PythonIdentity.parse_requirement(req) except ValueError as e: raise TargetDefinitionException(str(e))
def _maybe_resolve_bundles(self): if self._bundles is not None: def is_resolvable(item): return hasattr(item, 'resolve') def is_bundle(bundle): return isinstance(bundle, Bundle) def resolve(item): return list(item.resolve()) if is_resolvable(item) else [None] if is_resolvable(self._bundles): self._bundles = resolve(self._bundles) try: for item in iter(self._bundles): for bundle in resolve(item): if not is_bundle(bundle): raise TypeError() self._resolved_bundles.append(bundle) except TypeError: raise TargetDefinitionException( self, 'bundles must be one or more Bundle objects, ' 'got %s' % self._bundles) self._bundles = None
def resolve(self): # De-reference this pants pointer to an actual parsed target. resolved = Target.get(self.address) if not resolved: raise TargetDefinitionException(self, '%s%s' % (self._DEFINITION_ERROR_MSG, self.address)) for dep in resolved.resolve(): yield dep
def _find(): for root_dir, types in cls._TYPES_BY_ROOT.items(): if target_path.startswith(root_dir): # The only candidate root for this target. # Validate the target type, if restrictions were specified. if types and not isinstance(target, tuple(types)): # TODO: Find a way to use the BUILD file aliases in the error message, instead # of target.__class__.__name__. E.g., java_tests instead of JavaTests. raise TargetDefinitionException(target, 'Target type %s not allowed under %s' % (target.__class__.__name__, root_dir)) return root_dir return None
def _maybe_resolve_binary(self): if self._binaries is not None: binaries_list = [] for binary in self._binaries: binaries_list.extend(filter(lambda t: t.is_concrete, binary.resolve())) if len(binaries_list) != 1 or not isinstance(binaries_list[0], JvmBinary): raise TargetDefinitionException(self, 'must supply exactly 1 JvmBinary, got %s' % binaries_list) self._resolved_binary = binaries_list[0] self.update_dependencies([self._resolved_binary]) self._binaries = None
def update_dependencies(self, dependencies): if dependencies: for dependency in dependencies: if hasattr(dependency, 'address'): self.dependency_addresses.add(dependency.address) if not hasattr(dependency, "resolve"): raise TargetDefinitionException( self, 'Cannot add %s as a dependency of %s' % (dependency, self)) for resolved_dependency in dependency.resolve(): if resolved_dependency.is_concrete and not self.valid_dependency( resolved_dependency): raise TargetDefinitionException( self, 'Cannot add %s as a dependency of %s' % (resolved_dependency, self)) self._dependencies.add(resolved_dependency) if isinstance(resolved_dependency, InternalTarget): self._internal_dependencies.add(resolved_dependency) self._jar_dependencies = OrderedSet( filter(lambda tgt: isinstance(tgt, JarDependency), self._dependencies - self._internal_dependencies))
def iter_entry_points(cls, target): """Yields the name, entry_point pairs of binary targets in this PythonArtifact.""" for name, binary_target in target.provides.binaries.items(): concrete_target = binary_target.get() if not isinstance( concrete_target, PythonBinary) or concrete_target.entry_point is None: raise TargetDefinitionException( target, 'Cannot add a binary to a PythonArtifact if it does not contain an entry_point.' ) yield name, concrete_target.entry_point
def __init__(self, name, sources=None, java_sources=None, provides=None, dependencies=None, excludes=None, resources=None, exclusives=None): """ :param string name: The name of this target, which combined with this build file defines the target :class:`twitter.pants.base.address.Address`. :param sources: A list of filenames representing the source code this library is compiled from. :type sources: list of strings :param java_sources: :class:`twitter.pants.targets.java_library.JavaLibrary` or list of JavaLibrary targets this library has a circular dependency on. Prefer using dependencies to express non-circular dependencies. :param Artifact provides: The :class:`twitter.pants.targets.artifact.Artifact` to publish that represents this target outside the repo. :param dependencies: List of :class:`twitter.pants.base.target.Target` instances this target depends on. :type dependencies: list of targets :param excludes: List of :class:`twitter.pants.targets.exclude.Exclude` instances to filter this target's transitive dependencies against. :param resources: An optional list of paths (DEPRECATED) or ``resources`` targets containing resources that belong on this library's classpath. :param exclusives: An optional list of exclusives tags. """ super(ScalaLibrary, self).__init__(name, sources, provides, dependencies, excludes, exclusives=exclusives) if (sources is None) and (resources is None): raise TargetDefinitionException( self, 'Must specify sources and/or resources.') self.resources = resources self._java_sources = [] self._raw_java_sources = util.resolve(java_sources) self.add_labels('scala')
def _excludes(self, dep): """ A generator for Exclude objects that will recursively exclude all artifacts provided by the given dep. """ if isinstance(dep, JarDependency): yield Exclude(dep.org, dep.name) elif isinstance(dep, ExportableJvmLibrary): if not dep.provides: raise TargetDefinitionException(self, 'Targets passed to `overrides` must represent published artifacts. %s does not.' % dep) yield Exclude(dep.provides.org, dep.provides.name) elif isinstance(dep, JarLibrary): for d in dep._pre_override_dependencies: for exclude in self._excludes(d): yield exclude
def _construct_provider_map(cls, root_target, descendant, parents, providers, depmap): if isinstance(descendant, PythonTarget) and descendant.provides: providers.append(descendant) for dependency in cls._combined_dependencies(descendant): for prv in providers: for dep in dependency.resolve(): depmap[prv].add(dep) if dep in parents: raise TargetDefinitionException( root_target, '%s and %s combined have a cycle!' % (root_target, dep)) parents.add(dep) cls._construct_provider_map(root_target, dep, parents, providers, depmap) parents.remove(dep) if isinstance(descendant, PythonTarget) and descendant.provides: assert providers[-1] == descendant providers.pop()
def __init__(self, name, sources=None, provides=None, dependencies=None, excludes=None, resources=None, exclusives=None): """ :param string name: The name of this target, which combined with this build file defines the target :class:`twitter.pants.base.address.Address`. :param sources: A list of filenames representing the source code this library is compiled from. :type sources: list of strings :param Artifact provides: The :class:`twitter.pants.targets.artifact.Artifact` to publish that represents this target outside the repo. :param dependencies: List of :class:`twitter.pants.base.target.Target` instances this target depends on. :type dependencies: list of targets :param excludes: List of :class:`twitter.pants.targets.exclude.Exclude` instances to filter this target's transitive dependencies against. :param resources: An optional list of file paths (DEPRECATED) or ``resources`` targets (which in turn point to file paths). The paths indicate text file resources to place in this module's jar. :param exclusives: An optional map of exclusives tags. See CheckExclusives for details. """ super(JavaLibrary, self).__init__(name, sources, provides, dependencies, excludes, exclusives=exclusives) if (sources is None) and (resources is None): raise TargetDefinitionException( self, 'Must specify sources and/or resources.') self.resources = resources self.add_labels('java')
def __init__(self, name, sources=None, dependencies=None, excludes=None, resources=None, exclusives=None, premain=None, agent_class=None, can_redefine=False, can_retransform=False, can_set_native_method_prefix=False): """ :param string name: The name of this target, which combined with this build file defines the target :class:`twitter.pants.base.address.Address`. :param sources: A list of filenames representing the source code this library is compiled from. :type sources: list of strings :param dependencies: List of :class:`twitter.pants.base.target.Target` instances this target depends on. :type dependencies: list of targets :param excludes: List of :class:`twitter.pants.targets.exclude.Exclude` instances to filter this target's transitive dependencies against. :param resources: An optional list of file paths (DEPRECATED) or ``resources`` targets (which in turn point to file paths). The paths indicate text file resources to place in this module's jar. :param exclusives: An optional map of exclusives tags. See CheckExclusives for details. :param string premain: When an agent is specified at JVM launch time this attribute specifies the agent class. Exactly one of ``premain`` or ``agent_class`` must be specified. :param string agent_class: If an implementation supports a mechanism to start agents sometime after the VM has started then this attribute specifies the agent class. Exactly one of ``premain`` or ``agent_class`` must be specified. :param bool can_redefine: `True` if the ability to redefine classes is needed by this agent; `False` by default. :param bool can_retransform: `True` if the ability to retransform classes is needed by this agent; `False` by default. :param bool can_set_native_method_prefix: `True` if the ability to set he native method prefix is needed by this agent; `False` by default. """ super(JavaAgent, self).__init__(name, sources, provides=None, dependencies=dependencies, excludes=excludes, resources=resources, exclusives=exclusives) if not premain or agent_class: raise TargetDefinitionException( self, "Must have at least one of 'premain' or 'agent_class' " "defined.") if premain and not isinstance(premain, Compatibility.string): raise TargetDefinitionException( self, 'The premain must be a fully qualified class name, ' 'given %s of type %s' % (premain, type(premain))) if agent_class and not isinstance(agent_class, Compatibility.string): raise TargetDefinitionException( self, 'The agent_class must be a fully qualified class name, given ' '%s of type %s' % (agent_class, type(agent_class))) self._premain = premain self._agent_class = agent_class self._can_redefine = can_redefine self._can_retransform = can_retransform self._can_set_native_method_prefix = can_set_native_method_prefix self.add_labels('java_agent')
def __init__( self, name, source=None, dependencies=None, entry_point=None, inherit_path=False, # pex option zip_safe=True, # pex option always_write_cache=False, # pex option repositories=None, # pex option indices=None, # pex option ignore_errors=False, # pex option allow_pypi=False, # pex option platforms=(), compatibility=None, exclusives=None): """ :param name: target name :param source: the python source file that becomes this binary's __main__. If None specified, drops into an interpreter by default. :param dependencies: List of :class:`twitter.pants.base.target.Target` instances this target depends on. :type dependencies: list of targets :param entry_point: the default entry point for this binary. if None, drops into the entry point that is defined by source :param inherit_path: inherit the sys.path of the environment that this binary runs in :param zip_safe: whether or not this binary is safe to run in compacted (zip-file) form :param always_write_cache: whether or not the .deps cache of this PEX file should always be written to disk. :param repositories: a list of repositories to query for dependencies. :param indices: a list of indices to use for packages. :param platforms: extra platforms to target when building this binary. :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. :param dict exclusives: An optional dict of exclusives tags. See CheckExclusives for details. """ # TODO(John Sirois): Fixup TargetDefinitionException - it has awkward Target base-class # initialization requirements right now requiring this Target.__init__. Target.__init__(self, name, exclusives=exclusives) if source is None and entry_point is None: raise TargetDefinitionException( self, 'A python binary target must specify either source or entry_point.' ) PythonTarget.__init__( self, name, [] if source is None else [source], compatibility=compatibility, dependencies=dependencies, exclusives=exclusives, ) if not isinstance(platforms, (list, tuple)) and not isinstance( platforms, Compatibility.string): raise TargetDefinitionException( self, 'platforms must be a list, tuple or string.') self._entry_point = entry_point self._inherit_path = bool(inherit_path) self._zip_safe = bool(zip_safe) self._always_write_cache = bool(always_write_cache) self._repositories = maybe_list(repositories or []) self._indices = maybe_list(indices or []) self._ignore_errors = bool(ignore_errors) self._platforms = tuple(maybe_list(platforms or [])) if source and entry_point: entry_point_module = entry_point.split(':', 1)[0] source_entry_point = self._translate_to_entry_point( self.sources[0]) if entry_point_module != source_entry_point: raise TargetDefinitionException( self, 'Specified both source and entry_point but they do not agree: %s vs %s' % (source_entry_point, entry_point_module))
def check_value_for_arg(arg, value, values): if value not in values: raise TargetDefinitionException( self, "%s may only be set to %s ('%s' not valid)" % (arg, ', or '.join(map(repr, values)), value)) return value
def __init__(self, name, sources, provides=None, dependencies=None, excludes=None, compiler=_COMPILER_DEFAULT, language=_LANGUAGE_DEFAULT, rpc_style=_RPC_STYLE_DEFAULT, namespace_map=None, exclusives=None): """ :param string name: The name of this target, which combined with this build file defines the target :class:`twitter.pants.base.address.Address`. :param sources: A list of filenames representing the source code this library is compiled from. :type sources: list of strings :param Artifact provides: The :class:`twitter.pants.targets.artifact.Artifact` to publish that represents this target outside the repo. :param dependencies: List of :class:`twitter.pants.base.target.Target` instances this target depends on. :type dependencies: list of targets :param excludes: List of :class:`twitter.pants.targets.exclude.Exclude` instances to filter this target's transitive dependencies against. :param compiler: An optional compiler used to compile the thrift files. :param language: The language used to generate the output files. One of 'java' or 'scala' with a default of 'java'. :param rpc_style: An optional rpc style to generate service stubs with. One of 'sync', 'finagle' or 'ostrich' with a default of 'sync'. :param namespace_map: A dictionary of namespaces to remap (old: new) :param exclusives: An optional map of exclusives tags. See CheckExclusives for details. """ # It's critical that provides is set 1st since _provides() is called elsewhere in the # constructor flow. self._provides = provides super(JavaThriftLibrary, self).__init__(name, sources, dependencies, excludes, exclusives=exclusives) self.add_labels('codegen') # 'java' shouldn't be here, but is currently required to prevent lots of chunking islands. # See comment in goal.py for details. self.add_labels('java') if dependencies: if not isinstance(dependencies, Iterable): raise TargetDefinitionException( self, 'dependencies must be Iterable but was: %s' % dependencies) maybe_list(dependencies, expected_type=(JarDependency, JavaThriftLibrary, Pants), raise_type=partial(TargetDefinitionException, self)) def check_value_for_arg(arg, value, values): if value not in values: raise TargetDefinitionException( self, "%s may only be set to %s ('%s' not valid)" % (arg, ', or '.join(map(repr, values)), value)) return value # TODO(John Sirois): The defaults should be grabbed from the workspace config. # some gen BUILD files explicitly set this to None compiler = compiler or self._COMPILER_DEFAULT self.compiler = check_value_for_arg('compiler', compiler, self._COMPILERS) language = language or self._LANGUAGE_DEFAULT self.language = check_value_for_arg('language', language, self._LANGUAGES) rpc_style = rpc_style or self._RPC_STYLE_DEFAULT self.rpc_style = check_value_for_arg('rpc_style', rpc_style, self._RPC_STYLES) self.namespace_map = namespace_map