From 513bdfb0d29890d940c3e18d4566bf8599a69636 Mon Sep 17 00:00:00 2001 From: Dan Ryan Date: Sat, 26 May 2018 17:47:28 -0400 Subject: [PATCH 1/2] Update requirementslib to fix windows paths - Fixes #2256 Signed-off-by: Dan Ryan --- pipenv/vendor/requirementslib/__init__.py | 2 +- pipenv/vendor/requirementslib/requirements.py | 58 ++++++++++++++----- pipenv/vendor/requirementslib/utils.py | 11 +++- 3 files changed, 52 insertions(+), 19 deletions(-) diff --git a/pipenv/vendor/requirementslib/__init__.py b/pipenv/vendor/requirementslib/__init__.py index ef4d46a8d2..6727a81e2f 100644 --- a/pipenv/vendor/requirementslib/__init__.py +++ b/pipenv/vendor/requirementslib/__init__.py @@ -1,4 +1,4 @@ # -*- coding=utf-8 -*- -__version__ = "0.0.4" +__version__ = "0.0.6" from .requirements import Requirement diff --git a/pipenv/vendor/requirementslib/requirements.py b/pipenv/vendor/requirementslib/requirements.py index 04e561c6d3..e5989474d7 100644 --- a/pipenv/vendor/requirementslib/requirements.py +++ b/pipenv/vendor/requirementslib/requirements.py @@ -8,7 +8,7 @@ import six from attr import attrs, attrib, Factory, validators import attr -from ._compat import Link, path_to_url, _strip_extras +from ._compat import Link, path_to_url, _strip_extras, InstallRequirement from distlib.markers import Evaluator from packaging.markers import Marker, InvalidMarker from packaging.specifiers import SpecifierSet, InvalidSpecifier @@ -30,6 +30,11 @@ except ImportError: from pathlib2 import Path +try: + from urllib.parse import urlparse +except ImportError: + from urlparse import urlparse + HASH_STRING = " --hash={0}" @@ -261,7 +266,7 @@ def line_part(self): @property def pipfile_part(self): - pipfile_dict = attr.asdict(self, filter=_filter_none) + pipfile_dict = attr.asdict(self, filter=_filter_none).copy() if "version" not in pipfile_dict: pipfile_dict["version"] = "*" name = pipfile_dict.pop("name") @@ -305,16 +310,16 @@ def get_link(self): @req.default def get_requirement(self): - base = "{0}".format(self.link) - req = first(requirements.parse(base)) + prefix = "-e " if self.editable else "" + line = "{0}{1}".format(prefix, self.link.url) + req = first(requirements.parse(line)) + if self.path and self.link and self.link.scheme.startswith("file"): + req.local_file = True + req.path = self.path + req.uri = None + self._uri_scheme = "file" if self.editable: req.editable = True - if self.link and self.link.scheme.startswith("file"): - if self.path: - req.path = self.path - req.local_file = True - self._uri_scheme = "file" - req.uri = None req.link = self.link return req @@ -338,15 +343,24 @@ def from_line(cls, line): "Supplied requirement is not installable: {0!r}".format(line) ) - if is_valid_url(line): + if is_valid_url(line) and not is_installable_file(line): link = Link(line) else: - _path = Path(line) - link = Link(_path.absolute().as_uri()) - if _path.is_absolute() or _path.as_posix() == ".": - path = _path.as_posix() + if is_valid_url(line): + parsed = urlparse(line) + link = Link('{0}'.format(line)) + if parsed.scheme == "file": + path = Path(parsed.path).absolute().as_posix() + if get_converted_relative_path(path) == ".": + path = "." + line = path else: - path = get_converted_relative_path(line) + _path = Path(line) + link = Link(_path.absolute().as_uri()) + if _path.is_absolute() or _path.as_posix() == ".": + path = _path.as_posix() + else: + path = get_converted_relative_path(line) arg_dict = { "path": path, "uri": link.url_without_fragment, @@ -571,6 +585,7 @@ class Requirement(object): editable = attrib(default=None) hashes = attrib(default=Factory(list), converter=list) extras = attrib(default=Factory(list)) + _ireq = None _INCLUDE_FIELDS = ("name", "markers", "index", "editable", "hashes", "extras") @name.default @@ -749,6 +764,17 @@ def as_pipfile(self, include_index=False): def pipfile_entry(self): return self.as_pipfile().copy().popitem() + @property + def ireq(self): + if not self._ireq: + ireq_line = self.as_line() + if ireq_line.startswith("-e "): + ireq_line = ireq_line[len("-e "):] + self._ireq = InstallRequirement.from_editable(ireq_line) + else: + self._ireq = InstallRequirement.from_line(ireq_line) + return self._ireq + def _extras_to_string(extras): """Turn a list of extras into a string""" diff --git a/pipenv/vendor/requirementslib/utils.py b/pipenv/vendor/requirementslib/utils.py index b9358a35b5..5302630a8f 100644 --- a/pipenv/vendor/requirementslib/utils.py +++ b/pipenv/vendor/requirementslib/utils.py @@ -35,7 +35,10 @@ def is_vcs(pipfile_entry): def get_converted_relative_path(path, relative_to=os.curdir): """Given a vague relative path, return the path relative to the given location""" - return os.path.join(".", os.path.relpath(path, start=relative_to)) + relpath = os.path.relpath(path, start=relative_to) + if os.name == 'nt': + return os.altsep.join([".", relpath]) + return os.path.join(".", relpath) def multi_split(s, split): @@ -73,6 +76,10 @@ def is_installable_file(path): else: return False + parsed = urlparse(path) + if parsed.scheme == 'file': + path = parsed.path + if not os.path.exists(os.path.abspath(path)): return False @@ -90,7 +97,7 @@ def is_installable_file(path): def is_valid_url(url): """Checks if a given string is an url""" pieces = urlparse(url) - return all([pieces.scheme, pieces.netloc]) + return all([pieces.scheme, any([pieces.netloc, pieces.path])]) def pep423_name(name): From d55e400379f67d4cb2baaf8befb2c0ec8a24fe72 Mon Sep 17 00:00:00 2001 From: Dan Ryan Date: Sat, 26 May 2018 19:57:41 -0400 Subject: [PATCH 2/2] Better handling of wheels / update requirementslib Signed-off-by: Dan Ryan --- pipenv/patched/notpip/_internal/pep425tags.py | 7 ++----- pipenv/vendor/requirementslib/__init__.py | 2 +- pipenv/vendor/requirementslib/requirements.py | 7 +++++-- .../patched/_post-pip-update-pep425tags.patch | 21 +++++++++++++------ 4 files changed, 23 insertions(+), 14 deletions(-) diff --git a/pipenv/patched/notpip/_internal/pep425tags.py b/pipenv/patched/notpip/_internal/pep425tags.py index bea3158598..4205f6e0ba 100644 --- a/pipenv/patched/notpip/_internal/pep425tags.py +++ b/pipenv/patched/notpip/_internal/pep425tags.py @@ -10,10 +10,7 @@ import warnings from collections import OrderedDict -try: - import pip._internal.utils.glibc -except ImportError: - import pip.utils.glibc +import pipenv.patched.notpip._internal.utils.glibc logger = logging.getLogger(__name__) @@ -157,7 +154,7 @@ def is_manylinux1_compatible(): pass # Check glibc version. CentOS 5 uses glibc 2.5. - return pip._internal.utils.glibc.have_compatible_glibc(2, 5) + return pipenv.patched.notpip._internal.utils.glibc.have_compatible_glibc(2, 5) def get_darwin_arches(major, minor, machine): diff --git a/pipenv/vendor/requirementslib/__init__.py b/pipenv/vendor/requirementslib/__init__.py index 6727a81e2f..11e096755e 100644 --- a/pipenv/vendor/requirementslib/__init__.py +++ b/pipenv/vendor/requirementslib/__init__.py @@ -1,4 +1,4 @@ # -*- coding=utf-8 -*- -__version__ = "0.0.6" +__version__ = "0.0.7.dev0" from .requirements import Requirement diff --git a/pipenv/vendor/requirementslib/requirements.py b/pipenv/vendor/requirementslib/requirements.py index e5989474d7..4b167ca885 100644 --- a/pipenv/vendor/requirementslib/requirements.py +++ b/pipenv/vendor/requirementslib/requirements.py @@ -8,7 +8,7 @@ import six from attr import attrs, attrib, Factory, validators import attr -from ._compat import Link, path_to_url, _strip_extras, InstallRequirement +from ._compat import Link, path_to_url, _strip_extras, InstallRequirement, Wheel from distlib.markers import Evaluator from packaging.markers import Marker, InvalidMarker from packaging.specifiers import SpecifierSet, InvalidSpecifier @@ -306,7 +306,10 @@ def get_name(self): @link.default def get_link(self): target = "{0}#egg={1}".format(self.uri, self.name) - return Link(target) + link = Link(target) + if link.is_wheel and self._has_hashed_name: + self.name = os.path.basename(Wheel(link.path).name) + return link @req.default def get_requirement(self): diff --git a/tasks/vendoring/patches/patched/_post-pip-update-pep425tags.patch b/tasks/vendoring/patches/patched/_post-pip-update-pep425tags.patch index 70ccd170f0..ebebe17eaa 100644 --- a/tasks/vendoring/patches/patched/_post-pip-update-pep425tags.patch +++ b/tasks/vendoring/patches/patched/_post-pip-update-pep425tags.patch @@ -1,16 +1,25 @@ diff --git a/pipenv/patched/notpip/_internal/pep425tags.py b/pipenv/patched/notpip/_internal/pep425tags.py -index bea31585..9e9609f3 100644 +index bea31585..4205f6e0 100644 --- a/pipenv/patched/notpip/_internal/pep425tags.py +++ b/pipenv/patched/notpip/_internal/pep425tags.py -@@ -11,9 +11,9 @@ import warnings +@@ -10,10 +10,7 @@ import sysconfig + import warnings from collections import OrderedDict - try: +-try: - import pip._internal.utils.glibc -+ import pipenv.patched.notpip._internal.utils.glibc - except ImportError: +-except ImportError: - import pip.utils.glibc -+ import pipenv.patched.notpip.utils.glibc ++import pipenv.patched.notpip._internal.utils.glibc logger = logging.getLogger(__name__) +@@ -157,7 +154,7 @@ def is_manylinux1_compatible(): + pass + + # Check glibc version. CentOS 5 uses glibc 2.5. +- return pip._internal.utils.glibc.have_compatible_glibc(2, 5) ++ return pipenv.patched.notpip._internal.utils.glibc.have_compatible_glibc(2, 5) + + + def get_darwin_arches(major, minor, machine):