Files
2018-05-23 22:54:35 -04:00

558 lines
24 KiB
Diff

diff --git a/pipenv/patched/pip/_internal/download.py b/pipenv/patched/pip/_internal/download.py
index 06d72019..c3501bbf 100644
--- a/pipenv/patched/pip/_internal/download.py
+++ b/pipenv/patched/pip/_internal/download.py
@@ -19,6 +19,7 @@ from pip._vendor.lockfile import LockError
from pip._vendor.requests.adapters import BaseAdapter, HTTPAdapter
from pip._vendor.requests.auth import AuthBase, HTTPBasicAuth
from pip._vendor.requests.models import CONTENT_CHUNK_SIZE, Response
+from pip._vendor.requests.sessions import Session
from pip._vendor.requests.structures import CaseInsensitiveDict
from pip._vendor.requests.utils import get_netrc_auth
# NOTE: XMLRPC Client is not annotated in typeshed as on 2017-07-17, which is
@@ -70,7 +71,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(),
@@ -323,7 +324,7 @@ class InsecureHTTPAdapter(HTTPAdapter):
conn.ca_certs = None
-class PipSession(requests.Session):
+class PipSession(Session):
timeout = None
@@ -753,7 +754,7 @@ def _copy_dist_from_dir(link_path, location):
# build an sdist
setup_py = 'setup.py'
- sdist_args = [sys.executable]
+ sdist_args = [os.environ.get('PIP_PYTHON_PATH', sys.executable)]
sdist_args.append('-c')
sdist_args.append(SETUPTOOLS_SHIM % setup_py)
sdist_args.append('sdist')
diff --git a/pipenv/patched/pip/_internal/index.py b/pipenv/patched/pip/_internal/index.py
index 3c3a92b7..fad6a623 100644
--- a/pipenv/patched/pip/_internal/index.py
+++ b/pipenv/patched/pip/_internal/index.py
@@ -59,11 +59,12 @@ logger = logging.getLogger(__name__)
class InstallationCandidate(object):
- def __init__(self, project, version, location):
+ def __init__(self, project, version, location, requires_python=''):
self.project = project
self.version = parse_version(version)
self.location = location
self._key = (self.project, self.version, self.location)
+ self.requires_python = requires_python
def __repr__(self):
return "<InstallationCandidate({!r}, {!r}, {!r})>".format(
@@ -168,6 +169,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,
@@ -214,6 +218,24 @@ class PackageFinder(object):
)
self.dependency_links.extend(links)
+ @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):
"""
@@ -266,7 +288,7 @@ class PackageFinder(object):
return files, urls
- def _candidate_sort_key(self, candidate):
+ def _candidate_sort_key(self, candidate, ignore_compatibility=True):
"""
Function used to generate link sort key for link tuples.
The greater the return value, the more preferred it is.
@@ -284,12 +306,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
)
- 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()
@@ -474,7 +502,7 @@ class PackageFinder(object):
dependency_versions
)
- def find_requirement(self, req, upgrade):
+ def find_requirement(self, req, upgrade, ignore_compatibility=False):
"""Try to find a Link matching req
Expects req, an InstallRequirement and upgrade, a boolean
@@ -484,22 +512,25 @@ class PackageFinder(object):
all_candidates = self.find_all_candidates(req.name)
# Filter out anything which doesn't match our specifier
- compatible_versions = set(
- req.specifier.filter(
- # We turn the version object into a str here because otherwise
- # when we're debundled but setuptools isn't, Python will see
- # packaging.version.Version and
- # pkg_resources._vendor.packaging.version.Version as different
- # types. This way we'll use a str as a common data interchange
- # format. If we stop using the pkg_resources provided specifier
- # and start using our own, we can drop the cast to str().
- [str(c.version) for c in all_candidates],
- prereleases=(
- self.allow_all_prereleases
- if self.allow_all_prereleases else None
- ),
+ if not ignore_compatibility:
+ compatible_versions = set(
+ req.specifier.filter(
+ # We turn the version object into a str here because otherwise
+ # when we're debundled but setuptools isn't, Python will see
+ # packaging.version.Version and
+ # pkg_resources._vendor.packaging.version.Version as different
+ # types. This way we'll use a str as a common data interchange
+ # format. If we stop using the pkg_resources provided specifier
+ # and start using our own, we can drop the cast to str().
+ [str(c.version) for c in all_candidates],
+ prereleases=(
+ self.allow_all_prereleases
+ if self.allow_all_prereleases else None
+ ),
+ )
)
- )
+ else:
+ compatible_versions = [str(c.version) for c in all_candidates]
applicable_candidates = [
# Again, converting to str to deal with debundling.
c for c in all_candidates if str(c.version) in compatible_versions
@@ -584,7 +615,10 @@ class PackageFinder(object):
continue
seen.add(location)
- page = self._get_page(location)
+ try:
+ page = self._get_page(location)
+ except requests.HTTPError as e:
+ page = None
if page is None:
continue
@@ -621,7 +655,7 @@ class PackageFinder(object):
logger.debug('Skipping link %s; %s', link, reason)
self.logged_links.add(link)
- def _link_package_versions(self, link, search):
+ def _link_package_versions(self, link, search, ignore_compatibility=True):
"""Return an InstallationCandidate or None"""
version = None
if link.egg_fragment:
@@ -632,17 +666,18 @@ class PackageFinder(object):
if not ext:
self._log_skipped_link(link, 'not a file')
return
+ # Always ignore unsupported extensions even when we ignore compatibility
if ext not in SUPPORTED_EXTENSIONS:
self._log_skipped_link(
link, 'unsupported archive format: %s' % ext,
)
return
- if "binary" not in search.formats and ext == wheel_ext:
+ if "binary" not in search.formats and ext == wheel_ext and not ignore_compatibility:
self._log_skipped_link(
link, 'No binaries permitted for %s' % search.supplied,
)
return
- 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
if ext == wheel_ext:
@@ -656,7 +691,7 @@ class PackageFinder(object):
link, 'wrong project name (not %s)' % search.supplied)
return
- 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
@@ -692,14 +727,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
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 _get_page(self, link):
return HTMLPage.get_page(link, session=self.session)
diff --git a/pipenv/patched/pip/_internal/req/req_install.py b/pipenv/patched/pip/_internal/req/req_install.py
index ddd167c6..344bce5b 100644
--- a/pipenv/patched/pip/_internal/req/req_install.py
+++ b/pipenv/patched/pip/_internal/req/req_install.py
@@ -465,7 +465,7 @@ class InstallRequirement(object):
with indent_log():
script = SETUPTOOLS_SHIM % self.setup_py
- base_cmd = [sys.executable, '-c', script]
+ base_cmd = [os.environ.get('PIP_PYTHON_PATH', sys.executable), '-c', script]
if self.isolated:
base_cmd += ["--no-user-cfg"]
egg_info_cmd = base_cmd + ['egg_info']
@@ -836,7 +836,7 @@ class InstallRequirement(object):
def get_install_args(self, global_options, record_filename, root, prefix,
pycompile):
- install_args = [sys.executable, "-u"]
+ install_args = [os.environ.get('PIP_PYTHON_PATH', sys.executable), "-u"]
install_args.append('-c')
install_args.append(SETUPTOOLS_SHIM % self.setup_py)
install_args += list(global_options) + \
@@ -888,7 +888,7 @@ class InstallRequirement(object):
with self.build_env:
call_subprocess(
[
- sys.executable,
+ os.environ.get('PIP_PYTHON_PATH', sys.executable),
'-c',
SETUPTOOLS_SHIM % self.setup_py
] +
diff --git a/pipenv/patched/pip/_internal/req/req_set.py b/pipenv/patched/pip/_internal/req/req_set.py
index b2b55f89..50b5e2df 100644
--- a/pipenv/patched/pip/_internal/req/req_set.py
+++ b/pipenv/patched/pip/_internal/req/req_set.py
@@ -12,7 +12,7 @@ logger = logging.getLogger(__name__)
class RequirementSet(object):
- def __init__(self, require_hashes=False):
+ def __init__(self, require_hashes=False, ignore_compatibility=True):
"""Create a RequirementSet.
:param wheel_cache: The pip wheel cache, for passing to
@@ -27,6 +27,7 @@ class RequirementSet(object):
self.unnamed_requirements = []
self.successfully_downloaded = []
self.reqs_to_cleanup = []
+ self.ignore_compatibility = ignore_compatibility
def __str__(self):
reqs = [req for req in self.requirements.values()
@@ -68,7 +69,7 @@ class RequirementSet(object):
# environment markers.
if install_req.link and install_req.link.is_wheel:
wheel = Wheel(install_req.link.filename)
- if not wheel.supported():
+ if not wheel.supported() and not self.ignore_compatibility:
raise InstallationError(
"%s is not a supported wheel on this platform." %
wheel.filename
@@ -154,7 +155,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)
+ # raise KeyError("No project with the name %r" % project_name)
def cleanup_files(self):
"""Clean up files, remove builds."""
diff --git a/pipenv/patched/pip/_internal/resolve.py b/pipenv/patched/pip/_internal/resolve.py
index 3200fca8..14e3d298 100644
--- a/pipenv/patched/pip/_internal/resolve.py
+++ b/pipenv/patched/pip/_internal/resolve.py
@@ -36,7 +36,7 @@ class Resolver(object):
def __init__(self, preparer, session, finder, wheel_cache, use_user_site,
ignore_dependencies, ignore_installed, ignore_requires_python,
- force_reinstall, isolated, upgrade_strategy):
+ force_reinstall, isolated, upgrade_strategy, ignore_compatibility=False):
super(Resolver, self).__init__()
assert upgrade_strategy in self._allowed_strategies
@@ -56,7 +56,11 @@ 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.requires_python = None
+ if self.ignore_compatibility:
+ self.ignore_requires_python = True
self._discovered_dependencies = defaultdict(list)
@@ -238,7 +242,7 @@ class Resolver(object):
return abstract_dist
- def _resolve_one(self, requirement_set, req_to_install):
+ def _resolve_one(self, requirement_set, req_to_install, ignore_requires_python=False):
"""Prepare a single requirements file.
:return: A list of additional InstallRequirements to also install.
@@ -246,6 +250,9 @@ class Resolver(object):
# Tell user what we are doing for this requirement:
# obtain (editable), skipping, processing (local url), collecting
# (remote url or package name)
+ if ignore_requires_python or self.ignore_requires_python:
+ self.ignore_compatibility = True
+
if req_to_install.constraint or req_to_install.prepared:
return []
@@ -261,11 +268,17 @@ class Resolver(object):
try:
check_dist_requires_python(dist)
except UnsupportedPythonVersion as err:
- if self.ignore_requires_python:
+ if 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 = []
def add_req(subreq, extras_requested):
@@ -291,10 +304,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:
@@ -318,6 +335,19 @@ 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.from_req(
+ str(req),
+ req_to_install,
+ isolated=self.isolated,
+ wheel_cache=self.wheel_cache,
+ )
+
+ 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/misc.py b/pipenv/patched/pip/_internal/utils/misc.py
index 9d4c9b16..d0c8e437 100644
--- a/pipenv/patched/pip/_internal/utils/misc.py
+++ b/pipenv/patched/pip/_internal/utils/misc.py
@@ -93,7 +93,7 @@ def get_prog():
try:
prog = os.path.basename(sys.argv[0])
if prog in ('__main__.py', '-c'):
- return "%s -m pip" % sys.executable
+ return "%s -m pip" % os.environ.get('PIP_PYTHON_PATH', sys.executable)
else:
return prog
except (AttributeError, TypeError, IndexError):
diff --git a/pipenv/patched/pip/_internal/utils/packaging.py b/pipenv/patched/pip/_internal/utils/packaging.py
index 5f9bb93d..83edd874 100644
--- a/pipenv/patched/pip/_internal/utils/packaging.py
+++ b/pipenv/patched/pip/_internal/utils/packaging.py
@@ -1,6 +1,7 @@
from __future__ import absolute_import
import logging
+import os
import sys
from email.parser import FeedParser # type: ignore
@@ -28,7 +29,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
@@ -40,20 +41,23 @@ def get_metadata(dist):
return dist.get_metadata('PKG-INFO')
-def check_dist_requires_python(dist):
+def check_dist_requires_python(dist, absorb=True):
metadata = get_metadata(dist)
feed_parser = FeedParser()
feed_parser.feed(metadata)
pkg_info_dict = feed_parser.close()
requires_python = pkg_info_dict.get('Requires-Python')
+ if not absorb:
+ return requires_python
try:
if not check_requires_python(requires_python):
- raise exceptions.UnsupportedPythonVersion(
- "%s requires Python '%s' but the running Python is %s" % (
- dist.project_name,
- requires_python,
- '.'.join(map(str, sys.version_info[:3])),)
- )
+ # raise exceptions.UnsupportedPythonVersion(
+ # "%s requires Python '%s' but the running Python is %s" % (
+ # dist.project_name,
+ # requires_python,
+ # '.'.join(map(str, sys.version_info[:3])),)
+ # )
+ return
except specifiers.InvalidSpecifier as e:
logger.warning(
"Package %s has an invalid Requires-Python entry %s - %s",
diff --git a/pipenv/patched/pip/_internal/wheel.py b/pipenv/patched/pip/_internal/wheel.py
index c71f17d2..3e29a49d 100644
--- a/pipenv/patched/pip/_internal/wheel.py
+++ b/pipenv/patched/pip/_internal/wheel.py
@@ -85,7 +85,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:
@@ -655,7 +655,7 @@ class WheelBuilder(object):
# relies on site.py to find parts of the standard library outside the
# virtualenv.
return [
- sys.executable, '-u', '-c',
+ os.environ.get('PIP_PYTHON_PATH', sys.executable), '-u', '-c',
SETUPTOOLS_SHIM % req.setup_py
] + list(self.global_options)
diff --git a/pipenv/patched/pip/_internal/operations/prepare.py b/pipenv/patched/pip/_internal/operations/prepare.py
index 27e3a5dd..4d120faa 100644
--- a/pipenv/patched/pip/_internal/operations/prepare.py
+++ b/pipenv/patched/pip/_internal/operations/prepare.py
@@ -151,7 +151,11 @@ class IsSDist(DistAbstraction):
else:
self.req.build_env = NoOpBuildEnvironment(no_clean=False)
- self.req.run_egg_info()
+ try:
+ self.req.run_egg_info()
+ except (OSError, TypeError):
+ self.req._correct_build_location()
+ self.req.run_egg_info()
self.req.assert_source_matches_version()
@@ -233,15 +237,15 @@ class RequirementPreparer(object):
# FIXME: this won't upgrade when there's an existing
# 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)
- )
+ # 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)
+ # )
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 c2290ab9..bea31585 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
logger = logging.getLogger(__name__)