def test_requires_dists_none(pygoogleearth_zip_sdist): # type: (str) -> None assert [] == list(requires_dists(pygoogleearth_zip_sdist)) with example_distribution("MarkupSafe-1.0-cp27-cp27mu-linux_x86_64.whl") as (wheel_path, dist): assert [] == list(requires_dists(wheel_path)) assert [] == list(requires_dists(dist)) # This tests a strange case detailed here: # https://github.com/pantsbuild/pex/issues/1201#issuecomment-791715585 with downloaded_sdist("et-xmlfile==1.0.1") as sdist, warnings.catch_warnings( record=True ) as events: assert [] == list(requires_dists(sdist)) assert len(events) == 1 warning = events[0] assert PEXWarning == warning.category assert ( dedent( """\ Ignoring 1 `Requires` field in {sdist} metadata: 1.) Requires: python (>=2.6.0) You may have issues using the 'et_xmlfile' distribution as a result. More information on this workaround can be found here: https://github.com/pantsbuild/pex/issues/1201#issuecomment-791715585 """ ).format(sdist=sdist) == str(warning.message) )
def test_requires_dists(): # type: () -> None with example_distribution("aws_cfn_bootstrap-1.4-py2-none-any.whl") as (wheel_path, dist): expected_requirements = [ Requirement.parse(req) for req in ("python-daemon>=1.5.2,<2.0", "pystache>=0.4.0", "setuptools") ] assert expected_requirements == list(requires_dists(wheel_path)) assert expected_requirements == list(requires_dists(dist))
def _info( self, pex, # type: PEX options, # type: Namespace ): # type: (...) -> Result with self._distributions_output(pex, options) as (distributions, output): for distribution in distributions: if options.verbose: requires_python = dist_metadata.requires_python(distribution) requires_dists = list(dist_metadata.requires_dists(distribution)) self.dump_json( options, dict( project_name=distribution.project_name, version=distribution.version, requires_python=str(requires_python) if requires_python else None, requires_dists=[str(dist) for dist in requires_dists], location=distribution.location, ), output, ) else: output.write( "{project_name} {version} {location}".format( project_name=distribution.project_name, version=distribution.version, location=distribution.location, ) ) output.write("\n") return Ok()
def test_requires_dists(): # type: () -> None with example_distribution( "aws_cfn_bootstrap-1.4-py2-none-any.whl") as dist: assert [ Requirement.parse(req) for req in ( "python-daemon>=1.5.2,<2.0", "pystache>=0.4.0", "setuptools", ) ] == list(requires_dists(dist))
def _create_dependency_graph(pex): # type: (PEX) -> DiGraph graph = DiGraph( pex.path(), fontsize="14", labelloc="t", label="Dependency graph of {} for interpreter {} ({})".format( pex.path(), pex.interpreter.binary, pex.interpreter.identity.requirement ), ) marker_environment = pex.interpreter.identity.env_markers.copy() marker_environment["extra"] = [] present_dists = frozenset(dist.project_name for dist in pex.resolve()) for dist in pex.resolve(): graph.add_node( name=dist.project_name, label="{name} {version}".format(name=dist.project_name, version=dist.version), URL="https://pypi.org/project/{name}/{version}".format( name=dist.project_name, version=dist.version ), target="_blank", ) for req in requires_dists(dist): if ( req.project_name not in present_dists and req.marker and not req.marker.evaluate(environment=marker_environment) ): graph.add_node( name=req.project_name, color="lightgrey", style="filled", tooltip="inactive requirement", URL="https://pypi.org/project/{name}".format(name=req.project_name), target="_blank", ) graph.add_edge( start=dist.project_name, end=req.project_name, label="{specifier}{marker}".format( specifier=req.specifier if req.specifier else "", marker="; {}".format(req.marker) if req.marker else "", ) if (req.specifier or req.marker) else None, fontsize="10", ) return graph
def _resolve_requirement( self, requirement, # type: Requirement resolved_dists_by_key, # type: MutableMapping[Distribution, _RequirementKey] required, # type: Optional[bool] required_by=None, # type: Optional[Distribution] ): # type: (...) -> Iterator[_DistributionNotFound] requirement_key = _RequirementKey.create(requirement) if requirement_key in resolved_dists_by_key: return available_distributions = [ ranked_dist for ranked_dist in self._available_ranked_dists_by_key.get( requirement.key, []) if ranked_dist.satisfies(requirement) ] if not available_distributions: if required is True: yield _DistributionNotFound.create(requirement, required_by=required_by) return resolved_distribution = sorted(available_distributions, reverse=True)[0].distribution if len(available_distributions) > 1: TRACER.log( "Resolved {req} to {dist} and discarded {discarded}.".format( req=requirement, dist=resolved_distribution, discarded=", ".join( str(ranked_dist.distribution) for ranked_dist in available_distributions[1:]), ), V=9, ) for dep_requirement in dist_metadata.requires_dists( resolved_distribution): # A note regarding extras and why they're passed down one level (we don't pass / use # dep_requirement.extras for example): # # Say we're resolving the `requirement` 'requests[security]==2.25.1'. That means # `resolved_distribution` is the requests distribution. It will have metadata that # looks like so: # # $ grep Requires-Dist requests-2.25.1.dist-info/METADATA | grep security -C1 # Requires-Dist: certifi (>=2017.4.17) # Requires-Dist: pyOpenSSL (>=0.14) ; extra == 'security' # Requires-Dist: cryptography (>=1.3.4) ; extra == 'security' # Requires-Dist: PySocks (!=1.5.7,>=1.5.6) ; extra == 'socks' # # We want to recurse and resolve all standard requests requirements but also those that # are part of the 'security' extra. In order to resolve the latter we need to include # the 'security' extra environment marker. required = self._evaluate_marker(dep_requirement, extras=requirement.extras) if required is False: continue for not_found in self._resolve_requirement( dep_requirement, resolved_dists_by_key, required, required_by=resolved_distribution, ): yield not_found resolved_dists_by_key.update( (key, resolved_distribution) for key in requirement_key.satisfied_keys())
def test_requires_dists_none(): # type: () -> None with example_distribution( "MarkupSafe-1.0-cp27-cp27mu-linux_x86_64.whl") as dist: assert [] == list(requires_dists(dist))
def test_requires_dists_none(pygoogleearth_zip_sdist): # type: (str) -> None assert [] == list(requires_dists(pygoogleearth_zip_sdist)) with example_distribution("MarkupSafe-1.0-cp27-cp27mu-linux_x86_64.whl") as (wheel_path, dist): assert [] == list(requires_dists(wheel_path)) assert [] == list(requires_dists(dist))