Skip to content

Commit 6700d00

Browse files
authored
Fix sequential sync losing track of pip install processes (#3537)
Fix sequential sync losing track of pip install processes Co-authored-by: Dan Ryan <[email protected]>
2 parents b564376 + 06f3cae commit 6700d00

File tree

3 files changed

+63
-17
lines changed

3 files changed

+63
-17
lines changed

news/3537.bugfix.rst

+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Fix ``sync --sequential`` ignoring ``pip install`` errors and logs.

pipenv/core.py

+18-17
Original file line numberDiff line numberDiff line change
@@ -645,10 +645,10 @@ def do_where(virtualenv=False, bare=True):
645645
click.echo(location)
646646

647647

648-
def _cleanup_procs(procs, concurrent, failed_deps_queue, retry=True):
648+
def _cleanup_procs(procs, failed_deps_queue, retry=True):
649649
while not procs.empty():
650650
c = procs.get()
651-
if concurrent:
651+
if not c.blocking:
652652
c.block()
653653
failed = False
654654
if c.return_code != 0:
@@ -682,7 +682,7 @@ def _cleanup_procs(procs, concurrent, failed_deps_queue, retry=True):
682682
def batch_install(deps_list, procs, failed_deps_queue,
683683
requirements_dir, no_deps=False, ignore_hashes=False,
684684
allow_global=False, blocking=False, pypi_mirror=None,
685-
nprocs=PIPENV_MAX_SUBPROCESS, retry=True):
685+
retry=True):
686686
from .vendor.requirementslib.models.utils import strip_extras_markers_from_requirement
687687
failed = (not retry)
688688
if not failed:
@@ -753,12 +753,13 @@ def batch_install(deps_list, procs, failed_deps_queue,
753753
extra_indexes=extra_indexes,
754754
use_pep517=not failed,
755755
)
756-
if procs.qsize() < nprocs:
757-
c.dep = dep
758-
procs.put(c)
756+
c.dep = dep
757+
if dep.is_vcs or dep.editable:
758+
c.block()
759759

760+
procs.put(c)
760761
if procs.full() or procs.qsize() == len(deps_list):
761-
_cleanup_procs(procs, not blocking, failed_deps_queue, retry=retry)
762+
_cleanup_procs(procs, failed_deps_queue, retry=retry)
762763

763764

764765
def do_install_dependencies(
@@ -782,7 +783,6 @@ def do_install_dependencies(
782783
from six.moves import queue
783784
if requirements:
784785
bare = True
785-
blocking = not concurrent
786786
# Load the lockfile if it exists, or if only is being used (e.g. lock is being used).
787787
if skip_lock or only or not project.lockfile_exists:
788788
if not bare:
@@ -818,27 +818,27 @@ def do_install_dependencies(
818818
)
819819
sys.exit(0)
820820

821-
procs = queue.Queue(maxsize=PIPENV_MAX_SUBPROCESS)
821+
if concurrent:
822+
nprocs = PIPENV_MAX_SUBPROCESS
823+
else:
824+
nprocs = 1
825+
procs = queue.Queue(maxsize=nprocs)
822826
failed_deps_queue = queue.Queue()
823827
if skip_lock:
824828
ignore_hashes = True
825829

826830
install_kwargs = {
827831
"no_deps": no_deps, "ignore_hashes": ignore_hashes, "allow_global": allow_global,
828-
"blocking": blocking, "pypi_mirror": pypi_mirror
832+
"blocking": not concurrent, "pypi_mirror": pypi_mirror
829833
}
830-
if concurrent:
831-
install_kwargs["nprocs"] = PIPENV_MAX_SUBPROCESS
832-
else:
833-
install_kwargs["nprocs"] = 1
834834

835835
# with project.environment.activated():
836836
batch_install(
837837
deps_list, procs, failed_deps_queue, requirements_dir, **install_kwargs
838838
)
839839

840840
if not procs.empty():
841-
_cleanup_procs(procs, concurrent, failed_deps_queue)
841+
_cleanup_procs(procs, failed_deps_queue)
842842

843843
# Iterate over the hopefully-poorly-packaged dependencies…
844844
if not failed_deps_queue.empty():
@@ -850,15 +850,14 @@ def do_install_dependencies(
850850
failed_dep = failed_deps_queue.get()
851851
retry_list.append(failed_dep)
852852
install_kwargs.update({
853-
"nprocs": 1,
854853
"retry": False,
855854
"blocking": True,
856855
})
857856
batch_install(
858857
retry_list, procs, failed_deps_queue, requirements_dir, **install_kwargs
859858
)
860859
if not procs.empty():
861-
_cleanup_procs(procs, False, failed_deps_queue, retry=False)
860+
_cleanup_procs(procs, failed_deps_queue, retry=False)
862861

863862

864863
def convert_three_to_python(three, python):
@@ -2507,6 +2506,8 @@ def do_run(command, args, three=None, python=False, pypi_mirror=None):
25072506
previous_pipenv_active_value = os.environ.get("PIPENV_ACTIVE")
25082507
os.environ["PIPENV_ACTIVE"] = vistir.misc.fs_str("1")
25092508

2509+
os.environ.pop("PIP_SHIMS_BASE_MODULE", None)
2510+
25102511
try:
25112512
script = project.build_script(command, args)
25122513
cmd_string = ' '.join([script.command] + script.args)

tests/integration/test_sync.py

+44
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
# -*- coding: utf-8 -*-
22
from __future__ import absolute_import, print_function
3+
import json
34
import os
45

56
import pytest
@@ -68,3 +69,46 @@ def test_sync_should_not_lock(PipenvInstance, pypi):
6869
c = p.pipenv('sync')
6970
assert c.return_code == 0
7071
assert lockfile_content == p.lockfile
72+
73+
74+
@pytest.mark.sync
75+
@pytest.mark.lock
76+
def test_sync_sequential_detect_errors(PipenvInstance, pypi):
77+
with PipenvInstance(pypi=pypi) as p:
78+
with open(p.pipfile_path, 'w') as f:
79+
contents = """
80+
[packages]
81+
requests = "*"
82+
""".strip()
83+
f.write(contents)
84+
85+
c = p.pipenv('lock')
86+
assert c.return_code == 0
87+
88+
# Force hash mismatch when installing `requests`
89+
lock = p.lockfile
90+
lock['default']['requests']['hashes'] = ['sha256:' + '0' * 64]
91+
with open(p.lockfile_path, 'w') as f:
92+
json.dump(lock, f)
93+
94+
c = p.pipenv('sync --sequential')
95+
assert c.return_code != 0
96+
97+
98+
@pytest.mark.sync
99+
@pytest.mark.lock
100+
def test_sync_sequential_verbose(PipenvInstance, pypi):
101+
with PipenvInstance(pypi=pypi) as p:
102+
with open(p.pipfile_path, 'w') as f:
103+
contents = """
104+
[packages]
105+
requests = "*"
106+
""".strip()
107+
f.write(contents)
108+
109+
c = p.pipenv('lock')
110+
assert c.return_code == 0
111+
112+
c = p.pipenv('sync --sequential --verbose')
113+
for package in p.lockfile['default']:
114+
assert 'Successfully installed {}'.format(package) in c.out

0 commit comments

Comments
 (0)