Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Skip satisfied dependencies during installation #4216

Merged
merged 6 commits into from
May 19, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions news/3057.feature.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
``pipenv install`` and ``pipenv sync`` will no longer attempt to install satisfied dependencies during installation.
3 changes: 3 additions & 0 deletions pipenv/core.py
Original file line number Diff line number Diff line change
Expand Up @@ -735,6 +735,9 @@ def batch_install(deps_list, procs, failed_deps_queue,

deps_to_install = deps_list[:]
deps_to_install.extend(sequential_deps)
deps_to_install = [
dep for dep in deps_to_install if not project.environment.is_satisfied(dep)
]
sequential_dep_names = [d.name for d in sequential_deps]

deps_list_bar = progress.bar(
Expand Down
29 changes: 29 additions & 0 deletions pipenv/environment.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,12 +19,14 @@
import pipenv

from .vendor.cached_property import cached_property
from .vendor.packaging.utils import canonicalize_name
from .vendor import vistir

from .utils import normalize_path, make_posix


BASE_WORKING_SET = pkg_resources.WorkingSet(sys.path)
# TODO: Unittests for this class


class Environment(object):
Expand Down Expand Up @@ -712,6 +714,33 @@ def is_installed(self, pkgname):

return any(d for d in self.get_distributions() if d.project_name == pkgname)

def is_satisfied(self, req):
match = next(
iter(
d for d in self.get_distributions()
if canonicalize_name(d.project_name) == req.normalized_name
), None
)
if match is not None:
if req.editable and req.line_instance.is_local and self.find_egg(match):
requested_path = req.line_instance.path
return requested_path and vistir.compat.samefile(requested_path, match.location)
elif match.has_metadata("direct_url.json"):
direct_url_metadata = json.loads(match.get_metadata("direct_url.json"))
commit_id = direct_url_metadata.get("vcs_info", {}).get("commit_id", "")
vcs_type = direct_url_metadata.get("vcs_info", {}).get("vcs", "")
_, pipfile_part = req.as_pipfile().popitem()
return (
vcs_type == req.vcs and commit_id == req.commit_hash
and direct_url_metadata["url"] == pipfile_part[req.vcs]
)
elif req.line_instance.specifiers is not None:
return req.line_instance.specifiers.contains(
match.version, prereleases=True
)
return True
techalchemy marked this conversation as resolved.
Show resolved Hide resolved
return False

def run(self, cmd, cwd=os.curdir):
"""Run a command with :class:`~subprocess.Popen` in the context of the environment

Expand Down
18 changes: 10 additions & 8 deletions tasks/vendoring/patches/vendor/vistir-imports.patch
Original file line number Diff line number Diff line change
Expand Up @@ -15,30 +15,32 @@ diff --git a/pipenv/vendor/vistir/compat.py b/pipenv/vendor/vistir/compat.py
index b5904bc7..a44aafbe 100644
--- a/pipenv/vendor/vistir/compat.py
+++ b/pipenv/vendor/vistir/compat.py
@@ -43,7 +43,7 @@ __all__ = [
@@ -55,7 +55,7 @@ __all__ = [
if sys.version_info >= (3, 5): # pragma: no cover
from pathlib import Path
else: # pragma: no cover
- from pathlib2 import Path
+ from pipenv.vendor.pathlib2 import Path

if six.PY3: # pragma: no cover
if sys.version_info >= (3, 4): # pragma: no cover
# Only Python 3.4+ is supported
@@ -53,14 +53,14 @@ if six.PY3: # pragma: no cover
from weakref import finalize
@@ -85,8 +85,8 @@ if sys.version_info >= (3, 4): # pragma: no cover

else: # pragma: no cover
# Only Python 2.7 is supported
- from backports.functools_lru_cache import lru_cache
+ from pipenv.vendor.backports.functools_lru_cache import lru_cache
from .backports.functools import partialmethod # type: ignore
- from backports.shutil_get_terminal_size import get_terminal_size
+ from pipenv.vendor.backports.functools_lru_cache import lru_cache
+ from pipenv.vendor.backports.shutil_get_terminal_size import get_terminal_size
from .backports.functools import partialmethod # type: ignore
from .backports.surrogateescape import register_surrogateescape
from collections import (
@@ -110,7 +110,7 @@ else: # pragma: no cover

register_surrogateescape()
NamedTemporaryFile = _NamedTemporaryFile
- from backports.weakref import finalize # type: ignore
+ from pipenv.vendor.backports.weakref import finalize # type: ignore

try:
# Introduced Python 3.5
try:
from os.path import samefile