From b973702959b9e7a72666b2ebfb299a6934fc2ddf Mon Sep 17 00:00:00 2001 From: Matt Davis Date: Sat, 9 Apr 2022 19:06:17 -0400 Subject: [PATCH 1/5] comment out logic that makes pip install strict with respect to indexes. --- pipenv/core.py | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/pipenv/core.py b/pipenv/core.py index d30ff5bb03..e6bc1b5f9d 100644 --- a/pipenv/core.py +++ b/pipenv/core.py @@ -1487,13 +1487,14 @@ def pip_install( if not index and requirement.index: index = requirement.index if index and not extra_indexes: - extra_indexes = [] - if requirement.index: - extra_indexes = list( - filter(lambda d: d.get("name") == requirement.index, project.sources) - ) - if not extra_indexes: - extra_indexes = list(project.sources) + extra_indexes = list(project.sources) + # extra_indexes = [] + # if requirement.index: + # extra_indexes = list( + # filter(lambda d: d.get("name") == requirement.index, project.sources) + # ) + # if not extra_indexes: + # extra_indexes = list(project.sources) if requirement and requirement.vcs or requirement.editable: requirement.index = None # Install dependencies when a package is a non-editable VCS dependency. @@ -1519,8 +1520,8 @@ def pip_install( trusted_hosts=trusted_hosts, pypi_mirror=pypi_mirror, ) - if requirement.index in sources: - sources = list(filter(lambda d: d.get("name") == requirement.index, sources)) + # if requirement.index in sources: + # sources = list(filter(lambda d: d.get("name") == requirement.index, sources)) if r: with open(r, "r") as fh: if "--hash" not in fh.read(): From 75a565dae6c2a59530be18eaadbf4ac3a4d9afc1 Mon Sep 17 00:00:00 2001 From: Matt Davis Date: Sat, 9 Apr 2022 23:42:58 -0400 Subject: [PATCH 2/5] Allow option to search all sources during installation. --- pipenv/core.py | 33 +++++++++++++++++---------------- 1 file changed, 17 insertions(+), 16 deletions(-) diff --git a/pipenv/core.py b/pipenv/core.py index e6bc1b5f9d..8d48898230 100644 --- a/pipenv/core.py +++ b/pipenv/core.py @@ -1466,10 +1466,8 @@ def pip_install( use_pep517=True, ): piplogger = logging.getLogger("pipenv.patched.notpip._internal.commands.install") - src_dir = None if not trusted_hosts: trusted_hosts = [] - trusted_hosts.extend(os.environ.get("PIP_TRUSTED_HOSTS", [])) if not allow_global: src_dir = os.getenv( @@ -1484,23 +1482,26 @@ def pip_install( ignore_hashes = False line = None # Try installing for each source in project.sources. + search_all_sources = project.settings.get("install_search_all_sources", False) if not index and requirement.index: index = requirement.index if index and not extra_indexes: - extra_indexes = list(project.sources) - # extra_indexes = [] - # if requirement.index: - # extra_indexes = list( - # filter(lambda d: d.get("name") == requirement.index, project.sources) - # ) - # if not extra_indexes: - # extra_indexes = list(project.sources) + if search_all_sources: + extra_indexes = list(project.sources) + else: # Default: index restrictions apply during installation + extra_indexes = [] + if requirement.index: + extra_indexes = list( + filter(lambda d: d.get("name") == requirement.index, project.sources) + ) + if not extra_indexes: + extra_indexes = list(project.sources) if requirement and requirement.vcs or requirement.editable: requirement.index = None # Install dependencies when a package is a non-editable VCS dependency. # Don't specify a source directory when using --system. if not requirement.editable and no_deps is not True: - # Leave this off becauase old lockfiles don't have all deps included + # Leave this off because old Pipfile.lock don't have all deps included # TODO: When can it be turned back on? no_deps = False elif requirement.editable and no_deps is None: @@ -1520,8 +1521,8 @@ def pip_install( trusted_hosts=trusted_hosts, pypi_mirror=pypi_mirror, ) - # if requirement.index in sources: - # sources = list(filter(lambda d: d.get("name") == requirement.index, sources)) + if not search_all_sources and requirement.index in sources: + sources = list(filter(lambda d: d.get("name") == requirement.index, sources)) if r: with open(r, "r") as fh: if "--hash" not in fh.read(): @@ -1559,11 +1560,11 @@ def pip_install( if project.s.is_verbose(): click.echo(f"$ {cmd_list_to_shell(pip_command)}", err=True) cache_dir = Path(project.s.PIPENV_CACHE_DIR) - DEFAULT_EXISTS_ACTION = "w" + default_exists_action = "w" if selective_upgrade: - DEFAULT_EXISTS_ACTION = "i" + default_exists_action = "i" exists_action = vistir.misc.fs_str( - project.s.PIP_EXISTS_ACTION or DEFAULT_EXISTS_ACTION + project.s.PIP_EXISTS_ACTION or default_exists_action ) pip_config = { "PIP_CACHE_DIR": vistir.misc.fs_str(cache_dir.as_posix()), From 34ef11b0642aca912bc31f391a8940ca72ba68cc Mon Sep 17 00:00:00 2001 From: Matt Davis Date: Wed, 20 Apr 2022 19:35:11 -0400 Subject: [PATCH 3/5] format the prior documetnation Pipfile. --- docs/advanced.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/advanced.rst b/docs/advanced.rst index cafa190deb..1c33909f57 100644 --- a/docs/advanced.rst +++ b/docs/advanced.rst @@ -119,7 +119,7 @@ If you want to work with private registries that use the keychain for authentica can disable the "enforcement of no input". **Note:** Please be sure that the keychain will really not ask for -input. Otherwise the process will hang forever! +input. Otherwise the process will hang forever!:: [[source]] url = "https://pypi.org/simple" From 7a467c3e1530e69d99f51545fcbedf6b138b3e25 Mon Sep 17 00:00:00 2001 From: Matt Davis Date: Wed, 20 Apr 2022 19:57:09 -0400 Subject: [PATCH 4/5] Add documentation for install_search_all_sources. --- docs/advanced.rst | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/docs/advanced.rst b/docs/advanced.rst index 1c33909f57..6d071b2b6b 100644 --- a/docs/advanced.rst +++ b/docs/advanced.rst @@ -62,6 +62,19 @@ as sub-dependencies must be mirrored onto your private index or they will not re standard recommendation of ``pip`` maintainers: "To correctly make a private project installable is to point --index-url to an index that contains both PyPI and their private projects—which is our recommended best practice." +The above documentation holds true for both ``lock`` resolution and ``sync`` of packages. It was suggested that +once the resolution and the lock file are updated, it is theoretically possible to safely scan multiple indexes +for these packages when running ``pipenv sync`` or ``pipenv install --deploy`` since it will verify the package +hashes match the allowed hashes that were already captured from a safe locking cycle. +To enable this non-default behavior, add ``install_search_all_sources = true`` option +to your ``Pipfile`` in the ``pipenv`` section:: + + [pipenv] + install_search_all_sources = true + +**Note:** The locking cycle will still requires that each package be resolved from a single index. This feature was +requested as a workaround in order to support organizations where not everyone has access to the package sources. + ☤ Using a PyPI Mirror ---------------------------- From fec7f34794a7b9b45e2ad550167ce5aa90ce0a18 Mon Sep 17 00:00:00 2001 From: Matt Davis Date: Wed, 20 Apr 2022 20:01:40 -0400 Subject: [PATCH 5/5] Add news fragment. --- news/5041.feature.rst | 2 ++ 1 file changed, 2 insertions(+) create mode 100644 news/5041.feature.rst diff --git a/news/5041.feature.rst b/news/5041.feature.rst new file mode 100644 index 0000000000..2da1f6a28d --- /dev/null +++ b/news/5041.feature.rst @@ -0,0 +1,2 @@ +Added new Pipenv option ``install_search_all_sources`` that allows installation of packages from an +existing ``Pipfile.lock`` to search all defined indexes for the constrained package version and hash signatures.