mirror of
https://github.com/kennethreitz/pipenv.git
synced 2026-06-21 15:20:59 +00:00
7429881693
- Fix invocation of vcs hash retrieval - Add error handling for pip url retrieval Signed-off-by: Dan Ryan <dan@danryan.co>
512 lines
21 KiB
Diff
512 lines
21 KiB
Diff
diff --git a/pipenv/patched/pip/_internal/download.py b/pipenv/patched/pip/_internal/download.py
|
|
index 96f3b65c..3fb4ebef 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
|
|
@@ -69,7 +70,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(),
|
|
@@ -322,7 +323,7 @@ class InsecureHTTPAdapter(HTTPAdapter):
|
|
conn.ca_certs = None
|
|
|
|
|
|
-class PipSession(requests.Session):
|
|
+class PipSession(Session):
|
|
|
|
timeout = None
|
|
|
|
@@ -752,7 +753,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 8c0ec82c..ad00ba04 100644
|
|
--- a/pipenv/patched/pip/_internal/index.py
|
|
+++ b/pipenv/patched/pip/_internal/index.py
|
|
@@ -58,11 +58,12 @@ logger = logging.getLogger(__name__)
|
|
|
|
class InstallationCandidate(object):
|
|
|
|
- def __init__(self, project, version, location):
|
|
+ def __init__(self, project, version, location, requires_python=None):
|
|
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,
|
|
@@ -220,6 +224,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):
|
|
"""
|
|
@@ -272,7 +294,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.
|
|
@@ -292,14 +314,19 @@ 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()
|
|
@@ -484,7 +511,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
|
|
@@ -594,8 +621,9 @@ class PackageFinder(object):
|
|
continue
|
|
seen.add(location)
|
|
|
|
- page = self._get_page(location)
|
|
- if page is None:
|
|
+ try:
|
|
+ page = self._get_page(location)
|
|
+ except requests.HTTPError as e:
|
|
continue
|
|
|
|
yield page
|
|
@@ -631,7 +659,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:
|
|
@@ -647,12 +675,12 @@ class PackageFinder(object):
|
|
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:
|
|
@@ -666,7 +694,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
|
|
@@ -702,14 +730,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/operations/prepare.py b/pipenv/patched/pip/_internal/operations/prepare.py
|
|
index 7740c284..b6e946d8 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.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.vcs import vcs
|
|
|
|
logger = logging.getLogger(__name__)
|
|
@@ -123,7 +123,11 @@ class IsSDist(DistAbstraction):
|
|
"Installing build dependencies"
|
|
)
|
|
|
|
- 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()
|
|
|
|
|
|
@@ -205,16 +209,8 @@ class RequirementPreparer(object):
|
|
# installation.
|
|
# 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)
|
|
- )
|
|
+ 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 0b5c7832..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__)
|
|
|
|
diff --git a/pipenv/patched/pip/_internal/req/req_install.py b/pipenv/patched/pip/_internal/req/req_install.py
|
|
index 462c80aa..d039adc8 100644
|
|
--- a/pipenv/patched/pip/_internal/req/req_install.py
|
|
+++ b/pipenv/patched/pip/_internal/req/req_install.py
|
|
@@ -615,7 +615,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']
|
|
@@ -797,7 +797,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
|
|
] +
|
|
@@ -1015,7 +1015,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) + \
|
|
diff --git a/pipenv/patched/pip/_internal/req/req_set.py b/pipenv/patched/pip/_internal/req/req_set.py
|
|
index 2bc6b745..e552afc1 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.
|
|
"""
|
|
|
|
@@ -24,6 +24,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()
|
|
@@ -65,7 +66,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
|
|
@@ -151,7 +152,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 8480e48c..ffc4aa7d 100644
|
|
--- a/pipenv/patched/pip/_internal/resolve.py
|
|
+++ b/pipenv/patched/pip/_internal/resolve.py
|
|
@@ -35,7 +35,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
|
|
|
|
@@ -55,7 +55,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)
|
|
|
|
@@ -237,7 +241,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.
|
|
@@ -245,6 +249,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 []
|
|
|
|
@@ -260,11 +267,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):
|
|
@@ -290,10 +303,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:
|
|
@@ -317,6 +334,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 3236af63..439a831d 100644
|
|
--- a/pipenv/patched/pip/_internal/utils/misc.py
|
|
+++ b/pipenv/patched/pip/_internal/utils/misc.py
|
|
@@ -96,7 +96,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..276a9ccc 100644
|
|
--- a/pipenv/patched/pip/_internal/utils/packaging.py
|
|
+++ b/pipenv/patched/pip/_internal/utils/packaging.py
|
|
@@ -28,7 +28,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 +40,17 @@ 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])),)
|
|
- )
|
|
+ return requires_python
|
|
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 fcf9d3d3..d8aff848 100644
|
|
--- a/pipenv/patched/pip/_internal/wheel.py
|
|
+++ b/pipenv/patched/pip/_internal/wheel.py
|
|
@@ -83,7 +83,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:
|
|
@@ -665,7 +665,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/index.py b/pipenv/patched/pip/_internal/index.py
|
|
index 793dd1cb..426880e9 100644
|
|
--- a/pipenv/patched/pip/_internal/index.py
|
|
+++ b/pipenv/patched/pip/_internal/index.py
|
|
@@ -477,7 +477,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.links, search)
|