"""
Backports and helper functionality to support using new functionality.
"""
import atexit
import contextlib
import functools
import inspect
import os
import re
import sys
import types
from packaging import specifiers
from .environment import MYPY_RUNNING
from .utils import (
call_function_with_correct_args,
filter_allowed_args,
get_allowed_args,
get_method_args,
nullcontext,
suppress_setattr,
)
if sys.version_info[:2] < (3, 5):
from backports.tempfile import TemporaryDirectory
else:
from tempfile import TemporaryDirectory
from contextlib import ExitStack
if MYPY_RUNNING:
from optparse import Values
from typing import (
Any,
Callable,
Dict,
Generator,
Generic,
Iterable,
Iterator,
List,
Optional,
Tuple,
Type,
TypeVar,
Union,
)
from requests import Session
from .utils import TShim, TShimmedFunc, TShimmedPath
TFinder = TypeVar("TFinder")
TResolver = TypeVar("TResolver")
TReqTracker = TypeVar("TReqTracker")
TBuildTracker = TypeVar("TBuildTracker")
TReqSet = TypeVar("TReqSet")
TLink = TypeVar("TLink")
TSession = TypeVar("TSession", bound=Session)
TCommand = TypeVar("TCommand", covariant=True)
TCommandInstance = TypeVar("TCommandInstance")
TCmdDict = Dict[str, Union[Tuple[str, str, str], TCommandInstance]]
TInstallRequirement = TypeVar("TInstallRequirement")
TFormatControl = TypeVar("TFormatControl")
TShimmedCmdDict = Union[TShim, TCmdDict]
TWheelCache = TypeVar("TWheelCache")
TPreparer = TypeVar("TPreparer")
[docs]class SearchScope(object):
def __init__(self, find_links=None, index_urls=None):
self.index_urls = index_urls if index_urls else []
self.find_links = find_links
[docs] @classmethod
def create(cls, find_links=None, index_urls=None):
if not index_urls:
index_urls = ["https://pypi.org/simple"]
return cls(find_links=find_links, index_urls=index_urls)
[docs]class SelectionPreferences(object):
def __init__(
self,
allow_yanked=True,
allow_all_prereleases=False,
format_control=None,
prefer_binary=False,
ignore_requires_python=False,
):
self.allow_yanked = allow_yanked
self.allow_all_prereleases = allow_all_prereleases
self.format_control = format_control
self.prefer_binary = prefer_binary
self.ignore_requires_python = ignore_requires_python
[docs]class TargetPython(object):
fallback_get_tags = None # type: Optional[TShimmedFunc]
def __init__(
self,
platform=None, # type: Optional[str]
py_version_info=None, # type: Optional[Tuple[int, ...]]
abi=None, # type: Optional[str]
implementation=None, # type: Optional[str]
):
# type: (...) -> None
self._given_py_version_info = py_version_info
if py_version_info is None:
py_version_info = sys.version_info[:3]
elif len(py_version_info) < 3:
py_version_info += (3 - len(py_version_info)) * (0,)
else:
py_version_info = py_version_info[:3]
py_version = ".".join(map(str, py_version_info[:2]))
self.abi = abi
self.implementation = implementation
self.platform = platform
self.py_version = py_version
self.py_version_info = py_version_info
self._valid_tags = None
[docs]class CandidatePreferences(object):
def __init__(self, prefer_binary=False, allow_all_prereleases=False):
self.prefer_binary = prefer_binary
self.allow_all_prereleases = allow_all_prereleases
[docs]class LinkCollector(object):
def __init__(self, session=None, search_scope=None):
self.session = session
self.search_scope = search_scope
[docs]class CandidateEvaluator(object):
[docs] @classmethod
def create(
cls,
project_name, # type: str
target_python=None, # type: Optional[TargetPython]
prefer_binary=False, # type: bool
allow_all_prereleases=False, # type: bool
specifier=None, # type: Optional[specifiers.BaseSpecifier]
hashes=None, # type: Optional[Any]
):
if target_python is None:
target_python = TargetPython()
if specifier is None:
specifier = specifiers.SpecifierSet()
supported_tags = target_python.get_tags()
return cls(
project_name=project_name,
supported_tags=supported_tags,
specifier=specifier,
prefer_binary=prefer_binary,
allow_all_prereleases=allow_all_prereleases,
hashes=hashes,
)
def __init__(
self,
project_name, # type: str
supported_tags, # type: List[Any]
specifier, # type: specifiers.BaseSpecifier
prefer_binary=False, # type: bool
allow_all_prereleases=False, # type: bool
hashes=None, # type: Optional[Any]
):
self._allow_all_prereleases = allow_all_prereleases
self._hashes = hashes
self._prefer_binary = prefer_binary
self._project_name = project_name
self._specifier = specifier
self._supported_tags = supported_tags
[docs]class LinkEvaluator(object):
def __init__(
self,
allow_yanked,
project_name,
canonical_name,
formats,
target_python,
ignore_requires_python=False,
ignore_compatibility=True,
):
self._allow_yanked = allow_yanked
self._canonical_name = canonical_name
self._ignore_requires_python = ignore_requires_python
self._formats = formats
self._target_python = target_python
self._ignore_compatibility = ignore_compatibility
self.project_name = project_name
[docs]class InvalidWheelFilename(Exception):
"""Wheel Filename is Invalid"""
[docs]class Wheel(object):
wheel_file_re = re.compile(
r"""^(?P<namever>(?P<name>.+?)-(?P<ver>.*?))
((-(?P<build>\d[^-]*?))?-(?P<pyver>.+?)-(?P<abi>.+?)-(?P<plat>.+?)
\.whl|\.dist-info)$""",
re.VERBOSE,
)
def __init__(self, filename):
# type: (str) -> None
wheel_info = self.wheel_file_re.match(filename)
if not wheel_info:
raise InvalidWheelFilename("%s is not a valid wheel filename." % filename)
self.filename = filename
self.name = wheel_info.group("name").replace("_", "-")
# we'll assume "_" means "-" due to wheel naming scheme
# (https://github.com/pypa/pip/issues/1150)
self.version = wheel_info.group("ver").replace("_", "-")
self.build_tag = wheel_info.group("build")
self.pyversions = wheel_info.group("pyver").split(".")
self.abis = wheel_info.group("abi").split(".")
self.plats = wheel_info.group("plat").split(".")
# All the tag combinations from this file
self.file_tags = {
(x, y, z) for x in self.pyversions for y in self.abis for z in self.plats
}
[docs] def support_index_min(self, tags):
# type: (List[Any]) -> int
"""
Return the lowest index that one of the wheel's file_tag combinations
achieves in the given list of supported tags.
For example, if there are 8 supported tags and one of the file tags
is first in the list, then return 0.
:param tags: the PEP 425 tags to check the wheel against, in order
with most preferred first.
:raises ValueError: If none of the wheel's file tags match one of
the supported tags.
"""
return min(tags.index(tag) for tag in self.file_tags if tag in tags)
[docs] def supported(self, tags):
# type: (List[Any]) -> bool
"""
Return whether the wheel is compatible with one of the given tags.
:param tags: the PEP 425 tags to check the wheel against.
"""
return not self.file_tags.isdisjoint(tags)
[docs]def resolve_possible_shim(target):
# type: (TShimmedFunc) -> Optional[Union[Type, Callable]]
if target is None:
return target
if getattr(target, "shim", None) and isinstance(
target.shim, (types.MethodType, types.FunctionType)
):
return target.shim()
return target
[docs]@contextlib.contextmanager
def temp_environ():
"""Allow the ability to set os.environ temporarily"""
environ = dict(os.environ)
try:
yield
finally:
os.environ.clear()
os.environ.update(environ)
[docs]@contextlib.contextmanager
def get_tracker(tracker_creator=None, tracker_type="REQ"):
# type: (Optional[Callable]) -> Generator[Optional[TReqTracker, TBuildTracker], None, None]
env_var = "PIP_REQ_TRACKER"
prefix = "req-tracker"
if tracker_type == "BUILD": # Replaced the req tracker in pip>=22.1
env_var = "PIP_BUILD_TRACKER"
prefix = "build-tracker"
root = os.environ.get(env_var)
if not tracker_creator:
yield None
else:
req_tracker_args = []
_, required_args = get_method_args(tracker_creator.__init__) # type: ignore
with ExitStack() as ctx:
if root is None:
root = ctx.enter_context(TemporaryDirectory(prefix=prefix))
if root:
root = str(root)
ctx.enter_context(temp_environ())
os.environ[env_var] = root
if required_args is not None and "root" in required_args:
req_tracker_args.append(root)
with tracker_creator(*req_tracker_args) as tracker:
yield tracker
[docs]@contextlib.contextmanager
def ensure_resolution_dirs(**kwargs):
# type: (Any) -> Iterator[Dict[str, Any]]
"""
Ensures that the proper directories are scaffolded and present in the provided kwargs
for performing dependency resolution via pip.
:return: A new kwargs dictionary with scaffolded directories for **build_dir**, **src_dir**,
**download_dir**, and **wheel_download_dir** added to the key value pairs.
:rtype: Dict[str, Any]
"""
keys = ("build_dir", "src_dir", "download_dir", "wheel_download_dir")
if not any(kwargs.get(key) is None for key in keys):
yield kwargs
else:
with TemporaryDirectory(prefix="pip-shims-") as base_dir:
for key in keys:
if kwargs.get(key) is not None:
continue
target = os.path.join(base_dir, key)
os.makedirs(target)
kwargs[key] = target
yield kwargs
[docs]@contextlib.contextmanager
def wheel_cache(
cache_dir=None, # type: str
format_control=None, # type: Any
wheel_cache_provider=None, # type: TShimmedFunc
format_control_provider=None, # type: Optional[TShimmedFunc]
tempdir_manager_provider=None, # type: TShimmedFunc
):
tempdir_manager_provider = resolve_possible_shim(tempdir_manager_provider)
wheel_cache_provider = resolve_possible_shim(wheel_cache_provider)
format_control_provider = resolve_possible_shim(format_control_provider)
if not format_control and not format_control_provider:
raise TypeError("Format control or provider needed for wheel cache!")
if not format_control:
format_control = format_control_provider(None, None)
with ExitStack() as ctx:
ctx.enter_context(tempdir_manager_provider())
wheel_cache = wheel_cache_provider(cache_dir, format_control)
yield wheel_cache
[docs]def partial_command(shimmed_path, cmd_mapping=None):
# type: (Type, Optional[TShimmedCmdDict]) -> Union[Type[TCommandInstance], functools.partial]
"""
Maps a default set of arguments across all members of a
:class:`~pip_shims.models.ShimmedPath` instance, specifically for
:class:`~pip._internal.command.Command` instances which need
`summary` and `name` arguments.
:param :class:`~pip_shims.models.ShimmedPath` shimmed_path: A
:class:`~pip_shims.models.ShimmedCollection` instance
:param Any cmd_mapping: A reference to use for mapping against, e.g. an
import that depends on pip also
:return: A dictionary mapping new arguments to their default values
:rtype: Dict[str, str]
"""
basecls = shimmed_path.shim()
resolved_cmd_mapping = None # type: Optional[Dict[str, Any]]
cmd_mapping = resolve_possible_shim(cmd_mapping)
if cmd_mapping is not None and isinstance(cmd_mapping, dict):
resolved_cmd_mapping = cmd_mapping.copy()
base_args = [] # type: List[str]
for root_cls in basecls.mro():
if root_cls.__name__ == "Command":
_, root_init_args = get_method_args(root_cls.__init__)
if root_init_args is not None:
base_args = root_init_args.args
needs_name_and_summary = any(arg in base_args for arg in ("name", "summary"))
if not needs_name_and_summary:
basecls.name = shimmed_path.name
return basecls
elif (
not resolved_cmd_mapping
and needs_name_and_summary
and getattr(functools, "partialmethod", None)
):
new_init = functools.partial(
basecls.__init__, name=shimmed_path.name, summary="Summary"
)
basecls.__init__ = new_init
result = basecls
assert resolved_cmd_mapping is not None
for command_name, command_info in resolved_cmd_mapping.items():
if getattr(command_info, "class_name", None) == shimmed_path.name:
summary = getattr(command_info, "summary", "Command summary")
result = functools.partial(basecls, command_name, summary)
break
return result
[docs]def get_session(
install_cmd_provider=None, # type: Optional[TShimmedFunc]
install_cmd=None, # type: TCommandInstance
options=None, # type: Optional[Values]
):
# type: (...) -> TSession
session = None # type: Optional[TSession]
if install_cmd is None:
assert install_cmd_provider is not None
install_cmd_provider = resolve_possible_shim(install_cmd_provider)
assert isinstance(install_cmd_provider, (type, functools.partial))
install_cmd = install_cmd_provider()
if options is None:
options, _ = install_cmd.parser.parse_args([]) # type: ignore
session = install_cmd._build_session(options) # type: ignore
assert session is not None
atexit.register(session.close)
return session
[docs]def populate_options(
install_command=None, # type: TCommandInstance
options=None, # type: Optional[Values]
**kwargs, # type: Any
):
# (...) -> Tuple[Dict[str, Any], Values]
results = {}
if install_command is None and options is None:
raise TypeError("Must pass either options or InstallCommand to populate options")
if options is None and install_command is not None:
options, _ = install_command.parser.parse_args([]) # type: ignore
options_dict = options.__dict__
for provided_key, provided_value in kwargs.items():
if provided_key == "isolated":
options_key = "isolated_mode"
elif provided_key == "source_dir":
options_key = "src_dir"
else:
options_key = provided_key
if provided_key in options_dict and provided_value is not None:
setattr(options, options_key, provided_value)
results[provided_key] = provided_value
elif getattr(options, options_key, None) is not None:
results[provided_key] = getattr(options, options_key)
else:
results[provided_key] = provided_value
return results, options
[docs]def get_requirement_set(
install_command=None, # type: Optional[TCommandInstance]
req_set_provider=None, # type: Optional[TShimmedFunc]
build_dir=None, # type: Optional[str]
src_dir=None, # type: Optional[str]
download_dir=None, # type: Optional[str]
wheel_download_dir=None, # type: Optional[str]
session=None, # type: Optional[TSession]
wheel_cache=None, # type: Optional[TWheelCache]
upgrade=False, # type: bool
upgrade_strategy=None, # type: Optional[str]
ignore_installed=False, # type: bool
ignore_dependencies=False, # type: bool
force_reinstall=False, # type: bool
use_user_site=False, # type: bool
isolated=False, # type: bool
ignore_requires_python=False, # type: bool
require_hashes=None, # type: bool
cache_dir=None, # type: Optional[str]
options=None, # type: Optional[Values]
install_cmd_provider=None, # type: Optional[TShimmedFunc]
wheel_cache_provider=None, # type: Optional[TShimmedFunc]
):
# (...) -> TRequirementSet
"""
Creates a requirement set from the supplied parameters.
Not all parameters are passed through for all pip versions, but any
invalid parameters will be ignored if they are not needed to generate a
requirement set on the current pip version.
:param :class:`~pip_shims.models.ShimmedPathCollection` wheel_cache_provider: A
context manager provider which resolves to a `WheelCache` instance
:param install_command: A :class:`~pip._internal.commands.install.InstallCommand`
instance which is used to generate the finder.
:param :class:`~pip_shims.models.ShimmedPathCollection` req_set_provider: A provider
to build requirement set instances.
:param str build_dir: The directory to build requirements in. Removed in pip 10,
defeaults to None
:param str source_dir: The directory to use for source requirements. Removed in
pip 10, defaults to None
:param str download_dir: The directory to download requirement artifacts to. Removed
in pip 10, defaults to None
:param str wheel_download_dir: The directory to download wheels to. Removed in pip
10, defaults ot None
:param :class:`~requests.Session` session: The pip session to use. Removed in pip 10,
defaults to None
:param WheelCache wheel_cache: The pip WheelCache instance to use for caching wheels.
Removed in pip 10, defaults to None
:param bool upgrade: Whether to try to upgrade existing requirements. Removed in pip
10, defaults to False.
:param str upgrade_strategy: The upgrade strategy to use, e.g. "only-if-needed".
Removed in pip 10, defaults to None.
:param bool ignore_installed: Whether to ignore installed packages when resolving.
Removed in pip 10, defaults to False.
:param bool ignore_dependencies: Whether to ignore dependencies of requirements
when resolving. Removed in pip 10, defaults to False.
:param bool force_reinstall: Whether to force reinstall of packages when resolving.
Removed in pip 10, defaults to False.
:param bool use_user_site: Whether to use user site packages when resolving. Removed
in pip 10, defaults to False.
:param bool isolated: Whether to resolve in isolation. Removed in pip 10, defaults
to False.
:param bool ignore_requires_python: Removed in pip 10, defaults to False.
:param bool require_hashes: Whether to require hashes when resolving. Defaults to
False.
:param Values options: An :class:`~optparse.Values` instance from an install cmd
:param install_cmd_provider: A shim for providing new install command instances.
:type install_cmd_provider: :class:`~pip_shims.models.ShimmedPathCollection`
:return: A new requirement set instance
:rtype: :class:`~pip._internal.req.req_set.RequirementSet`
"""
wheel_cache_provider = resolve_possible_shim(wheel_cache_provider)
req_set_provider = resolve_possible_shim(req_set_provider)
if install_command is None:
install_cmd_provider = resolve_possible_shim(install_cmd_provider)
assert isinstance(install_cmd_provider, (type, functools.partial))
install_command = install_cmd_provider()
required_args = inspect.getargs(
req_set_provider.__init__.__code__
).args # type: ignore
results, options = populate_options(
install_command,
options,
build_dir=build_dir,
src_dir=src_dir,
download_dir=download_dir,
upgrade=upgrade,
upgrade_strategy=upgrade_strategy,
ignore_installed=ignore_installed,
ignore_dependencies=ignore_dependencies,
force_reinstall=force_reinstall,
use_user_site=use_user_site,
isolated=isolated,
ignore_requires_python=ignore_requires_python,
require_hashes=require_hashes,
cache_dir=cache_dir,
)
if session is None and "session" in required_args:
session = get_session(install_cmd=install_command, options=options)
with ExitStack() as stack:
if wheel_cache is None:
wheel_cache = stack.enter_context(wheel_cache_provider(cache_dir=cache_dir))
results["wheel_cache"] = wheel_cache
results["session"] = session
results["wheel_download_dir"] = wheel_download_dir
return call_function_with_correct_args(req_set_provider, **results)
[docs]def get_package_finder(
install_cmd=None, # type: Optional[TCommand]
options=None, # type: Optional[Values]
session=None, # type: Optional[TSession]
platform=None, # type: Optional[str]
python_versions=None, # type: Optional[Tuple[str, ...]]
abi=None, # type: Optional[str]
implementation=None, # type: Optional[str]
target_python=None, # type: Optional[Any]
ignore_requires_python=None, # type: Optional[bool]
target_python_builder=None, # type: Optional[TShimmedFunc]
install_cmd_provider=None, # type: Optional[TShimmedFunc]
):
# type: (...) -> TFinder
"""Shim for compatibility to generate package finders.
Build and return a :class:`~pip._internal.index.package_finder.PackageFinder`
instance using the :class:`~pip._internal.commands.install.InstallCommand` helper
method to construct the finder, shimmed with backports as needed for compatibility.
:param install_cmd_provider: A shim for providing new install command instances.
:type install_cmd_provider: :class:`~pip_shims.models.ShimmedPathCollection`
:param install_cmd: A :class:`~pip._internal.commands.install.InstallCommand`
instance which is used to generate the finder.
:param optparse.Values options: An optional :class:`optparse.Values` instance
generated by calling `install_cmd.parser.parse_args()` typically.
:param session: An optional session instance, can be created by the `install_cmd`.
:param Optional[str] platform: An optional platform string, e.g. linux_x86_64
:param Optional[Tuple[str, ...]] python_versions: A tuple of 2-digit strings
representing python versions, e.g. ("27", "35", "36", "37"...)
:param Optional[str] abi: The target abi to support, e.g. "cp38"
:param Optional[str] implementation: An optional implementation string for limiting
searches to a specific implementation, e.g. "cp" or "py"
:param target_python: A :class:`~pip._internal.models.target_python.TargetPython`
instance (will be translated to alternate arguments if necessary on incompatible
pip versions).
:param Optional[bool] ignore_requires_python: Whether to ignore `requires_python`
on resulting candidates, only valid after pip version 19.3.1
:param target_python_builder: A 'TargetPython' builder (e.g. the class itself,
uninstantiated)
:return: A :class:`pip._internal.index.package_finder.PackageFinder` instance
:rtype: :class:`pip._internal.index.package_finder.PackageFinder`
:Example:
>>> from pip_shims.shims import InstallCommand, get_package_finder
>>> install_cmd = InstallCommand()
>>> finder = get_package_finder(
... install_cmd, python_versions=("27", "35", "36", "37", "38"), implementation="
cp"
... )
>>> candidates = finder.find_all_candidates("requests")
>>> requests_222 = next(iter(c for c in candidates if c.version.public == "2.22.0"))
>>> requests_222
<InstallationCandidate('requests', <Version('2.22.0')>, <Link https://files.pythonhos
ted.org/packages/51/bd/23c926cd341ea6b7dd0b2a00aba99ae0f828be89d72b2190f27c11d4b7fb/r
equests-2.22.0-py2.py3-none-any.whl#sha256=9cf5292fcd0f598c671cfc1e0d7d1a7f13bb8085e9
a590f48c010551dc6c4b31 (from https://pypi.org/simple/requests/) (requires-python:>=2.
7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*)>)>
"""
if install_cmd is None:
install_cmd_provider = resolve_possible_shim(install_cmd_provider)
assert isinstance(install_cmd_provider, (type, functools.partial))
install_cmd = install_cmd_provider()
if options is None:
options, _ = install_cmd.parser.parse_args([]) # type: ignore
if session is None:
session = get_session(install_cmd=install_cmd, options=options) # type: ignore
builder_args = inspect.getargs(
install_cmd._build_package_finder.__code__
) # type: ignore
build_kwargs = {"options": options, "session": session}
expects_targetpython = "target_python" in builder_args.args
received_python = any(arg for arg in [platform, python_versions, abi, implementation])
if expects_targetpython and received_python and not target_python:
if target_python_builder is None:
target_python_builder = TargetPython
py_version_info = None
if python_versions:
py_version_info_python = max(python_versions)
py_version_info = tuple([int(part) for part in py_version_info_python])
target_python_args = {
"platform": platform,
"platforms": [platform] if platform else None,
"abi": abi,
"abis": [abi] if abi else None,
"implementation": implementation,
"py_version_info": py_version_info,
}
target_python = call_function_with_correct_args(
target_python_builder, **target_python_args
)
build_kwargs["target_python"] = target_python
elif any(
arg in builder_args.args
for arg in ["platform", "python_versions", "abi", "implementation"]
):
if target_python and not received_python:
tags = target_python.get_tags()
version_impl = {t[0] for t in tags}
# impls = set([v[:2] for v in version_impl])
# impls.remove("py")
# impl = next(iter(impls), "py") if not target_python
versions = {v[2:] for v in version_impl}
build_kwargs.update(
{
"platform": target_python.platform,
"python_versions": versions,
"abi": target_python.abi,
"implementation": target_python.implementation,
}
)
if (
ignore_requires_python is not None
and "ignore_requires_python" in builder_args.args
):
build_kwargs["ignore_requires_python"] = ignore_requires_python
return install_cmd._build_package_finder(**build_kwargs) # type: ignore
[docs]def shim_unpack(
unpack_fn, # type: TShimmedFunc
download_dir, # type str
tempdir_manager_provider, # type: TShimmedFunc
ireq=None, # type: Optional[Any]
link=None, # type: Optional[Any]
location=None, # type Optional[str],
hashes=None, # type: Optional[Any]
progress_bar="off", # type: str
only_download=None, # type: Optional[bool]
downloader_provider=None, # type: Optional[TShimmedFunc]
session=None, # type: Optional[Any]
verbosity=0, # type: Optional[int]
):
# (...) -> None
"""
Accepts all parameters that have been valid to pass
to :func:`pip._internal.download.unpack_url` and selects or
drops parameters as needed before invoking the provided
callable.
:param unpack_fn: A callable or shim referring to the pip implementation
:type unpack_fn: Callable
:param str download_dir: The directory to download the file to
:param TShimmedFunc tempdir_manager_provider: A callable or shim referring to
`global_tempdir_manager` function from pip or a shimmed no-op context manager
:param Optional[:class:`~pip._internal.req.req_install.InstallRequirement`] ireq:
an Install Requirement instance, defaults to None
:param Optional[:class:`~pip._internal.models.link.Link`] link: A Link instance,
defaults to None.
:param Optional[str] location: A location or source directory if the target is
a VCS url, defaults to None.
:param Optional[Any] hashes: A Hashes instance, defaults to None
:param str progress_bar: Indicates progress par usage during download, defatuls to
off.
:param Optional[bool] only_download: Whether to skip install, defaults to None.
:param Optional[ShimmedPathCollection] downloader_provider: A downloader class
to instantiate, if applicable.
:param Optional[`~requests.Session`] session: A PipSession instance, defaults to
None.
:param Optional[int] verbosity: 1 or 0 to indicate verbosity flag, defaults to 0.
:return: The result of unpacking the url.
:rtype: None
"""
unpack_fn = resolve_possible_shim(unpack_fn)
downloader_provider = resolve_possible_shim(downloader_provider)
tempdir_manager_provider = resolve_possible_shim(tempdir_manager_provider)
required_args = inspect.getargs(unpack_fn.__code__).args # type: ignore
unpack_kwargs = {"download_dir": download_dir}
with tempdir_manager_provider():
if ireq:
if not link and ireq.link:
link = ireq.link
if only_download is None:
only_download = ireq.is_wheel
if hashes is None:
hashes = ireq.hashes(True)
if location is None and getattr(ireq, "source_dir", None):
location = ireq.source_dir
unpack_kwargs.update({"link": link, "location": location})
if hashes is not None and "hashes" in required_args:
unpack_kwargs["hashes"] = hashes
if "progress_bar" in required_args:
unpack_kwargs["progress_bar"] = progress_bar
if only_download is not None and "only_download" in required_args:
unpack_kwargs["only_download"] = only_download
if session is not None and "session" in required_args:
unpack_kwargs["session"] = session
if (
"download" in required_args or "downloader" in required_args
) and downloader_provider is not None:
arg_name = "download" if "download" in required_args else "downloader"
assert session is not None
assert progress_bar is not None
unpack_kwargs[arg_name] = downloader_provider(session, progress_bar)
if "verbosity" in required_args:
unpack_kwargs["verbosity"] = verbosity
return unpack_fn(**unpack_kwargs) # type: ignore
[docs]def _ensure_finder(
finder=None, # type: Optional[TFinder]
finder_provider=None, # type: Optional[Callable]
install_cmd=None, # type: Optional[TCommandInstance]
options=None, # type: Optional[Values]
session=None, # type: Optional[TSession]
):
if not any([finder, finder_provider, install_cmd]):
raise TypeError(
"RequirementPreparer requires a packagefinder but no InstallCommand"
" was provided to build one and none was passed in."
)
if finder is not None:
return finder
else:
if session is None:
session = get_session(install_cmd=install_cmd, options=options)
if finder_provider is not None and options is not None:
finder_provider(options=options, session=session)
else:
finder = get_package_finder(install_cmd, options=options, session=session)
return finder
[docs]@contextlib.contextmanager
def make_preparer(
preparer_fn, # type: TShimmedFunc
build_tracker_fn=None, # type: Optional[TShimmedFunc]
req_tracker_fn=None, # type: Optional[TShimmedFunc]
build_dir=None, # type: Optional[str]
src_dir=None, # type: Optional[str]
download_dir=None, # type: Optional[str]
wheel_download_dir=None, # type: Optional[str]
progress_bar="off", # type: str
build_isolation=False, # type: bool
session=None, # type: Optional[TSession]
finder=None, # type: Optional[TFinder]
options=None, # type: Optional[Values]
require_hashes=None, # type: Optional[bool]
use_user_site=None, # type: Optional[bool]
req_tracker=None, # type: Optional[Union[TReqTracker, TShimmedFunc]]
build_tracker=None, # type: Optional[Union[TBuildTracker, TShimmedFunc]]
install_cmd_provider=None, # type: Optional[TShimmedFunc]
downloader_provider=None, # type: Optional[TShimmedFunc]
install_cmd=None, # type: Optional[TCommandInstance]
finder_provider=None, # type: Optional[TShimmedFunc]
verbosity=0, # type: Optional[int]
check_build_deps=False, # type: Optional[bool]
):
# (...) -> ContextManager
"""
Creates a requirement preparer for preparing pip requirements.
Provides a compatibilty shim that accepts all previously valid arguments and
discards any that are no longer used.
:raises TypeError: No requirement tracker provided and one cannot be generated
:raises TypeError: No valid sessions provided and one cannot be generated
:raises TypeError: No valid finders provided and one cannot be generated
:param TShimmedFunc preparer_fn: Callable or shim for generating preparers.
:param Optional[TShimmedFunc] req_tracker_fn: Callable or shim for generating
requirement trackers, defualts to None
:param Optional[str] build_dir: Directory for building packages and wheels,
defaults to None
:param Optional[str] src_dir: Directory to find or extract source files, defaults
to None
:param Optional[str] download_dir: Target directory to download files, defaults to
None
:param Optional[str] wheel_download_dir: Target directoryto download wheels, defaults
to None
:param str progress_bar: Whether to display a progress bar, defaults to off
:param bool build_isolation: Whether to build requirements in isolation, defaults
to False
:param Optional[TSession] session: Existing session to use for getting requirements,
defaults to None
:param Optional[TFinder] finder: The package finder to use during resolution,
defaults to None
:param Optional[Values] options: Pip options to use if needed, defaults to None
:param Optional[bool] require_hashes: Whether to require hashes for preparation
:param Optional[bool] use_user_site: Whether to use the user site directory for
preparing requirements
:param Optional[Union[TReqTracker, TShimmedFunc]] req_tracker: The requirement
tracker to use for building packages, defaults to None
:param Optional[Union[TBuildTracker, TShimmedFunc]] build_tracker: The build
tracker to use for building packages, defaults to None and fallsback to req_tracker.
:param Optional[TShimmedFunc] downloader_provider: A downloader provider
:param Optional[TCommandInstance] install_cmd: The install command used to create
the finder, session, and options if needed, defaults to None
:param Optional[TShimmedFunc] finder_provider: A package finder provider
:yield: A new requirement preparer instance
:rtype: ContextManager[:class:`~pip._internal.operations.prepare.RequirementPreparer`]
:Example:
>>> from pip_shims.shims import (
... InstallCommand, get_package_finder, make_preparer, get_requirement_tracker
... )
>>> install_cmd = InstallCommand()
>>> pip_options, _ = install_cmd.parser.parse_args([])
>>> session = install_cmd._build_session(pip_options)
>>> finder = get_package_finder(
... install_cmd, session=session, options=pip_options
... )
>>> with make_preparer(
... options=pip_options, finder=finder, session=session, install_cmd=ic
... ) as preparer:
... print(preparer)
<pip._internal.operations.prepare.RequirementPreparer object at 0x7f8a2734be80>
"""
preparer_fn = resolve_possible_shim(preparer_fn)
downloader_provider = resolve_possible_shim(downloader_provider)
finder_provider = resolve_possible_shim(finder_provider)
required_args, required_kwargs = get_allowed_args(preparer_fn) # type: ignore
if not req_tracker and not req_tracker_fn and "req_tracker" in required_args:
raise TypeError("No requirement tracker and no req tracker generator found!")
if not build_tracker and not build_tracker_fn and "build_tracker" in required_args:
raise TypeError("No build tracker and no build tracker generator found!")
if "downloader" in required_args and not downloader_provider:
raise TypeError("no downloader provided, but one is required to continue!")
pip_options_created = options is None
session_is_required = "session" in required_args
finder_is_required = "finder" in required_args
downloader_is_required = "downloader" in required_args
options_map = {
"src_dir": src_dir,
"download_dir": download_dir,
"wheel_download_dir": wheel_download_dir,
"build_dir": build_dir,
"progress_bar": progress_bar,
"build_isolation": build_isolation,
"require_hashes": require_hashes,
"use_user_site": use_user_site,
}
if install_cmd is None:
assert install_cmd_provider is not None
install_cmd_provider = resolve_possible_shim(install_cmd_provider)
assert isinstance(install_cmd_provider, (type, functools.partial))
install_cmd = install_cmd_provider()
preparer_args, options = populate_options(install_cmd, options, **options_map)
if options is not None and pip_options_created:
for k, v in options_map.items():
suppress_setattr(options, k, v, filter_none=True)
if session_is_required:
if session is None:
session = get_session(install_cmd=install_cmd, options=options)
preparer_args["session"] = session
if finder_is_required:
finder = _ensure_finder(
finder=finder,
finder_provider=finder_provider,
install_cmd=install_cmd,
options=options,
session=session,
)
preparer_args["finder"] = finder
if downloader_is_required:
preparer_args["downloader"] = downloader_provider(session, progress_bar)
if "in_tree_build" in required_args:
preparer_args["in_tree_build"] = True
if "verbosity" in required_args:
preparer_args["verbosity"] = verbosity
if "check_build_deps" in required_args:
preparer_args["check_build_deps"] = check_build_deps
if "build_tracker" in required_args:
build_tracker_fn = resolve_possible_shim(build_tracker_fn)
build_tracker_fn = nullcontext if not build_tracker_fn else build_tracker_fn
with build_tracker_fn() as tracker_ctx:
build_tracker = tracker_ctx if build_tracker is None else build_tracker
preparer_args["build_tracker"] = build_tracker
preparer_args["lazy_wheel"] = True
result = call_function_with_correct_args(preparer_fn, **preparer_args)
yield result
if "req_tracker" in required_args:
req_tracker_fn = resolve_possible_shim(req_tracker_fn)
req_tracker_fn = nullcontext if not req_tracker_fn else req_tracker_fn
with req_tracker_fn() as tracker_ctx:
req_tracker = tracker_ctx if req_tracker is None else req_tracker
preparer_args["req_tracker"] = req_tracker
preparer_args["lazy_wheel"] = True
result = call_function_with_correct_args(preparer_fn, **preparer_args)
yield result
[docs]@contextlib.contextmanager
def _ensure_wheel_cache(
wheel_cache=None, # type: Optional[Type[TWheelCache]]
wheel_cache_provider=None, # type: Optional[Callable]
format_control=None, # type: Optional[TFormatControl]
format_control_provider=None, # type: Optional[Type[TShimmedFunc]]
options=None, # type: Optional[Values]
cache_dir=None, # type: Optional[str]
):
if wheel_cache is not None:
yield wheel_cache
elif wheel_cache_provider is not None:
with ExitStack() as stack:
cache_dir = getattr(options, "cache_dir", cache_dir)
format_control = getattr(
options,
"format_control",
format_control_provider(None, None), # TFormatControl
)
wheel_cache = stack.enter_context(
wheel_cache_provider(cache_dir, format_control)
)
yield wheel_cache
[docs]def get_ireq_output_path(wheel_cache, ireq):
if getattr(wheel_cache, "get_path_for_link", None):
return wheel_cache.get_path_for_link(ireq.link)
elif getattr(wheel_cache, "cached_wheel", None):
return wheel_cache.cached_wheel(ireq.link, ireq.name).url_without_fragment
[docs]def get_resolver(
resolver_fn, # type: TShimmedFunc
install_req_provider=None, # type: Optional[TShimmedFunc]
format_control_provider=None, # type: Optional[TShimmedFunc]
wheel_cache_provider=None, # type: Optional[TShimmedFunc]
finder=None, # type: Optional[TFinder]
upgrade_strategy="to-satisfy-only", # type: str
force_reinstall=None, # type: Optional[bool]
ignore_dependencies=None, # type: Optional[bool]
ignore_requires_python=None, # type: Optional[bool]
ignore_installed=True, # type: bool
use_user_site=False, # type: bool
isolated=None, # type: Optional[bool]
wheel_cache=None, # type: Optional[TWheelCache]
preparer=None, # type: Optional[TPreparer]
session=None, # type: Optional[TSession]
options=None, # type: Optional[Values]
make_install_req=None, # type: Optional[Callable]
install_cmd_provider=None, # type: Optional[TShimmedFunc]
install_cmd=None, # type: Optional[TCommandInstance]
use_pep517=True, # type: bool
):
# (...) -> TResolver
"""
A resolver creation compatibility shim for generating a resolver.
Consumes any argument that was previously used to instantiate a
resolver, discards anything that is no longer valid.
.. note:: This is only valid for **pip >= 10.0.0**
:raises ValueError: A session is required but not provided and one cannot be created
:raises ValueError: A finder is required but not provided and one cannot be created
:raises ValueError: An install requirement provider is required and has not been
provided
:param TShimmedFunc resolver_fn: The resolver function used to create new resolver
instances.
:param TShimmedFunc install_req_provider: The provider function to use to generate
install requirements if needed.
:param TShimmedFunc format_control_provider: The provider function to use to generate
a format_control instance if needed.
:param TShimmedFunc wheel_cache_provider: The provider function to use to generate
a wheel cache if needed.
:param Optional[TFinder] finder: The package finder to use during resolution,
defaults to None.
:param str upgrade_strategy: Upgrade strategy to use, defaults to ``only-if-needed``.
:param Optional[bool] force_reinstall: Whether to simulate or assume package
reinstallation during resolution, defaults to None
:param Optional[bool] ignore_dependencies: Whether to ignore package dependencies,
defaults to None
:param Optional[bool] ignore_requires_python: Whether to ignore indicated
required_python versions on packages, defaults to None
:param bool ignore_installed: Whether to ignore installed packages during resolution,
defaults to True
:param bool use_user_site: Whether to use the user site location during resolution,
defaults to False
:param Optional[bool] isolated: Whether to isolate the resolution process, defaults
to None
:param Optional[TWheelCache] wheel_cache: The wheel cache to use, defaults to None
:param Optional[TPreparer] preparer: The requirement preparer to use, defaults to
None
:param Optional[TSession] session: Existing session to use for getting requirements,
defaults to None
:param Optional[Values] options: Pip options to use if needed, defaults to None
:param Optional[functools.partial] make_install_req: The partial function to pass in
to the resolver for actually generating install requirements, if necessary
:param Optional[TCommandInstance] install_cmd: The install command used to create
the finder, session, and options if needed, defaults to None.
:param bool use_pep517: Whether to use the pep517 build process.
:return: A new resolver instance.
:rtype: :class:`~pip._internal.legacy_resolve.Resolver`
:Example:
>>> import os
>>> from tempdir import TemporaryDirectory
>>> from pip_shims.shims import (
... InstallCommand, get_package_finder, make_preparer, get_requirement_tracker,
... get_resolver, InstallRequirement, RequirementSet
... )
>>> install_cmd = InstallCommand()
>>> pip_options, _ = install_cmd.parser.parse_args([])
>>> session = install_cmd._build_session(pip_options)
>>> finder = get_package_finder(
... install_cmd, session=session, options=pip_options
... )
>>> wheel_cache = WheelCache(USER_CACHE_DIR, FormatControl(None, None))
>>> with TemporaryDirectory() as temp_base:
... reqset = RequirementSet()
... ireq = InstallRequirement.from_line("requests")
... ireq.is_direct = True
... build_dir = os.path.join(temp_base, "build")
... src_dir = os.path.join(temp_base, "src")
... ireq.build_location(build_dir)
... with make_preparer(
... options=pip_options, finder=finder, session=session,
... build_dir=build_dir, install_cmd=install_cmd,
... ) as preparer:
... resolver = get_resolver(
... finder=finder, ignore_dependencies=False, ignore_requires_python=True,
... preparer=preparer, session=session, options=pip_options,
... install_cmd=install_cmd, wheel_cache=wheel_cache,
... )
... resolver.require_hashes = False
... reqset.add_requirement(ireq)
... results = resolver.resolve(reqset)
... #reqset.cleanup_files()
... for result_req in reqset.requirements:
... print(result_req)
requests
chardet
certifi
urllib3
idna
"""
resolver_fn = resolve_possible_shim(resolver_fn)
install_req_provider = resolve_possible_shim(install_req_provider)
format_control_provider = resolve_possible_shim(format_control_provider)
wheel_cache_provider = resolve_possible_shim(wheel_cache_provider)
install_cmd_provider = resolve_possible_shim(install_cmd_provider)
required_args = inspect.getargs(resolver_fn.__init__.__code__).args # type: ignore
install_cmd_dependency_map = {"session": session, "finder": finder}
resolver_kwargs = {} # type: Dict[str, Any]
if install_cmd is None:
assert isinstance(install_cmd_provider, (type, functools.partial))
install_cmd = install_cmd_provider()
if options is None and install_cmd is not None:
options, _ = install_cmd.parser.parse_args([]) # type: ignore
for arg, val in install_cmd_dependency_map.items():
if arg not in required_args:
continue
elif val is None and install_cmd is None:
raise TypeError(
"Preparer requires a {} but did not receive one "
"and cannot generate one".format(arg)
)
elif arg == "session" and val is None:
val = get_session(install_cmd=install_cmd, options=options)
elif arg == "finder" and val is None:
val = get_package_finder(install_cmd, options=options, session=session)
resolver_kwargs[arg] = val
if "make_install_req" in required_args:
if make_install_req is None and install_req_provider is not None:
make_install_req_kwargs = {
"isolated": isolated,
"wheel_cache": wheel_cache,
"use_pep517": use_pep517,
}
factory_args, factory_kwargs = filter_allowed_args(
install_req_provider, **make_install_req_kwargs
)
make_install_req = functools.partial(
install_req_provider, *factory_args, **factory_kwargs
)
assert make_install_req is not None
resolver_kwargs["make_install_req"] = make_install_req
if "isolated" in required_args:
resolver_kwargs["isolated"] = isolated
resolver_kwargs.update(
{
"upgrade_strategy": upgrade_strategy,
"force_reinstall": force_reinstall,
"ignore_dependencies": ignore_dependencies,
"ignore_requires_python": ignore_requires_python,
"ignore_installed": ignore_installed,
"use_user_site": use_user_site,
"preparer": preparer,
}
)
if "wheel_cache" in required_args:
with _ensure_wheel_cache(
wheel_cache=wheel_cache,
wheel_cache_provider=wheel_cache_provider,
format_control_provider=format_control_provider,
options=options,
) as wheel_cache:
resolver_kwargs["wheel_cache"] = wheel_cache
return resolver_fn(**resolver_kwargs) # type: ignore
return resolver_fn(**resolver_kwargs) # type: ignore
[docs]def resolve( # noqa:C901
ireq, # type: TInstallRequirement
reqset_provider=None, # type: Optional[TShimmedFunc]
req_tracker_provider=None, # type: Optional[TShimmedFunc]
install_cmd_provider=None, # type: Optional[TShimmedFunc]
install_command=None, # type: Optional[TCommand]
finder_provider=None, # type: Optional[TShimmedFunc]
resolver_provider=None, # type: Optional[TShimmedFunc]
wheel_cache_provider=None, # type: Optional[TShimmedFunc]
format_control_provider=None, # type: Optional[TShimmedFunc]
make_preparer_provider=None, # type: Optional[TShimmedFunc]
tempdir_manager_provider=None, # type: Optional[TShimmedFunc]
options=None, # type: Optional[Values]
session=None, # type: Optional[TSession]
resolver=None, # type: Optional[TResolver]
finder=None, # type: Optional[TFinder]
upgrade_strategy="to-satisfy-only", # type: str
force_reinstall=None, # type: Optional[bool]
ignore_dependencies=None, # type: Optional[bool]
ignore_requires_python=None, # type: Optional[bool]
ignore_installed=True, # type: bool
use_user_site=False, # type: bool
isolated=None, # type: Optional[bool]
build_dir=None, # type: Optional[str]
source_dir=None, # type: Optional[str]
download_dir=None, # type: Optional[str]
cache_dir=None, # type: Optional[str]
wheel_download_dir=None, # type: Optional[str]
wheel_cache=None, # type: Optional[TWheelCache]
require_hashes=None, # type: bool
check_supported_wheels=True, # type: bool
):
# (...) -> Set[TInstallRequirement]
"""
Resolves the provided **InstallRequirement**, returning a dictionary.
Maps a dictionary of names to corresponding ``InstallRequirement`` values.
:param :class:`~pip._internal.req.req_install.InstallRequirement` ireq: An
InstallRequirement to initiate the resolution process
:param :class:`~pip_shims.models.ShimmedPathCollection` reqset_provider: A provider
to build requirement set instances.
:param :class:`~pip_shims.models.ShimmedPathCollection` req_tracker_provider: A
provider to build requirement tracker instances
:param install_cmd_provider: A shim for providing new install command instances.
:type install_cmd_provider: :class:`~pip_shims.models.ShimmedPathCollection`
:param Optional[TCommandInstance] install_command: The install command used to
create the finder, session, and options if needed, defaults to None.
:param :class:`~pip_shims.models.ShimmedPathCollection` finder_provider: A provider
to package finder instances.
:param :class:`~pip_shims.models.ShimmedPathCollection` resolver_provider: A provider
to build resolver instances
:param TShimmedFunc wheel_cache_provider: The provider function to use to generate a
wheel cache if needed.
:param TShimmedFunc format_control_provider: The provider function to use to generate
a format_control instance if needed.
:param TShimmedFunc make_preparer_provider: Callable or shim for generating preparers.
:param Optional[TShimmedFunc] tempdir_manager_provider: Shim for generating tempdir
manager for pip temporary directories
:param Optional[Values] options: Pip options to use if needed, defaults to None
:param Optional[TSession] session: Existing session to use for getting requirements,
defaults to None
:param :class:`~pip._internal.legacy_resolve.Resolver` resolver: A pre-existing
resolver instance to use for resolution
:param Optional[TFinder] finder: The package finder to use during resolution,
defaults to None.
:param str upgrade_strategy: Upgrade strategy to use, defaults to ``only-if-needed``.
:param Optional[bool] force_reinstall: Whether to simulate or assume package
reinstallation during resolution, defaults to None
:param Optional[bool] ignore_dependencies: Whether to ignore package dependencies,
defaults to None
:param Optional[bool] ignore_requires_python: Whether to ignore indicated
required_python versions on packages, defaults to None
:param bool ignore_installed: Whether to ignore installed packages during
resolution, defaults to True
:param bool use_user_site: Whether to use the user site location during resolution,
defaults to False
:param Optional[bool] isolated: Whether to isolate the resolution process, defaults
to None
:param Optional[str] build_dir: Directory for building packages and wheels, defaults
to None
:param str source_dir: The directory to use for source requirements. Removed in pip
10, defaults to None
:param Optional[str] download_dir: Target directory to download files, defaults to
None
:param str cache_dir: The cache directory to use for caching artifacts during
resolution
:param Optional[str] wheel_download_dir: Target directoryto download wheels, defaults
to None
:param Optional[TWheelCache] wheel_cache: The wheel cache to use, defaults to None
:param bool require_hashes: Whether to require hashes when resolving. Defaults to
False.
:param bool check_supported_wheels: Whether to check support of wheels before including
them in resolution.
:return: A dictionary mapping requirements to corresponding
:class:`~pip._internal.req.req_install.InstallRequirement`s
:rtype: :class:`~pip._internal.req.req_install.InstallRequirement`
:Example:
>>> from pip_shims.shims import resolve, InstallRequirement
>>> ireq = InstallRequirement.from_line("requests>=2.20")
>>> results = resolve(ireq)
>>> for k, v in results.items():
... print("{0}: {1!r}".format(k, v))
requests: <InstallRequirement object: requests>=2.20 from https://files.pythonhosted.
org/packages/51/bd/23c926cd341ea6b7dd0b2a00aba99ae0f828be89d72b2190f27c11d4b7fb/reque
sts-2.22.0-py2.py3-none-any.whl#sha256=9cf5292fcd0f598c671cfc1e0d7d1a7f13bb8085e9a590
f48c010551dc6c4b31 editable=False>
idna: <InstallRequirement object: idna<2.9,>=2.5 from https://files.pythonhosted.org/
packages/14/2c/cd551d81dbe15200be1cf41cd03869a46fe7226e7450af7a6545bfc474c9/idna-2.8-
py2.py3-none-any.whl#sha256=ea8b7f6188e6fa117537c3df7da9fc686d485087abf6ac197f9c46432
f7e4a3c (from requests>=2.20) editable=False>
urllib3: <InstallRequirement object: urllib3!=1.25.0,!=1.25.1,<1.26,>=1.21.1 from htt
ps://files.pythonhosted.org/packages/b4/40/a9837291310ee1ccc242ceb6ebfd9eb21539649f19
3a7c8c86ba15b98539/urllib3-1.25.7-py2.py3-none-any.whl#sha256=a8a318824cc77d1fd4b2bec
2ded92646630d7fe8619497b142c84a9e6f5a7293 (from requests>=2.20) editable=False>
chardet: <InstallRequirement object: chardet<3.1.0,>=3.0.2 from https://files.pythonh
osted.org/packages/bc/a9/01ffebfb562e4274b6487b4bb1ddec7ca55ec7510b22e4c51f14098443b8
/chardet-3.0.4-py2.py3-none-any.whl#sha256=fc323ffcaeaed0e0a02bf4d117757b98aed530d9ed
4531e3e15460124c106691 (from requests>=2.20) editable=False>
certifi: <InstallRequirement object: certifi>=2017.4.17 from https://files.pythonhost
ed.org/packages/18/b0/8146a4f8dd402f60744fa380bc73ca47303cccf8b9190fd16a827281eac2/ce
rtifi-2019.9.11-py2.py3-none-any.whl#sha256=fd7c7c74727ddcf00e9acd26bba8da604ffec95bf
1c2144e67aff7a8b50e6cef (from requests>=2.20) editable=False>
"""
reqset_provider = resolve_possible_shim(reqset_provider)
finder_provider = resolve_possible_shim(finder_provider)
resolver_provider = resolve_possible_shim(resolver_provider)
wheel_cache_provider = resolve_possible_shim(wheel_cache_provider)
format_control_provider = resolve_possible_shim(format_control_provider)
make_preparer_provider = resolve_possible_shim(make_preparer_provider)
req_tracker_provider = resolve_possible_shim(req_tracker_provider)
install_cmd_provider = resolve_possible_shim(install_cmd_provider)
tempdir_manager_provider = resolve_possible_shim(tempdir_manager_provider)
if install_command is None:
assert isinstance(install_cmd_provider, (type, functools.partial))
install_command = install_cmd_provider()
kwarg_map = {
"upgrade_strategy": upgrade_strategy,
"force_reinstall": force_reinstall,
"ignore_dependencies": ignore_dependencies,
"ignore_requires_python": ignore_requires_python,
"ignore_installed": ignore_installed,
"use_user_site": use_user_site,
"isolated": isolated,
"build_dir": build_dir,
"src_dir": source_dir,
"download_dir": download_dir,
"require_hashes": require_hashes,
"cache_dir": cache_dir,
}
kwargs, options = populate_options(install_command, options, **kwarg_map)
with ExitStack() as ctx:
ctx.enter_context(tempdir_manager_provider())
kwargs = ctx.enter_context(
ensure_resolution_dirs(wheel_download_dir=wheel_download_dir, **kwargs)
)
wheel_download_dir = kwargs.pop("wheel_download_dir")
if session is None:
session = get_session(install_cmd=install_command, options=options)
if finder is None:
finder = finder_provider(
install_command, options=options, session=session
) # type: ignore
format_control = getattr(options, "format_control", None)
if not format_control:
format_control = format_control_provider(None, None) # type: ignore
wheel_cache = ctx.enter_context(
wheel_cache_provider(kwargs["cache_dir"], format_control)
) # type: ignore
ireq.is_direct = True # type: ignore
build_location_kwargs = {
"build_dir": kwargs["build_dir"],
"autodelete": True,
"parallel_builds": False,
}
call_function_with_correct_args(ireq.build_location, **build_location_kwargs)
if reqset_provider is None:
raise TypeError(
"cannot resolve without a requirement set provider... failed!"
)
reqset = reqset_provider(
install_command,
options=options,
session=session,
wheel_download_dir=wheel_download_dir,
**kwargs,
) # type: ignore
preparer_args = {
"build_dir": kwargs["build_dir"],
"src_dir": kwargs["src_dir"],
"download_dir": kwargs["download_dir"],
"wheel_download_dir": wheel_download_dir,
"build_isolation": kwargs["isolated"],
"install_cmd": install_command,
"options": options,
"finder": finder,
"session": session,
"use_user_site": use_user_site,
"require_hashes": require_hashes,
}
if isinstance(req_tracker_provider, (types.FunctionType, functools.partial)):
preparer_args["req_tracker"] = ctx.enter_context(req_tracker_provider())
resolver_keys = [
"upgrade_strategy",
"force_reinstall",
"ignore_dependencies",
"ignore_installed",
"use_user_site",
"isolated",
"use_user_site",
]
resolver_args = {key: kwargs[key] for key in resolver_keys if key in kwargs}
if resolver_provider is None:
raise TypeError("Cannot resolve without a resolver provider... failed!")
preparer = ctx.enter_context(make_preparer_provider(**preparer_args))
resolver = resolver_provider(
finder=finder,
preparer=preparer,
session=session,
options=options,
install_cmd=install_command,
wheel_cache=wheel_cache,
**resolver_args,
) # type: ignore
resolver.require_hashes = kwargs.get("require_hashes", False) # type: ignore
_, required_resolver_args = get_method_args(resolver.resolve)
resolver_args = []
if "requirement_set" in required_resolver_args.args:
if hasattr(reqset, "add_requirement"):
reqset.add_requirement(ireq)
else: # Pip >= 22.1.0
resolver._add_requirement_to_set(reqset, ireq)
resolver_args.append(reqset)
elif "root_reqs" in required_resolver_args.args:
resolver_args.append([ireq])
if "check_supported_wheels" in required_resolver_args.args:
resolver_args.append(check_supported_wheels)
if getattr(reqset, "prepare_files", None):
if hasattr(reqset, "add_requirement"):
reqset.add_requirement(ireq)
else: # Pip >= 22.1.0
resolver._add_requirement_to_set(reqset, ireq)
results = reqset.prepare_files(finder)
result = reqset.requirements
reqset.cleanup_files()
return result
if make_preparer_provider is None:
raise TypeError("Cannot create requirement preparer, cannot resolve!")
result_reqset = resolver.resolve(*resolver_args) # type: ignore
if result_reqset is None:
result_reqset = reqset
results = result_reqset.requirements
cleanup_fn = getattr(reqset, "cleanup_files", None)
if cleanup_fn is not None:
cleanup_fn()
return results
[docs]def build_wheel( # noqa:C901
req=None, # type: Optional[TInstallRequirement]
reqset=None, # type: Optional[Union[TReqSet, Iterable[TInstallRequirement]]]
output_dir=None, # type: Optional[str]
preparer=None, # type: Optional[TPreparer]
wheel_cache=None, # type: Optional[TWheelCache]
build_options=None, # type: Optional[List[str]]
global_options=None, # type: Optional[List[str]]
check_binary_allowed=None, # type: Optional[Callable[TInstallRequirement, bool]]
no_clean=False, # type: bool
session=None, # type: Optional[TSession]
finder=None, # type: Optional[TFinder]
install_command=None, # type: Optional[TCommand]
req_tracker=None, # type: Optional[TReqTracker]
build_dir=None, # type: Optional[str]
src_dir=None, # type: Optional[str]
download_dir=None, # type: Optional[str]
wheel_download_dir=None, # type: Optional[str]
cache_dir=None, # type: Optional[str]
use_user_site=False, # type: bool
use_pep517=None, # type: Optional[bool]
verify=False, # type: bool
editable=False, # type: bool
format_control_provider=None, # type: Optional[TShimmedFunc]
wheel_cache_provider=None, # type: Optional[TShimmedFunc]
preparer_provider=None, # type: Optional[TShimmedFunc]
wheel_builder_provider=None, # type: Optional[TShimmedFunc]
build_one_provider=None, # type: Optional[TShimmedFunc]
build_one_inside_env_provider=None, # type: Optional[TShimmedFunc]
build_many_provider=None, # type: Optional[TShimmedFunc]
install_command_provider=None, # type: Optional[TShimmedFunc]
finder_provider=None, # type: Optional[TShimmedFunc]
reqset_provider=None, # type: Optional[TShimmedFunc]
):
# type: (...) -> Generator[Union[str, Tuple[List[TInstallRequirement], ...]], None, None]
"""
Build a wheel or a set of wheels
:raises TypeError: Raised when no requirements are provided
:param Optional[TInstallRequirement] req: An `InstallRequirement` to build
:param Optional[TReqSet] reqset: A `RequirementSet` instance (`pip<10`) or an
iterable of `InstallRequirement` instances (`pip>=10`) to build
:param Optional[str] output_dir: Target output directory, only useful when building
one wheel using pip>=20.0
:param Optional[TPreparer] preparer: A preparer instance, defaults to None
:param Optional[TWheelCache] wheel_cache: A wheel cache instance, defaults to None
:param Optional[List[str]] build_options: A list of build options to pass in
:param Optional[List[str]] global_options: A list of global options to pass in
:param Optional[Callable[TInstallRequirement, bool]] check_binary_allowed: A callable
to check whether we are allowed to build and cache wheels for an ireq
:param bool no_clean: Whether to avoid cleaning up wheels
:param Optional[TSession] session: A `PipSession` instance to pass to create a
`finder` if necessary
:param Optional[TFinder] finder: A `PackageFinder` instance to use for generating a
`WheelBuilder` instance on `pip<20`
:param Optional[TCommandInstance] install_command: The install command used to
create the finder, session, and options if needed, defaults to None.
:param Optional[TReqTracker] req_tracker: An optional requirement tracker instance,
if one already exists
:param Optional[str] build_dir: Passthrough parameter for building preparer
:param Optional[str] src_dir: Passthrough parameter for building preparer
:param Optional[str] download_dir: Passthrough parameter for building preparer
:param Optional[str] wheel_download_dir: Passthrough parameter for building preparer
:param Optional[str] cache_dir: Passthrough cache directory for wheel cache options
:param bool use_user_site: Whether to use the user site directory when preparing
install requirements on `pip<20`
:param Optional[bool] use_pep517: When set to *True* or *False*, prefers building
with or without pep517 as specified, otherwise uses requirement preference.
Only works for single requirements.
:param Optional[TShimmedFunc] format_control_provider: A provider for the
`FormatControl` class
:param Optional[TShimmedFunc] wheel_cache_provider: A provider for the `WheelCache`
class
:param Optional[TShimmedFunc] preparer_provider: A provider for the
`RequirementPreparer` class
:param Optional[TShimmedFunc] wheel_builder_provider: A provider for the
`WheelBuilder` class, if it exists
:param Optional[TShimmedFunc] build_one_provider: A provider for the `_build_one`
function, if it exists
:param Optional[TShimmedFunc] build_one_inside_env_provider: A provider for the
`_build_one_inside_env` function, if it exists
:param Optional[TShimmedFunc] build_many_provider: A provider for the `build`
function, if it exists
:param Optional[TShimmedFunc] install_command_provider: A shim for providing new
install command instances
:param TShimmedFunc finder_provider: A provider to package finder instances
:param TShimmedFunc reqset_provider: A provider for requirement set generation
:return: A tuple of successful and failed install requirements or else a path to
a wheel
:rtype: Optional[Union[str, Tuple[List[TInstallRequirement], List[TInstallRequirement]]]]
"""
wheel_cache_provider = resolve_possible_shim(wheel_cache_provider)
preparer_provider = resolve_possible_shim(preparer_provider)
wheel_builder_provider = resolve_possible_shim(wheel_builder_provider)
build_one_provider = resolve_possible_shim(build_one_provider)
build_one_inside_env_provider = resolve_possible_shim(build_one_inside_env_provider)
build_many_provider = resolve_possible_shim(build_many_provider)
install_cmd_provider = resolve_possible_shim(install_command_provider)
format_control_provider = resolve_possible_shim(format_control_provider)
finder_provider = resolve_possible_shim(finder_provider) or get_package_finder
reqset_provider = resolve_possible_shim(reqset_provider)
global_options = [] if global_options is None else global_options
build_options = [] if build_options is None else build_options
options = None
kwarg_map = {
"cache_dir": cache_dir,
"src_dir": src_dir,
"download_dir": download_dir,
"wheel_download_dir": wheel_download_dir,
"build_dir": build_dir,
"use_user_site": use_user_site,
}
if not req and not reqset:
raise TypeError("Must provide either a requirement or requirement set to build")
with ExitStack() as ctx:
kwargs = kwarg_map.copy()
if wheel_cache is None and (reqset is not None or output_dir is None):
if install_command is None:
assert isinstance(install_cmd_provider, (type, functools.partial))
install_command = install_cmd_provider()
kwargs, options = populate_options(install_command, options, **kwarg_map)
format_control = getattr(options, "format_control", None)
if not format_control:
format_control = format_control_provider(None, None) # type: ignore
wheel_cache = ctx.enter_context(
wheel_cache_provider(options.cache_dir, format_control)
)
if req and not reqset and not output_dir:
output_dir = get_ireq_output_path(wheel_cache, req)
if not reqset and build_one_provider:
build_one_kwargs = {
"req": req,
"output_dir": output_dir,
"verify": verify,
"editable": editable,
"build_options": build_options,
"global_options": global_options,
}
yield call_function_with_correct_args(build_one_provider, **build_one_kwargs)
elif build_many_provider:
yield build_many_provider(
reqset, wheel_cache, build_options, global_options, check_binary_allowed
)
else:
builder_args, builder_kwargs = get_allowed_args(wheel_builder_provider)
if "requirement_set" in builder_args and not reqset:
reqset = reqset_provider()
if session is None and finder is None:
session = get_session(install_cmd=install_command, options=options)
finder = finder_provider(
install_command, options=options, session=session
)
if preparer is None:
preparer_kwargs = {
"build_dir": kwargs["build_dir"],
"src_dir": kwargs["src_dir"],
"download_dir": kwargs["download_dir"],
"wheel_download_dir": kwargs["wheel_download_dir"],
"finder": finder,
"session": session
if session
else get_session(install_cmd=install_command, options=options),
"install_cmd": install_command,
"options": options,
"use_user_site": use_user_site,
"req_tracker": req_tracker,
}
preparer = ctx.enter_context(preparer_provider(**preparer_kwargs))
check_bin = check_binary_allowed if check_binary_allowed else lambda x: True
builder_kwargs = {
"requirement_set": reqset,
"finder": finder,
"preparer": preparer,
"wheel_cache": wheel_cache,
"no_clean": no_clean,
"build_options": build_options,
"global_options": global_options,
"check_binary_allowed": check_bin,
}
builder = call_function_with_correct_args(
wheel_builder_provider, **builder_kwargs
)
if req and not reqset:
if not output_dir:
output_dir = get_ireq_output_path(wheel_cache, req)
if use_pep517 is not None:
req.use_pep517 = use_pep517
yield builder._build_one(req, output_dir)
else:
yield builder.build(reqset)