diff --git a/news/3577.feature.rst b/news/3577.feature.rst new file mode 100644 index 0000000000..7944c09878 --- /dev/null +++ b/news/3577.feature.rst @@ -0,0 +1 @@ +Added a new environment variable, ``PIPENV_RESOLVE_VCS``, to toggle dependency resolution off for non-editable VCS, file, and URL based dependencies. diff --git a/pipenv/core.py b/pipenv/core.py index b97e1f47c0..f855f5ba71 100644 --- a/pipenv/core.py +++ b/pipenv/core.py @@ -1388,6 +1388,8 @@ def pip_install( src_dir = os.environ["PIP_SRC"] src = ["--src", os.environ["PIP_SRC"]] if not requirement.editable: + # Leave this off becauase old lockfiles don't have all deps included + # TODO: When can it be turned back on? no_deps = False if src_dir is not None: @@ -1441,7 +1443,7 @@ def pip_install( ignore_hashes = True if not requirement.hashes else ignore_hashes line = requirement.as_line(include_hashes=not ignore_hashes) line = "{0} {1}".format(line, " ".join(src)) - if environments.is_verbose() + if environments.is_verbose(): click.echo( "Writing first requirement line to temporary file: {0!r}".format(line), err=True diff --git a/pipenv/environments.py b/pipenv/environments.py index 1408c99c77..93df0785ce 100644 --- a/pipenv/environments.py +++ b/pipenv/environments.py @@ -234,6 +234,15 @@ def _is_env_truthy(name): NOTE: This only affects the ``install`` and ``uninstall`` commands. """ +PIPENV_RESOLVE_VCS = _is_env_truthy(os.environ.get("PIPENV_RESOLVE_VCS", True)) +"""Tells Pipenv whether to resolve all VCS dependencies in full. + +As of Pipenv 2018.11.26, only editable VCS dependencies were resolved in full. +To retain this behavior and avoid handling any conflicts that arise from the new +approach, you may set this to '0', 'off', or 'false'. +""" + + PIPENV_PYUP_API_KEY = os.environ.get( "PIPENV_PYUP_API_KEY", "1ab8d58f-5122e025-83674263-bc1e79e0" ) diff --git a/pipenv/utils.py b/pipenv/utils.py index 7eb7c48519..1328fa52d7 100644 --- a/pipenv/utils.py +++ b/pipenv/utils.py @@ -30,7 +30,9 @@ import parse from . import environments -from .exceptions import PipenvUsageError, RequirementError, PipenvCmdError +from .exceptions import ( + PipenvUsageError, RequirementError, PipenvCmdError, ResolutionFailure +) from .pep508checker import lookup from .vendor.urllib3 import util as urllib3_util @@ -419,6 +421,7 @@ def get_deps_from_line(cls, line): def get_deps_from_req(cls, req): # type: (Requirement) -> Tuple[Set[str], Dict[str, Dict[str, Union[str, bool, List[str]]]]] from requirementslib.models.utils import _requirement_to_str_lowercase_name + from requirementslib.utils import is_installable_dir constraints = set() # type: Set[str] locked_deps = dict() # type: Dict[str, Dict[str, Union[str, bool, List[str]]]] if req.is_file_or_url or req.is_vcs and not req.is_wheel: @@ -437,7 +440,16 @@ def get_deps_from_req(cls, req): raise RequirementError(req=req) setup_info = req.req.setup_info locked_deps[pep423_name(name)] = entry - requirements = [v for v in getattr(setup_info, "requires", {}).values()] + requirements = [] + # Allow users to toggle resolution off for non-editable VCS packages + # but leave it on for local, installable folders on the filesystem + if environments.PIPENV_RESOLVE_VCS or not ( + req.editable or ( + req.is_file_or_url and parsed_line.is_local and + is_installable_dir(parsed_line.path) + ) + ): + requirements = [v for v in getattr(setup_info, "requires", {}).values()] for r in requirements: if getattr(r, "url", None) and not getattr(r, "editable", False): if r is not None: