Skip to content

Commit

Permalink
Merge pull request #4216 from pypa/feature/only-install-missing
Browse files Browse the repository at this point in the history
  • Loading branch information
techalchemy authored May 19, 2020
2 parents edce45c + 4c10c35 commit 23a2e7c
Show file tree
Hide file tree
Showing 4 changed files with 43 additions and 8 deletions.
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
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

0 comments on commit 23a2e7c

Please sign in to comment.