]> git.ipfire.org Git - thirdparty/Python/cpython.git/commitdiff
gh-93975: Nicer error reporting in test_venv (GH-93959)
authorJason R. Coombs <jaraco@jaraco.com>
Sat, 18 Jun 2022 20:47:27 +0000 (16:47 -0400)
committerGitHub <noreply@github.com>
Sat, 18 Jun 2022 20:47:27 +0000 (13:47 -0700)
- 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.

Lib/test/test_venv.py
Misc/NEWS.d/next/Tests/2022-06-17-13-55-11.gh-issue-93957.X4ovYV.rst [new file with mode: 0644]

index e6a870fcf22008297c5f2daf7d8ebe5661923d31..1545a94affc5e4d850ae9858f24ebe7887e10ddc 100644 (file)
@@ -5,6 +5,7 @@ Copyright (C) 2011-2012 Vinay Sajip.
 Licensed to the PSF under a contributor agreement.
 """
 
+import contextlib
 import ensurepip
 import os
 import os.path
@@ -558,16 +559,10 @@ class EnsurePipTest(BaseTest):
 
                 # 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 @@ class EnsurePipTest(BaseTest):
         # 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 @@ class EnsurePipTest(BaseTest):
         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 (file)
index 0000000..2719933
--- /dev/null
@@ -0,0 +1,2 @@
+Provide nicer error reporting from subprocesses in
+test_venv.EnsurePipTest.test_with_pip.