[Python-checkins] gh-93975: Nicer error reporting in test_venv (GH-93959)

miss-islington webhook-mailer at python.org
Sat Jun 18 16:47:36 EDT 2022


https://github.com/python/cpython/commit/6066f450b91f1cbebf33a245c14e660052ccd90a
commit: 6066f450b91f1cbebf33a245c14e660052ccd90a
branch: main
author: Jason R. Coombs <jaraco at jaraco.com>
committer: miss-islington <31488909+miss-islington at users.noreply.github.com>
date: 2022-06-18T13:47:27-07:00
summary:

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.

files:
A Misc/NEWS.d/next/Tests/2022-06-17-13-55-11.gh-issue-93957.X4ovYV.rst
M Lib/test/test_venv.py

diff --git a/Lib/test/test_venv.py b/Lib/test/test_venv.py
index e6a870fcf2200..1545a94affc5e 100644
--- a/Lib/test/test_venv.py
+++ b/Lib/test/test_venv.py
@@ -5,6 +5,7 @@
 Licensed to the PSF under a contributor agreement.
 """
 
+import contextlib
 import ensurepip
 import os
 import os.path
@@ -558,16 +559,10 @@ def do_test_with_pip(self, system_site_packages):
 
                 # Actually run the create command with all that unhelpful
                 # config in place to ensure we ignore it
-                try:
+                with self.nicer_error():
                     self.run_with_capture(venv.create, self.env_dir,
                                           system_site_packages=system_site_packages,
                                           with_pip=True)
-                except subprocess.CalledProcessError as exc:
-                    # The output this produces can be a little hard to read,
-                    # but at least it has all the details
-                    details = exc.output.decode(errors="replace")
-                    msg = "{}\n\n**Subprocess Output**\n{}"
-                    self.fail(msg.format(exc, details))
         # Ensure pip is available in the virtual environment
         envpy = os.path.join(os.path.realpath(self.env_dir), self.bindir, self.exe)
         # Ignore DeprecationWarning since pip code is not part of Python
@@ -588,13 +583,14 @@ def do_test_with_pip(self, system_site_packages):
         # Check the private uninstall command provided for the Windows
         # installers works (at least in a virtual environment)
         with EnvironmentVarGuard() as envvars:
-            # It seems ensurepip._uninstall calls subprocesses which do not
-            # inherit the interpreter settings.
-            envvars["PYTHONWARNINGS"] = "ignore"
-            out, err = check_output([envpy,
-                '-W', 'ignore::DeprecationWarning',
-                '-W', 'ignore::ImportWarning', '-I',
-                '-m', 'ensurepip._uninstall'])
+            with self.nicer_error():
+                # It seems ensurepip._uninstall calls subprocesses which do not
+                # inherit the interpreter settings.
+                envvars["PYTHONWARNINGS"] = "ignore"
+                out, err = check_output([envpy,
+                    '-W', 'ignore::DeprecationWarning',
+                    '-W', 'ignore::ImportWarning', '-I',
+                    '-m', 'ensurepip._uninstall'])
         # We force everything to text, so unittest gives the detailed diff
         # if we get unexpected results
         err = err.decode("latin-1") # Force to text, prevent decoding errors
@@ -620,10 +616,30 @@ def do_test_with_pip(self, system_site_packages):
         if not system_site_packages:
             self.assert_pip_not_installed()
 
+    @contextlib.contextmanager
+    def nicer_error(self):
+        """
+        Capture output from a failed subprocess for easier debugging.
+
+        The output this handler produces can be a little hard to read,
+        but at least it has all the details.
+        """
+        try:
+            yield
+        except subprocess.CalledProcessError as exc:
+            out = exc.output.decode(errors="replace")
+            err = exc.stderr.decode(errors="replace")
+            self.fail(
+                f"{exc}\n\n"
+                f"**Subprocess Output**\n{out}\n\n"
+                f"**Subprocess Error**\n{err}"
+            )
+
     @requires_venv_with_pip()
     def test_with_pip(self):
         self.do_test_with_pip(False)
         self.do_test_with_pip(True)
 
+
 if __name__ == "__main__":
     unittest.main()
diff --git a/Misc/NEWS.d/next/Tests/2022-06-17-13-55-11.gh-issue-93957.X4ovYV.rst b/Misc/NEWS.d/next/Tests/2022-06-17-13-55-11.gh-issue-93957.X4ovYV.rst
new file mode 100644
index 0000000000000..2719933f6b94c
--- /dev/null
+++ b/Misc/NEWS.d/next/Tests/2022-06-17-13-55-11.gh-issue-93957.X4ovYV.rst
@@ -0,0 +1,2 @@
+Provide nicer error reporting from subprocesses in
+test_venv.EnsurePipTest.test_with_pip.



More information about the Python-checkins mailing list