Files
pipenv/tasks/vendoring/patches/patched/pip19.patch
Dan Ryan d937050884 Update pip patch
Signed-off-by: Dan Ryan <dan@danryan.co>
2019-03-24 23:30:13 -04:00

543 lines
23 KiB
Diff

diff --git a/pipenv/patched/pip/_internal/download.py b/pipenv/patched/pip/_internal/download.py
index 2bbe1762..872af328 100644
--- a/pipenv/patched/pip/_internal/download.py
+++ b/pipenv/patched/pip/_internal/download.py
@@ -77,7 +77,7 @@ def user_agent():
Return a string representing the user agent.
"""
data = {
- "installer": {"name": "pip", "version": pip.__version__},
+ "installer": {"name": "pip", "version": pipenv.patched.notpip.__version__},
"python": platform.python_version(),
"implementation": {
"name": platform.python_implementation(),
diff --git a/pipenv/patched/pip/_internal/index.py b/pipenv/patched/pip/_internal/index.py
index 9eda3a35..67dd952c 100644
--- a/pipenv/patched/pip/_internal/index.py
+++ b/pipenv/patched/pip/_internal/index.py
@@ -331,6 +331,9 @@ class PackageFinder(object):
# The Session we'll use to make requests
self.session = session
+ # Kenneth's Hack
+ self.extra = None
+
# The valid tags to check potential found wheel candidates against
self.valid_tags = get_supported(
versions=versions,
@@ -369,6 +372,23 @@ class PackageFinder(object):
)
return "\n".join(lines)
+ @staticmethod
+ def get_extras_links(links):
+ requires = []
+ extras = {}
+
+ current_list = requires
+
+ for link in links:
+ if not link:
+ current_list = requires
+ if link.startswith('['):
+ current_list = []
+ extras[link[1:-1]] = current_list
+ else:
+ current_list.append(link)
+ return extras
+
@staticmethod
def _sort_locations(locations, expand_dir=False):
# type: (Sequence[str], bool) -> Tuple[List[str], List[str]]
@@ -427,8 +447,8 @@ class PackageFinder(object):
return files, urls
- def _candidate_sort_key(self, candidate):
- # type: (InstallationCandidate) -> CandidateSortingKey
+ def _candidate_sort_key(self, candidate, ignore_compatibility=True):
+ # type: (InstallationCandidate, bool) -> CandidateSortingKey
"""
Function used to generate link sort key for link tuples.
The greater the return value, the more preferred it is.
@@ -448,14 +468,18 @@ class PackageFinder(object):
if candidate.location.is_wheel:
# can raise InvalidWheelFilename
wheel = Wheel(candidate.location.filename)
- if not wheel.supported(self.valid_tags):
+ if not wheel.supported(self.valid_tags) and not ignore_compatibility:
raise UnsupportedWheel(
"%s is not a supported wheel for this platform. It "
"can't be sorted." % wheel.filename
)
if self.prefer_binary:
binary_preference = 1
- pri = -(wheel.support_index_min(self.valid_tags))
+ tags = self.valid_tags if not ignore_compatibility else None
+ try:
+ pri = -(wheel.support_index_min(tags=tags))
+ except TypeError:
+ pri = -(support_num)
if wheel.build_tag is not None:
match = re.match(r'^(\d+)(.*)$', wheel.build_tag)
build_tag_groups = match.groups()
@@ -608,7 +632,10 @@ class PackageFinder(object):
page_versions = []
for page in self._get_pages(url_locations, project_name):
- logger.debug('Analyzing links from page %s', page.url)
+ try:
+ logger.debug('Analyzing links from page %s', page.url)
+ except AttributeError:
+ continue
with indent_log():
page_versions.extend(
self._package_versions(page.iter_links(), search)
@@ -628,8 +655,8 @@ class PackageFinder(object):
# This is an intentional priority ordering
return file_versions + find_links_versions + page_versions
- def find_requirement(self, req, upgrade):
- # type: (InstallRequirement, bool) -> Optional[Link]
+ def find_requirement(self, req, upgrade, ignore_compatibility=False):
+ # type: (InstallRequirement, bool, bool) -> Optional[Link]
"""Try to find a Link matching req
Expects req, an InstallRequirement and upgrade, a boolean
@@ -784,8 +811,8 @@ class PackageFinder(object):
logger.debug('Skipping link %s; %s', link, reason)
self.logged_links.add(link)
- def _link_package_versions(self, link, search):
- # type: (Link, Search) -> Optional[InstallationCandidate]
+ def _link_package_versions(self, link, search, ignore_compatibility=True):
+ # type: (Link, Search, bool) -> Optional[InstallationCandidate]
"""Return an InstallationCandidate or None"""
version = None
if link.egg_fragment:
@@ -801,12 +828,12 @@ class PackageFinder(object):
link, 'unsupported archive format: %s' % ext,
)
return None
- if "binary" not in search.formats and ext == WHEEL_EXTENSION:
+ if "binary" not in search.formats and ext == WHEEL_EXTENSION and not ignore_compatibility:
self._log_skipped_link(
link, 'No binaries permitted for %s' % search.supplied,
)
return None
- if "macosx10" in link.path and ext == '.zip':
+ if "macosx10" in link.path and ext == '.zip' and not ignore_compatibility:
self._log_skipped_link(link, 'macosx10 one')
return None
if ext == WHEEL_EXTENSION:
@@ -820,7 +847,7 @@ class PackageFinder(object):
link, 'wrong project name (not %s)' % search.supplied)
return None
- if not wheel.supported(self.valid_tags):
+ if not wheel.supported(self.valid_tags) and not ignore_compatibility:
self._log_skipped_link(
link, 'it is not compatible with this Python')
return None
@@ -856,14 +883,14 @@ class PackageFinder(object):
link.filename, link.requires_python)
support_this_python = True
- if not support_this_python:
+ if not support_this_python and not ignore_compatibility:
logger.debug("The package %s is incompatible with the python "
"version in use. Acceptable python versions are: %s",
link, link.requires_python)
return None
logger.debug('Found link %s, version: %s', link, version)
- return InstallationCandidate(search.supplied, version, link)
+ return InstallationCandidate(search.supplied, version, link, link.requires_python)
def _find_name_version_sep(egg_info, canonical_name):
diff --git a/pipenv/patched/pip/_internal/models/candidate.py b/pipenv/patched/pip/_internal/models/candidate.py
index 4475458a..6748957d 100644
--- a/pipenv/patched/pip/_internal/models/candidate.py
+++ b/pipenv/patched/pip/_internal/models/candidate.py
@@ -13,11 +13,12 @@ class InstallationCandidate(KeyBasedCompareMixin):
"""Represents a potential "candidate" for installation.
"""
- def __init__(self, project, version, location):
- # type: (Any, str, Link) -> None
+ def __init__(self, project, version, location, requires_python=None):
+ # type: (Any, str, Link, Any) -> None
self.project = project
self.version = parse_version(version) # type: _BaseVersion
self.location = location
+ self.requires_python = requires_python
super(InstallationCandidate, self).__init__(
key=(self.project, self.version, self.location),
diff --git a/pipenv/patched/pip/_internal/operations/prepare.py b/pipenv/patched/pip/_internal/operations/prepare.py
index 4f31dd5a..ed0c86b2 100644
--- a/pipenv/patched/pip/_internal/operations/prepare.py
+++ b/pipenv/patched/pip/_internal/operations/prepare.py
@@ -17,7 +17,7 @@ from pip._internal.exceptions import (
from pip._internal.utils.compat import expanduser
from pip._internal.utils.hashes import MissingHashes
from pip._internal.utils.logging import indent_log
-from pip._internal.utils.misc import display_path, normalize_path
+from pip._internal.utils.misc import display_path, normalize_path, rmtree
from pip._internal.utils.typing import MYPY_CHECK_RUNNING
from pip._internal.vcs import vcs
@@ -258,14 +258,7 @@ class RequirementPreparer(object):
# package unpacked in `req.source_dir`
# package unpacked in `req.source_dir`
if os.path.exists(os.path.join(req.source_dir, 'setup.py')):
- raise PreviousBuildDirError(
- "pip can't proceed with requirements '%s' due to a"
- " pre-existing build directory (%s). This is "
- "likely due to a previous installation that failed"
- ". pip is being responsible and not assuming it "
- "can delete this. Please delete it and try again."
- % (req, req.source_dir)
- )
+ rmtree(req.source_dir)
req.populate_link(finder, upgrade_allowed, require_hashes)
# We can't hit this spot and have populate_link return None.
diff --git a/pipenv/patched/pip/_internal/pep425tags.py b/pipenv/patched/pip/_internal/pep425tags.py
index 1e782d1a..3c760ca3 100644
--- a/pipenv/patched/pip/_internal/pep425tags.py
+++ b/pipenv/patched/pip/_internal/pep425tags.py
@@ -10,7 +10,10 @@ import sysconfig
import warnings
from collections import OrderedDict
-import pip._internal.utils.glibc
+try:
+ import pip._internal.utils.glibc
+except ImportError:
+ import pip.utils.glibc
from pip._internal.utils.compat import get_extension_suffixes
from pip._internal.utils.typing import MYPY_CHECK_RUNNING
diff --git a/pipenv/patched/pip/_internal/req/req_install.py b/pipenv/patched/pip/_internal/req/req_install.py
index a4834b00..2c22e141 100644
--- a/pipenv/patched/pip/_internal/req/req_install.py
+++ b/pipenv/patched/pip/_internal/req/req_install.py
@@ -588,7 +588,8 @@ class InstallRequirement(object):
self.setup_py, self.link,
)
script = SETUPTOOLS_SHIM % self.setup_py
- base_cmd = [sys.executable, '-c', script]
+ sys_executable = os.environ.get('PIP_PYTHON_PATH', sys.executable)
+ base_cmd = [sys_executable, '-c', script]
if self.isolated:
base_cmd += ["--no-user-cfg"]
egg_info_cmd = base_cmd + ['egg_info']
@@ -746,9 +747,10 @@ class InstallRequirement(object):
with indent_log():
# FIXME: should we do --install-headers here too?
with self.build_env:
+ sys_executable = os.environ.get('PIP_PYTHON_PATH', sys.executable)
call_subprocess(
[
- sys.executable,
+ sys_executable,
'-c',
SETUPTOOLS_SHIM % self.setup_py
] +
@@ -995,7 +997,8 @@ class InstallRequirement(object):
pycompile # type: bool
):
# type: (...) -> List[str]
- install_args = [sys.executable, "-u"]
+ sys_executable = os.environ.get('PIP_PYTHON_PATH', sys.executable)
+ install_args = [sys_executable, "-u"]
install_args.append('-c')
install_args.append(SETUPTOOLS_SHIM % self.setup_py)
install_args += list(global_options) + \
diff --git a/pipenv/patched/pip/_internal/req/req_set.py b/pipenv/patched/pip/_internal/req/req_set.py
index d1410e93..69a53bf2 100644
--- a/pipenv/patched/pip/_internal/req/req_set.py
+++ b/pipenv/patched/pip/_internal/req/req_set.py
@@ -18,7 +18,7 @@ logger = logging.getLogger(__name__)
class RequirementSet(object):
- def __init__(self, require_hashes=False, check_supported_wheels=True):
+ def __init__(self, require_hashes=False, check_supported_wheels=True, ignore_compatibility=True):
# type: (bool, bool) -> None
"""Create a RequirementSet.
"""
@@ -26,6 +26,9 @@ class RequirementSet(object):
self.requirements = OrderedDict() # type: Dict[str, InstallRequirement] # noqa: E501
self.require_hashes = require_hashes
self.check_supported_wheels = check_supported_wheels
+ if ignore_compatibility:
+ self.check_supported_wheels = False
+ self.ignore_compatibility = (check_supported_wheels is False or ignore_compatibility is True)
# Mapping of alias: real_name
self.requirement_aliases = {} # type: Dict[str, str]
@@ -186,7 +189,7 @@ class RequirementSet(object):
return self.requirements[name]
if name in self.requirement_aliases:
return self.requirements[self.requirement_aliases[name]]
- raise KeyError("No project with the name %r" % project_name)
+ pass
def cleanup_files(self):
# type: () -> None
diff --git a/pipenv/patched/pip/_internal/resolve.py b/pipenv/patched/pip/_internal/resolve.py
index 33f572f1..dfe149ad 100644
--- a/pipenv/patched/pip/_internal/resolve.py
+++ b/pipenv/patched/pip/_internal/resolve.py
@@ -19,6 +19,7 @@ from pip._internal.exceptions import (
UnsupportedPythonVersion,
)
from pip._internal.req.constructors import install_req_from_req_string
+from pip._internal.req.req_install import InstallRequirement
from pip._internal.utils.logging import indent_log
from pip._internal.utils.misc import dist_in_usersite, ensure_dir
from pip._internal.utils.packaging import check_dist_requires_python
@@ -58,7 +59,8 @@ class Resolver(object):
force_reinstall, # type: bool
isolated, # type: bool
upgrade_strategy, # type: str
- use_pep517=None # type: Optional[bool]
+ use_pep517=None, # type: Optional[bool]
+ ignore_compatibility=False, # type: bool
):
# type: (...) -> None
super(Resolver, self).__init__()
@@ -81,8 +83,12 @@ class Resolver(object):
self.ignore_dependencies = ignore_dependencies
self.ignore_installed = ignore_installed
self.ignore_requires_python = ignore_requires_python
+ self.ignore_compatibility = ignore_compatibility
self.use_user_site = use_user_site
self.use_pep517 = use_pep517
+ self.requires_python = None
+ if self.ignore_compatibility:
+ self.ignore_requires_python = True
self._discovered_dependencies = \
defaultdict(list) # type: DefaultDict[str, List]
@@ -273,7 +279,8 @@ class Resolver(object):
def _resolve_one(
self,
requirement_set, # type: RequirementSet
- req_to_install # type: InstallRequirement
+ req_to_install, # type: InstallRequirement
+ ignore_requires_python=False # type: bool
):
# type: (...) -> List[InstallRequirement]
"""Prepare a single requirements file.
@@ -298,11 +305,18 @@ class Resolver(object):
try:
check_dist_requires_python(dist)
except UnsupportedPythonVersion as err:
- if self.ignore_requires_python:
+ if self.ignore_requires_python or ignore_requires_python or self.ignore_compatibility:
logger.warning(err.args[0])
else:
raise
+ # A huge hack, by Kenneth Reitz.
+ try:
+ self.requires_python = check_dist_requires_python(dist, absorb=False)
+ except TypeError:
+ self.requires_python = None
+
+
more_reqs = [] # type: List[InstallRequirement]
def add_req(subreq, extras_requested):
@@ -329,10 +343,14 @@ class Resolver(object):
# We add req_to_install before its dependencies, so that we
# can refer to it when adding dependencies.
if not requirement_set.has_requirement(req_to_install.name):
+ available_requested = sorted(
+ set(dist.extras) & set(req_to_install.extras)
+ )
# 'unnamed' requirements will get added here
req_to_install.is_direct = True
requirement_set.add_requirement(
req_to_install, parent_req_name=None,
+ extras_requested=available_requested,
)
if not self.ignore_dependencies:
@@ -356,6 +374,20 @@ class Resolver(object):
for subreq in dist.requires(available_requested):
add_req(subreq, extras_requested=available_requested)
+ # Hack for deep-resolving extras.
+ for available in available_requested:
+ if hasattr(dist, '_DistInfoDistribution__dep_map'):
+ for req in dist._DistInfoDistribution__dep_map[available]:
+ req = InstallRequirement(
+ req,
+ req_to_install,
+ isolated=self.isolated,
+ wheel_cache=self.wheel_cache,
+ use_pep517=None
+ )
+
+ more_reqs.append(req)
+
if not req_to_install.editable and not req_to_install.satisfied_by:
# XXX: --no-install leads this to report 'Successfully
# downloaded' for only non-editable reqs, even though we took
diff --git a/pipenv/patched/pip/_internal/utils/packaging.py b/pipenv/patched/pip/_internal/utils/packaging.py
index 7aaf7b5e..d56f0512 100644
--- a/pipenv/patched/pip/_internal/utils/packaging.py
+++ b/pipenv/patched/pip/_internal/utils/packaging.py
@@ -37,7 +37,7 @@ def check_requires_python(requires_python):
requires_python_specifier = specifiers.SpecifierSet(requires_python)
# We only use major.minor.micro
- python_version = version.parse('.'.join(map(str, sys.version_info[:3])))
+ python_version = version.parse('{0}.{1}.{2}'.format(*sys.version_info[:3]))
return python_version in requires_python_specifier
@@ -57,9 +57,11 @@ def get_metadata(dist):
return feed_parser.close()
-def check_dist_requires_python(dist):
+def check_dist_requires_python(dist, absorb=False):
pkg_info_dict = get_metadata(dist)
requires_python = pkg_info_dict.get('Requires-Python')
+ if absorb:
+ return requires_python
try:
if not check_requires_python(requires_python):
raise exceptions.UnsupportedPythonVersion(
diff --git a/pipenv/patched/pip/_internal/utils/temp_dir.py b/pipenv/patched/pip/_internal/utils/temp_dir.py
index 2c81ad55..ff2ccc5a 100644
--- a/pipenv/patched/pip/_internal/utils/temp_dir.py
+++ b/pipenv/patched/pip/_internal/utils/temp_dir.py
@@ -5,8 +5,10 @@ import itertools
import logging
import os.path
import tempfile
+import warnings
from pip._internal.utils.misc import rmtree
+from pipenv.vendor.vistir.compat import finalize, ResourceWarning
logger = logging.getLogger(__name__)
@@ -47,6 +49,20 @@ class TempDirectory(object):
self.path = path
self.delete = delete
self.kind = kind
+ self._finalizer = None
+ if path:
+ self._register_finalizer()
+
+ def _register_finalizer(self):
+ if self.delete and self.path:
+ self._finalizer = finalize(
+ self,
+ self._cleanup,
+ self.path,
+ warn_message = None
+ )
+ else:
+ self._finalizer = None
def __repr__(self):
return "<{} {!r}>".format(self.__class__.__name__, self.path)
@@ -74,14 +90,30 @@ class TempDirectory(object):
self.path = os.path.realpath(
tempfile.mkdtemp(prefix="pip-{}-".format(self.kind))
)
+ self._register_finalizer()
logger.debug("Created temporary directory: {}".format(self.path))
+ @classmethod
+ def _cleanup(cls, name, warn_message=None):
+ try:
+ rmtree(name)
+ except OSError:
+ pass
+ else:
+ if warn_message:
+ warnings.warn(warn_message, ResourceWarning)
+
def cleanup(self):
"""Remove the temporary directory created and reset state
"""
- if self.path is not None and os.path.exists(self.path):
- rmtree(self.path)
- self.path = None
+ if getattr(self._finalizer, "detach", None) and self._finalizer.detach():
+ if os.path.exists(self.path):
+ try:
+ rmtree(self.path)
+ except OSError:
+ pass
+ else:
+ self.path = None
class AdjacentTempDirectory(TempDirectory):
@@ -152,4 +184,5 @@ class AdjacentTempDirectory(TempDirectory):
self.path = os.path.realpath(
tempfile.mkdtemp(prefix="pip-{}-".format(self.kind))
)
+ self._register_finalizer()
logger.debug("Created temporary directory: {}".format(self.path))
diff --git a/pipenv/patched/pip/_internal/wheel.py b/pipenv/patched/pip/_internal/wheel.py
index 67bcc7f7..968cdff9 100644
--- a/pipenv/patched/pip/_internal/wheel.py
+++ b/pipenv/patched/pip/_internal/wheel.py
@@ -114,7 +114,7 @@ def fix_script(path):
firstline = script.readline()
if not firstline.startswith(b'#!python'):
return False
- exename = sys.executable.encode(sys.getfilesystemencoding())
+ exename = os.environ.get('PIP_PYTHON_PATH', sys.executable).encode(sys.getfilesystemencoding())
firstline = b'#!' + exename + os.linesep.encode("ascii")
rest = script.read()
with open(path, 'wb') as script:
@@ -201,7 +201,8 @@ def message_about_scripts_not_on_PATH(scripts):
]
# If an executable sits with sys.executable, we don't warn for it.
# This covers the case of venv invocations without activating the venv.
- not_warn_dirs.append(os.path.normcase(os.path.dirname(sys.executable)))
+ executable_loc = os.environ.get("PIP_PYTHON_PATH", sys.executable)
+ not_warn_dirs.append(os.path.normcase(os.path.dirname(executable_loc)))
warn_for = {
parent_dir: scripts for parent_dir, scripts in grouped_by_dir.items()
if os.path.normcase(parent_dir) not in not_warn_dirs
@@ -901,8 +902,9 @@ class WheelBuilder(object):
# isolating. Currently, it breaks Python in virtualenvs, because it
# relies on site.py to find parts of the standard library outside the
# virtualenv.
+ executable_loc = os.environ.get('PIP_PYTHON_PATH', sys.executable)
return [
- sys.executable, '-u', '-c',
+ executable_loc, '-u', '-c',
SETUPTOOLS_SHIM % req.setup_py
] + list(self.global_options)
diff --git a/pipenv/patched/pip/_internal/utils/misc.py b/pipenv/patched/pip/_internal/utils/misc.py
index 84605ee3..649311c0 100644
--- a/pipenv/patched/pip/_internal/utils/misc.py
+++ b/pipenv/patched/pip/_internal/utils/misc.py
@@ -117,8 +117,8 @@ def get_prog():
@retry(stop_max_delay=3000, wait_fixed=500)
def rmtree(dir, ignore_errors=False):
# type: (str, bool) -> None
- shutil.rmtree(dir, ignore_errors=ignore_errors,
- onerror=rmtree_errorhandler)
+ from pipenv.vendor.vistir.path import rmtree as vistir_rmtree, handle_remove_readonly
+ vistir_rmtree(dir, onerror=handle_remove_readonly, ignore_errors=ignore_errors)
def rmtree_errorhandler(func, path, exc_info):