Skip to content

Commit 3f5b7ac

Browse files
committed
[3.9] gh-93975: Nicer error reporting in test_venv (GH-93959)
- gh-93957: Provide nicer error reporting from subprocesses in test_venv.EnsurePipTest.test_with_pip. - Update changelog This change does three things: 1. Extract a function for trapping output in subprocesses. 2. Emit both stdout and stderr when encountering an error. 3. Apply the change to `ensurepip._uninstall` check.. (cherry picked from commit 6066f45) Co-authored-by: Jason R. Coombs <[email protected]>
1 parent 893adbf commit 3f5b7ac

File tree

2 files changed

+28
-10
lines changed

2 files changed

+28
-10
lines changed

Lib/test/test_venv.py

Lines changed: 26 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
Licensed to the PSF under a contributor agreement.
66
"""
77

8+
import contextlib
89
import ensurepip
910
import os
1011
import os.path
@@ -479,16 +480,10 @@ def do_test_with_pip(self, system_site_packages):
479480

480481
# Actually run the create command with all that unhelpful
481482
# config in place to ensure we ignore it
482-
try:
483+
with self.nicer_error():
483484
self.run_with_capture(venv.create, self.env_dir,
484485
system_site_packages=system_site_packages,
485486
with_pip=True)
486-
except subprocess.CalledProcessError as exc:
487-
# The output this produces can be a little hard to read,
488-
# but at least it has all the details
489-
details = exc.output.decode(errors="replace")
490-
msg = "{}\n\n**Subprocess Output**\n{}"
491-
self.fail(msg.format(exc, details))
492487
# Ensure pip is available in the virtual environment
493488
envpy = os.path.join(os.path.realpath(self.env_dir), self.bindir, self.exe)
494489
# Ignore DeprecationWarning since pip code is not part of Python
@@ -508,9 +503,10 @@ def do_test_with_pip(self, system_site_packages):
508503
# Check the private uninstall command provided for the Windows
509504
# installers works (at least in a virtual environment)
510505
with EnvironmentVarGuard() as envvars:
511-
out, err = check_output([envpy,
512-
'-W', 'ignore::DeprecationWarning', '-I',
513-
'-m', 'ensurepip._uninstall'])
506+
with self.nicer_error():
507+
out, err = check_output([envpy,
508+
'-W', 'ignore::DeprecationWarning', '-I',
509+
'-m', 'ensurepip._uninstall'])
514510
# We force everything to text, so unittest gives the detailed diff
515511
# if we get unexpected results
516512
err = err.decode("latin-1") # Force to text, prevent decoding errors
@@ -536,12 +532,32 @@ def do_test_with_pip(self, system_site_packages):
536532
if not system_site_packages:
537533
self.assert_pip_not_installed()
538534

535+
@contextlib.contextmanager
536+
def nicer_error(self):
537+
"""
538+
Capture output from a failed subprocess for easier debugging.
539+
540+
The output this handler produces can be a little hard to read,
541+
but at least it has all the details.
542+
"""
543+
try:
544+
yield
545+
except subprocess.CalledProcessError as exc:
546+
out = exc.output.decode(errors="replace")
547+
err = exc.stderr.decode(errors="replace")
548+
self.fail(
549+
f"{exc}\n\n"
550+
f"**Subprocess Output**\n{out}\n\n"
551+
f"**Subprocess Error**\n{err}"
552+
)
553+
539554
# Issue #26610: pip/pep425tags.py requires ctypes
540555
@unittest.skipUnless(ctypes, 'pip requires ctypes')
541556
@requires_zlib()
542557
def test_with_pip(self):
543558
self.do_test_with_pip(False)
544559
self.do_test_with_pip(True)
545560

561+
546562
if __name__ == "__main__":
547563
unittest.main()
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
Provide nicer error reporting from subprocesses in
2+
test_venv.EnsurePipTest.test_with_pip.

0 commit comments

Comments
 (0)