From af20293b06e57ee56c241e81caae0bf3825476a4 Mon Sep 17 00:00:00 2001 From: Matt Davis Date: Thu, 28 Jul 2022 20:32:19 -0400 Subject: [PATCH] Let the great unraveling of pip_shims begin! --- pipenv/core.py | 29 ++++++++----------- pipenv/environment.py | 38 +++---------------------- pipenv/project.py | 5 ++-- pipenv/utils/resolver.py | 61 +++++++++++++++------------------------- 4 files changed, 39 insertions(+), 94 deletions(-) diff --git a/pipenv/core.py b/pipenv/core.py index 0413e481..9a82df63 100644 --- a/pipenv/core.py +++ b/pipenv/core.py @@ -17,6 +17,12 @@ import vistir from pipenv import environments, exceptions, pep508checker, progress from pipenv._compat import decode_for_output, fix_utf8 +from pipenv.patched.pip._internal.exceptions import PipError +from pipenv.patched.pip._internal.network.session import PipSession +from pipenv.patched.pip._internal.req.constructors import ( + install_req_from_parsed_requirement, +) +from pipenv.patched.pip._internal.req.req_file import parse_requirements from pipenv.utils.constants import MYPY_RUNNING from pipenv.utils.dependencies import ( convert_deps_to_pip, @@ -30,7 +36,6 @@ from pipenv.utils.dependencies import ( from pipenv.utils.indexes import get_source_list, parse_indexes, prepare_pip_source_args from pipenv.utils.internet import download_file, get_host_and_port, is_valid_url from pipenv.utils.processes import run_command -from pipenv.utils.resolver import venv_resolve_deps from pipenv.utils.shell import ( cmd_list_to_shell, find_python, @@ -160,12 +165,6 @@ def cleanup_virtualenv(project, bare=True): def import_requirements(project, r=None, dev=False): - from pipenv.patched.pip._internal.req.constructors import ( - install_req_from_parsed_requirement, - ) - from pipenv.patched.pip._vendor import requests - from pipenv.vendor.pip_shims.shims import parse_requirements - # Parse requirements.txt file with Pip's parser. # Pip requires a `PipSession` which is a subclass of requests.Session. # Since we're not making any network calls, it's initialized to nothing. @@ -191,7 +190,7 @@ def import_requirements(project, r=None, dev=False): trusted_hosts = sorted(set(trusted_hosts)) reqs = [ install_req_from_parsed_requirement(f) - for f in parse_requirements(r, session=requests) + for f in parse_requirements(r, session=PipSession()) ] for package in reqs: if package.name not in BAD_PACKAGES: @@ -1124,6 +1123,8 @@ def do_lock( err=True, ) + from pipenv.utils.resolver import venv_resolve_deps + # Mutates the lockfile venv_resolve_deps( packages, @@ -1372,8 +1373,6 @@ def get_pip_args( selective_upgrade: bool = False, src_dir: Optional[str] = None, ) -> List[str]: - from pipenv.patched.pip._vendor.packaging.version import parse as parse_version - arg_map = { "pre": ["--pre"], "verbose": ["--verbose"], @@ -1388,10 +1387,8 @@ def get_pip_args( ], "src_dir": src_dir, } - if project.environment.pip_version >= parse_version("19.0"): - arg_map["no_use_pep517"].append("--no-use-pep517") - if project.environment.pip_version < parse_version("19.1"): - arg_map["no_use_pep517"].append("--no-build-isolation") + # TODO: Why do we use no pep517? + arg_map["no_use_pep517"].append("--no-use-pep517") arg_set = [] for key in arg_map.keys(): if key in locals() and locals().get(key): @@ -1407,11 +1404,9 @@ def get_requirement_line( include_hashes: bool = True, format_for_file: bool = False, ) -> Union[List[str], str]: - line = None if requirement.vcs or requirement.is_file_or_url: if src_dir and requirement.line_instance.wheel_kwargs: requirement.line_instance._wheel_kwargs.update({"src_dir": src_dir}) - requirement.line_instance.vcsrepo line = requirement.line_instance.line if requirement.line_instance.markers: line = f"{line}; {requirement.line_instance.markers}" @@ -1950,8 +1945,6 @@ def do_install( selective_upgrade=False, site_packages=None, ): - from .vendor.pip_shims.shims import PipError - requirements_directory = vistir.path.create_tracked_tempdir( suffix="-requirements", prefix="pipenv-" ) diff --git a/pipenv/environment.py b/pipenv/environment.py index 49dae5c2..0d48d468 100644 --- a/pipenv/environment.py +++ b/pipenv/environment.py @@ -14,6 +14,8 @@ from sysconfig import get_paths, get_python_version, get_scheme_names import pkg_resources 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._vendor.packaging.utils import canonicalize_name from pipenv.utils.constants import is_type_checking from pipenv.utils.indexes import prepare_pip_source_args @@ -26,10 +28,8 @@ if is_type_checking(): from types import ModuleType from typing import ContextManager, Dict, Generator, List, Optional, Set, Union - import pip_shims.shims import tomlkit - from pipenv.patched.pip._vendor.packaging.version import Version from pipenv.project import Project, TPipfile, TSource BASE_WORKING_SET = pkg_resources.WorkingSet(sys.path) @@ -539,21 +539,6 @@ class Environment: return "purelib", purelib return "platlib", self.paths["platlib"] - @property - def pip_version(self) -> Version: - """ - Get the pip version in the environment. Useful for knowing which args we can use - when installing. - """ - from pipenv.patched.pip._vendor.packaging.version import parse as parse_version - - pip = next( - iter(pkg for pkg in self.get_installed_packages() if pkg.key == "pip"), None - ) - if pip is not None: - return parse_version(pip.version) - return parse_version("20.2") - def expand_egg_links(self) -> None: """ Expand paths specified in egg-link files to prevent pip errors during @@ -641,10 +626,8 @@ class Environment: return packages @contextlib.contextmanager - def get_finder( - self, pre: bool = False - ) -> ContextManager[pip_shims.shims.PackageFinder]: - from .vendor.pip_shims.shims import InstallCommand, get_package_finder + def get_finder(self, pre: bool = False) -> ContextManager[PackageFinder]: + from .vendor.pip_shims.shims import get_package_finder pip_command = InstallCommand() pip_args = prepare_pip_source_args(self.sources) @@ -660,22 +643,9 @@ class Environment: def get_package_info( self, pre: bool = False ) -> Generator[pkg_resources.Distribution, None, None]: - from .vendor.pip_shims.shims import parse_version, pip_version - - dependency_links = [] packages = self.get_installed_packages() - # This code is borrowed from pip's current implementation - if parse_version(pip_version) < parse_version("19.0"): - for dist in packages: - if dist.has_metadata("dependency_links.txt"): - dependency_links.extend( - dist.get_metadata_lines("dependency_links.txt") - ) with self.get_finder() as finder: - if parse_version(pip_version) < parse_version("19.0"): - finder.add_dependency_links(dependency_links) - for dist in packages: typ = "unknown" all_candidates = finder.find_all_candidates(dist.key) diff --git a/pipenv/project.py b/pipenv/project.py index 951ca018..1532632a 100644 --- a/pipenv/project.py +++ b/pipenv/project.py @@ -23,15 +23,16 @@ from pipenv.cmdparse import Script from pipenv.core import system_which from pipenv.environment import Environment from pipenv.environments import Setting, is_in_virtualenv, normalize_pipfile_path +from pipenv.patched.pip._internal.commands.install import InstallCommand from pipenv.utils.constants import is_type_checking from pipenv.utils.dependencies import ( get_canonical_names, is_editable, is_star, + pep423_name, python_version, ) from pipenv.utils.internet import get_url_name, is_valid_url, proper_case -from pipenv.utils.resolver import pep423_name from pipenv.utils.shell import ( find_requirements, find_windows_executable, @@ -641,8 +642,6 @@ class Project: def create_pipfile(self, python=None): """Creates the Pipfile, filled with juicy defaults.""" - from .vendor.pip_shims.shims import InstallCommand - # Inherit the pip's index configuration of install command. command = InstallCommand() indexes = command.cmd_opts.get_option("--extra-index-url").default diff --git a/pipenv/utils/resolver.py b/pipenv/utils/resolver.py index c1d77ae6..d55c4cd7 100644 --- a/pipenv/utils/resolver.py +++ b/pipenv/utils/resolver.py @@ -1,5 +1,3 @@ -from __future__ import annotations - import contextlib import hashlib import os @@ -7,12 +5,24 @@ import subprocess import sys import warnings from functools import lru_cache +from typing import Dict, List, Optional, Set, Tuple, Union from pipenv import environments from pipenv.exceptions import RequirementError, ResolutionFailure -from pipenv.utils.constants import MYPY_RUNNING +from pipenv.patched.pip._internal.cache import WheelCache +from pipenv.patched.pip._internal.commands.install import InstallCommand +from pipenv.patched.pip._internal.exceptions import InstallationError +from pipenv.patched.pip._internal.network.cache import SafeFileCache +from pipenv.patched.pip._internal.operations.build.build_tracker import ( + get_build_tracker, +) +from pipenv.patched.pip._internal.req.req_file import parse_requirements +from pipenv.patched.pip._internal.utils.hashes import FAVORITE_HASH +from pipenv.patched.pip._internal.utils.temp_dir import global_tempdir_manager +from pipenv.project import Project from pipenv.vendor import click from pipenv.vendor.requirementslib import Pipfile, Requirement +from pipenv.vendor.requirementslib.models.requirements import Line from pipenv.vendor.requirementslib.models.utils import DIRECT_URL_RE from pipenv.vendor.vistir import TemporaryDirectory, open_file from pipenv.vendor.vistir.path import create_tracked_tempdir @@ -32,12 +42,6 @@ from .locking import format_requirement_for_lockfile, prepare_lockfile from .shell import make_posix, subprocess_run, temp_environ from .spinner import create_spinner -if MYPY_RUNNING: - from typing import Any, Dict, List, Optional, Set, Tuple, Union # noqa - - from pipenv.project import Project # noqa - from pipenv.vendor.requirementslib.models.requirements import Line # noqa - class HashCacheMixin: @@ -64,9 +68,7 @@ class HashCacheMixin: return hash_value.decode("utf8") def _get_file_hash(self, link): - from pipenv.vendor.pip_shims import shims - - h = hashlib.new(shims.FAVORITE_HASH) + h = hashlib.new(FAVORITE_HASH) with open_file(link.url, self.session) as fp: for chunk in iter(lambda: fp.read(8096), b""): h.update(chunk) @@ -122,18 +124,14 @@ class Resolver: @staticmethod @lru_cache() def _get_pip_command(): - from pipenv.vendor.pip_shims import shims - - return shims.InstallCommand() + return InstallCommand(name="InstallCommand", summary="pip Install command.") @property def hash_cache(self): - from pipenv.vendor.pip_shims import shims - if not self._hash_cache: - self._hash_cache = type( - "HashCache", (HashCacheMixin, shims.SafeFileCache), {} - )(os.path.join(self.project.s.PIPENV_CACHE_DIR, "hashes"), self.session) + self._hash_cache = type("HashCache", (HashCacheMixin, SafeFileCache), {})( + os.path.join(self.project.s.PIPENV_CACHE_DIR, "hashes"), self.session + ) return self._hash_cache @classmethod @@ -595,12 +593,10 @@ class Resolver: @property def parsed_constraints(self): - from pipenv.vendor.pip_shims import shims - pip_options = self.pip_options pip_options.extra_index_urls = [] if self._parsed_constraints is None: - self._parsed_constraints = shims.parse_requirements( + self._parsed_constraints = parse_requirements( self.constraint_file, finder=self.finder, session=self.session, @@ -628,12 +624,6 @@ class Resolver: @contextlib.contextmanager def get_resolver(self, clear=False): - from pipenv.vendor.pip_shims.shims import ( - WheelCache, - get_build_tracker, - global_tempdir_manager, - ) - with global_tempdir_manager(), get_build_tracker() as build_tracker, TemporaryDirectory( suffix="-build", prefix="pipenv-" ) as directory: @@ -664,9 +654,6 @@ class Resolver: yield resolver def resolve(self): - from pipenv.exceptions import ResolutionFailure - from pipenv.vendor.pip_shims.shims import InstallationError - self.constraints # For some reason it is important to evaluate constraints before resolver context with temp_environ(), self.get_resolver() as resolver: try: @@ -712,8 +699,6 @@ class Resolver: return cleaned_checksums def _get_hashes_from_pypi(self, ireq): - from pipenv.vendor.pip_shims import shims - pkg_url = f"https://pypi.org/pypi/{ireq.name}/json" session = _get_requests_session(self.project.s.PIPENV_MAX_RETRIES) try: @@ -731,8 +716,8 @@ class Resolver: if spec: version = spec.version for release in cleaned_releases[version]: - collected_hashes.add(release["digests"][shims.FAVORITE_HASH]) - return self.prepend_hash_types(collected_hashes, shims.FAVORITE_HASH) + collected_hashes.add(release["digests"][FAVORITE_HASH]) + return self.prepend_hash_types(collected_hashes, FAVORITE_HASH) except (ValueError, KeyError, ConnectionError): if self.project.s.is_verbose(): click.echo( @@ -783,9 +768,7 @@ class Resolver: return self.hashes def _get_hash_from_link(self, link): - from pipenv.vendor.pip_shims import shims - - if link.hash and link.hash_name == shims.FAVORITE_HASH: + if link.hash and link.hash_name == FAVORITE_HASH: return f"{link.hash_name}:{link.hash}" return self.hash_cache.get_hash(link)