From 71b3c0719fe930e5a95797ee3994d60e76b0cb33 Mon Sep 17 00:00:00 2001 From: Matt Davis Date: Sat, 6 Aug 2022 21:52:59 -0400 Subject: [PATCH 01/10] Look ahead at what dropping pip-shims is like. --- pipenv/__init__.py | 1 - pipenv/core.py | 7 - pipenv/environment.py | 27 +- pipenv/utils/dependencies.py | 16 +- pipenv/vendor/pip_shims/LICENSE | 13 - pipenv/vendor/pip_shims/__init__.py | 54 - pipenv/vendor/pip_shims/compat.py | 1632 ----------------- pipenv/vendor/pip_shims/environment.py | 45 - pipenv/vendor/pip_shims/models.py | 1171 ------------ pipenv/vendor/pip_shims/shims.py | 75 - pipenv/vendor/pip_shims/utils.py | 453 ----- pipenv/vendor/requirementslib/__init__.py | 2 +- pipenv/vendor/requirementslib/models/cache.py | 9 +- .../requirementslib/models/dependencies.py | 188 +- .../requirementslib/models/old_pip_utils.py | 287 +-- .../requirementslib/models/requirements.py | 143 +- .../requirementslib/models/resolvers.py | 6 +- .../requirementslib/models/setup_info.py | 61 +- pipenv/vendor/requirementslib/models/url.py | 15 +- pipenv/vendor/requirementslib/models/utils.py | 20 +- pipenv/vendor/requirementslib/models/vcs.py | 58 +- pipenv/vendor/requirementslib/utils.py | 69 +- pipenv/vendor/vendor.txt | 1 - .../patches/vendor/pip_shims-import.patch | 22 - 24 files changed, 446 insertions(+), 3929 deletions(-) delete mode 100644 pipenv/vendor/pip_shims/LICENSE delete mode 100644 pipenv/vendor/pip_shims/__init__.py delete mode 100644 pipenv/vendor/pip_shims/compat.py delete mode 100644 pipenv/vendor/pip_shims/environment.py delete mode 100644 pipenv/vendor/pip_shims/models.py delete mode 100644 pipenv/vendor/pip_shims/shims.py delete mode 100644 pipenv/vendor/pip_shims/utils.py delete mode 100644 tasks/vendoring/patches/vendor/pip_shims-import.patch diff --git a/pipenv/__init__.py b/pipenv/__init__.py index f3334b134b..7f5d2cef7f 100644 --- a/pipenv/__init__.py +++ b/pipenv/__init__.py @@ -27,7 +27,6 @@ # Load patched pip instead of system pip -os.environ["PIP_SHIMS_BASE_MODULE"] = "pipenv.patched.pip" os.environ["PIP_DISABLE_PIP_VERSION_CHECK"] = "1" # Hack to make things work better. diff --git a/pipenv/core.py b/pipenv/core.py index c95b18a28d..63f0d9ee46 100644 --- a/pipenv/core.py +++ b/pipenv/core.py @@ -2105,7 +2105,6 @@ def do_install( pypi_mirror=pypi_mirror, skip_lock=skip_lock, ) - pip_shims_module = os.environ.pop("PIP_SHIMS_BASE_MODULE", None) for pkg_line in pkg_list: click.secho( fix_utf8(f"Installing {pkg_line}..."), @@ -2240,8 +2239,6 @@ def do_install( # Update project settings with pre preference. if pre: project.update_settings({"allow_prereleases": pre}) - if pip_shims_module: - os.environ["PIP_SHIMS_BASE_MODULE"] = pip_shims_module do_init( project, dev=dev, @@ -2444,8 +2441,6 @@ def do_shell( # otherwise its value will be changed os.environ["PIPENV_ACTIVE"] = "1" - os.environ.pop("PIP_SHIMS_BASE_MODULE", None) - if fancy: shell.fork(*fork_args) return @@ -2596,7 +2591,6 @@ def do_run( load_dot_env(project, quiet=quiet) env = os.environ.copy() - env.pop("PIP_SHIMS_BASE_MODULE", None) path = env.get("PATH", "") if project.virtualenv_location: @@ -2614,7 +2608,6 @@ def do_run( # such as in inline_activate_virtual_environment # otherwise its value will be changed env["PIPENV_ACTIVE"] = "1" - env.pop("PIP_SHIMS_BASE_MODULE", None) try: script = project.build_script(command, args) diff --git a/pipenv/environment.py b/pipenv/environment.py index 36016bbb85..aacac721b4 100644 --- a/pipenv/environment.py +++ b/pipenv/environment.py @@ -16,6 +16,7 @@ import pipenv from pipenv.patched.pip._internal.commands.install import InstallCommand from pipenv.patched.pip._internal.index.package_finder import PackageFinder +from pipenv.patched.pip._internal.req.req_uninstall import UninstallPathSet from pipenv.patched.pip._vendor.packaging.utils import canonicalize_name from pipenv.utils.constants import is_type_checking from pipenv.utils.indexes import prepare_pip_source_args @@ -1024,32 +1025,24 @@ def uninstall(self, pkgname, *args, **kwargs): ) if monkey_patch: monkey_patch.activate() - pip_shims = self.safe_import("pip_shims") - pathset_base = pip_shims.UninstallPathSet - pathset_base._permitted = PatchedUninstaller._permitted dist = next( iter(d for d in self.get_working_set() if d.project_name == pkgname), None ) - pathset = pathset_base.from_dist(dist) - if pathset is not None: - pathset.remove(auto_confirm=auto_confirm, verbose=verbose) + path_set = UninstallPathSet.from_dist(dist) + if path_set is not None: + path_set.remove(auto_confirm=auto_confirm, verbose=verbose) try: - yield pathset + yield path_set except Exception: - if pathset is not None: - pathset.rollback() + if path_set is not None: + path_set.rollback() else: - if pathset is not None: - pathset.commit() - if pathset is None: + if path_set is not None: + path_set.commit() + if path_set is None: return -class PatchedUninstaller: - def _permitted(self, path): - return True - - SETUPTOOLS_SHIM = ( "import setuptools, tokenize;__file__=%r;" "f=getattr(tokenize, 'open', open)(__file__);" diff --git a/pipenv/utils/dependencies.py b/pipenv/utils/dependencies.py index b4ca1a7028..bf6ccb3cee 100644 --- a/pipenv/utils/dependencies.py +++ b/pipenv/utils/dependencies.py @@ -4,6 +4,7 @@ from typing import Mapping, Sequence from pipenv.patched.pip._vendor.packaging.markers import Marker +from pipenv.patched.pip._vendor.packaging.version import parse from .constants import SCHEME_LIST, VCS_LIST from .shell import temp_path @@ -61,10 +62,7 @@ def get_canonical_names(packages): def pep440_version(version): """Normalize version to PEP 440 standards""" - # Use pip built-in version parser. - from pipenv.vendor.pip_shims import shims - - return str(shims.parse_version(version)) + return str(parse(version)) def pep423_name(name): @@ -307,12 +305,6 @@ def locked_repository(requirement): if not requirement.is_vcs: return - original_base = os.environ.pop("PIP_SHIMS_BASE_MODULE", None) - os.environ["PIP_SHIMS_BASE_MODULE"] = "pipenv.patched.pip" src_dir = create_tracked_tempdir(prefix="pipenv-", suffix="-src") - try: - with requirement.req.locked_vcs_repo(src_dir=src_dir) as repo: - yield repo - finally: - if original_base: - os.environ["PIP_SHIMS_BASE_MODULE"] = original_base + with requirement.req.locked_vcs_repo(src_dir=src_dir) as repo: + yield repo diff --git a/pipenv/vendor/pip_shims/LICENSE b/pipenv/vendor/pip_shims/LICENSE deleted file mode 100644 index b89786873e..0000000000 --- a/pipenv/vendor/pip_shims/LICENSE +++ /dev/null @@ -1,13 +0,0 @@ -Copyright (c) 2018-2021, Dan Ryan and Frost Ming - -Permission to use, copy, modify, and distribute this software for any -purpose with or without fee is hereby granted, provided that the above -copyright notice and this permission notice appear in all copies. - -THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES -WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR -ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN -ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF -OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. diff --git a/pipenv/vendor/pip_shims/__init__.py b/pipenv/vendor/pip_shims/__init__.py deleted file mode 100644 index 2e93ff5b03..0000000000 --- a/pipenv/vendor/pip_shims/__init__.py +++ /dev/null @@ -1,54 +0,0 @@ -# -*- coding=utf-8 -*- -""" -This library is a set of compatibility access shims to the ``pip`` internal API. -It provides compatibility with pip versions 8.0 through the current release. The -shims are provided using a lazy import strategy by hacking a module by overloading -a class instance's ``getattr`` method. This library exists due to my constant -writing of the same set of import shims. - -Submodules -========== - -.. autosummary:: - :toctree: _autosummary - - pip_shims.models - pip_shims.compat - pip_shims.utils - pip_shims.shims - pip_shims.environment - -""" -from __future__ import absolute_import - -import sys - -from . import shims - -__version__ = "0.7.3" - - -if "pip_shims" in sys.modules: - # mainly to keep a reference to the old module on hand so it doesn't get - # weakref'd away - if __name__ != "pip_shims": - del sys.modules["pip_shims"] - - -if __name__ in sys.modules: - old_module = sys.modules[__name__] - - -module = sys.modules["pip_shims"] = sys.modules[__name__] = shims._new() -module.shims = shims -module.__dict__.update( - { - "__file__": __file__, - "__package__": "pip_shims", - "__path__": __path__, - "__doc__": __doc__, - "__all__": module.__all__ + ["shims"], - "__version__": __version__, - "__name__": __name__, - } -) diff --git a/pipenv/vendor/pip_shims/compat.py b/pipenv/vendor/pip_shims/compat.py deleted file mode 100644 index 000aa17dc5..0000000000 --- a/pipenv/vendor/pip_shims/compat.py +++ /dev/null @@ -1,1632 +0,0 @@ -""" -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 pipenv.patched.pip._vendor.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 pipenv.patched.pip._vendor.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") - - -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 - - @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) - - -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 - - -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 - - def get_tags(self): - if self._valid_tags is None and self.fallback_get_tags: - fallback_func = resolve_possible_shim(self.fallback_get_tags) - versions = None - if self._given_py_version_info: - versions = ["".join(map(str, self._given_py_version_info[:2]))] - self._valid_tags = fallback_func( - versions=versions, - platform=self.platform, - abi=self.abi, - impl=self.implementation, - ) - return self._valid_tags - - -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 - - -class LinkCollector(object): - def __init__(self, session=None, search_scope=None): - self.session = session - self.search_scope = search_scope - - -class CandidateEvaluator(object): - @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 - - -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 - - -class InvalidWheelFilename(Exception): - """Wheel Filename is Invalid""" - - -class Wheel(object): - wheel_file_re = re.compile( - r"""^(?P(?P.+?)-(?P.*?)) - ((-(?P\d[^-]*?))?-(?P.+?)-(?P.+?)-(?P.+?) - \.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 - } - - def get_formatted_file_tags(self): - # type: () -> List[str] - """ - Return the wheel's tags as a sorted list of strings. - """ - return sorted("-".join(tag) for tag in self.file_tags) - - 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) - - 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) - - -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 - - -@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) - - -@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 - - -@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 - - -@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 - - -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:`~pipenv.patched.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 - - -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 - - -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 - - -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:`~pipenv.patched.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:`~pipenv.patched.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) - - -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:`~pipenv.patched.pip._internal.index.package_finder.PackageFinder` - instance using the :class:`~pipenv.patched.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:`~pipenv.patched.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:`~pipenv.patched.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:`pipenv.patched.pip._internal.index.package_finder.PackageFinder` instance - :rtype: :class:`pipenv.patched.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 - , =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 - - -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:`pipenv.patched.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:`~pipenv.patched.pip._internal.req.req_install.InstallRequirement`] ireq: - an Install Requirement instance, defaults to None - :param Optional[:class:`~pipenv.patched.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 - - -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 - - -@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:`~pipenv.patched.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) - - """ - 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 - - -@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 - - -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 - - -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:`~pipenv.patched.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 - - -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:`~pipenv.patched.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:`~pipenv.patched.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:`~pipenv.patched.pip._internal.req.req_install.InstallRequirement`s - :rtype: :class:`~pipenv.patched.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: =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: =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: =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: =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: =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 - - -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) diff --git a/pipenv/vendor/pip_shims/environment.py b/pipenv/vendor/pip_shims/environment.py deleted file mode 100644 index 2268ea26f5..0000000000 --- a/pipenv/vendor/pip_shims/environment.py +++ /dev/null @@ -1,45 +0,0 @@ -# -*- coding=utf-8 -*- -""" -Module with functionality to learn about the environment. -""" -from __future__ import absolute_import - -import importlib -import os - - -def get_base_import_path(): - base_import_path = os.environ.get("PIP_SHIMS_BASE_MODULE", "pip") - return base_import_path - - -BASE_IMPORT_PATH = get_base_import_path() - - -def get_pip_version(import_path=BASE_IMPORT_PATH): - try: - pip = importlib.import_module(import_path) - except ImportError: - if import_path != "pip": - return get_pip_version(import_path="pip") - else: - import subprocess - - version = subprocess.check_output(["pip", "--version"]) - if version: - version = version.decode("utf-8").split()[1] - return version - return "0.0.0" - version = getattr(pip, "__version__", None) - return version - - -def is_type_checking(): - try: - from typing import TYPE_CHECKING - except ImportError: - return False - return TYPE_CHECKING - - -MYPY_RUNNING = os.environ.get("MYPY_RUNNING", is_type_checking()) diff --git a/pipenv/vendor/pip_shims/models.py b/pipenv/vendor/pip_shims/models.py deleted file mode 100644 index f31c6d691b..0000000000 --- a/pipenv/vendor/pip_shims/models.py +++ /dev/null @@ -1,1171 +0,0 @@ -# -*- coding: utf-8 -*- -""" -Helper module for shimming functionality across pip versions. -""" -from __future__ import absolute_import, print_function - -import collections -import functools -import importlib -import inspect -import operator -import sys -import types -import weakref -from collections.abc import Mapping, Sequence - -from . import compat -from .environment import BASE_IMPORT_PATH, MYPY_RUNNING, get_pip_version -from .utils import ( - add_mixin_to_class, - apply_alias, - ensure_function, - fallback_is_artifact, - fallback_is_file_url, - fallback_is_vcs, - get_method_args, - has_property, - make_classmethod, - make_method, - nullcontext, - parse_version, - resolve_possible_shim, - set_default_kwargs, - split_package, - suppress_setattr, -) - -if MYPY_RUNNING: - from pipenv.patched.pip._vendor.packaging.version import _BaseVersion - - Module = types.ModuleType - from typing import ( # noqa:F811 - Any, - Callable, - ContextManager, - Dict, - Iterable, - List, - Mapping, - Optional, - Set, - Tuple, - Type, - TypeVar, - Union, - ) - - -ImportTypesBase = collections.namedtuple( - "ImportTypes", ["FUNCTION", "CLASS", "MODULE", "CONTEXTMANAGER"] -) - - -class ImportTypes(ImportTypesBase): - FUNCTION = 0 - CLASS = 1 - MODULE = 2 - CONTEXTMANAGER = 3 - METHOD = 4 - ATTRIBUTE = 5 - - -class PipVersion(Sequence): - def __init__( - self, - version, - round_prereleases_up=True, - base_import_path=None, - vendor_import_path="pipenv.patched.pip._vendor", - ): - # type: (str, bool, Optional[str], str) -> None - self.version = version - self.vendor_import_path = vendor_import_path - self.round_prereleases_up = round_prereleases_up - parsed_version = self._parse() - if round_prereleases_up and parsed_version.is_prerelease: - parsed_version._version = parsed_version._version._replace(dev=None, pre=None) - self.version = str(parsed_version) - parsed_version = self._parse() - if base_import_path is None: - if parsed_version >= parse_version("10.0.0"): - base_import_path = "{}._internal".format(BASE_IMPORT_PATH) - else: - base_import_path = "{}".format(BASE_IMPORT_PATH) - self.base_import_path = base_import_path - self.parsed_version = parsed_version - - @property - def version_tuple(self): - return tuple(self.parsed_version._version) - - @property - def version_key(self): - return self.parsed_version._key - - def is_valid(self, compared_to): - # type: (PipVersion) -> bool - return self == compared_to - - def __len__(self): - # type: () -> int - return len(self.version_tuple) - - def __getitem__(self, item): - return self.version_tuple[item] - - def _parse(self): - # type: () -> _BaseVersion - return parse_version(self.version) - - def __hash__(self): - # type: () -> int - return hash(self.parsed_version) - - def __str__(self): - # type: () -> str - return "{!s}".format(self.parsed_version) - - def __repr__(self): - # type: () -> str - return ( - "" - ).format( - self.version, - self.base_import_path, - self.vendor_import_path, - self.parsed_version, - ) - - def __gt__(self, other): - # type: (PipVersion) -> bool - return self.parsed_version > other.parsed_version - - def __lt__(self, other): - # type: (PipVersion) -> bool - return self.parsed_version < other.parsed_version - - def __le__(self, other): - # type: (PipVersion) -> bool - return self.parsed_version <= other.parsed_version - - def __ge__(self, other): - # type: (PipVersion) -> bool - return self.parsed_version >= other.parsed_version - - def __ne__(self, other): - # type: (object) -> bool - if not isinstance(other, PipVersion): - return NotImplemented - return self.parsed_version != other.parsed_version - - def __eq__(self, other): - # type: (object) -> bool - if not isinstance(other, PipVersion): - return NotImplemented - return self.parsed_version == other.parsed_version - - -version_cache = weakref.WeakValueDictionary() # type: Mapping[str, PipVersion] -CURRENT_PIP_VERSION = None # type: Optional[PipVersion] - - -def pip_version_lookup(version, *args, **kwargs): - # type: (str, Any, Any) -> PipVersion - try: - cached = version_cache.get(version) - except KeyError: - cached = None - if cached is not None: - return cached - pip_version = PipVersion(version, *args, **kwargs) - version_cache[version] = pip_version - return pip_version - - -def lookup_current_pip_version(): - # type: () -> PipVersion - global CURRENT_PIP_VERSION - if CURRENT_PIP_VERSION is not None: - return CURRENT_PIP_VERSION - CURRENT_PIP_VERSION = pip_version_lookup(get_pip_version()) - return CURRENT_PIP_VERSION - - -class PipVersionRange(Sequence): - def __init__(self, start, end): - # type: (PipVersion, PipVersion) -> None - if start > end: - raise ValueError("Start version must come before end version") - self._versions = (start, end) - - def __str__(self): - # type: () -> str - return "{!s} -> {!s}".format(self._versions[0], self._versions[-1]) - - @property - def base_import_paths(self): - # type: () -> Set[str] - return {version.base_import_path for version in self._versions} - - @property - def vendor_import_paths(self): - # type: () -> Set[str] - return {version.vendor_import_path for version in self._versions} - - def is_valid(self): - # type: () -> bool - return pip_version_lookup(get_pip_version()) in self - - def __contains__(self, item): - # type: (PipVersion) -> bool - if not isinstance(item, PipVersion): - raise TypeError("Need a PipVersion instance to compare") - return item >= self[0] and item <= self[-1] - - def __getitem__(self, item): - # type: (int) -> PipVersion - return self._versions[item] - - def __len__(self): - # type: () -> int - return len(self._versions) - - def __lt__(self, other): - # type: ("PipVersionRange") -> bool - return (other.is_valid() and not self.is_valid()) or ( - not (self.is_valid() or other.is_valid()) - or (self.is_valid() and other.is_valid()) - and self._versions[-1] < other._versions[-1] - ) - - def __hash__(self): - # type: () -> int - return hash(self._versions) - - -class ShimmedPath(object): - __modules = {} # type: Dict[str, Module] - - def __init__( - self, - name, # type: str - import_target, # type: str - import_type, # type: int - version_range, # type: PipVersionRange - provided_methods=None, # type: Optional[Dict[str, Callable]] - provided_functions=None, # type: Optional[Dict[str, Callable]] - provided_classmethods=None, # type: Optional[Dict[str, Callable]] - provided_contextmanagers=None, # type: Optional[Dict[str, Callable]] - provided_mixins=None, # type: Optional[List[Type]] - default_args=None, # type: Dict[str, Sequence[List[Any], Dict[str, Any]]] - ): - # type: (...) -> None - if provided_methods is None: - provided_methods = {} - if provided_classmethods is None: - provided_classmethods = {} - if provided_functions is None: - provided_functions = {} - if provided_contextmanagers is None: - provided_contextmanagers = {} - if provided_mixins is None: - provided_mixins = [] - if default_args is None: - default_args = {} - self.version_range = version_range - self.name = name - self.full_import_path = import_target - module_path, name_to_import = split_package(import_target) - self.module_path = module_path - self.name_to_import = name_to_import - self.import_type = import_type - self._imported = None # type: Optional[Module] - self._provided = None # type: Optional[Union[Module, Type, Callable, Any]] - self.provided_methods = provided_methods - self.provided_functions = provided_functions - self.provided_classmethods = provided_classmethods - self.provided_contextmanagers = provided_contextmanagers - self.provided_mixins = [m for m in provided_mixins if m is not None] - self.default_args = default_args - self.aliases = [] # type: List[List[str]] - self._shimmed = None # type: Optional[Any] - - def _as_tuple(self): - # type: () -> Tuple[str, PipVersionRange, str, int] - return (self.name, self.version_range, self.full_import_path, self.import_type) - - def alias(self, aliases): - # type: (List[str]) -> "ShimmedPath" - self.aliases.append(aliases) - return self - - @classmethod - def _import_module(cls, module): - # type: (str) -> Optional[Module] - if module in ShimmedPath.__modules: - result = ShimmedPath.__modules[module] - if result is not None: - return result - try: - imported = importlib.import_module(module) - except ImportError: - return None - else: - ShimmedPath.__modules[module] = imported - return imported - - @classmethod - def _parse_provides_dict( - cls, - provides, # type: Dict[str, Callable] - prepend_arg_to_callables=None, # type: Optional[str] - ): - # type: (...) -> Dict[str, Callable] - creating_methods = False - creating_classmethods = False - if prepend_arg_to_callables is not None: - if prepend_arg_to_callables == "self": - creating_methods = True - elif prepend_arg_to_callables == "cls": - creating_classmethods = True - provides_map = {} - for item_name, item_value in provides.items(): - if isinstance(item_value, ShimmedPath): - item_value = item_value.shim() - if inspect.isfunction(item_value): - callable_args = inspect.getargs(item_value.__code__).args - if "self" not in callable_args and creating_methods: - item_value = make_method(item_value)(item_name) - elif "cls" not in callable_args and creating_classmethods: - item_value = make_classmethod(item_value)(item_name) - elif isinstance(item_value, str): - module_path, name = split_package(item_value) - module = cls._import_module(module_path) - item_value = getattr(module, name, None) - if item_value is not None: - provides_map[item_name] = item_value - return provides_map - - def _update_default_kwargs(self, parent, provided): - # type: (Union[Module, None], Union[Type, Module]) -> Tuple[Optional[Module], Union[Type, Module]] # noqa - for func_name, defaults in self.default_args.items(): - # * Note that we set default args here because we have the - # * option to use it, even though currently we dont - # * so we are forcibly ignoring the linter warning about it - default_args, default_kwargs = defaults # noqa:W0612 - provided = set_default_kwargs( - provided, func_name, *default_args, **default_kwargs - ) - return parent, provided - - def _ensure_functions(self, provided): - # type: (Union[Module, Type, None]) -> Any - functions = self._parse_provides_dict(self.provided_functions) - if provided is None: - provided = __module__ # type: ignore # noqa:F821 - for funcname, func in functions.items(): - func = ensure_function(provided, funcname, func) - setattr(provided, funcname, func) - return provided - - def _ensure_methods(self, provided): - # type: (Type) -> Type - """Given a base class, a new name, and any number of functions to - attach, turns those functions into classmethods, attaches them, - and returns an updated class object. - """ - if not self.is_class: - return provided - if not inspect.isclass(provided): - raise TypeError("Provided argument is not a class: {!r}".format(provided)) - methods = self._parse_provides_dict( - self.provided_methods, prepend_arg_to_callables="self" - ) - classmethods = self._parse_provides_dict( - self.provided_classmethods, prepend_arg_to_callables="cls" - ) - if not methods and not classmethods: - return provided - classname = provided.__name__ - type_ = type(classname, (provided,), {}) - - if classmethods: - for method_name, clsmethod in classmethods.items(): - if method_name not in provided.__dict__: - type.__setattr__(type_, method_name, clsmethod) - - if methods: - for method_name, clsmethod in methods.items(): - if method_name not in provided.__dict__: - type.__setattr__(type_, method_name, clsmethod) - return type_ - - @property - def is_class(self): - # type: () -> bool - return self.import_type == ImportTypes.CLASS - - @property - def is_module(self): - # type: () -> bool - return self.import_type == ImportTypes.MODULE - - @property - def is_method(self): - # type: () -> bool - return self.import_type == ImportTypes.METHOD - - @property - def is_function(self): - # type: () -> bool - return self.import_type == ImportTypes.FUNCTION - - @property - def is_contextmanager(self): - # type: () -> bool - return self.import_type == ImportTypes.CONTEXTMANAGER - - @property - def is_attribute(self): - # type: () -> bool - return self.import_type == ImportTypes.ATTRIBUTE - - def __contains__(self, pip_version): - # type: (str) -> bool - return pip_version_lookup(pip_version) in self.version_range - - @property - def is_valid(self): - # type: () -> bool - return self.version_range.is_valid() - - @property - def sort_order(self): - # type: () -> int - return 1 if self.is_valid else 0 - - def _shim_base(self, imported, attribute_name): - # type: (Union[Module, None], str) -> Any - result = getattr(imported, attribute_name, None) - return self._apply_aliases(imported, result) - - def _apply_aliases(self, imported, target): - # type: (Union[Module, None], Any) -> Any - for alias_list in self.aliases: - target = apply_alias(imported, target, *alias_list) - suppress_setattr(imported, self.name, target) - return target - - def _shim_parent(self, imported, attribute_name): - # type: (Union[Module, None], str) -> Tuple[Optional[Module], Any] - result = self._shim_base(imported, attribute_name) - if result is not None: - imported, result = self._update_default_kwargs(imported, result) - suppress_setattr(imported, attribute_name, result) - return imported, result - - def update_sys_modules(self, imported): - # type: (Optional[Module]) -> None - if imported is None: - return None - if self.calculated_module_path in sys.modules: - del sys.modules[self.calculated_module_path] - sys.modules[self.calculated_module_path] = imported - - def shim_class(self, imported, attribute_name): - # type: (Union[Module, None], str) -> Type - imported, result = self._shim_parent(imported, attribute_name) - if result is not None: - assert inspect.isclass(result) # noqa - result = self._ensure_methods(result) - if self.provided_mixins: - result = add_mixin_to_class(result, self.provided_mixins) - self._imported = imported - self._provided = result - self.update_sys_modules(imported) - if imported is not None: - ShimmedPath.__modules[imported.__name__] = imported - return result - - def shim_module(self, imported, attribute_name): - # type: (Union[Module, None], str) -> Module - imported, result = self._shim_parent(imported, attribute_name) - if result is not None: - result = self._ensure_functions(result) - full_import_path = "{}.{}".format(self.calculated_module_path, attribute_name) - self._imported = imported - assert isinstance(result, types.ModuleType) - self._provided = result - if full_import_path in sys.modules: - del sys.modules[full_import_path] - sys.modules[full_import_path] = result - self.update_sys_modules(imported) - if imported is not None: - ShimmedPath.__modules[imported.__name__] = imported - return result # type: ignore - - def shim_function(self, imported, attribute_name): - # type: (Union[Module, None], str) -> Callable - return self._shim_base(imported, attribute_name) - - def shim_attribute(self, imported, attribute_name): - # type: (Union[Module, None], Any) -> Any - return self._shim_base(imported, attribute_name) - - def shim_contextmanager(self, imported, attribute_name): - # type: (Union[Module, None], str) -> Callable - result = self._shim_base(imported, attribute_name) - if result is None: - result = nullcontext - suppress_setattr(imported, attribute_name, result) - self.update_sys_modules(imported) - return result - - @property - def shimmed(self): - # type: () -> Any - if self._shimmed is None: - self._shimmed = self.shim() - return self._shimmed - - def shim(self): - # type: () -> (Union[Module, Callable, ContextManager, Type]) - imported = self._import() - if self.is_class: - return self.shim_class(imported, self.name_to_import) - elif self.is_module: - return self.shim_module(imported, self.name_to_import) - elif self.is_contextmanager: - return self.shim_contextmanager(imported, self.name_to_import) - elif self.is_function: - return self.shim_function(imported, self.name_to_import) - elif self.is_attribute: - return self.shim_attribute(imported, self.name_to_import) - return self._shim_base(imported, self.name_to_import) - - @property - def calculated_module_path(self): - current_pip = lookup_current_pip_version() - prefix = current_pip.base_import_path - return ".".join([prefix, self.module_path]).rstrip(".") - - def _import(self, prefix=None): - # type: (Optional[str]) -> Optional[Module] - # TODO: Decide whether to use _imported and _shimmed or to set the shimmed - # always to _imported and never save the unshimmed module - if self._imported is not None: - return self._imported - result = self._import_module(self.calculated_module_path) - return result - - def __hash__(self): - # type: () -> int - return hash(self._as_tuple()) - - -class ShimmedPathCollection(object): - - __registry = {} # type: Dict[str, Any] - - def __init__(self, name, import_type, paths=None): - # type: (str, int, Optional[Sequence[ShimmedPath]]) -> None - self.name = name - self.import_type = import_type - self.paths = set() # type: Set[ShimmedPath] - self.top_path = None - self._default = None - self._default_args = {} # type: Dict[str, Sequence[List[Any], Dict[str, Any]]] - self.provided_methods = {} # type: Dict[str, Callable] - self.provided_functions = {} # type: Dict[str, Callable] - self.provided_contextmanagers = {} # type: Dict[str, Callable] - self.provided_classmethods = {} # type: Dict[str, Callable] - self.provided_mixins = [] # type: List[Type] - self.pre_shim_functions = [] # type: List[Callable] - self.aliases = [] # type: List[List[str]] - if paths is not None: - if isinstance(paths, str): - self.create_path(paths, version_start=lookup_current_pip_version()) - else: - self.paths.update(set(paths)) - self.register() - - def register(self): - # type: () -> None - self.__registry[self.name] = self - - @classmethod - def get_registry(cls): - # type: () -> Dict[str, "ShimmedPathCollection"] - return cls.__registry.copy() - - def add_path(self, path): - # type: (ShimmedPath) -> None - self.paths.add(path) - - def set_default(self, default): - # type: (Any) -> None - if isinstance(default, (ShimmedPath, ShimmedPathCollection)): - default = default.shim() - try: - default.__qualname__ = default.__name__ = self.name - except AttributeError: - pass - self._default = default - - def set_default_args(self, callable_name, *args, **kwargs): - # type: (str, Any, Any) -> None - self._default_args.update({callable_name: [args, kwargs]}) - - def provide_function(self, name, fn): - # type: (str, Union[Callable, ShimmedPath, ShimmedPathCollection]) -> None - if isinstance(fn, (ShimmedPath, ShimmedPathCollection)): - fn = resolve_possible_shim(fn) # type: ignore - self.provided_functions[name] = fn # type: ignore - - def provide_method(self, name, fn): - # type: (str, Union[Callable, ShimmedPath, ShimmedPathCollection, property]) -> None - if isinstance(fn, (ShimmedPath, ShimmedPathCollection)): - fn = resolve_possible_shim(fn) # type: ignore - self.provided_methods[name] = fn # type: ignore - - def alias(self, aliases): - # type: (List[str]) -> None - """ - Takes a list of methods, functions, attributes, etc and ensures they - all exist on the object pointing at the same referent. - - :param List[str] aliases: Names to map to the same functionality if they do not - exist. - :return: None - :rtype: None - """ - self.aliases.append(aliases) - - def add_mixin(self, mixin): - # type: (Optional[Union[Type, ShimmedPathCollection]]) -> None - if isinstance(mixin, ShimmedPathCollection): - mixin = mixin.shim() - if mixin is not None and inspect.isclass(mixin): - self.provided_mixins.append(mixin) - - def create_path(self, import_path, version_start, version_end=None): - # type: (str, str, Optional[str]) -> None - pip_version_start = pip_version_lookup(version_start) - if version_end is None: - version_end = "9999" - pip_version_end = pip_version_lookup(version_end) - version_range = PipVersionRange(pip_version_start, pip_version_end) - new_path = ShimmedPath( - self.name, - import_path, - self.import_type, - version_range, - self.provided_methods, - self.provided_functions, - self.provided_classmethods, - self.provided_contextmanagers, - self.provided_mixins, - self._default_args, - ) - if self.aliases: - for alias_list in self.aliases: - new_path.alias(alias_list) - self.add_path(new_path) - - def _sort_paths(self): - # type: () -> List[ShimmedPath] - return sorted(self.paths, key=operator.attrgetter("version_range"), reverse=True) - - def _get_top_path(self): - # type: () -> Optional[ShimmedPath] - return next(iter(self._sort_paths()), None) - - @classmethod - def traverse(cls, shim): - # type: (Union[ShimmedPath, ShimmedPathCollection, Any]) -> Any - if isinstance(shim, (ShimmedPath, ShimmedPathCollection)): - result = shim.shim() - return result - return shim - - def shim(self): - # type: () -> Any - top_path = self._get_top_path() # type: Union[ShimmedPath, None] - if not self.pre_shim_functions: - result = self.traverse(top_path) - else: - for fn in self.pre_shim_functions: - result = fn(top_path) - result = self.traverse(result) - if result == nullcontext and self._default is not None: - default_result = self.traverse(self._default) - if default_result: - return default_result - if result is None and self._default is not None: - result = self.traverse(self._default) - return result - - def pre_shim(self, fn): - # type: (Callable) -> None - self.pre_shim_functions.append(fn) - - -def import_pip(): - return importlib.import_module("pip") - - -_strip_extras = ShimmedPathCollection("_strip_extras", ImportTypes.FUNCTION) -_strip_extras.create_path("req.req_install._strip_extras", "7.0.0", "18.0.0") -_strip_extras.create_path("req.constructors._strip_extras", "18.1.0") - -cmdoptions = ShimmedPathCollection("cmdoptions", ImportTypes.MODULE) -cmdoptions.create_path("cli.cmdoptions", "18.1", "9999") -cmdoptions.create_path("cmdoptions", "7.0.0", "18.0") - -commands_dict = ShimmedPathCollection("commands_dict", ImportTypes.ATTRIBUTE) -commands_dict.create_path("commands.commands_dict", "7.0.0", "9999") - -SessionCommandMixin = ShimmedPathCollection("SessionCommandMixin", ImportTypes.CLASS) -SessionCommandMixin.create_path("cli.req_command.SessionCommandMixin", "19.3.0", "9999") - -Command = ShimmedPathCollection("Command", ImportTypes.CLASS) -Command.set_default_args("__init__", name="PipCommand", summary="Default pip command.") -Command.add_mixin(SessionCommandMixin) -Command.create_path("cli.base_command.Command", "18.1", "9999") -Command.create_path("basecommand.Command", "7.0.0", "18.0") - -ConfigOptionParser = ShimmedPathCollection("ConfigOptionParser", ImportTypes.CLASS) -ConfigOptionParser.create_path("cli.parser.ConfigOptionParser", "18.1", "9999") -ConfigOptionParser.create_path("baseparser.ConfigOptionParser", "7.0.0", "18.0") - -InstallCommand = ShimmedPathCollection("InstallCommand", ImportTypes.CLASS) -InstallCommand.pre_shim( - functools.partial(compat.partial_command, cmd_mapping=commands_dict) -) -InstallCommand.create_path("commands.install.InstallCommand", "7.0.0", "9999") - -DistributionNotFound = ShimmedPathCollection("DistributionNotFound", ImportTypes.CLASS) -DistributionNotFound.create_path("exceptions.DistributionNotFound", "7.0.0", "9999") - -FAVORITE_HASH = ShimmedPathCollection("FAVORITE_HASH", ImportTypes.ATTRIBUTE) -FAVORITE_HASH.create_path("utils.hashes.FAVORITE_HASH", "7.0.0", "9999") - -FormatControl = ShimmedPathCollection("FormatControl", ImportTypes.CLASS) -FormatControl.create_path("models.format_control.FormatControl", "18.1", "9999") -FormatControl.create_path("index.FormatControl", "7.0.0", "18.0") - -FrozenRequirement = ShimmedPathCollection("FrozenRequirement", ImportTypes.CLASS) -FrozenRequirement.create_path("FrozenRequirement", "7.0.0", "9.0.3") -FrozenRequirement.create_path("operations.freeze.FrozenRequirement", "10.0.0", "9999") - -get_installed_distributions = ShimmedPathCollection( - "get_installed_distributions", ImportTypes.FUNCTION -) -get_installed_distributions.create_path( - "utils.misc.get_installed_distributions", "10", "21.2.999" -) -get_installed_distributions.create_path("utils.get_installed_distributions", "7", "9.0.3") - -get_supported = ShimmedPathCollection("get_supported", ImportTypes.FUNCTION) -get_supported.create_path("pep425tags.get_supported", "7.0.0", "9999") - -get_tags = ShimmedPathCollection("get_tags", ImportTypes.FUNCTION) -get_tags.create_path("pep425tags.get_tags", "7.0.0", "9999") - -index_group = ShimmedPathCollection("index_group", ImportTypes.FUNCTION) -index_group.create_path("cli.cmdoptions.index_group", "18.1", "9999") -index_group.create_path("cmdoptions.index_group", "7.0.0", "18.0") - -InstallationError = ShimmedPathCollection("InstallationError", ImportTypes.CLASS) -InstallationError.create_path("exceptions.InstallationError", "7.0.0", "9999") - -UninstallationError = ShimmedPathCollection("UninstallationError", ImportTypes.CLASS) -UninstallationError.create_path("exceptions.UninstallationError", "7.0.0", "9999") - -DistributionNotFound = ShimmedPathCollection("DistributionNotFound", ImportTypes.CLASS) -DistributionNotFound.create_path("exceptions.DistributionNotFound", "7.0.0", "9999") - -RequirementsFileParseError = ShimmedPathCollection( - "RequirementsFileParseError", ImportTypes.CLASS -) -RequirementsFileParseError.create_path( - "exceptions.RequirementsFileParseError", "7.0.0", "9999" -) - -BestVersionAlreadyInstalled = ShimmedPathCollection( - "BestVersionAlreadyInstalled", ImportTypes.CLASS -) -BestVersionAlreadyInstalled.create_path( - "exceptions.BestVersionAlreadyInstalled", "7.0.0", "9999" -) - -BadCommand = ShimmedPathCollection("BadCommand", ImportTypes.CLASS) -BadCommand.create_path("exceptions.BadCommand", "7.0.0", "9999") - -CommandError = ShimmedPathCollection("CommandError", ImportTypes.CLASS) -CommandError.create_path("exceptions.CommandError", "7.0.0", "9999") - -PreviousBuildDirError = ShimmedPathCollection("PreviousBuildDirError", ImportTypes.CLASS) -PreviousBuildDirError.create_path("exceptions.PreviousBuildDirError", "7.0.0", "9999") - -install_req_from_editable = ShimmedPathCollection( - "install_req_from_editable", ImportTypes.FUNCTION -) -install_req_from_editable.create_path( - "req.constructors.install_req_from_editable", "18.1", "9999" -) -install_req_from_editable.create_path( - "req.req_install.InstallRequirement.from_editable", "7.0.0", "18.0" -) - -install_req_from_line = ShimmedPathCollection( - "install_req_from_line", ImportTypes.FUNCTION -) -install_req_from_line.create_path( - "req.constructors.install_req_from_line", "18.1", "9999" -) -install_req_from_line.create_path( - "req.req_install.InstallRequirement.from_line", "7.0.0", "18.0" -) - -install_req_from_req_string = ShimmedPathCollection( - "install_req_from_req_string", ImportTypes.FUNCTION -) -install_req_from_req_string.create_path( - "req.constructors.install_req_from_req_string", "19.0", "9999" -) - -InstallRequirement = ShimmedPathCollection("InstallRequirement", ImportTypes.CLASS) -InstallRequirement.provide_method("from_line", install_req_from_line) -InstallRequirement.provide_method("from_editable", install_req_from_editable) -InstallRequirement.alias(["build_location", "ensure_build_location"]) - -InstallRequirement.create_path("req.req_install.InstallRequirement", "7.0.0", "9999") - -is_archive_file = ShimmedPathCollection("is_archive_file", ImportTypes.FUNCTION) -is_archive_file.create_path("req.constructors.is_archive_file", "19.3", "9999") -is_archive_file.create_path("download.is_archive_file", "7.0.0", "19.2.3") - -is_file_url = ShimmedPathCollection("is_file_url", ImportTypes.FUNCTION) -is_file_url.set_default(fallback_is_file_url) -is_file_url.create_path("download.is_file_url", "7.0.0", "19.2.3") - -Downloader = ShimmedPathCollection("Downloader", ImportTypes.CLASS) -Downloader.create_path("network.download.Downloader", "19.3.9", "9999") - -unpack_url = ShimmedPathCollection("unpack_url", ImportTypes.FUNCTION) -unpack_url.create_path("download.unpack_url", "7.0.0", "19.3.9") -unpack_url.create_path("operations.prepare.unpack_url", "20.0", "9999") - -is_installable_dir = ShimmedPathCollection("is_installable_dir", ImportTypes.FUNCTION) -is_installable_dir.create_path("utils.misc.is_installable_dir", "10.0.0", "9999") -is_installable_dir.create_path("utils.is_installable_dir", "7.0.0", "9.0.3") - -Link = ShimmedPathCollection("Link", ImportTypes.CLASS) -Link.provide_method("is_vcs", property(fallback_is_vcs)) -Link.provide_method("is_artifact", property(fallback_is_artifact)) -Link.create_path("models.link.Link", "19.0.0", "9999") -Link.create_path("index.Link", "7.0.0", "18.1") - -make_abstract_dist = ShimmedPathCollection("make_abstract_dist", ImportTypes.FUNCTION) -make_abstract_dist.create_path( - "distributions.make_distribution_for_install_requirement", "20.0.0", "9999" -) -make_abstract_dist.create_path( - "distributions.make_distribution_for_install_requirement", "19.1.2", "19.3.9" -) -make_abstract_dist.create_path( - "operations.prepare.make_abstract_dist", "10.0.0", "19.1.1" -) -make_abstract_dist.create_path("req.req_set.make_abstract_dist", "7.0.0", "9.0.3") - -make_distribution_for_install_requirement = ShimmedPathCollection( - "make_distribution_for_install_requirement", ImportTypes.FUNCTION -) -make_distribution_for_install_requirement.create_path( - "distributions.make_distribution_for_install_requirement", "20.0.0", "9999" -) -make_distribution_for_install_requirement.create_path( - "distributions.make_distribution_for_install_requirement", "19.1.2", "19.9.9" -) - -make_option_group = ShimmedPathCollection("make_option_group", ImportTypes.FUNCTION) -make_option_group.create_path("cli.cmdoptions.make_option_group", "18.1", "9999") -make_option_group.create_path("cmdoptions.make_option_group", "7.0.0", "18.0") - -PackageFinder = ShimmedPathCollection("PackageFinder", ImportTypes.CLASS) -PackageFinder.create_path("index.PackageFinder", "7.0.0", "19.9") -PackageFinder.create_path("index.package_finder.PackageFinder", "20.0", "9999") - -CandidateEvaluator = ShimmedPathCollection("CandidateEvaluator", ImportTypes.CLASS) -CandidateEvaluator.set_default(compat.CandidateEvaluator) -CandidateEvaluator.create_path("index.CandidateEvaluator", "19.1.0", "19.3.9") -CandidateEvaluator.create_path("index.package_finder.CandidateEvaluator", "20.0", "9999") - -CandidatePreferences = ShimmedPathCollection("CandidatePreferences", ImportTypes.CLASS) -CandidatePreferences.set_default(compat.CandidatePreferences) -CandidatePreferences.create_path("index.CandidatePreferences", "19.2.0", "19.9") -CandidatePreferences.create_path( - "index.package_finder.CandidatePreferences", "20.0", "9999" -) - -LinkCollector = ShimmedPathCollection("LinkCollector", ImportTypes.CLASS) -LinkCollector.set_default(compat.LinkCollector) -LinkCollector.create_path("collector.LinkCollector", "19.3.0", "19.9") -LinkCollector.create_path("index.collector.LinkCollector", "20.0", "9999") - -LinkEvaluator = ShimmedPathCollection("LinkEvaluator", ImportTypes.CLASS) -LinkEvaluator.set_default(compat.LinkEvaluator) -LinkEvaluator.create_path("index.LinkEvaluator", "19.2.0", "19.9") -LinkEvaluator.create_path("index.package_finder.LinkEvaluator", "20.0", "9999") - -TargetPython = ShimmedPathCollection("TargetPython", ImportTypes.CLASS) -compat.TargetPython.fallback_get_tags = get_tags -TargetPython.set_default(compat.TargetPython) -TargetPython.create_path("models.target_python.TargetPython", "19.2.0", "9999") - -SearchScope = ShimmedPathCollection("SearchScope", ImportTypes.CLASS) -SearchScope.set_default(compat.SearchScope) -SearchScope.create_path("models.search_scope.SearchScope", "19.2.0", "9999") - -SelectionPreferences = ShimmedPathCollection("SelectionPreferences", ImportTypes.CLASS) -SelectionPreferences.set_default(compat.SelectionPreferences) -SelectionPreferences.create_path( - "models.selection_prefs.SelectionPreferences", "19.2.0", "9999" -) - -parse_requirements = ShimmedPathCollection("parse_requirements", ImportTypes.FUNCTION) -parse_requirements.create_path("req.req_file.parse_requirements", "7.0.0", "9999") - -path_to_url = ShimmedPathCollection("path_to_url", ImportTypes.FUNCTION) -path_to_url.create_path("download.path_to_url", "7.0.0", "19.2.3") -path_to_url.create_path("utils.urls.path_to_url", "19.3.0", "9999") - -PipError = ShimmedPathCollection("PipError", ImportTypes.CLASS) -PipError.create_path("exceptions.PipError", "7.0.0", "9999") - -RequirementPreparer = ShimmedPathCollection("RequirementPreparer", ImportTypes.CLASS) -RequirementPreparer.create_path("operations.prepare.RequirementPreparer", "7", "9999") - -RequirementSet = ShimmedPathCollection("RequirementSet", ImportTypes.CLASS) -RequirementSet.create_path("req.req_set.RequirementSet", "7.0.0", "9999") - -BuildTracker = ShimmedPathCollection("BuildTracker", ImportTypes.CONTEXTMANAGER) -BuildTracker.create_path("operations.build.build_tracker.BuildTracker", "22.1", "9999") - -RequirementTracker = ShimmedPathCollection( - "RequirementTracker", ImportTypes.CONTEXTMANAGER -) -RequirementTracker.create_path("req.req_tracker.RequirementTracker", "7.0.0", "9999") - -TempDirectory = ShimmedPathCollection("TempDirectory", ImportTypes.CLASS) -TempDirectory.create_path("utils.temp_dir.TempDirectory", "7.0.0", "9999") - -global_tempdir_manager = ShimmedPathCollection( - "global_tempdir_manager", ImportTypes.CONTEXTMANAGER -) -global_tempdir_manager.create_path( - "utils.temp_dir.global_tempdir_manager", "7.0.0", "9999" -) - -shim_unpack = ShimmedPathCollection("shim_unpack", ImportTypes.FUNCTION) -shim_unpack.set_default( - functools.partial( - compat.shim_unpack, - unpack_fn=unpack_url, - downloader_provider=Downloader, - tempdir_manager_provider=global_tempdir_manager, - ) -) - -get_requirement_tracker = ShimmedPathCollection( - "get_requirement_tracker", ImportTypes.CONTEXTMANAGER -) -get_requirement_tracker.set_default( - functools.partial(compat.get_tracker, RequirementTracker.shim()) -) -get_requirement_tracker.create_path( - "req.req_tracker.get_requirement_tracker", "7.0.0", "9999" -) -get_build_tracker = ShimmedPathCollection("get_build_tracker", ImportTypes.CONTEXTMANAGER) -get_build_tracker.set_default( - functools.partial(compat.get_tracker, BuildTracker.shim(), tracker_type="BUILD") -) -get_build_tracker.create_path( - "operations.build.build_tracker.get_build_tracker", "7.0.0", "9999" -) - -Resolver = ShimmedPathCollection("Resolver", ImportTypes.CLASS) -Resolver.create_path("resolve.Resolver", "7.0.0", "19.1.1") -Resolver.create_path("legacy_resolve.Resolver", "19.1.2", "20.0.89999") -Resolver.create_path("resolution.legacy.resolver.Resolver", "20.0.99999", "99999") - -SafeFileCache = ShimmedPathCollection("SafeFileCache", ImportTypes.CLASS) -SafeFileCache.create_path("network.cache.SafeFileCache", "19.3.0", "9999") -SafeFileCache.create_path("download.SafeFileCache", "7.0.0", "19.2.3") - -UninstallPathSet = ShimmedPathCollection("UninstallPathSet", ImportTypes.CLASS) -UninstallPathSet.create_path("req.req_uninstall.UninstallPathSet", "7.0.0", "9999") - -url_to_path = ShimmedPathCollection("url_to_path", ImportTypes.FUNCTION) -url_to_path.create_path("download.url_to_path", "7.0.0", "19.2.3") -url_to_path.create_path("utils.urls.url_to_path", "19.3.0", "9999") - -USER_CACHE_DIR = ShimmedPathCollection("USER_CACHE_DIR", ImportTypes.ATTRIBUTE) -USER_CACHE_DIR.create_path("locations.USER_CACHE_DIR", "7.0.0", "9999") - -VcsSupport = ShimmedPathCollection("VcsSupport", ImportTypes.CLASS) -VcsSupport.create_path("vcs.VcsSupport", "7.0.0", "19.1.1") -VcsSupport.create_path("vcs.versioncontrol.VcsSupport", "19.2", "9999") - -Wheel = ShimmedPathCollection("Wheel", ImportTypes.CLASS) -Wheel.create_path("wheel.Wheel", "7.0.0", "19.3.9") -Wheel.set_default(compat.Wheel) - -WheelCache = ShimmedPathCollection("WheelCache", ImportTypes.CLASS) -WheelCache.create_path("cache.WheelCache", "10.0.0", "9999") -WheelCache.create_path("wheel.WheelCache", "7", "9.0.3") - -WheelBuilder = ShimmedPathCollection("WheelBuilder", ImportTypes.CLASS) -WheelBuilder.create_path("wheel.WheelBuilder", "7.0.0", "19.9") - -build = ShimmedPathCollection("build", ImportTypes.FUNCTION) -build.create_path("wheel_builder.build", "19.9", "9999") - -build_one = ShimmedPathCollection("build_one", ImportTypes.FUNCTION) -build_one.create_path("wheel_builder._build_one", "19.9", "9999") - -build_one_inside_env = ShimmedPathCollection("build_one_inside_env", ImportTypes.FUNCTION) -build_one_inside_env.create_path("wheel_builder._build_one_inside_env", "19.9", "9999") - -AbstractDistribution = ShimmedPathCollection("AbstractDistribution", ImportTypes.CLASS) -AbstractDistribution.create_path( - "distributions.base.AbstractDistribution", "19.1.2", "9999" -) - -InstalledDistribution = ShimmedPathCollection("InstalledDistribution", ImportTypes.CLASS) -InstalledDistribution.create_path( - "distributions.installed.InstalledDistribution", "19.1.2", "9999" -) - -SourceDistribution = ShimmedPathCollection("SourceDistribution", ImportTypes.CLASS) -SourceDistribution.create_path("req.req_set.IsSDist", "7.0.0", "9.0.3") -SourceDistribution.create_path("operations.prepare.IsSDist", "10.0.0", "19.1.1") -SourceDistribution.create_path( - "distributions.source.SourceDistribution", "19.1.2", "19.2.3" -) -SourceDistribution.create_path( - "distributions.source.legacy.SourceDistribution", "19.3.0", "19.9" -) -SourceDistribution.create_path("distributions.sdist.SourceDistribution", "20.0", "9999") - -WheelDistribution = ShimmedPathCollection("WheelDistribution", ImportTypes.CLASS) -WheelDistribution.create_path("distributions.wheel.WheelDistribution", "19.1.2", "9999") - -Downloader = ShimmedPathCollection("Downloader", ImportTypes.CLASS) -Downloader.create_path("network.download.Downloader", "20.0.0", "9999") - -PyPI = ShimmedPathCollection("PyPI", ImportTypes.ATTRIBUTE) -PyPI.create_path("models.index.PyPI", "7.0.0", "9999") - -stdlib_pkgs = ShimmedPathCollection("stdlib_pkgs", ImportTypes.ATTRIBUTE) -stdlib_pkgs.create_path("utils.compat.stdlib_pkgs", "18.1", "9999") -stdlib_pkgs.create_path("compat.stdlib_pkgs", "7", "18.0") - -DEV_PKGS = ShimmedPathCollection("DEV_PKGS", ImportTypes.ATTRIBUTE) -DEV_PKGS.create_path("commands.freeze.DEV_PKGS", "9.0.0", "9999") -DEV_PKGS.set_default({"setuptools", "pip", "distribute", "wheel"}) - - -wheel_cache = ShimmedPathCollection("wheel_cache", ImportTypes.FUNCTION) -wheel_cache.set_default( - functools.partial( - compat.wheel_cache, - wheel_cache_provider=WheelCache, - tempdir_manager_provider=global_tempdir_manager, - format_control_provider=FormatControl, - ) -) - - -get_package_finder = ShimmedPathCollection("get_package_finder", ImportTypes.FUNCTION) -get_package_finder.set_default( - functools.partial( - compat.get_package_finder, - install_cmd_provider=InstallCommand, - target_python_builder=TargetPython.shim(), - ) -) - - -make_preparer = ShimmedPathCollection("make_preparer", ImportTypes.FUNCTION) -make_preparer.set_default( - functools.partial( - compat.make_preparer, - install_cmd_provider=InstallCommand, - preparer_fn=RequirementPreparer, - downloader_provider=Downloader, - build_tracker_fn=get_build_tracker, - req_tracker_fn=get_requirement_tracker, - finder_provider=get_package_finder, - ) -) - - -get_resolver = ShimmedPathCollection("get_resolver", ImportTypes.FUNCTION) -get_resolver.set_default( - functools.partial( - compat.get_resolver, - install_cmd_provider=InstallCommand, - resolver_fn=Resolver, - install_req_provider=install_req_from_req_string, - wheel_cache_provider=wheel_cache, - format_control_provider=FormatControl, - ) -) - - -get_requirement_set = ShimmedPathCollection("get_requirement_set", ImportTypes.FUNCTION) -get_requirement_set.set_default( - functools.partial( - compat.get_requirement_set, - install_cmd_provider=InstallCommand, - req_set_provider=RequirementSet, - wheel_cache_provider=wheel_cache, - ) -) - - -resolve = ShimmedPathCollection("resolve", ImportTypes.FUNCTION) -resolve.set_default( - functools.partial( - compat.resolve, - install_cmd_provider=InstallCommand, - reqset_provider=get_requirement_set, - finder_provider=get_package_finder, - resolver_provider=get_resolver, - wheel_cache_provider=wheel_cache, - format_control_provider=FormatControl, - make_preparer_provider=make_preparer, - req_tracker_provider=get_requirement_tracker, - tempdir_manager_provider=global_tempdir_manager, - ) -) - - -build_wheel = ShimmedPathCollection("build_wheel", ImportTypes.FUNCTION) -build_wheel.set_default( - functools.partial( - compat.build_wheel, - install_command_provider=InstallCommand, - wheel_cache_provider=wheel_cache, - wheel_builder_provider=WheelBuilder, - build_one_provider=build_one, - build_one_inside_env_provider=build_one_inside_env, - build_many_provider=build, - preparer_provider=make_preparer, - format_control_provider=FormatControl, - reqset_provider=get_requirement_set, - ) -) diff --git a/pipenv/vendor/pip_shims/shims.py b/pipenv/vendor/pip_shims/shims.py deleted file mode 100644 index e655b01766..0000000000 --- a/pipenv/vendor/pip_shims/shims.py +++ /dev/null @@ -1,75 +0,0 @@ -# -*- coding=utf-8 -*- -""" -Main module with magic self-replacement mechanisms to handle import speedups. -""" -from __future__ import absolute_import - -import sys -import types - -from pipenv.patched.pip._vendor.packaging.version import parse as parse_version - -from .models import ( - ShimmedPathCollection, - get_package_finder, - import_pip, - lookup_current_pip_version, -) - - -class _shims(types.ModuleType): - CURRENT_PIP_VERSION = str(lookup_current_pip_version()) - - @classmethod - def parse_version(cls, version): - return parse_version(version) - - def __dir__(self): - result = list(self._locations.keys()) + list(self.__dict__.keys()) - result.extend( - ( - "__file__", - "__doc__", - "__all__", - "__docformat__", - "__name__", - "__path__", - "__package__", - "__version__", - ) - ) - return result - - @classmethod - def _new(cls): - return cls() - - @property - def __all__(self): - return list(self._locations.keys()) - - def __init__(self): - self.pip = import_pip() - self._locations = ShimmedPathCollection.get_registry() - self._locations["get_package_finder"] = get_package_finder - self.pip_version = str(lookup_current_pip_version()) - self.parsed_pip_version = lookup_current_pip_version() - - def __getattr__(self, *args, **kwargs): - locations = super(_shims, self).__getattribute__("_locations") - if args[0] in locations: - return locations[args[0]].shim() - return super(_shims, self).__getattribute__(*args, **kwargs) - - -old_module = sys.modules[__name__] if __name__ in sys.modules else None -module = sys.modules[__name__] = _shims() -module.__dict__.update( - { - "__file__": __file__, - "__package__": __package__, - "__doc__": __doc__, - "__all__": module.__all__, - "__name__": __name__, - } -) diff --git a/pipenv/vendor/pip_shims/utils.py b/pipenv/vendor/pip_shims/utils.py deleted file mode 100644 index 893ed63ac2..0000000000 --- a/pipenv/vendor/pip_shims/utils.py +++ /dev/null @@ -1,453 +0,0 @@ -# -*- coding=utf-8 -*- -""" -Shared utility functions which are not specific to any particular module. -""" -from __future__ import absolute_import - -import contextlib -import copy -import inspect -import sys -from collections.abc import Callable -from functools import wraps - -from pipenv.patched.pip._vendor.packaging.version import _BaseVersion, parse - -from .environment import MYPY_RUNNING - -if MYPY_RUNNING: - from types import ModuleType - from typing import ( - Any, - Dict, - Iterator, - List, - Optional, - Sequence, - Tuple, - Type, - TypeVar, - Union, - ) - - TShimmedPath = TypeVar("TShimmedPath") - TShimmedPathCollection = TypeVar("TShimmedPathCollection") - TShim = Union[TShimmedPath, TShimmedPathCollection] - TShimmedFunc = Union[TShimmedPath, TShimmedPathCollection, Callable, Type] - - -STRING_TYPES = (str,) -if sys.version_info < (3, 0): - STRING_TYPES = STRING_TYPES + (unicode,) # noqa:F821 - - -class BaseMethod(Callable): - def __init__(self, func_base, name, *args, **kwargs): - # type: (Callable, str, Any, Any) -> None - self.func = func_base - self.__name__ = self.__qualname__ = name - - def __call__(self, *args, **kwargs): - # type: (Any, Any) -> Any - return self.func(*args, **kwargs) - - -class BaseClassMethod(Callable): - def __init__(self, func_base, name, *args, **kwargs): - # type: (Callable, str, Any, Any) -> None - self.func = func_base - self.__name__ = self.__qualname__ = name - - def __call__(self, cls, *args, **kwargs): - # type: (Type, Any, Any) -> Any - return self.func(*args, **kwargs) - - -def make_method(fn): - # type: (Callable) -> Callable - @wraps(fn) - def method_creator(*args, **kwargs): - # type: (Any, Any) -> Callable - return BaseMethod(fn, *args, **kwargs) - - return method_creator - - -def make_classmethod(fn): - # type: (Callable) -> Callable - @wraps(fn) - def classmethod_creator(*args, **kwargs): - # type: (Any, Any) -> Callable - return classmethod(BaseClassMethod(fn, *args, **kwargs)) - - return classmethod_creator - - -def memoize(obj): - # type: (Any) -> Callable - cache = obj.cache = {} - - @wraps(obj) - def memoizer(*args, **kwargs): - key = str(args) + str(kwargs) - if key not in cache: - cache[key] = obj(*args, **kwargs) - return cache[key] - - return memoizer - - -@memoize -def _parse(version): - # type: (str) -> Tuple[int, ...] - if isinstance(version, STRING_TYPES): - return tuple(int(i) for i in version.split(".")) - return version - - -@memoize -def parse_version(version): - # type: (str) -> _BaseVersion - if not isinstance(version, STRING_TYPES): - raise TypeError("Can only derive versions from string, got {!r}".format(version)) - return parse(version) - - -@memoize -def split_package(module, subimport=None): - # type: (str, Optional[str]) -> Tuple[str, str] - """ - Used to determine what target to import. - - Either splits off the final segment or uses the provided sub-import to return a - 2-tuple of the import path and the target module or sub-path. - - :param str module: A package to import from - :param Optional[str] subimport: A class, function, or subpackage to import - :return: A 2-tuple of the corresponding import package and sub-import path - :rtype: Tuple[str, str] - - :Example: - - >>> from pip_shims.utils import split_package - >>> split_package("pipenv.patched.pip._internal.req.req_install", subimport="InstallRequirement") - ("pipenv.patched.pip._internal.req.req_install", "InstallRequirement") - >>> split_package("pipenv.patched.pip._internal.cli.base_command") - ("pipenv.patched.pip._internal.cli", "base_command") - """ - package = None - if subimport: - package = subimport - else: - module, _, package = module.rpartition(".") - return module, package - - -def get_method_args(target_method): - # type: (Callable) -> Tuple[Callable, Optional[inspect.Arguments]] - """ - Returns the arguments for a callable. - - :param Callable target_method: A callable to retrieve arguments for - :return: A 2-tuple of the original callable and its resulting arguments - :rtype: Tuple[Callable, Optional[inspect.Arguments]] - """ - inspected_args = None - try: - inspected_args = inspect.getargs(target_method.__code__) - except AttributeError: - target_func = getattr(target_method, "__func__", None) - if target_func is not None: - inspected_args = inspect.getargs(target_func.__code__) - else: - target_func = target_method - return target_func, inspected_args - - -def set_default_kwargs(basecls, method, *args, **default_kwargs): - # type: (Union[Type, ModuleType], Callable, Any, Any) -> Union[Type, ModuleType] # noqa - target_method = getattr(basecls, method, None) - if target_method is None: - return basecls - target_func, inspected_args = get_method_args(target_method) - if inspected_args is not None: - pos_args = inspected_args.args - else: - pos_args = [] - # Spit back the base class if we can't find matching arguments - # to put defaults in place of - if not any(arg in pos_args for arg in list(default_kwargs.keys())): - return basecls - prepended_defaults = tuple() # type: Tuple[Any, ...] - # iterate from the function's argument order to make sure we fill this - # out in the correct order - for arg in args: - prepended_defaults += (arg,) - for arg in pos_args: - if arg in default_kwargs: - prepended_defaults = prepended_defaults + (default_kwargs[arg],) - if not prepended_defaults: - return basecls - new_defaults = prepended_defaults + target_method.__defaults__ - target_method.__defaults__ = new_defaults - setattr(basecls, method, target_method) - return basecls - - -def ensure_function(parent, funcname, func): - # type: (Union[ModuleType, Type, Callable, Any], str, Callable) -> Callable - """Given a module, a function name, and a function object, attaches the given - function to the module and ensures it is named properly according to the provided - argument - - :param Any parent: The parent to attack the function to - :param str funcname: The name to give the function - :param Callable func: The function to rename and attach to **parent** - :returns: The function with its name, qualname, etc set to mirror **parent** - :rtype: Callable - """ - qualname = funcname - if parent is None: - parent = __module__ # type: ignore # noqa:F821 - parent_is_module = inspect.ismodule(parent) - parent_is_class = inspect.isclass(parent) - module = None - if parent_is_module: - module = parent.__name__ - elif parent_is_class: - qualname = "{}.{}".format(parent.__name__, qualname) - module = getattr(parent, "__module__", None) - else: - module = getattr(parent, "__module__", None) - try: - func.__name__ = funcname - except AttributeError: - if getattr(func, "__func__", None) is not None: - func = func.__func__ - func.__name__ = funcname - func.__qualname__ = qualname - - func.__module__ = module - return func - - -def add_mixin_to_class(basecls, mixins): - # type: (Type, List[Type]) -> Type - """ - Given a class, adds the provided mixin classes as base classes and gives a new class - - :param Type basecls: An initial class to generate a new class from - :param List[Type] mixins: A list of mixins to add as base classes - :return: A new class with the provided mixins as base classes - :rtype: Type[basecls, *mixins] - """ - if not any(mixins): - return basecls - base_dict = basecls.__dict__.copy() - class_tuple = (basecls,) # type: Tuple[Type, ...] - for mixin in mixins: - if not mixin: - continue - mixin_dict = mixin.__dict__.copy() - base_dict.update(mixin_dict) - class_tuple = class_tuple + (mixin,) - base_dict.update(basecls.__dict__) - return type(basecls.__name__, class_tuple, base_dict) - - -def fallback_is_file_url(link): - # type: (Any) -> bool - return link.url.lower().startswith("file:") - - -def fallback_is_artifact(self): - # type: (Any) -> bool - return not getattr(self, "is_vcs", False) - - -def fallback_is_vcs(self): - # type: (Any) -> bool - return not getattr(self, "is_artifact", True) - - -def resolve_possible_shim(target): - # type: (TShimmedFunc) -> Optional[Union[Type, Callable]] - if target is None: - return target - if getattr(target, "shim", None): - return target.shim() - return target - - -@contextlib.contextmanager -def nullcontext(*args, **kwargs): - # type: (Any, Any) -> Iterator - try: - yield - finally: - pass - - -def has_property(target, name): - # type: (Any, str) -> bool - if getattr(target, name, None) is not None: - return True - return False - - -def apply_alias(imported, target, *aliases): - # type: (Union[ModuleType, Type, None], Any, Any) -> Any - """ - Given a target with attributes, point non-existant aliases at the first existing one - - :param Union[ModuleType, Type] imported: A Module or Class base - :param Any target: The target which is a member of **imported** and will have aliases - :param str aliases: A list of aliases, the first found attribute will be the basis - for all non-existant names which will be created as pointers - :return: The original target - :rtype: Any - """ - base_value = None # type: Optional[Any] - applied_aliases = set() - unapplied_aliases = set() - for alias in aliases: - if has_property(target, alias): - base_value = getattr(target, alias) - applied_aliases.add(alias) - else: - unapplied_aliases.add(alias) - is_callable = inspect.ismethod(base_value) or inspect.isfunction(base_value) - for alias in unapplied_aliases: - if is_callable: - func_copy = copy.deepcopy(base_value) - alias_value = ensure_function(imported, alias, func_copy) - else: - alias_value = base_value - setattr(target, alias, alias_value) - return target - - -def suppress_setattr(obj, attr, value, filter_none=False): - """ - Set an attribute, suppressing any exceptions and skipping the attempt on failure. - - :param Any obj: Object to set the attribute on - :param str attr: The attribute name to set - :param Any value: The value to set the attribute to - :param bool filter_none: [description], defaults to False - :return: Nothing - :rtype: None - - :Example: - - >>> class MyClass(object): - ... def __init__(self, name): - ... self.name = name - ... self.parent = None - ... def __repr__(self): - ... return "<{0!r} instance (name={1!r}, parent={2!r})>".format( - ... self.__class__.__name__, self.name, self.parent - ... ) - ... def __str__(self): - ... return self.name - >>> me = MyClass("Dan") - >>> dad = MyClass("John") - >>> grandfather = MyClass("Joe") - >>> suppress_setattr(dad, "parent", grandfather) - >>> dad - <'MyClass' instance (name='John', parent=<'MyClass' instance (name='Joe', parent=None - )>)> - >>> suppress_setattr(me, "parent", dad) - >>> me - <'MyClass' instance (name='Dan', parent=<'MyClass' instance (name='John', parent=<'My - Class' instance (name='Joe', parent=None)>)>)> - >>> suppress_setattr(me, "grandparent", grandfather) - >>> me - <'MyClass' instance (name='Dan', parent=<'MyClass' instance (name='John', parent=<'My - Class' instance (name='Joe', parent=None)>)>)> - """ - if filter_none and value is None: - pass - try: - setattr(obj, attr, value) - except Exception: # noqa - pass - - -def get_allowed_args(fn_or_class): - # type: (Union[Callable, Type]) -> Tuple[List[str], Dict[str, Any]] - """ - Given a callable or a class, returns the arguments and default kwargs passed in. - - :param Union[Callable, Type] fn_or_class: A function, method or class to inspect. - :return: A 2-tuple with a list of arguments and a dictionary of keywords mapped to - default values. - :rtype: Tuple[List[str], Dict[str, Any]] - """ - try: - signature = inspect.signature(fn_or_class) - except AttributeError: - import funcsigs - - signature = funcsigs.signature(fn_or_class) - args = [] - kwargs = {} - for arg, param in signature.parameters.items(): - if ( - param.kind in (param.POSITIONAL_OR_KEYWORD, param.POSITIONAL_ONLY) - ) and param.default is param.empty: - args.append(arg) - else: - kwargs[arg] = param.default if param.default is not param.empty else None - return args, kwargs - - -def call_function_with_correct_args(fn, **provided_kwargs): - # type: (Callable, Dict[str, Any]) -> Any - """ - Determines which arguments from **provided_kwargs** to call **fn** and calls it. - - Consumes a list of allowed arguments (e.g. from :func:`~inspect.getargs()`) and - uses it to determine which of the arguments in the provided kwargs should be passed - through to the given callable. - - :param Callable fn: A callable which has some dynamic arguments - :param List[str] allowed_args: A list of allowed arguments which can be passed to - the supplied function - :return: The result of calling the function - :rtype: Any - """ - # signature = inspect.signature(fn) - args = [] - kwargs = {} - func_args, func_kwargs = get_allowed_args(fn) - for arg in func_args: - args.append(provided_kwargs[arg]) - for arg in func_kwargs: - if not provided_kwargs.get(arg): - continue - kwargs[arg] = provided_kwargs[arg] - return fn(*args, **kwargs) - - -def filter_allowed_args(fn, **provided_kwargs): - # type: (Callable, Dict[str, Any]) -> Tuple[List[Any], Dict[str, Any]] - """ - Given a function and a kwarg mapping, return only those kwargs used in the function. - - :param Callable fn: A function to inspect - :param Dict[str, Any] kwargs: A mapping of kwargs to filter - :return: A new, filtered kwarg mapping - :rtype: Tuple[List[Any], Dict[str, Any]] - """ - args = [] - kwargs = {} - func_args, func_kwargs = get_allowed_args(fn) - for arg in func_args: - if arg in provided_kwargs: - args.append(provided_kwargs[arg]) - for arg in func_kwargs: - if arg not in provided_kwargs: - continue - kwargs[arg] = provided_kwargs[arg] - return args, kwargs diff --git a/pipenv/vendor/requirementslib/__init__.py b/pipenv/vendor/requirementslib/__init__.py index 8ac49359cf..dc222118b6 100644 --- a/pipenv/vendor/requirementslib/__init__.py +++ b/pipenv/vendor/requirementslib/__init__.py @@ -10,7 +10,7 @@ from .models.pipfile import Pipfile from .models.requirements import Requirement -__version__ = "1.6.9" +__version__ = "1.6.10.dev0" logger = logging.getLogger(__name__) diff --git a/pipenv/vendor/requirementslib/models/cache.py b/pipenv/vendor/requirementslib/models/cache.py index b1476be0b6..8a5b9d46c1 100644 --- a/pipenv/vendor/requirementslib/models/cache.py +++ b/pipenv/vendor/requirementslib/models/cache.py @@ -1,6 +1,3 @@ -# -*- coding=utf-8 -*- -from __future__ import absolute_import, print_function, unicode_literals - import atexit import copy import hashlib @@ -11,7 +8,9 @@ import pipenv.vendor.vistir as vistir from pipenv.patched.pip._vendor.packaging.requirements import Requirement -from pipenv.vendor.pip_shims.shims import FAVORITE_HASH, SafeFileCache +from pipenv.patched.pip._internal.network.cache import SafeFileCache +from pipenv.patched.pip._internal.utils.hashes import FAVORITE_HASH +from pipenv.patched.pip._internal.vcs.versioncontrol import VcsSupport from pipenv.vendor.platformdirs import user_cache_dir from .utils import as_tuple, get_pinned_version, key_from_req, lookup_table @@ -205,8 +204,6 @@ def __init__(self, *args, **kwargs): super(HashCache, self).__init__(*args, **kwargs) def get_hash(self, location): - from pipenv.vendor.pip_shims import VcsSupport - # if there is no location hash (i.e., md5 / sha256 / etc) we on't want to store it hash_value = None vcs = VcsSupport() diff --git a/pipenv/vendor/requirementslib/models/dependencies.py b/pipenv/vendor/requirementslib/models/dependencies.py index bfc7e9610a..b8d95d64a0 100644 --- a/pipenv/vendor/requirementslib/models/dependencies.py +++ b/pipenv/vendor/requirementslib/models/dependencies.py @@ -13,13 +13,24 @@ from pipenv.patched.pip._vendor.packaging.markers import Marker from pipenv.patched.pip._vendor.packaging.utils import canonicalize_name from pipenv.patched.pip._vendor.packaging.version import parse -from pipenv.vendor.pip_shims import shims +from pipenv.patched.pip._internal.cache import WheelCache +from pipenv.patched.pip._internal.models.format_control import FormatControl +from pipenv.patched.pip._internal.operations.build.build_tracker import get_build_tracker +from pipenv.patched.pip._internal.req.constructors import install_req_from_line +from pipenv.patched.pip._internal.req.req_install import InstallRequirement +from pipenv.patched.pip._internal.req.req_set import RequirementSet +from pipenv.patched.pip._internal.utils.temp_dir import TempDirectory, global_tempdir_manager from pipenv.vendor.vistir.compat import fs_str -from pipenv.vendor.vistir.contextmanagers import cd, temp_environ +from pipenv.vendor.vistir.contextmanagers import temp_environ from pipenv.vendor.vistir.path import create_tracked_tempdir from ..environment import MYPY_RUNNING -from ..utils import _ensure_dir, prepare_pip_source_args +from ..utils import ( + _ensure_dir, + get_package_finder, + get_pip_command, + prepare_pip_source_args, +) from .cache import CACHE_DIR, DependencyCache from .setup_info import SetupInfo from .utils import ( @@ -49,7 +60,9 @@ ) from pipenv.patched.pip._vendor.packaging.requirements import Requirement as PackagingRequirement - from shims import Command, InstallationCandidate, InstallRequirement, PackageFinder + from pipenv.patched.pip._internal.commands.base_command import Command + from pipenv.patched.pip._internal.index.package_finder import PackageFinder + from pipenv.patched.pip._internal.models.candidate import InstallationCandidate TRequirement = TypeVar("TRequirement") RequirementType = TypeVar( @@ -68,8 +81,8 @@ @contextlib.contextmanager def _get_wheel_cache(): - with shims.global_tempdir_manager(): - yield shims.WheelCache(CACHE_DIR, shims.FormatControl(set(), set())) + with global_tempdir_manager(): + yield WheelCache(CACHE_DIR, FormatControl(set(), set())) def _get_filtered_versions(ireq, versions, prereleases): @@ -98,15 +111,6 @@ def find_all_matches(finder, ireq, pre=False): return candidates -def get_pip_command(): - # type: () -> Command - # Use pip's parser for pip.conf management and defaults. - # General options (find_links, index_url, extra_index_url, trusted_host, - # and pre) are deferred to pip. - pip_command = shims.InstallCommand() - return pip_command - - @attr.s class AbstractDependency(object): name = attr.ib() # type: STRING_TYPE @@ -214,7 +218,7 @@ def get_deps(self, candidate): req = Requirement.from_line(key) req = req.merge_markers(self.markers) - self.dep_dict[key] = req.get_abstract_dependencies() + self.dep_dict[key] = req.abstract_dependencies() return self.dep_dict[key] @classmethod @@ -274,26 +278,23 @@ def from_string(cls, line, parent=None): return abstract_dep -def get_abstract_dependencies(reqs, sources=None, parent=None): +def get_abstract_dependencies(reqs, parent=None): """Get all abstract dependencies for a given list of requirements. Given a set of requirements, convert each requirement to an Abstract Dependency. :param reqs: A list of Requirements :type reqs: list[:class:`~requirementslib.models.requirements.Requirement`] - :param sources: Pipfile-formatted sources, defaults to None - :param sources: list[dict], optional :param parent: The parent of this list of dependencies, defaults to None :param parent: :class:`~requirementslib.models.requirements.Requirement`, optional :return: A list of Abstract Dependencies :rtype: list[:class:`~requirementslib.models.dependency.AbstractDependency`] """ - deps = [] from .requirements import Requirement for req in reqs: - if isinstance(req, shims.InstallRequirement): + if isinstance(req, InstallRequirement): requirement = Requirement.from_line("{0}{1}".format(req.name, req.specifier)) if req.link: requirement.req.link = req.link @@ -323,19 +324,18 @@ def get_dependencies(ireq, sources=None, parent=None): :return: A set of dependency lines for generating new InstallRequirements. :rtype: set(str) """ - if not isinstance(ireq, shims.InstallRequirement): + if not isinstance(ireq, InstallRequirement): name = getattr(ireq, "project_name", getattr(ireq, "project", ireq.name)) version = getattr(ireq, "version", None) if not version: - ireq = shims.InstallRequirement.from_line("{0}".format(name)) + ireq = install_req_from_line("{0}".format(name)) else: - ireq = shims.InstallRequirement.from_line("{0}=={1}".format(name, version)) - pip_options = get_pip_options(sources=sources) + ireq = install_req_from_line("{0}=={1}".format(name, version)) getters = [ get_dependencies_from_cache, get_dependencies_from_wheel_cache, get_dependencies_from_json, - functools.partial(get_dependencies_from_index, pip_options=pip_options), + functools.partial(get_dependencies_from_index, sources=sources), ] for getter in getters: deps = getter(ireq) @@ -345,7 +345,7 @@ def get_dependencies(ireq, sources=None, parent=None): def get_dependencies_from_wheel_cache(ireq): - # type: (shims.InstallRequirement) -> Optional[Set[shims.InstallRequirement]] + # type: (InstallRequirement) -> Optional[Set[InstallRequirement]] """Retrieves dependencies for the given install requirement from the wheel cache. @@ -358,7 +358,7 @@ def get_dependencies_from_wheel_cache(ireq): if ireq.editable or not is_pinned_requirement(ireq): return with _get_wheel_cache() as wheel_cache: - matches = wheel_cache.get(ireq.link, name_from_req(ireq.req)) + matches = wheel_cache.get(ireq.link, name_from_req(ireq.req), ireq.markers) if matches: matches = set(matches) if not DEPENDENCY_CACHE.get(ireq): @@ -406,7 +406,7 @@ def gen(ireq): if not requires_dist: # The API can return None for this. return for requires in requires_dist: - i = shims.InstallRequirement.from_line(requires) + i = install_req_from_line(requires) # See above, we don't handle requirements with extras. if not _marker_contains_extra(i): yield format_requirement(i) @@ -442,7 +442,7 @@ def get_dependencies_from_cache(ireq): try: broken = False for line in cached: - dep_ireq = shims.InstallRequirement.from_line(line) + dep_ireq = install_req_from_line(line) name = canonicalize_name(dep_ireq.name) if _marker_contains_extra(dep_ireq): broken = True # The "extra =" marker breaks everything. @@ -464,6 +464,68 @@ def is_python(section): return section.startswith("[") and ":" in section +def get_resolver( + finder, build_tracker, pip_options, session, directory, install_command=None +): + wheel_cache = WheelCache(pip_options.cache_dir, pip_options.format_control) + if install_command is None: + install_command = get_pip_command() + preparer = install_command.make_requirement_preparer( + temp_build_dir=directory, + options=pip_options, + build_tracker=build_tracker, + session=session, + finder=finder, + use_user_site=False, + ) + resolver = install_command.make_resolver( + preparer=preparer, + finder=finder, + options=pip_options, + wheel_cache=wheel_cache, + use_user_site=False, + ignore_installed=True, + ignore_requires_python=pip_options.ignore_requires_python, + force_reinstall=pip_options.force_reinstall, + upgrade_strategy="to-satisfy-only", + use_pep517=pip_options.use_pep517, + ) + return resolver + + +def resolve(ireq, sources, install_command, pip_options): + with global_tempdir_manager(), get_build_tracker() as build_tracker, TempDirectory() as directory: + session, finder = get_finder( + sources=sources, pip_command=install_command, pip_options=pip_options + ) + resolver = get_resolver( + finder=finder, + build_tracker=build_tracker, + pip_options=pip_options, + session=session, + directory=directory, + install_command=install_command, + ) + reqset = RequirementSet(install_command) + reqset.add_named_requirement(ireq) + resolver_args = [] + resolver_args.append([ireq]) + resolver_args.append(True) # check_supported_wheels + if getattr(reqset, "prepare_files", None): + reqset.prepare_files(finder) + result = reqset.requirements + reqset.cleanup_files() + return result + result_reqset = resolver.resolve(*resolver_args) + 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 + + def get_dependencies_from_index(dep, sources=None, pip_options=None, wheel_cache=None): """Retrieves dependencies for the given install requirement from the pip resolver. @@ -475,14 +537,12 @@ def get_dependencies_from_index(dep, sources=None, pip_options=None, wheel_cache :return: A set of dependency lines for generating new InstallRequirements. :rtype: set(str) or None """ - - session, finder = get_finder(sources=sources, pip_options=pip_options) + install_command = get_pip_command() + if pip_options is None: + pip_options = get_pip_options(sources=sources, pip_command=install_command) dep.is_direct = True - requirements = None setup_requires = {} - with temp_environ(), ExitStack() as stack: - if not wheel_cache: - wheel_cache = stack.enter_context(_get_wheel_cache()) + with temp_environ(): os.environ["PIP_EXISTS_ACTION"] = "i" if dep.editable and not dep.prepared and not dep.req: setup_info = SetupInfo.from_ireq(dep) @@ -490,7 +550,12 @@ def get_dependencies_from_index(dep, sources=None, pip_options=None, wheel_cache setup_requires.update(results["setup_requires"]) requirements = set(results["requires"].values()) else: - results = shims.resolve(dep) + results = resolve( + dep, + sources=sources, + install_command=install_command, + pip_options=pip_options, + ) requirements = [v for v in results.values() if v.name != dep.name] requirements = set([format_requirement(r) for r in requirements]) if not dep.editable and is_pinned_requirement(dep) and requirements is not None: @@ -537,16 +602,14 @@ def get_finder(sources=None, pip_command=None, pip_options=None): """ if not pip_command: - pip_command = shims.InstallCommand() + pip_command = get_pip_command() if not sources: sources = [{"url": "https://pypi.org/simple", "name": "pypi", "verify_ssl": True}] if not pip_options: pip_options = get_pip_options(sources=sources, pip_command=pip_command) session = pip_command._build_session(pip_options) atexit.register(session.close) - finder = shims.get_package_finder( - shims.InstallCommand(), options=pip_options, session=session - ) + finder = get_package_finder(get_pip_command(), options=pip_options, session=session) return session, finder @@ -576,40 +639,31 @@ def start_resolver(finder=None, session=None, wheel_cache=None): _build_dir = create_tracked_tempdir(fs_str("build")) _source_dir = create_tracked_tempdir(fs_str("source")) + pip_options.src_dir = _source_dir try: - with ExitStack() as ctx: - ctx.enter_context(shims.global_tempdir_manager()) + with global_tempdir_manager(), get_build_tracker() as build_tracker: if not wheel_cache: - wheel_cache = ctx.enter_context(_get_wheel_cache()) - _ensure_dir(fs_str(os.path.join(wheel_cache.cache_dir, "wheels"))) - preparer = ctx.enter_context( - shims.make_preparer( - options=pip_options, - finder=finder, - session=session, - build_dir=_build_dir, - src_dir=_source_dir, - download_dir=download_dir, - wheel_download_dir=WHEEL_DOWNLOAD_DIR, - progress_bar="off", - build_isolation=False, - install_cmd=pip_command, - ) - ) - resolver = shims.get_resolver( + wheel_cache = _get_wheel_cache() + _ensure_dir(str(os.path.join(wheel_cache.cache_dir, "wheels"))) + preparer = pip_command.make_requirement_preparer( + temp_build_dir=_build_dir, + options=pip_options, + build_tracker=build_tracker, + session=session, finder=finder, - ignore_dependencies=False, - ignore_requires_python=True, + use_user_site=False, + ) + resolver = pip_command.make_resolver( preparer=preparer, - session=session, + finder=finder, options=pip_options, - install_cmd=pip_command, wheel_cache=wheel_cache, - force_reinstall=True, + use_user_site=False, ignore_installed=True, + ignore_requires_python=pip_options.ignore_requires_python, + force_reinstall=pip_options.force_reinstall, upgrade_strategy="to-satisfy-only", - isolated=False, - use_user_site=False, + use_pep517=pip_options.use_pep517, ) yield resolver finally: diff --git a/pipenv/vendor/requirementslib/models/old_pip_utils.py b/pipenv/vendor/requirementslib/models/old_pip_utils.py index 4cf2d5daf8..a773b1b759 100644 --- a/pipenv/vendor/requirementslib/models/old_pip_utils.py +++ b/pipenv/vendor/requirementslib/models/old_pip_utils.py @@ -16,148 +16,149 @@ logger = logging.getLogger(__name__) -try: # Required for pip>=22.1 - from typing import Dict, Iterable, List, Optional - - from pipenv.patched.pip._internal.models.link import Link - from pipenv.patched.pip._internal.network.download import Downloader - from pipenv.patched.pip._internal.operations.prepare import ( - File, - get_file_url, - get_http_url, - unpack_vcs_link, - ) - from pipenv.patched.pip._internal.utils.hashes import Hashes - from pipenv.patched.pip._internal.utils.unpacking import unpack_file - - def is_socket(path): - # type: (str) -> bool - return stat.S_ISSOCK(os.lstat(path).st_mode) - - def copy2_fixed(src, dest): - # type: (str, str) -> None - """Wrap shutil.copy2() but map errors copying socket files to - SpecialFileError as expected. - - See also https://bugs.python.org/issue37700. - """ - try: - shutil.copy2(src, dest) - except OSError: - for f in [src, dest]: - try: - is_socket_file = is_socket(f) - except OSError: - # An error has already occurred. Another error here is not - # a problem and we can ignore it. - pass - else: - if is_socket_file: - raise shutil.SpecialFileError( - "`{f}` is a socket".format(**locals()) - ) - - raise - - def _copy2_ignoring_special_files(src: str, dest: str) -> None: - """Copying special files is not supported, but as a convenience to - users we skip errors copying them. - - This supports tools that may create e.g. socket files in the - project source directory. - """ - try: - copy2_fixed(src, dest) - except shutil.SpecialFileError as e: - # SpecialFileError may be raised due to either the source or - # destination. If the destination was the cause then we would actually - # care, but since the destination directory is deleted prior to - # copy we ignore all of them assuming it is caused by the source. - logger.warning( - "Ignoring special file error '%s' encountered copying %s to %s.", - str(e), - src, - dest, - ) - - def _copy_source_tree(source: str, target: str) -> None: - target_abspath = os.path.abspath(target) - target_basename = os.path.basename(target_abspath) - target_dirname = os.path.dirname(target_abspath) - - def ignore(d: str, names: List[str]) -> List[str]: - skipped: List[str] = [] - if d == source: - # Pulling in those directories can potentially be very slow, - # exclude the following directories if they appear in the top - # level dir (and only it). - # See discussion at https://github.com/pypa/pip/pull/6770 - skipped += [".tox", ".nox"] - if os.path.abspath(d) == target_dirname: - # Prevent an infinite recursion if the target is in source. - # This can happen when TMPDIR is set to ${PWD}/... - # and we copy PWD to TMPDIR. - skipped += [target_basename] - return skipped - - shutil.copytree( - source, - target, - ignore=ignore, - symlinks=True, - copy_function=_copy2_ignoring_special_files, +from typing import Dict, Iterable, List, Optional + +from pipenv.patched.pip._internal.models.link import Link +from pipenv.patched.pip._internal.network.download import Downloader +from pipenv.patched.pip._internal.operations.prepare import ( + File, + get_file_url, + get_http_url, + unpack_vcs_link, +) +from pipenv.patched.pip._internal.utils.hashes import Hashes +from pipenv.patched.pip._internal.utils.unpacking import unpack_file + + +def is_socket(path): + # type: (str) -> bool + return stat.S_ISSOCK(os.lstat(path).st_mode) + + +def copy2_fixed(src, dest): + # type: (str, str) -> None + """Wrap shutil.copy2() but map errors copying socket files to + SpecialFileError as expected. + + See also https://bugs.python.org/issue37700. + """ + try: + shutil.copy2(src, dest) + except OSError: + for f in [src, dest]: + try: + is_socket_file = is_socket(f) + except OSError: + # An error has already occurred. Another error here is not + # a problem and we can ignore it. + pass + else: + if is_socket_file: + raise shutil.SpecialFileError( + "`{f}` is a socket".format(**locals()) + ) + + raise + + +def _copy2_ignoring_special_files(src: str, dest: str) -> None: + """Copying special files is not supported, but as a convenience to + users we skip errors copying them. + + This supports tools that may create e.g. socket files in the + project source directory. + """ + try: + copy2_fixed(src, dest) + except shutil.SpecialFileError as e: + # SpecialFileError may be raised due to either the source or + # destination. If the destination was the cause then we would actually + # care, but since the destination directory is deleted prior to + # copy we ignore all of them assuming it is caused by the source. + logger.warning( + "Ignoring special file error '%s' encountered copying %s to %s.", + str(e), + src, + dest, ) - def old_unpack_url( - link: Link, - location: str, - download: Downloader, - verbosity: int, - download_dir: Optional[str] = None, - hashes: Optional[Hashes] = None, - ) -> Optional[File]: - """Unpack link into location, downloading if required. - - :param hashes: A Hashes object, one of whose embedded hashes must match, - or HashMismatch will be raised. If the Hashes is empty, no matches are - required, and unhashable types of requirements (like VCS ones, which - would ordinarily raise HashUnsupported) are allowed. - """ - # non-editable vcs urls - if link.is_vcs: - unpack_vcs_link(link, location, verbosity=verbosity) - return None - - # Once out-of-tree-builds are no longer supported, could potentially - # replace the below condition with `assert not link.is_existing_dir` - # - unpack_url does not need to be called for in-tree-builds. - # - # As further cleanup, _copy_source_tree and accompanying tests can - # be removed. - # - # TODO when use-deprecated=out-of-tree-build is removed - if link.is_existing_dir(): - if os.path.isdir(location): - rmtree(location) - _copy_source_tree(link.file_path, location) - return None - - # file urls - if link.is_file: - file = get_file_url(link, download_dir, hashes=hashes) - # http urls - else: - file = get_http_url( - link, - download, - download_dir, - hashes=hashes, - ) - # unpack the archive to the build dir location. even when only downloading - # archives, they have to be unpacked to parse dependencies, except wheels - if not link.is_wheel: - unpack_file(file.path, location, file.content_type) - return file - -except ImportError: - raise + +def _copy_source_tree(source: str, target: str) -> None: + target_abspath = os.path.abspath(target) + target_basename = os.path.basename(target_abspath) + target_dirname = os.path.dirname(target_abspath) + + def ignore(d: str, names: List[str]) -> List[str]: + skipped: List[str] = [] + if d == source: + # Pulling in those directories can potentially be very slow, + # exclude the following directories if they appear in the top + # level dir (and only it). + # See discussion at https://github.com/pypa/pip/pull/6770 + skipped += [".tox", ".nox"] + if os.path.abspath(d) == target_dirname: + # Prevent an infinite recursion if the target is in source. + # This can happen when TMPDIR is set to ${PWD}/... + # and we copy PWD to TMPDIR. + skipped += [target_basename] + return skipped + + shutil.copytree( + source, + target, + ignore=ignore, + symlinks=True, + copy_function=_copy2_ignoring_special_files, + ) + + +def old_unpack_url( + link: Link, + location: str, + download: Downloader, + verbosity: int, + download_dir: Optional[str] = None, + hashes: Optional[Hashes] = None, +) -> Optional[File]: + """Unpack link into location, downloading if required. + + :param hashes: A Hashes object, one of whose embedded hashes must match, + or HashMismatch will be raised. If the Hashes is empty, no matches are + required, and unhashable types of requirements (like VCS ones, which + would ordinarily raise HashUnsupported) are allowed. + """ + # non-editable vcs urls + if link.is_vcs: + unpack_vcs_link(link, location, verbosity=verbosity) + return None + + # Once out-of-tree-builds are no longer supported, could potentially + # replace the below condition with `assert not link.is_existing_dir` + # - unpack_url does not need to be called for in-tree-builds. + # + # As further cleanup, _copy_source_tree and accompanying tests can + # be removed. + # + # TODO when use-deprecated=out-of-tree-build is removed + if link.is_existing_dir(): + if os.path.isdir(location): + rmtree(location) + _copy_source_tree(link.file_path, location) + return None + + # file urls + if link.is_file: + file = get_file_url(link, download_dir, hashes=hashes) + # http urls + else: + file = get_http_url( + link, + download, + download_dir, + hashes=hashes, + ) + # unpack the archive to the build dir location. even when only downloading + # archives, they have to be unpacked to parse dependencies, except wheels + if not link.is_wheel: + unpack_file(file.path, location, file.content_type) + return file diff --git a/pipenv/vendor/requirementslib/models/requirements.py b/pipenv/vendor/requirementslib/models/requirements.py index 8d717f4ce1..f3fc34e450 100644 --- a/pipenv/vendor/requirementslib/models/requirements.py +++ b/pipenv/vendor/requirementslib/models/requirements.py @@ -1,7 +1,3 @@ -# -*- coding: utf-8 -*- - -from __future__ import absolute_import, print_function - import collections import copy import os @@ -14,7 +10,6 @@ from urllib.parse import unquote import pipenv.vendor.attr as attr -import pipenv.vendor.pip_shims as pip_shims from pipenv.vendor.cached_property import cached_property from pipenv.patched.pip._vendor.packaging.markers import Marker from pipenv.patched.pip._vendor.packaging.requirements import Requirement as PackagingRequirement @@ -25,6 +20,17 @@ SpecifierSet, ) from pipenv.patched.pip._vendor.packaging.utils import canonicalize_name +from pipenv.patched.pip._vendor.packaging.version import parse +from pipenv.patched.pip._internal.models.link import Link +from pipenv.patched.pip._internal.models.wheel import Wheel +from pipenv.patched.pip._internal.req.constructors import ( + _strip_extras, + install_req_from_editable, + install_req_from_line, +) +from pipenv.patched.pip._internal.req.req_install import InstallRequirement +from pipenv.patched.pip._internal.utils.temp_dir import global_tempdir_manager +from pipenv.patched.pip._internal.utils.urls import path_to_url, url_to_path from pipenv.vendor.vistir.contextmanagers import temp_path from pipenv.vendor.vistir.misc import dedup from pipenv.vendor.vistir.path import ( @@ -47,6 +53,7 @@ is_vcs, strip_ssh_from_git_uri, ) +from .dependencies import AbstractDependency, get_abstract_dependencies, get_dependencies from .markers import normalize_marker_str from .setup_info import ( SetupInfo, @@ -100,12 +107,8 @@ Union, ) - from pipenv.vendor.pip_shims.shims import ( - InstallationCandidate, - InstallRequirement, - Link, - PackageFinder, - ) + from pipenv.patched.pip._internal.index.package_finder import PackageFinder + from pipenv.patched.pip._internal.models.candidate import InstallationCandidate RequirementType = TypeVar( "RequirementType", covariant=True, bound=PackagingRequirement @@ -113,7 +116,6 @@ F = TypeVar("F", "FileRequirement", "VCSRequirement", covariant=True) from urllib.parse import SplitResult - from .dependencies import AbstractDependency from .vcs import VCSRepository NON_STRING_ITERABLE = Union[List, Set, Tuple] @@ -330,7 +332,7 @@ def line_for_ireq(self): if not line: if self.is_path or self.is_file: if not self.path and self.url is not None: - line = pip_shims.shims.url_to_path(self.url) + line = url_to_path(self.url) else: line = self.path if self.extras: @@ -572,14 +574,14 @@ def parse_extras(self): strip_ssh=self.parsed_url.is_implicit_ssh, ) except ValueError: - self.line, extras = pip_shims.shims._strip_extras(self.line) + self.line, extras = _strip_extras(self.line) else: - self.line, extras = pip_shims.shims._strip_extras(self.line) + self.line, extras = _strip_extras(self.line) extras_set = set() # type: Set[STRING_TYPE] if extras is not None: extras_set = set(parse_extras(extras)) if self._name: - self._name, name_extras = pip_shims.shims._strip_extras(self._name) + self._name, name_extras = _strip_extras(self._name) if name_extras: name_extras = set(parse_extras(name_extras)) extras_set |= name_extras @@ -660,7 +662,7 @@ def is_artifact(self): if self.link is None: return False - return not self.link.is_vcs + return getattr(self.link, "is_vcs", False) @property def is_vcs(self): @@ -767,7 +769,7 @@ def ref(self): @property def ireq(self): - # type: () -> Optional[pip_shims.InstallRequirement] + # type: () -> Optional[InstallRequirement] if self._ireq is None: self.parse_ireq() return self._ireq @@ -791,7 +793,7 @@ def wheel_kwargs(self): def get_setup_info(self): # type: () -> SetupInfo setup_info = None - with pip_shims.shims.global_tempdir_manager(): + with global_tempdir_manager(): setup_info = SetupInfo.from_ireq(self.ireq, subdir=self.subdirectory) if not setup_info.name: setup_info.get_info() @@ -897,7 +899,7 @@ def vcsrepo(self, repo): ireq = self.ireq wheel_kwargs = self.wheel_kwargs.copy() wheel_kwargs["src_dir"] = repo.checkout_directory - with pip_shims.shims.global_tempdir_manager(), temp_path(): + with global_tempdir_manager(), temp_path(): ireq.ensure_has_source_dir(wheel_kwargs["src_dir"]) sys.path = [repo.checkout_directory, "", ".", get_python_lib(plat_specific=0)] setupinfo = SetupInfo.create( @@ -913,13 +915,13 @@ def get_ireq(self): # type: () -> InstallRequirement line = self.line_for_ireq if self.editable: - ireq = pip_shims.shims.install_req_from_editable(line) + ireq = install_req_from_editable(line) else: - ireq = pip_shims.shims.install_req_from_line(line) + ireq = install_req_from_line(line) if self.is_named: - ireq = pip_shims.shims.install_req_from_line(self.line) + ireq = install_req_from_line(self.line) if self.is_file or self.is_remote_url: - ireq.link = pip_shims.shims.Link(expand_env_variables(self.link.url)) + ireq.link = Link(expand_env_variables(self.link.url)) if self.extras and not ireq.extras: ireq.extras = set(self.extras) if self.parsed_marker is not None and not ireq.markers: @@ -939,9 +941,7 @@ def parse_ireq(self): def _parse_wheel(self): # type: () -> Optional[STRING_TYPE] if not self.is_wheel: - pass - from pipenv.vendor.pip_shims.shims import Wheel - + return _wheel = Wheel(self.link.filename) name = _wheel.name version = _wheel.version @@ -1029,7 +1029,7 @@ def parse_name(self): if self.is_local: name = self._parse_name_from_path() if name is not None: - name, extras = pip_shims.shims._strip_extras(name) + name, extras = _strip_extras(name) if extras is not None and not self.extras: self.extras = tuple(sorted(set(parse_extras(extras)))) self._name = name @@ -1066,7 +1066,7 @@ def _parse_requirement_from_vcs(self): if self.ref and self._requirement is not None: self._requirement.revision = self.ref if self._vcsrepo is not None: - with pip_shims.shims.global_tempdir_manager(): + with global_tempdir_manager(): self._requirement.revision = self._vcsrepo.get_commit_hash() return self._requirement @@ -1127,7 +1127,7 @@ def parse_link(self): or (os.path.exists(self.line) or os.path.isabs(self.line)) ) ): - url = pip_shims.shims.path_to_url(os.path.abspath(self.line)) + url = path_to_url(os.path.abspath(self.line)) self._parsed_url = parsed_url = URI.parse(url) elif any( [ @@ -1524,14 +1524,12 @@ def get_link_from_line(cls, line): if parsed_url.scheme == "file" and parsed_url.path: # This is a "file://" URI. Use url_to_path and path_to_url to # ensure the path is absolute. Also we need to build relpath. - path = Path( - pip_shims.shims.url_to_path(urllib_parse.urlunsplit(parsed_url)) - ).as_posix() + path = Path(url_to_path(urllib_parse.urlunsplit(parsed_url))).as_posix() try: relpath = get_converted_relative_path(path) except ValueError: relpath = None - uri = pip_shims.shims.path_to_url(path) + uri = path_to_url(path) else: # This is a remote URI. Simply use it. path = None @@ -1615,20 +1613,20 @@ def setup_info(self): self._parsed_line._setup_info and not self._parsed_line._setup_info.name ): - with pip_shims.shims.global_tempdir_manager(): + with global_tempdir_manager(): self._parsed_line._setup_info.get_info() self._setup_info = self.parsed_line._setup_info elif self.parsed_line and ( self.parsed_line.ireq and not self.parsed_line.is_wheel ): - with pip_shims.shims.global_tempdir_manager(): + with global_tempdir_manager(): self._setup_info = SetupInfo.from_ireq( self.parsed_line.ireq, subdir=self.subdirectory ) else: if self.link and not self.link.is_wheel: self._setup_info = Line(self.line_part).setup_info - with pip_shims.shims.global_tempdir_manager(): + with global_tempdir_manager(): self._setup_info.get_info() return self._setup_info @@ -1644,7 +1642,7 @@ def get_uri(self): # type: () -> STRING_TYPE if self.path and not self.uri: self._uri_scheme = "path" - return pip_shims.shims.path_to_url(os.path.abspath(self.path)) + return path_to_url(os.path.abspath(self.path)) elif ( getattr(self, "req", None) and self.req is not None @@ -1666,8 +1664,7 @@ def get_name(self): return self.setup_info.name @link.default - def get_link(self): - # type: () -> pip_shims.shims.Link + def get_link(self) -> Link: target = "{0}".format(self.uri) if hasattr(self, "name") and not self._has_hashed_name: target = "{0}#egg={1}".format(target, self.name) @@ -1676,7 +1673,7 @@ def get_link(self): @req.default def get_requirement(self): - # type: () -> RequirementType + # type () -> RequirementType if self.name is None: if self._parsed_line is not None and self._parsed_line.name is not None: self.name = self._parsed_line.name @@ -1709,7 +1706,7 @@ def is_local(self): uri = getattr(self, "uri", None) if uri is None: if getattr(self, "path", None) and self.path is not None: - uri = pip_shims.shims.path_to_url(os.path.abspath(self.path)) + uri = path_to_url(os.path.abspath(self.path)) elif ( getattr(self, "req", None) and self.req is not None @@ -1788,7 +1785,7 @@ def from_pipfile(cls, name, pipfile): uri_scheme = "file" if not uri: - uri = pip_shims.shims.path_to_url(path) + uri = path_to_url(path) link_info = None # type: Optional[LinkInfo] if uri and isinstance(uri, str): link_info = cls.get_link_from_line(uri) @@ -1849,7 +1846,7 @@ def line_part(self): seed = None # type: Optional[STRING_TYPE] if self.link is not None: link_url = self.link.url_without_fragment - is_vcs = getattr(self.link, "is_vcs", not self.link.is_artifact) + is_vcs = getattr(self.link, "is_vcs", False) if self._uri_scheme and self._uri_scheme == "path": # We may need any one of these for passing to pip seed = self.path or link_url or self.uri @@ -1898,7 +1895,7 @@ def pipfile_part(self): key_match = next(iter(k for k in collision_order if k in pipfile_dict.keys())) is_vcs = None if self.link is not None: - is_vcs = getattr(self.link, "is_vcs", not self.link.is_artifact) + is_vcs = getattr(self.link, "is_vcs", False) if self._uri_scheme: dict_key = self._uri_scheme target_key = dict_key if dict_key in pipfile_dict else key_match @@ -1950,14 +1947,14 @@ class VCSRequirement(FileRequirement): _repo = attr.ib(default=None) # type: Optional[VCSRepository] _base_line = attr.ib(default=None) # type: Optional[STRING_TYPE] name = attr.ib() # type: STRING_TYPE - link = attr.ib() # type: Optional[pip_shims.shims.Link] + link = attr.ib() # type: Optional[Link] req = attr.ib() # type: Optional[RequirementType] def __attrs_post_init__(self): # type: () -> None if not self.uri: if self.path: - self.uri = pip_shims.shims.path_to_url(self.path) + self.uri = path_to_url(self.path) if self.uri is not None: split = urllib_parse.urlsplit(self.uri) scheme, rest = split[0], split[1:] @@ -1979,9 +1976,8 @@ def url(self): raise ValueError("No valid url found for requirement {0!r}".format(self)) @link.default - def get_link(self): - # type: () -> pip_shims.shims.Link - uri = self.uri if self.uri else pip_shims.shims.path_to_url(self.path) + def get_link(self) -> Link: + uri = self.uri if self.uri else path_to_url(self.path) vcs_uri = build_vcs_uri( self.vcs, add_ssh_scheme_to_git_uri(uri), @@ -2014,12 +2010,12 @@ def vcs_uri(self): def setup_info(self): if self._parsed_line and self._parsed_line.setup_info: if not self._parsed_line.setup_info.name: - with pip_shims.shims.global_tempdir_manager(): + with global_tempdir_manager(): self._parsed_line._setup_info.get_info() return self._parsed_line.setup_info subdir = self.subdirectory or self.parsed_line.subdirectory if self._repo: - with pip_shims.shims.global_tempdir_manager(): + with global_tempdir_manager(): self._setup_info = SetupInfo.from_ireq( Line(self._repo.checkout_directory).ireq, subdir=subdir ) @@ -2027,7 +2023,7 @@ def setup_info(self): return self._setup_info ireq = self.parsed_line.ireq - with pip_shims.shims.global_tempdir_manager(): + with global_tempdir_manager(): self._setup_info = SetupInfo.from_ireq(ireq, subdir=subdir) return self._setup_info @@ -2124,7 +2120,7 @@ def get_checkout_dir(self, src_dir=None): if self.is_local: path = self.path if not path: - path = pip_shims.shims.url_to_path(self.uri) + path = url_to_path(self.uri) if path and os.path.exists(path): checkout_dir = os.path.abspath(path) return checkout_dir @@ -2169,7 +2165,7 @@ def get_vcs_repo(self, src_dir=None, checkout_dir=None): def get_commit_hash(self): # type: () -> STRING_TYPE - with pip_shims.shims.global_tempdir_manager(): + with global_tempdir_manager(): hash_ = self.repo.get_commit_hash() return hash_ @@ -2196,7 +2192,7 @@ def locked_vcs_repo(self, src_dir=None): self.req = self.parsed_line.requirement else: self.req = self.get_requirement() - with pip_shims.shims.global_tempdir_manager(): + with global_tempdir_manager(): revision = self.req.revision = vcsrepo.get_commit_hash() # Remove potential ref in the end of uri after ref is parsed @@ -2274,7 +2270,7 @@ def from_pipfile(cls, name, pipfile): else: creation_args["path"] = target if os.path.isabs(target): - creation_args["uri"] = pip_shims.shims.path_to_url(target) + creation_args["uri"] = path_to_url(target) elif key in pipfile_keys: creation_args[key] = pipfile[key] creation_args["name"] = name @@ -2343,7 +2339,7 @@ def _choose_vcs_source(pipfile): @property def pipfile_part(self): - # type: () -> Dict[S, Dict[S, Union[List[S], S, bool, RequirementType, pip_shims.shims.Link]]] + # type: () -> Dict[S, Dict[S, Union[List[S], S, bool, RequirementType, Link]]] excludes = [ "_repo", "_base_line", @@ -2368,7 +2364,7 @@ def pipfile_part(self): name = self.name = self.setup_info.name if "vcs" in pipfile_dict: pipfile_dict = self._choose_vcs_source(pipfile_dict) - name, _ = pip_shims.shims._strip_extras(name) + name, _ = _strip_extras(name) return {name: pipfile_dict} # type: ignore @@ -2400,7 +2396,7 @@ class Requirement(object): _line_instance = attr.ib(default=None, eq=False, order=False) # type: Optional[Line] _ireq = attr.ib( default=None, eq=False, order=False - ) # type: Optional[pip_shims.InstallRequirement] + ) # type: Optional[InstallRequirement] def __hash__(self): return hash(self.as_line()) @@ -2623,7 +2619,7 @@ def build_backend(self): if self.req is not None and ( not isinstance(self.req, NamedRequirement) and self.req.is_local ): - with pip_shims.shims.global_tempdir_manager(): + with global_tempdir_manager(): setup_info = self.run_requires() build_backend = setup_info.get("build_backend") return build_backend @@ -2669,7 +2665,7 @@ def copy(self): @lru_cache() def from_line(cls, line): # type: (AnyStr) -> Requirement - if isinstance(line, pip_shims.shims.InstallRequirement): + if isinstance(line, InstallRequirement): line = format_requirement(line) parsed_line = Line(line) r = ( @@ -2828,7 +2824,7 @@ def get_specifier(self): return LegacySpecifier(self.specifiers) def get_version(self): - return pip_shims.shims.parse_version(self.get_specifier().version) + return parse(self.get_specifier().version) def get_requirement(self): req_line = self.req.req.line @@ -2937,7 +2933,7 @@ def pipfile_entry(self): def ireq(self): return self.as_ireq() - def get_dependencies(self, sources=None): + def dependencies(self, sources=None): """Retrieve the dependencies of the current requirement. Retrieves dependencies of the current requirement. This only works on pinned @@ -2948,16 +2944,13 @@ def get_dependencies(self, sources=None): :return: A set of requirement strings of the dependencies of this requirement. :rtype: set(str) """ - - from .dependencies import get_dependencies - if not sources: sources = [ {"name": "pypi", "url": "https://pypi.org/simple", "verify_ssl": True} ] return get_dependencies(self.as_ireq(), sources=sources) - def get_abstract_dependencies(self, sources=None): + def abstract_dependencies(self, sources=None): """Retrieve the abstract dependencies of this requirement. Returns the abstract dependencies of the current requirement in order to resolve. @@ -2968,12 +2961,6 @@ def get_abstract_dependencies(self, sources=None): :rtype: list[ :class:`~requirementslib.models.dependency.AbstractDependency` ] """ - from .dependencies import ( - AbstractDependency, - get_abstract_dependencies, - get_dependencies, - ) - if not self.abstract_dep: parent = getattr(self, "parent", None) self.abstract_dep = AbstractDependency.from_requirement(self, parent=parent) @@ -2982,11 +2969,11 @@ def get_abstract_dependencies(self, sources=None): {"url": "https://pypi.org/simple", "name": "pypi", "verify_ssl": True} ] if is_pinned_requirement(self.ireq): - deps = self.get_dependencies() + deps = self.dependencies() else: ireq = sorted(self.find_all_matches(), key=lambda k: k.version) - deps = get_dependencies(ireq.pop(), sources=sources) - return get_abstract_dependencies(deps, sources=sources, parent=self.abstract_dep) + deps = get_dependencies(ireq.pop()) + return get_abstract_dependencies(deps, parent=self.abstract_dep) def find_all_matches(self, sources=None, finder=None): # type: (Optional[List[Dict[S, Union[S, bool]]]], Optional[PackageFinder]) -> List[InstallationCandidate] @@ -3018,7 +3005,7 @@ def run_requires(self, sources=None, finder=None): from .dependencies import get_finder finder = get_finder(sources=sources) - with pip_shims.shims.global_tempdir_manager(): + with global_tempdir_manager(): info = SetupInfo.from_requirement(self, finder=finder) if info is None: return {} diff --git a/pipenv/vendor/requirementslib/models/resolvers.py b/pipenv/vendor/requirementslib/models/resolvers.py index 1f6818b064..01bfe93d7a 100644 --- a/pipenv/vendor/requirementslib/models/resolvers.py +++ b/pipenv/vendor/requirementslib/models/resolvers.py @@ -1,8 +1,8 @@ -# -*- coding=utf-8 -*- from contextlib import contextmanager import pipenv.vendor.attr as attr -from pipenv.vendor.pip_shims.shims import Wheel +from pipenv.patched.pip._internal.models.wheel import Wheel +from pipenv.patched.pip._internal.vcs.versioncontrol import VcsSupport from .cache import HashCache from .utils import format_requirement, is_pinned_requirement, version_from_ireq @@ -199,8 +199,6 @@ def get_hashes_for_one(self, ireq): if ireq.editable: return set() - from pipenv.vendor.pip_shims import VcsSupport - vcs = VcsSupport() if ( ireq.link diff --git a/pipenv/vendor/requirementslib/models/setup_info.py b/pipenv/vendor/requirementslib/models/setup_info.py index 69de266e28..5184c953d4 100644 --- a/pipenv/vendor/requirementslib/models/setup_info.py +++ b/pipenv/vendor/requirementslib/models/setup_info.py @@ -1,6 +1,3 @@ -# -*- coding=utf-8 -*- -from __future__ import absolute_import, print_function - import ast import atexit import configparser @@ -23,8 +20,10 @@ from pipenv.patched.pip._vendor.packaging.markers import Marker from pipenv.patched.pip._vendor.packaging.specifiers import SpecifierSet from pipenv.patched.pip._vendor.packaging.version import parse -from pipenv.vendor.pip_shims import shims -from pipenv.vendor.pip_shims.utils import call_function_with_correct_args +from pipenv.patched.pip._internal.commands.install import InstallCommand +from pipenv.patched.pip._internal.network.download import Downloader +from pipenv.patched.pip._internal.utils.temp_dir import global_tempdir_manager +from pipenv.patched.pip._internal.utils.urls import url_to_path from pipenv.vendor.platformdirs import user_cache_dir from pipenv.vendor.vistir.contextmanagers import cd, temp_path from pipenv.vendor.vistir.misc import run @@ -32,6 +31,8 @@ from ..environment import MYPY_RUNNING from ..exceptions import RequirementError +from ..utils import get_pip_command +from .old_pip_utils import old_unpack_url from .utils import ( get_default_pyproject_backend, get_name_variants, @@ -73,7 +74,8 @@ import pipenv.patched.pip._vendor.requests as requests from pipenv.patched.pip._vendor.packaging.requirements import Requirement as PackagingRequirement - from pipenv.vendor.pip_shims.shims import InstallRequirement, PackageFinder + from pipenv.patched.pip._internal.index.package_finder import PackageFinder + from pipenv.patched.pip._internal.req.req_install import InstallRequirement from pkg_resources import DistInfoDistribution, EggInfoDistribution, PathMetadata from pkg_resources import Requirement as PkgResourcesRequirement @@ -1510,10 +1512,10 @@ def from_ireq(cls, ireq, subdir=None, finder=None, session=None): return None stack = ExitStack() if not session: - cmd = shims.InstallCommand() + cmd = get_pip_command() options, _ = cmd.parser.parse_args([]) session = cmd._build_session(options) - stack.enter_context(shims.global_tempdir_manager()) + stack.enter_context(global_tempdir_manager()) vcs, uri = split_vcs_method_from_uri(ireq.link.url_without_fragment) parsed = urlparse(uri) if "file" in parsed.scheme: @@ -1528,19 +1530,17 @@ def from_ireq(cls, ireq, subdir=None, finder=None, session=None): is_file = True if "file:/" in uri and "file:///" not in uri: uri = uri.replace("file:/", "file:///") - path = shims.url_to_path(uri) + path = url_to_path(uri) kwargs = _prepare_wheel_building_kwargs(ireq) is_artifact_or_vcs = getattr( ireq.link, "is_vcs", getattr(ireq.link, "is_artifact", False) ) is_vcs = True if vcs else is_artifact_or_vcs - + download_dir = None if not (ireq.editable and is_file and is_vcs): if ireq.is_wheel: - only_download = True download_dir = kwargs["wheel_download_dir"] else: - only_download = False download_dir = kwargs["download_dir"] elif path is not None and os.path.isdir(path): raise RequirementError( @@ -1561,32 +1561,19 @@ def from_ireq(cls, ireq, subdir=None, finder=None, session=None): "autodelete": False, "parallel_builds": True, } - call_function_with_correct_args(build_location_func, **build_kwargs) + build_location_func(**build_kwargs) ireq.ensure_has_source_dir(kwargs["src_dir"]) - try: # Support for pip >= 21.1 - from pipenv.patched.pip._internal.network.download import Downloader - - from pipenv.vendor.requirementslib.models.old_pip_utils import old_unpack_url - - location = None - if getattr(ireq, "source_dir", None): - location = ireq.source_dir - old_unpack_url( - link=ireq.link, - location=location, - download=Downloader(session, "off"), - verbosity=1, - download_dir=download_dir, - hashes=ireq.hashes(True), - ) - except ImportError: - shims.shim_unpack( - download_dir=download_dir, - ireq=ireq, - only_download=only_download, - session=session, - hashes=ireq.hashes(False), - ) + location = None + if getattr(ireq, "source_dir", None): + location = ireq.source_dir + old_unpack_url( + link=ireq.link, + location=location, + download=Downloader(session, "off"), + verbosity=1, + download_dir=download_dir, + hashes=ireq.hashes(True), + ) created = cls.create( ireq.source_dir, subdirectory=subdir, ireq=ireq, kwargs=kwargs, stack=stack ) diff --git a/pipenv/vendor/requirementslib/models/url.py b/pipenv/vendor/requirementslib/models/url.py index c04efc1871..a3c711f634 100644 --- a/pipenv/vendor/requirementslib/models/url.py +++ b/pipenv/vendor/requirementslib/models/url.py @@ -7,7 +7,8 @@ import pipenv.vendor.attr as attr from pipenv.vendor.orderedmultidict import omdict -from pipenv.vendor.pip_shims import shims +from pipenv.patched.pip._internal.models.link import Link +from pipenv.patched.pip._internal.req.constructors import _strip_extras from pipenv.patched.pip._vendor.urllib3.util import parse_url as urllib3_parse from pipenv.patched.pip._vendor.urllib3.util.url import Url @@ -18,8 +19,6 @@ if MYPY_RUNNING: from typing import Dict, Optional, Text, Tuple, TypeVar, Union - from shims import Link - _T = TypeVar("_T") STRING_TYPE = Union[bytes, str, Text] S = TypeVar("S", bytes, str, Text) @@ -139,7 +138,7 @@ def _parse_fragment(self): if key == "egg": from .utils import parse_extras - name, stripped_extras = shims._strip_extras(val) + name, stripped_extras = _strip_extras(val) if stripped_extras: extras = tuple(parse_extras(stripped_extras)) elif key == "subdirectory": @@ -370,9 +369,7 @@ def name_with_extras(self): @property def as_link(self): # type: () -> Link - link = shims.Link( - self.to_string(escape_password=False, strip_ssh=False, direct=False) - ) + link = Link(self.to_string(escape_password=False, strip_ssh=False, direct=False)) return link @property @@ -480,14 +477,14 @@ def update_url_name_and_fragment(name_with_extras, ref, parsed_dict): if name_with_extras: fragment = "" # type: Optional[str] parsed_extras = () - name, extras = shims._strip_extras(name_with_extras) + name, extras = _strip_extras(name_with_extras) if extras: parsed_extras = parsed_extras + tuple(parse_extras(extras)) if parsed_dict["fragment"] is not None: fragment = "{0}".format(parsed_dict["fragment"]) if fragment.startswith("egg="): _, _, fragment_part = fragment.partition("=") - fragment_name, fragment_extras = shims._strip_extras(fragment_part) + fragment_name, fragment_extras = _strip_extras(fragment_part) name = name if name else fragment_name if fragment_extras: parsed_extras = parsed_extras + tuple(parse_extras(fragment_extras)) diff --git a/pipenv/vendor/requirementslib/models/utils.py b/pipenv/vendor/requirementslib/models/utils.py index 24c392ecb3..a07f7024eb 100644 --- a/pipenv/vendor/requirementslib/models/utils.py +++ b/pipenv/vendor/requirementslib/models/utils.py @@ -1,6 +1,3 @@ -# -*- coding: utf-8 -*- -from __future__ import absolute_import, print_function - import io import os import re @@ -16,6 +13,8 @@ from pipenv.patched.pip._vendor.packaging.markers import InvalidMarker, Marker, Op, Value, Variable from pipenv.patched.pip._vendor.packaging.specifiers import InvalidSpecifier, Specifier, SpecifierSet from pipenv.patched.pip._vendor.packaging.version import parse as parse_version +from pipenv.patched.pip._internal.models.link import Link +from pipenv.patched.pip._internal.req.constructors import install_req_from_line from pipenv.vendor.plette.models import Package, PackageCollection from pipenv.vendor.tomlkit.container import Container from pipenv.vendor.tomlkit.items import AoT, Array, Bool, InlineTable, Item, String, Table @@ -50,7 +49,6 @@ from pipenv.patched.pip._vendor.packaging.markers import Value as PkgResourcesValue from pipenv.patched.pip._vendor.packaging.markers import Variable as PkgResourcesVariable from pipenv.patched.pip._vendor.packaging.requirements import Requirement as PackagingRequirement - from pipenv.vendor.pip_shims.shims import Link from pkg_resources import Requirement as PkgResourcesRequirement from pipenv.patched.pip._vendor.urllib3.util.url import Url @@ -115,7 +113,6 @@ def create_link(link): if not isinstance(link, str): raise TypeError("must provide a string to instantiate a new link") - from pipenv.vendor.pip_shims.shims import Link # noqa: F811 return Link(link) @@ -309,11 +306,11 @@ def convert_direct_url_to_url(direct_url): # type: (AnyStr) -> AnyStr """Converts direct URLs to standard, link-style URLs. - Given a direct url as defined by *PEP 508*, convert to a :class:`~pip_shims.shims.Link` + Given a direct url as defined by *PEP 508*, convert to a :class:`Link` compatible URL by moving the name and extras into an **egg_fragment**. :param str direct_url: A pep-508 compliant direct url. - :return: A reformatted URL for use with Link objects and :class:`~pip_shims.shims.InstallRequirement` objects. + :return: A reformatted URL for use with Link objects and :class:`InstallRequirement` objects. :rtype: AnyStr """ direct_match = DIRECT_URL_RE.match(direct_url) # type: Optional[Match] @@ -350,10 +347,10 @@ def convert_url_to_direct_url(url, name=None): # type: (AnyStr, Optional[AnyStr]) -> AnyStr """Converts normal link-style URLs to direct urls. - Given a :class:`~pip_shims.shims.Link` compatible URL, convert to a direct url as + Given a :class:`Link` compatible URL, convert to a direct url as defined by *PEP 508* by extracting the name and extras from the **egg_fragment**. - :param AnyStr url: A :class:`~pip_shims.shims.InstallRequirement` compliant URL. + :param AnyStr url: A :class:`InstallRequirement` compliant URL. :param Optiona[AnyStr] name: A name to use in case the supplied URL doesn't provide one. :return: A pep-508 compliant direct url. :rtype: AnyStr @@ -871,11 +868,6 @@ def make_install_requirement( :return: A generated InstallRequirement :rtype: :class:`~pipenv.patched.pip._internal.req.req_install.InstallRequirement` """ - - # If no extras are specified, the extras string is blank - from pipenv.vendor.pip_shims.shims import install_req_from_line - - extras_string = "" requirement_string = "{0}".format(name) if extras: # Sort extras for stability diff --git a/pipenv/vendor/requirementslib/models/vcs.py b/pipenv/vendor/requirementslib/models/vcs.py index 24cf085298..ad271d44ae 100644 --- a/pipenv/vendor/requirementslib/models/vcs.py +++ b/pipenv/vendor/requirementslib/models/vcs.py @@ -1,12 +1,10 @@ -# -*- coding=utf-8 -*- -from __future__ import absolute_import, print_function - import importlib import os import sys import pipenv.vendor.attr as attr -import pipenv.vendor.pip_shims as pip_shims +from pipenv.patched.pip._internal.utils.temp_dir import global_tempdir_manager +from pipenv.patched.pip._internal.vcs.versioncontrol import VcsSupport from ..environment import MYPY_RUNNING from .url import URI @@ -41,7 +39,6 @@ def get_repo_backend(self): default_run_args = self.monkeypatch_pip() else: default_run_args = self.DEFAULT_RUN_ARGS - from pipenv.vendor.pip_shims.shims import VcsSupport VCS_SUPPORT = VcsSupport() backend = VCS_SUPPORT.get_backend(self.vcs_type) @@ -58,29 +55,13 @@ def is_local(self): url = url.split("+")[1] return url.startswith("file") - def obtain(self, verbosity=1): - # type: () -> None - lt_pip_19_2 = ( - pip_shims.parsed_pip_version.parsed_version < pip_shims.parse_version("19.2") - ) - gte_pip_22_0 = ( - pip_shims.parsed_pip_version.parsed_version >= pip_shims.parse_version("22.0") - ) - if lt_pip_19_2: - self.repo_backend = self.repo_backend(self.url) + def obtain(self, verbosity=1) -> None: if os.path.exists( self.checkout_directory ) and not self.repo_backend.is_repository_directory(self.checkout_directory): self.repo_backend.unpack(self.checkout_directory) elif not os.path.exists(self.checkout_directory): - if lt_pip_19_2: - self.repo_backend.obtain(self.checkout_directory) - elif gte_pip_22_0: - self.repo_backend.obtain( - self.checkout_directory, self.parsed_url, verbosity - ) - else: # at least Pip 19.2 but not quite pip 22.x - self.repo_backend.obtain(self.checkout_directory, self.parsed_url) + self.repo_backend.obtain(self.checkout_directory, self.parsed_url, verbosity) else: if self.ref: self.checkout_ref(self.ref) @@ -102,39 +83,24 @@ def checkout_ref(self, ref): def update(self, ref): # type: (str) -> None target_ref = self.repo_backend.make_rev_options(ref) - if pip_shims.parse_version(pip_shims.pip_version) > pip_shims.parse_version( - "18.0" - ): - self.repo_backend.update(self.checkout_directory, self.url, target_ref) - else: - self.repo_backend.update(self.checkout_directory, target_ref) + self.repo_backend.update(self.checkout_directory, self.url, target_ref) self.commit_sha = self.get_commit_hash() def get_commit_hash(self, ref=None): # type: (Optional[str]) -> str - with pip_shims.shims.global_tempdir_manager(): + with global_tempdir_manager(): return self.repo_backend.get_revision(self.checkout_directory) @classmethod def monkeypatch_pip(cls): # type: () -> Tuple[Any, ...] - from pipenv.vendor.pip_shims.compat import get_allowed_args - - target_module = pip_shims.shims.VcsSupport.__module__ + target_module = VcsSupport.__module__ pip_vcs = importlib.import_module(target_module) - args, kwargs = get_allowed_args(pip_vcs.VersionControl.run_command) - run_command_defaults = pip_vcs.VersionControl.run_command.__defaults__ - if "show_stdout" not in args and "show_stdout" not in kwargs: - new_defaults = run_command_defaults - else: - # set the default to not write stdout, the first option sets this value - new_defaults = [False] + list(run_command_defaults)[1:] - new_defaults = tuple(new_defaults) - try: - pip_vcs.VersionControl.run_command.__defaults__ = new_defaults - except AttributeError: - pip_vcs.VersionControl.run_command.__func__.__defaults__ = new_defaults - + run_command_defaults = pip_vcs.VersionControl.run_command.__func__.__defaults__ + # set the default to not write stdout, the first option sets this value + new_defaults = [False] + list(run_command_defaults)[1:] + new_defaults = tuple(new_defaults) + pip_vcs.VersionControl.run_command.__func__.__defaults__ = new_defaults sys.modules[target_module] = pip_vcs cls.DEFAULT_RUN_ARGS = new_defaults return new_defaults diff --git a/pipenv/vendor/requirementslib/utils.py b/pipenv/vendor/requirementslib/utils.py index 82f32f82d9..1ee543b20d 100644 --- a/pipenv/vendor/requirementslib/utils.py +++ b/pipenv/vendor/requirementslib/utils.py @@ -10,8 +10,10 @@ import pipenv.vendor.tomlkit as tomlkit import pipenv.vendor.vistir as vistir -from pipenv.vendor.pip_shims import shims -from pipenv.vendor.vistir.compat import fs_decode +from pipenv.patched.pip._internal.commands.install import InstallCommand +from pipenv.patched.pip._internal.models.target_python import TargetPython +from pipenv.patched.pip._internal.utils.filetypes import is_archive_file +from pipenv.patched.pip._internal.utils.misc import is_installable_dir from pipenv.vendor.vistir.path import ensure_mkdir_p, is_valid_url from .environment import MYPY_RUNNING @@ -71,20 +73,6 @@ def setup_logger(): ] -def is_installable_dir(path): - # type: (STRING_TYPE) -> bool - if shims.is_installable_dir(path): - return True - pyproject_path = os.path.join(path, "pyproject.toml") - if os.path.exists(pyproject_path): - pyproject = Path(pyproject_path) - pyproject_toml = tomlkit.loads(pyproject.read_text()) - build_system = pyproject_toml.get("build-system", {}).get("build-backend", "") - if build_system: - return True - return False - - def strip_ssh_from_git_uri(uri): # type: (S) -> S """Return git+ssh:// formatted URI to git+git@ format.""" @@ -164,8 +152,8 @@ def convert_entry_to_path(path): elif "path" in path: path = path["path"] if not os.name == "nt": - return fs_decode(path) - return Path(fs_decode(path)).as_posix() + return os.fsdecode(path) + return Path(os.fsdecode(path)).as_posix() def is_installable_file(path): @@ -194,19 +182,19 @@ def is_installable_file(path): or (len(parsed.scheme) == 1 and os.name == "nt") ) if parsed.scheme and parsed.scheme == "file": - path = fs_decode(vistir.path.url_to_path(path)) + path = os.fsdecode(vistir.path.url_to_path(path)) normalized_path = vistir.path.normalize_path(path) if is_local and not os.path.exists(normalized_path): return False - is_archive = shims.is_archive_file(normalized_path) + is_archive = is_archive_file(normalized_path) is_local_project = os.path.isdir(normalized_path) and is_installable_dir( normalized_path ) if is_local and is_local_project or is_archive: return True - if not is_local and shims.is_archive_file(parsed.path): + if not is_local and is_archive_file(parsed.path): return True return False @@ -280,6 +268,35 @@ def prepare_pip_source_args(sources, pip_args=None): return pip_args +def get_package_finder( + install_cmd=None, + options=None, + session=None, + platform=None, + python_versions=None, + abi=None, + implementation=None, + ignore_requires_python=None, +): + """Reduced Shim for compatibility to generate package finders.""" + 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 = TargetPython( + platforms=[platform] if platform else None, + py_version_info=py_version_info, + abis=[abi] if abi else None, + implementation=implementation, + ) + return install_cmd._build_package_finder( + options=options, + session=session, + target_python=target_python, + ignore_requires_python=ignore_requires_python, + ) + + @ensure_mkdir_p(mode=0o777) def _ensure_dir(path): return path @@ -656,3 +673,13 @@ def remerge_visit(path, key, value): if not sourced: return ret return ret, source_map + + +def get_pip_command() -> InstallCommand: + # Use pip's parser for pip.conf management and defaults. + # General options (find_links, index_url, extra_index_url, trusted_host, + # and pre) are deferred to pip. + pip_command = InstallCommand( + name="InstallCommand", summary="requirementslib pip Install command." + ) + return pip_command diff --git a/pipenv/vendor/vendor.txt b/pipenv/vendor/vendor.txt index bb1cadfe97..91be446db4 100644 --- a/pipenv/vendor/vendor.txt +++ b/pipenv/vendor/vendor.txt @@ -14,7 +14,6 @@ orderedmultidict==1.0.1 parse==1.19.0 pep517==0.11.0 pexpect==4.8.0 -pip-shims==0.7.3 pipdeptree==2.2.1 platformdirs==2.4.0 plette[validation]==0.2.3 diff --git a/tasks/vendoring/patches/vendor/pip_shims-import.patch b/tasks/vendoring/patches/vendor/pip_shims-import.patch deleted file mode 100644 index 2e242cc080..0000000000 --- a/tasks/vendoring/patches/vendor/pip_shims-import.patch +++ /dev/null @@ -1,22 +0,0 @@ -diff --git a/pipenv/vendor/pip_shims/__init__.py b/pipenv/vendor/pip_shims/__init__.py -index c66a075a..febea8df 100644 ---- a/pipenv/vendor/pip_shims/__init__.py -+++ b/pipenv/vendor/pip_shims/__init__.py -@@ -31,10 +31,15 @@ __version__ = "0.7.0" - if "pip_shims" in sys.modules: - # mainly to keep a reference to the old module on hand so it doesn't get - # weakref'd away -- old_module = sys.modules["pip_shims"] -+ if __name__ != "pip_shims": -+ del sys.modules["pip_shims"] - - --module = sys.modules["pip_shims"] = shims._new() -+if __name__ in sys.modules: -+ old_module = sys.modules[__name__] -+ -+ -+module = sys.modules["pip_shims"] = sys.modules[__name__] = shims._new() - module.shims = shims - module.__dict__.update( - { From 710ad786be69c64e932d4ce0c8cfa64a20a0987c Mon Sep 17 00:00:00 2001 From: Matt Davis Date: Sat, 6 Aug 2022 23:57:30 -0400 Subject: [PATCH 02/10] Attempt at fixing failing test. --- tests/unit/test_utils.py | 1 - 1 file changed, 1 deletion(-) diff --git a/tests/unit/test_utils.py b/tests/unit/test_utils.py index 04df666357..3aa22dbbb7 100644 --- a/tests/unit/test_utils.py +++ b/tests/unit/test_utils.py @@ -84,7 +84,6 @@ def mock_unpack(link, source_dir, download_dir, only_download=False, session=Non @pytest.mark.utils @pytest.mark.parametrize("deps, expected", DEP_PIP_PAIRS) @pytest.mark.needs_internet -@mock.patch("pipenv.patched.pip._internal.operations.prepare.unpack_url", mock_unpack) def test_convert_deps_to_pip(deps, expected): if expected.startswith("Django"): expected = expected.lower() From 9583f41816c1af2cb11fc4b6b8e5ed8e978f4375 Mon Sep 17 00:00:00 2001 From: Matt Davis Date: Sun, 7 Aug 2022 23:22:05 -0400 Subject: [PATCH 03/10] latest changes to requirementslib. Revert back to vistir for create_tracked_tempfile. --- pipenv/utils/dependencies.py | 5 +- .../requirementslib/models/requirements.py | 63 ++++++++----------- .../requirementslib/models/setup_info.py | 4 +- tests/unit/test_utils.py | 2 +- 4 files changed, 32 insertions(+), 42 deletions(-) diff --git a/pipenv/utils/dependencies.py b/pipenv/utils/dependencies.py index bf6ccb3cee..cf38da7089 100644 --- a/pipenv/utils/dependencies.py +++ b/pipenv/utils/dependencies.py @@ -1,6 +1,5 @@ import os from contextlib import contextmanager -from tempfile import NamedTemporaryFile from typing import Mapping, Sequence from pipenv.patched.pip._vendor.packaging.markers import Marker @@ -272,7 +271,9 @@ def convert_deps_to_pip( return dependencies # Write requirements.txt to tmp directory. - f = NamedTemporaryFile(suffix="-requirements.txt", delete=False) + from pipenv.vendor.vistir.path import create_tracked_tempfile + + f = create_tracked_tempfile(suffix="-requirements.txt", delete=False) f.write("\n".join(dependencies).encode("utf-8")) f.close() return f.name diff --git a/pipenv/vendor/requirementslib/models/requirements.py b/pipenv/vendor/requirementslib/models/requirements.py index f3fc34e450..386fed74f5 100644 --- a/pipenv/vendor/requirementslib/models/requirements.py +++ b/pipenv/vendor/requirementslib/models/requirements.py @@ -558,25 +558,26 @@ def parse_extras(self): :rtype: :class:`~Line` """ extras = None - line = "{0}".format(self.line) - if any([self.is_vcs, self.is_url, "@" in line]): - try: - if self.parsed_url.name: - self._name = self.parsed_url.name - if ( - self.parsed_url.host - and self.parsed_url.path - and self.parsed_url.scheme - ): - self.line = self.parsed_url.to_string( - escape_password=False, - direct=False, - strip_ssh=self.parsed_url.is_implicit_ssh, - ) - except ValueError: + if not self.line: + line = "{0}".format(self.line) + if any([self.is_vcs, self.is_url, "@" in line]): + try: + if self.parsed_url.name: + self._name = self.parsed_url.name + if ( + self.parsed_url.host + and self.parsed_url.path + and self.parsed_url.scheme + ): + self.line = self.parsed_url.to_string( + escape_password=False, + direct=False, + strip_ssh=self.parsed_url.is_implicit_ssh, + ) + except ValueError: + self.line, extras = _strip_extras(self.line) + else: self.line, extras = _strip_extras(self.line) - else: - self.line, extras = _strip_extras(self.line) extras_set = set() # type: Set[STRING_TYPE] if extras is not None: extras_set = set(parse_extras(extras)) @@ -587,7 +588,6 @@ def parse_extras(self): extras_set |= name_extras if extras_set is not None: self.extras = tuple(sorted(extras_set)) - return self def get_url(self): # type: () -> STRING_TYPE @@ -850,14 +850,12 @@ def vcsrepo(self): self._vcsrepo = self._get_vcsrepo() return self._vcsrepo - @property + @cached_property def parsed_url(self): # type: () -> URI - if self._parsed_url is None: - self._parsed_url = URI.parse(self.line) - return self._parsed_url + return URI.parse(self.line) - @property + @cached_property def is_direct_url(self): # type: () -> bool try: @@ -1177,7 +1175,6 @@ def parse_link(self): self._link = parsed_link else: self._link = link - return self def parse_markers(self): # type: () -> None @@ -2523,7 +2520,10 @@ def get_line_instance(self): else: line_parts.append(self.req.line_part) if not self.is_vcs and not self.vcs and self.extras_as_pip: - line_parts.append(self.extras_as_pip) + if self.is_file_or_url: + line_parts.append(f"#egg={self.extras_as_pip}") + else: + line_parts.append(self.extras_as_pip) if self._specifiers and not (self.is_file_or_url or self.is_vcs): line_parts.append(self._specifiers) if self.markers: @@ -2545,16 +2545,7 @@ def get_line_instance(self): @property def line_instance(self): # type: () -> Optional[Line] - if self._line_instance is None: - self.line_instance = self.get_line_instance() - return self._line_instance - - @line_instance.setter - def line_instance(self, line_instance): - # type: (Line) -> None - if self.req: - self.req._parsed_line = line_instance - self._line_instance = line_instance + return self.get_line_instance() @property def specifiers(self): diff --git a/pipenv/vendor/requirementslib/models/setup_info.py b/pipenv/vendor/requirementslib/models/setup_info.py index 5184c953d4..656bf9cdc2 100644 --- a/pipenv/vendor/requirementslib/models/setup_info.py +++ b/pipenv/vendor/requirementslib/models/setup_info.py @@ -1532,9 +1532,7 @@ def from_ireq(cls, ireq, subdir=None, finder=None, session=None): uri = uri.replace("file:/", "file:///") path = url_to_path(uri) kwargs = _prepare_wheel_building_kwargs(ireq) - is_artifact_or_vcs = getattr( - ireq.link, "is_vcs", getattr(ireq.link, "is_artifact", False) - ) + is_artifact_or_vcs = getattr(ireq.link, "is_vcs", False) is_vcs = True if vcs else is_artifact_or_vcs download_dir = None if not (ireq.editable and is_file and is_vcs): diff --git a/tests/unit/test_utils.py b/tests/unit/test_utils.py index 3aa22dbbb7..94b6721ed4 100644 --- a/tests/unit/test_utils.py +++ b/tests/unit/test_utils.py @@ -60,7 +60,7 @@ "extras": ["voice"], } }, - "https://github.com/Rapptz/discord.py/archive/async.zip#egg=discord.py[voice]", + "https://github.com/Rapptz/discord.py/archive/async.zip#egg=[voice]", ), ( { From 1d0d67199834529b2df2fac835aa01c06fd18053 Mon Sep 17 00:00:00 2001 From: Matt Davis Date: Sun, 7 Aug 2022 23:52:53 -0400 Subject: [PATCH 04/10] Revert "latest changes to requirementslib. Revert back to vistir for create_tracked_tempfile." This reverts commit 9583f41816c1af2cb11fc4b6b8e5ed8e978f4375. --- pipenv/utils/dependencies.py | 5 +- .../requirementslib/models/requirements.py | 63 +++++++++++-------- .../requirementslib/models/setup_info.py | 4 +- tests/unit/test_utils.py | 2 +- 4 files changed, 42 insertions(+), 32 deletions(-) diff --git a/pipenv/utils/dependencies.py b/pipenv/utils/dependencies.py index cf38da7089..bf6ccb3cee 100644 --- a/pipenv/utils/dependencies.py +++ b/pipenv/utils/dependencies.py @@ -1,5 +1,6 @@ import os from contextlib import contextmanager +from tempfile import NamedTemporaryFile from typing import Mapping, Sequence from pipenv.patched.pip._vendor.packaging.markers import Marker @@ -271,9 +272,7 @@ def convert_deps_to_pip( return dependencies # Write requirements.txt to tmp directory. - from pipenv.vendor.vistir.path import create_tracked_tempfile - - f = create_tracked_tempfile(suffix="-requirements.txt", delete=False) + f = NamedTemporaryFile(suffix="-requirements.txt", delete=False) f.write("\n".join(dependencies).encode("utf-8")) f.close() return f.name diff --git a/pipenv/vendor/requirementslib/models/requirements.py b/pipenv/vendor/requirementslib/models/requirements.py index 386fed74f5..f3fc34e450 100644 --- a/pipenv/vendor/requirementslib/models/requirements.py +++ b/pipenv/vendor/requirementslib/models/requirements.py @@ -558,26 +558,25 @@ def parse_extras(self): :rtype: :class:`~Line` """ extras = None - if not self.line: - line = "{0}".format(self.line) - if any([self.is_vcs, self.is_url, "@" in line]): - try: - if self.parsed_url.name: - self._name = self.parsed_url.name - if ( - self.parsed_url.host - and self.parsed_url.path - and self.parsed_url.scheme - ): - self.line = self.parsed_url.to_string( - escape_password=False, - direct=False, - strip_ssh=self.parsed_url.is_implicit_ssh, - ) - except ValueError: - self.line, extras = _strip_extras(self.line) - else: + line = "{0}".format(self.line) + if any([self.is_vcs, self.is_url, "@" in line]): + try: + if self.parsed_url.name: + self._name = self.parsed_url.name + if ( + self.parsed_url.host + and self.parsed_url.path + and self.parsed_url.scheme + ): + self.line = self.parsed_url.to_string( + escape_password=False, + direct=False, + strip_ssh=self.parsed_url.is_implicit_ssh, + ) + except ValueError: self.line, extras = _strip_extras(self.line) + else: + self.line, extras = _strip_extras(self.line) extras_set = set() # type: Set[STRING_TYPE] if extras is not None: extras_set = set(parse_extras(extras)) @@ -588,6 +587,7 @@ def parse_extras(self): extras_set |= name_extras if extras_set is not None: self.extras = tuple(sorted(extras_set)) + return self def get_url(self): # type: () -> STRING_TYPE @@ -850,12 +850,14 @@ def vcsrepo(self): self._vcsrepo = self._get_vcsrepo() return self._vcsrepo - @cached_property + @property def parsed_url(self): # type: () -> URI - return URI.parse(self.line) + if self._parsed_url is None: + self._parsed_url = URI.parse(self.line) + return self._parsed_url - @cached_property + @property def is_direct_url(self): # type: () -> bool try: @@ -1175,6 +1177,7 @@ def parse_link(self): self._link = parsed_link else: self._link = link + return self def parse_markers(self): # type: () -> None @@ -2520,10 +2523,7 @@ def get_line_instance(self): else: line_parts.append(self.req.line_part) if not self.is_vcs and not self.vcs and self.extras_as_pip: - if self.is_file_or_url: - line_parts.append(f"#egg={self.extras_as_pip}") - else: - line_parts.append(self.extras_as_pip) + line_parts.append(self.extras_as_pip) if self._specifiers and not (self.is_file_or_url or self.is_vcs): line_parts.append(self._specifiers) if self.markers: @@ -2545,7 +2545,16 @@ def get_line_instance(self): @property def line_instance(self): # type: () -> Optional[Line] - return self.get_line_instance() + if self._line_instance is None: + self.line_instance = self.get_line_instance() + return self._line_instance + + @line_instance.setter + def line_instance(self, line_instance): + # type: (Line) -> None + if self.req: + self.req._parsed_line = line_instance + self._line_instance = line_instance @property def specifiers(self): diff --git a/pipenv/vendor/requirementslib/models/setup_info.py b/pipenv/vendor/requirementslib/models/setup_info.py index 656bf9cdc2..5184c953d4 100644 --- a/pipenv/vendor/requirementslib/models/setup_info.py +++ b/pipenv/vendor/requirementslib/models/setup_info.py @@ -1532,7 +1532,9 @@ def from_ireq(cls, ireq, subdir=None, finder=None, session=None): uri = uri.replace("file:/", "file:///") path = url_to_path(uri) kwargs = _prepare_wheel_building_kwargs(ireq) - is_artifact_or_vcs = getattr(ireq.link, "is_vcs", False) + is_artifact_or_vcs = getattr( + ireq.link, "is_vcs", getattr(ireq.link, "is_artifact", False) + ) is_vcs = True if vcs else is_artifact_or_vcs download_dir = None if not (ireq.editable and is_file and is_vcs): diff --git a/tests/unit/test_utils.py b/tests/unit/test_utils.py index 94b6721ed4..3aa22dbbb7 100644 --- a/tests/unit/test_utils.py +++ b/tests/unit/test_utils.py @@ -60,7 +60,7 @@ "extras": ["voice"], } }, - "https://github.com/Rapptz/discord.py/archive/async.zip#egg=[voice]", + "https://github.com/Rapptz/discord.py/archive/async.zip#egg=discord.py[voice]", ), ( { From e1cbae00169a2a579c8a4fb4dbc3c9640c16ad7d Mon Sep 17 00:00:00 2001 From: Matt Davis Date: Mon, 8 Aug 2022 00:28:27 -0400 Subject: [PATCH 05/10] Patch to requirementslib logic based on testing. --- pipenv/vendor/requirementslib/models/requirements.py | 7 ++++++- tests/unit/test_utils.py | 2 +- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/pipenv/vendor/requirementslib/models/requirements.py b/pipenv/vendor/requirementslib/models/requirements.py index f3fc34e450..b1c9b3fc14 100644 --- a/pipenv/vendor/requirementslib/models/requirements.py +++ b/pipenv/vendor/requirementslib/models/requirements.py @@ -2517,13 +2517,18 @@ def update_name_from_path(self, path): def get_line_instance(self): # type: () -> Line line_parts = [] + local_editable = False if self.req: if self.req.line_part.startswith("-e "): + local_editable = True line_parts.extend(self.req.line_part.split(" ", 1)) else: line_parts.append(self.req.line_part) if not self.is_vcs and not self.vcs and self.extras_as_pip: - line_parts.append(self.extras_as_pip) + if self.is_file_or_url and not local_editable: + line_parts.append(f"#egg={self.extras_as_pip}") + else: + line_parts.append(self.extras_as_pip) if self._specifiers and not (self.is_file_or_url or self.is_vcs): line_parts.append(self._specifiers) if self.markers: diff --git a/tests/unit/test_utils.py b/tests/unit/test_utils.py index 3aa22dbbb7..94b6721ed4 100644 --- a/tests/unit/test_utils.py +++ b/tests/unit/test_utils.py @@ -60,7 +60,7 @@ "extras": ["voice"], } }, - "https://github.com/Rapptz/discord.py/archive/async.zip#egg=discord.py[voice]", + "https://github.com/Rapptz/discord.py/archive/async.zip#egg=[voice]", ), ( { From 5ec46f9433a56c0fe34139ba0ce2960e696da9ac Mon Sep 17 00:00:00 2001 From: Matt Davis Date: Wed, 24 Aug 2022 09:48:03 -0400 Subject: [PATCH 06/10] Vendor in requirementslib 2.0.0 --- pipenv/vendor/requirementslib/__init__.py | 7 +- pipenv/vendor/requirementslib/models/cache.py | 188 +----------------- .../requirementslib/models/old_pip_utils.py | 12 +- .../requirementslib/models/setup_info.py | 33 +-- pipenv/vendor/requirementslib/models/utils.py | 9 - pipenv/vendor/vendor.txt | 2 +- tasks/vendoring/__init__.py | 1 + 7 files changed, 21 insertions(+), 231 deletions(-) diff --git a/pipenv/vendor/requirementslib/__init__.py b/pipenv/vendor/requirementslib/__init__.py index dc222118b6..a12704956a 100644 --- a/pipenv/vendor/requirementslib/__init__.py +++ b/pipenv/vendor/requirementslib/__init__.py @@ -1,16 +1,11 @@ -# -*- coding=utf-8 -*- -from __future__ import absolute_import, print_function - import logging import warnings -import setuptools - from .models.lockfile import Lockfile from .models.pipfile import Pipfile from .models.requirements import Requirement -__version__ = "1.6.10.dev0" +__version__ = "2.0.0" logger = logging.getLogger(__name__) diff --git a/pipenv/vendor/requirementslib/models/cache.py b/pipenv/vendor/requirementslib/models/cache.py index 8a5b9d46c1..7a69133a5c 100644 --- a/pipenv/vendor/requirementslib/models/cache.py +++ b/pipenv/vendor/requirementslib/models/cache.py @@ -8,9 +8,9 @@ import pipenv.vendor.vistir as vistir from pipenv.patched.pip._vendor.packaging.requirements import Requirement -from pipenv.patched.pip._internal.network.cache import SafeFileCache from pipenv.patched.pip._internal.utils.hashes import FAVORITE_HASH from pipenv.patched.pip._internal.vcs.versioncontrol import VcsSupport +from pipenv.patched.pip._vendor.cachecontrol.cache import DictCache from pipenv.vendor.platformdirs import user_cache_dir from .utils import as_tuple, get_pinned_version, key_from_req, lookup_table @@ -18,66 +18,12 @@ CACHE_DIR = os.environ.get("PIPENV_CACHE_DIR", user_cache_dir("pipenv")) -# Pip-tools cache implementation -class CorruptCacheError(Exception): - def __init__(self, path): - self.path = path - - def __str__(self): - lines = [ - "The dependency cache seems to have been corrupted.", - "Inspect, or delete, the following file:", - " {}".format(self.path), - ] - return os.linesep.join(lines) - - -def read_cache_file(cache_file_path): - with open(cache_file_path, "r") as cache_file: - try: - doc = json.load(cache_file) - except ValueError: - raise CorruptCacheError(cache_file_path) - - # Check version and load the contents - assert doc["__format__"] == 1, "Unknown cache file format" - return doc["dependencies"] - - class DependencyCache(object): - """Creates a new persistent dependency cache for the current Python - version. The cache file is written to the appropriate user cache dir for - the current platform, i.e. - - ~/.cache/pip-tools/depcache-pyX.Y.json - - Where X.Y indicates the Python version. - """ - - def __init__(self, cache_dir=None): - if cache_dir is None: - cache_dir = CACHE_DIR - if not pathlib.Path(CACHE_DIR).absolute().is_dir(): - try: - vistir.path.mkdir_p(os.path.abspath(cache_dir)) - except OSError: - pass + """Creates a new in memory dependency cache for the current Python + version.""" - py_version = ".".join(str(digit) for digit in sys.version_info[:2]) - cache_filename = "depcache-py{}.json".format(py_version) - - self._cache_file = os.path.join(cache_dir, cache_filename) - self._cache = None - - @property - def cache(self): - """The dictionary that is the actual in-memory cache. - - This property lazily loads the cache from disk. - """ - if self._cache is None: - self.read_cache() - return self._cache + def __init__(self): + self.cache = {} def as_cache_key(self, ireq): """Given a requirement, return its cache key. This behavior is a little @@ -98,13 +44,6 @@ def as_cache_key(self, ireq): extras_string = "[{}]".format(",".join(extras)) return name, "{}{}".format(version, extras_string) - def read_cache(self): - """Reads the cached contents into memory.""" - if os.path.exists(self._cache_file): - self._cache = read_cache_file(self._cache_file) - else: - self._cache = {} - def write_cache(self): """Writes the cache to disk as JSON.""" doc = { @@ -116,7 +55,6 @@ def write_cache(self): def clear(self): self._cache = {} - self.write_cache() def __contains__(self, ireq): pkgname, pkgversion_and_extras = self.as_cache_key(ireq) @@ -130,7 +68,6 @@ def __setitem__(self, ireq, values): pkgname, pkgversion_and_extras = self.as_cache_key(ireq) self.cache.setdefault(pkgname, {}) self.cache[pkgname][pkgversion_and_extras] = values - self.write_cache() def __delitem__(self, ireq): pkgname, pkgversion_and_extras = self.as_cache_key(ireq) @@ -138,7 +75,6 @@ def __delitem__(self, ireq): del self.cache[pkgname][pkgversion_and_extras] except KeyError: return - self.write_cache() def get(self, ireq, default=None): pkgname, pkgversion_and_extras = self.as_cache_key(ireq) @@ -183,7 +119,7 @@ def _reverse_dependencies(self, cache_keys): ) -class HashCache(SafeFileCache): +class HashCache(DictCache): """Caches hashes of PyPI artifacts so we do not need to re-download them. Hashes are only cached when the URL appears to contain a hash in it @@ -198,13 +134,11 @@ def __init__(self, *args, **kwargs): session = requests.session() atexit.register(session.close) - cache_dir = kwargs.pop("cache_dir", CACHE_DIR) self.session = session - kwargs.setdefault("directory", os.path.join(cache_dir, "hash-cache")) super(HashCache, self).__init__(*args, **kwargs) def get_hash(self, location): - # if there is no location hash (i.e., md5 / sha256 / etc) we on't want to store it + # if there is no location hash (i.e., md5 / sha256 / etc) we don't want to store it hash_value = None vcs = VcsSupport() orig_scheme = location.scheme @@ -232,111 +166,3 @@ def _get_file_hash(self, location): for chunk in iter(lambda: fp.read(8096), b""): h.update(chunk) return ":".join([FAVORITE_HASH, h.hexdigest()]) - - -class _JSONCache(object): - """A persistent cache backed by a JSON file. - - The cache file is written to the appropriate user cache dir for the - current platform, i.e. - - ~/.cache/pip-tools/depcache-pyX.Y.json - - Where X.Y indicates the Python version. - """ - - filename_format = None - - def __init__(self, cache_dir=CACHE_DIR): - vistir.mkdir_p(cache_dir) - python_version = ".".join(str(digit) for digit in sys.version_info[:2]) - cache_filename = self.filename_format.format( - python_version=python_version, - ) - self._cache_file = os.path.join(cache_dir, cache_filename) - self._cache = None - - @property - def cache(self): - """The dictionary that is the actual in-memory cache. - - This property lazily loads the cache from disk. - """ - if self._cache is None: - self.read_cache() - return self._cache - - def as_cache_key(self, ireq): - """Given a requirement, return its cache key. - - This behavior is a little weird in order to allow backwards - compatibility with cache files. For a requirement without extras, this - will return, for example:: - - ("ipython", "2.1.0") - - For a requirement with extras, the extras will be comma-separated and - appended to the version, inside brackets, like so:: - - ("ipython", "2.1.0[nbconvert,notebook]") - """ - extras = tuple(sorted(ireq.extras)) - if not extras: - extras_string = "" - else: - extras_string = "[{}]".format(",".join(extras)) - name = key_from_req(ireq.req) - version = get_pinned_version(ireq) - return name, "{}{}".format(version, extras_string) - - def read_cache(self): - """Reads the cached contents into memory.""" - if os.path.exists(self._cache_file): - self._cache = read_cache_file(self._cache_file) - else: - self._cache = {} - - def write_cache(self): - """Writes the cache to disk as JSON.""" - doc = { - "__format__": 1, - "dependencies": self._cache, - } - with open(self._cache_file, "w") as f: - json.dump(doc, f, sort_keys=True) - - def clear(self): - self._cache = {} - self.write_cache() - - def __contains__(self, ireq): - pkgname, pkgversion_and_extras = self.as_cache_key(ireq) - return pkgversion_and_extras in self.cache.get(pkgname, {}) - - def __getitem__(self, ireq): - pkgname, pkgversion_and_extras = self.as_cache_key(ireq) - return self.cache[pkgname][pkgversion_and_extras] - - def __setitem__(self, ireq, values): - pkgname, pkgversion_and_extras = self.as_cache_key(ireq) - self.cache.setdefault(pkgname, {}) - self.cache[pkgname][pkgversion_and_extras] = values - self.write_cache() - - def __delitem__(self, ireq): - pkgname, pkgversion_and_extras = self.as_cache_key(ireq) - try: - del self.cache[pkgname][pkgversion_and_extras] - except KeyError: - return - self.write_cache() - - def get(self, ireq, default=None): - pkgname, pkgversion_and_extras = self.as_cache_key(ireq) - return self.cache.get(pkgname, {}).get(pkgversion_and_extras, default) - - -class RequiresPythonCache(_JSONCache): - """Cache a candidate's Requires-Python information.""" - - filename_format = "pyreqcache-py{python_version}.json" diff --git a/pipenv/vendor/requirementslib/models/old_pip_utils.py b/pipenv/vendor/requirementslib/models/old_pip_utils.py index a773b1b759..ca46c69faf 100644 --- a/pipenv/vendor/requirementslib/models/old_pip_utils.py +++ b/pipenv/vendor/requirementslib/models/old_pip_utils.py @@ -54,19 +54,17 @@ def copy2_fixed(src, dest): pass else: if is_socket_file: - raise shutil.SpecialFileError( - "`{f}` is a socket".format(**locals()) - ) + raise shutil.SpecialFileError("`{f}` is a socket".format(**locals())) raise def _copy2_ignoring_special_files(src: str, dest: str) -> None: - """Copying special files is not supported, but as a convenience to - users we skip errors copying them. + """Copying special files is not supported, but as a convenience to users we + skip errors copying them. - This supports tools that may create e.g. socket files in the - project source directory. + This supports tools that may create e.g. socket files in the project + source directory. """ try: copy2_fixed(src, dest) diff --git a/pipenv/vendor/requirementslib/models/setup_info.py b/pipenv/vendor/requirementslib/models/setup_info.py index 751592b93f..4ab4039cdc 100644 --- a/pipenv/vendor/requirementslib/models/setup_info.py +++ b/pipenv/vendor/requirementslib/models/setup_info.py @@ -47,12 +47,6 @@ except ModuleNotFoundError: pkg_resources_requirements = None -try: - from setuptools.dist import Distribution, distutils -except ImportError: - import distutils - from distutils.core import Distribution - from contextlib import ExitStack from os import scandir @@ -79,6 +73,11 @@ from pkg_resources import DistInfoDistribution, EggInfoDistribution, PathMetadata from pkg_resources import Requirement as PkgResourcesRequirement + try: + from setuptools.dist import Distribution + except ImportError: + from distutils.core import Distribution + TRequirement = TypeVar("TRequirement") RequirementType = TypeVar( "RequirementType", covariant=True, bound=PackagingRequirement @@ -548,26 +547,6 @@ def parse_setup_cfg(path: str) -> "Dict[str, Any]": return SetupReader.read_setup_cfg(Path(path)) -@contextlib.contextmanager -def _suppress_distutils_logs(): - # type: () -> Generator[None, None, None] - """Hack to hide noise generated by `setup.py develop`. - - There isn't a good way to suppress them now, so let's monky-patch. - See https://bugs.python.org/issue25392. - """ - - f = distutils.log.Log._log - - def _log(log, level, msg, args): - if level >= distutils.log.ERROR: - f(log, level, msg, args) - - distutils.log.Log._log = _log - yield - distutils.log.Log._log = f - - def build_pep517(source_dir, build_dir, config_settings=None, dist_type="wheel"): if config_settings is None: config_settings = {} @@ -904,7 +883,7 @@ def run_setup(script_path, egg_base=None): target_cwd = os.path.dirname(os.path.abspath(script_path)) if egg_base is None: egg_base = os.path.join(target_cwd, "reqlib-metadata") - with temp_path(), cd(target_cwd), _suppress_distutils_logs(): + with temp_path(), cd(target_cwd): # This is for you, Hynek # see https://github.com/hynek/environ_config/blob/69b1c8a/setup.py args = ["egg_info"] diff --git a/pipenv/vendor/requirementslib/models/utils.py b/pipenv/vendor/requirementslib/models/utils.py index a07f7024eb..a35be1bf4a 100644 --- a/pipenv/vendor/requirementslib/models/utils.py +++ b/pipenv/vendor/requirementslib/models/utils.py @@ -1018,12 +1018,3 @@ def replace_with_env(match): return value if value else match.group() return re.sub(r"\$\{([A-Z0-9_]+)\}", replace_with_env, line) - - -SETUPTOOLS_SHIM = ( - "import setuptools, tokenize;__file__=%r;" - "f=getattr(tokenize, 'open', open)(__file__);" - "code=f.read().replace('\\r\\n', '\\n');" - "f.close();" - "exec(compile(code, __file__, 'exec'))" -) diff --git a/pipenv/vendor/vendor.txt b/pipenv/vendor/vendor.txt index 43abde33c0..db2301528b 100644 --- a/pipenv/vendor/vendor.txt +++ b/pipenv/vendor/vendor.txt @@ -20,7 +20,7 @@ pyparsing==3.0.9 python-dateutil==2.8.2 python-dotenv==0.19.0 pythonfinder==1.2.10 -requirementslib==1.6.9 +requirementslib==2.0.0 shellingham==1.4.0 six==1.16.0 termcolor==1.1.0 diff --git a/tasks/vendoring/__init__.py b/tasks/vendoring/__init__.py index 5175063510..0887035009 100644 --- a/tasks/vendoring/__init__.py +++ b/tasks/vendoring/__init__.py @@ -62,6 +62,7 @@ "requests": "pipenv.patched.pip._vendor.requests", "packaging": "pipenv.patched.pip._vendor.packaging", "urllib3": "pipenv.patched.pip._vendor.urllib3", + "zipp": "pipenv.vendor.zipp", } GLOBAL_REPLACEMENT = [ From c48cfe60e963c976e6316de1eefd2cb890386b62 Mon Sep 17 00:00:00 2001 From: Matt Davis Date: Wed, 24 Aug 2022 09:50:50 -0400 Subject: [PATCH 07/10] add news fragment. --- news/5228.vendor.rst | 1 + 1 file changed, 1 insertion(+) create mode 100644 news/5228.vendor.rst diff --git a/news/5228.vendor.rst b/news/5228.vendor.rst new file mode 100644 index 0000000000..88929c26ac --- /dev/null +++ b/news/5228.vendor.rst @@ -0,0 +1 @@ +Vendor in ``requirementslib==2.0.0`` and drop ``pip-shims`` entirely. From 641a8500256e62bcd987527ce6049247e283d2c4 Mon Sep 17 00:00:00 2001 From: Matt Davis Date: Wed, 24 Aug 2022 10:51:03 -0400 Subject: [PATCH 08/10] Drop sysconfig default patch. --- pipenv/patched/pip/_internal/locations/__init__.py | 2 +- .../patches/patched/_post_pip_import.patch | 13 ------------- 2 files changed, 1 insertion(+), 14 deletions(-) diff --git a/pipenv/patched/pip/_internal/locations/__init__.py b/pipenv/patched/pip/_internal/locations/__init__.py index fe5dd5b44c..23eaea6423 100644 --- a/pipenv/patched/pip/_internal/locations/__init__.py +++ b/pipenv/patched/pip/_internal/locations/__init__.py @@ -41,7 +41,7 @@ _PLATLIBDIR: str = getattr(sys, "platlibdir", "lib") -_USE_SYSCONFIG_DEFAULT = sys.version_info >= (3, 7) +_USE_SYSCONFIG_DEFAULT = sys.version_info >= (3, 10) def _should_use_sysconfig() -> bool: diff --git a/tasks/vendoring/patches/patched/_post_pip_import.patch b/tasks/vendoring/patches/patched/_post_pip_import.patch index 8359065430..aced2cf21e 100644 --- a/tasks/vendoring/patches/patched/_post_pip_import.patch +++ b/tasks/vendoring/patches/patched/_post_pip_import.patch @@ -40,16 +40,3 @@ index 0ba06c52..6fdb59b7 100644 class LinkCandidate(_InstallRequirementBackedCandidate): -diff --git a/pipenv/patched/pip/_internal/locations/__init__.py b/pipenv/patched/pip/_internal/locations/__init__.py -index 23eaea64..fe5dd5b4 100644 ---- a/pipenv/patched/pip/_internal/locations/__init__.py -+++ b/pipenv/patched/pip/_internal/locations/__init__.py -@@ -41,7 +41,7 @@ logger = logging.getLogger(__name__) - - _PLATLIBDIR: str = getattr(sys, "platlibdir", "lib") - --_USE_SYSCONFIG_DEFAULT = sys.version_info >= (3, 10) -+_USE_SYSCONFIG_DEFAULT = sys.version_info >= (3, 7) - - - def _should_use_sysconfig() -> bool: From 64b877bdfbeac8f096b9dce5a7258b54ed0a4c78 Mon Sep 17 00:00:00 2001 From: Matt Davis Date: Wed, 24 Aug 2022 10:53:30 -0400 Subject: [PATCH 09/10] Remove setuptools import usages in pipenv. --- pipenv/environment.py | 27 --------------------------- pipenv/help.py | 4 ---- 2 files changed, 31 deletions(-) diff --git a/pipenv/environment.py b/pipenv/environment.py index 761d1bff3b..e46616a736 100644 --- a/pipenv/environment.py +++ b/pipenv/environment.py @@ -955,24 +955,6 @@ def which(self, search, as_path=True): result = str(result.path) return result - def get_install_args(self, editable=False, setup_path=None): - install_arg = "install" if not editable else "develop" - install_keys = ["headers", "purelib", "platlib", "scripts", "data"] - install_args = [ - self.environment.python, - "-u", - "-c", - SETUPTOOLS_SHIM % setup_path, - install_arg, - "--single-version-externally-managed", - "--no-deps", - "--prefix={}".format(self.base_paths["prefix"]), - "--no-warn-script-location", - ] - for key in install_keys: - install_args.append(f"--install-{key}={self.base_paths[key]}") - return install_args - def install(self, requirements): if not isinstance(requirements, (tuple, list)): requirements = [requirements] @@ -1048,12 +1030,3 @@ def uninstall(self, pkgname, *args, **kwargs): path_set.commit() if path_set is None: return - - -SETUPTOOLS_SHIM = ( - "import setuptools, tokenize;__file__=%r;" - "f=getattr(tokenize, 'open', open)(__file__);" - "code=f.read().replace('\\r\\n', '\\n');" - "f.close();" - "exec(compile(code, __file__, 'exec'))" -) diff --git a/pipenv/help.py b/pipenv/help.py index 569e3e827a..12ff1479ae 100644 --- a/pipenv/help.py +++ b/pipenv/help.py @@ -8,16 +8,12 @@ def get_pipenv_diagnostics(project): - import setuptools - print("
$ pipenv --support") print("") print(f"Pipenv version: `{pipenv.__version__!r}`") print("") print(f"Pipenv location: `{os.path.dirname(pipenv.__file__)!r}`") print("") - print(f"setuptools version: `{setuptools.__version__!r}`") - print("") print(f"Python location: `{sys.executable!r}`") print("") print(f"OS Name: `{os.name!r}`") From 66b39bb73304fa28487580c4ab55910f94548f95 Mon Sep 17 00:00:00 2001 From: Matt Davis Date: Wed, 24 Aug 2022 10:55:11 -0400 Subject: [PATCH 10/10] Add news fragment. --- news/5228.bugfix.rst | 2 ++ 1 file changed, 2 insertions(+) create mode 100644 news/5228.bugfix.rst diff --git a/news/5228.bugfix.rst b/news/5228.bugfix.rst new file mode 100644 index 0000000000..ee6909f79e --- /dev/null +++ b/news/5228.bugfix.rst @@ -0,0 +1,2 @@ +Remove eager and unnecessary importing of ``setuptools`` and ``pkg_resources`` to avoid conflict upgrading ``setuptools``. +Roll back ``sysconfig`` patch of ``pip`` because it was problematic for some ``--system`` commands.