From a7e6cfa21d487b758f789d581d9e1ea78dbb8c91 Mon Sep 17 00:00:00 2001 From: Dan Ryan Date: Mon, 9 Apr 2018 16:21:23 -0400 Subject: [PATCH] Resolve dependencies of local wheels - Fixes #1937, #1683 - Modifies the resolved wheel info on the way into the lockfile to retain the relative path Signed-off-by: Dan Ryan --- HISTORY.txt | 3 ++- pipenv/core.py | 6 ++++++ pipenv/patched/piptools/resolver.py | 2 +- pipenv/project.py | 5 ++++- pipenv/utils.py | 11 ++++++++--- 5 files changed, 21 insertions(+), 6 deletions(-) diff --git a/HISTORY.txt b/HISTORY.txt index 1ef0cdac..a6427367 100644 --- a/HISTORY.txt +++ b/HISTORY.txt @@ -3,7 +3,8 @@ - Ensure lock hash does not change based on injected env vars. - Fix bug in detecting .venv at project root when in subdirectories. - Parse quoting in [scripts] section correctly + clearer run errors. - - Fix bug resolving & locking markers correctly + - Fix bug resolving & locking markers correctly + - Resolve dependencies of wheel files. 11.9.0: - Vastly improve markers capabilities. - Support for environment variables in Pipfiles. diff --git a/pipenv/core.py b/pipenv/core.py index 5fa05917..b441e325 100644 --- a/pipenv/core.py +++ b/pipenv/core.py @@ -1128,6 +1128,12 @@ def do_lock( # Add default dependencies to lockfile. for dep in results: # Add version information to lockfile. + pipfile_version = project.packages[dep['name']] if dep['name'] in project.packages else None + if pipfile_version and hasattr(pipfile_version, 'keys') and any(k for k in ['file', 'path'] if k in pipfile_version): + lockfile['default'].update( + {dep['name']: dict(pipfile_version)} + ) + continue lockfile['default'].update( {dep['name']: {'version': '=={0}'.format(dep['version'])}} ) diff --git a/pipenv/patched/piptools/resolver.py b/pipenv/patched/piptools/resolver.py index acea5d9f..e53fa47e 100755 --- a/pipenv/patched/piptools/resolver.py +++ b/pipenv/patched/piptools/resolver.py @@ -120,7 +120,7 @@ class Resolver(object): @staticmethod def check_constraints(constraints): for constraint in constraints: - if constraint.link is not None and not constraint.editable: + if constraint.link is not None and not constraint.editable and not (constraint.is_wheel or constraint.is_artifact): msg = ('pip-compile does not support URLs as packages, unless they are editable. ' 'Perhaps add -e option?') raise UnsupportedConstraint(msg, constraint) diff --git a/pipenv/project.py b/pipenv/project.py index 001652fe..7dfde817 100644 --- a/pipenv/project.py +++ b/pipenv/project.py @@ -128,7 +128,10 @@ class Project(object): ): # If they are editable, do resolve them if 'editable' not in v: - continue + # allow wheels to be passed through + if not (hasattr(v, 'keys') and v.get('path', v.get('file', '')).endswith('.whl')): + continue + ps.update({k: v}) else: ps.update({k: v}) diff --git a/pipenv/utils.py b/pipenv/utils.py index 80db89d4..161068ff 100644 --- a/pipenv/utils.py +++ b/pipenv/utils.py @@ -66,7 +66,7 @@ requests = requests.Session() def get_requirement(dep): - from pip9.req.req_install import _strip_extras + from pip9.req.req_install import _strip_extras, Wheel import requirements """Pre-clean requirement strings passed to the requirements parser. @@ -137,6 +137,8 @@ def get_requirement(dep): elif req.local_file and path and not req.vcs: req.path = path req.uri = None + if dep_link and dep_link.is_wheel and not req.name: + req.name = os.path.basename(Wheel(dep_link.path).name) elif req.vcs and req.uri and cleaned_uri and cleaned_uri != uri: req.uri = strip_ssh_from_git_uri(req.uri) req.line = strip_ssh_from_git_uri(req.line) @@ -535,11 +537,14 @@ def convert_deps_from_pip(dep): # File installs. if (req.uri or req.path or is_installable_file(req.name)) and not req.vcs: # Assign a package name to the file, last 7 of it's sha256 hex digest. + if not req.uri and not req.path: req.path = os.path.abspath(req.name) + hashable_path = req.uri if req.uri else req.path - req.name = hashlib.sha256(hashable_path.encode('utf-8')).hexdigest() - req.name = req.name[len(req.name) - 7:] + if not req.name: + req.name = hashlib.sha256(hashable_path.encode('utf-8')).hexdigest() + req.name = req.name[len(req.name) - 7:] # {path: uri} TOML (spec 4 I guess...) if req.uri: dependency[req.name] = {'file': hashable_path}