From 5a8ddcc4524dca3880d7fc2818814ffae1cfb8a2 Mon Sep 17 00:00:00 2001 From: "Gregory P. Smith" Date: Wed, 2 Jun 2021 21:15:26 -0700 Subject: [3.9] bpo-43776: Remove list call from args in Popen repr (GH-25338) (GH-26510) Removes the `list` call in the Popen `repr`. Current implementation: For cmd = `python --version`, with `shell=True`. ```bash ``` For `shell=False` and args=`['python', '--version']`, the output is correct: ```bash ``` With the new changes the `repr` yields: For cmd = `python --version`, with `shell=True`: ```bash ``` For `shell=False` and args=`['python', '--version']`, the output: ```bash ``` Automerge-Triggered-By: GH:gpshead. (cherry picked from commit db0c5b786df961785ae8c803f5572ae0c8dadcc7) Co-authored-by: M. Kocher Co-authored-by: M. Kocher --- Lib/subprocess.py | 2 +- Lib/test/test_subprocess.py | 40 ++++++++++------------ .../2021-04-12-00-00-00.bpo-43776.p14y7a.rst | 1 + 3 files changed, 20 insertions(+), 23 deletions(-) create mode 100644 Misc/NEWS.d/next/Library/2021-04-12-00-00-00.bpo-43776.p14y7a.rst diff --git a/Lib/subprocess.py b/Lib/subprocess.py index 0311e3a..4effc1d 100644 --- a/Lib/subprocess.py +++ b/Lib/subprocess.py @@ -989,7 +989,7 @@ class Popen(object): def __repr__(self): obj_repr = ( f"<{self.__class__.__name__}: " - f"returncode: {self.returncode} args: {list(self.args)!r}>" + f"returncode: {self.returncode} args: {self.args!r}>" ) if len(obj_repr) > 80: obj_repr = obj_repr[:76] + "...>" diff --git a/Lib/test/test_subprocess.py b/Lib/test/test_subprocess.py index e8f9699..ed04813 100644 --- a/Lib/test/test_subprocess.py +++ b/Lib/test/test_subprocess.py @@ -20,6 +20,7 @@ import threading import gc import textwrap import json +import pathlib from test.support import FakePath try: @@ -1373,28 +1374,23 @@ class ProcessTestCase(BaseTestCase): p.communicate(b"x" * 2**20) def test_repr(self): - # Run a command that waits for user input, to check the repr() of - # a Proc object while and after the sub-process runs. - code = 'import sys; input(); sys.exit(57)' - cmd = [sys.executable, '-c', code] - result = "') - ) - - proc.communicate(input='exit...\n') - proc.wait() - - self.assertIsNotNone(proc.returncode) - self.assertTrue( - repr(proc).startswith(result.format(proc.returncode)) and - repr(proc).endswith('>') - ) + path_cmd = pathlib.Path("my-tool.py") + pathlib_cls = path_cmd.__class__.__name__ + + cases = [ + ("ls", True, 123, ""), + ('a' * 100, True, 0, + ""), + (["ls"], False, None, ""), + (["ls", '--my-opts', 'a' * 100], False, None, + ""), + (path_cmd, False, 7, f"") + ] + with unittest.mock.patch.object(subprocess.Popen, '_execute_child'): + for cmd, shell, code, sx in cases: + p = subprocess.Popen(cmd, shell=shell) + p.returncode = code + self.assertEqual(repr(p), sx) def test_communicate_epipe_only_stdin(self): # Issue 10963: communicate() should hide EPIPE diff --git a/Misc/NEWS.d/next/Library/2021-04-12-00-00-00.bpo-43776.p14y7a.rst b/Misc/NEWS.d/next/Library/2021-04-12-00-00-00.bpo-43776.p14y7a.rst new file mode 100644 index 0000000..51bc791 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2021-04-12-00-00-00.bpo-43776.p14y7a.rst @@ -0,0 +1 @@ +When :class:`subprocess.Popen` args are provided as a string or as :class:`pathlib.Path`, the Popen instance repr now shows the right thing. \ No newline at end of file -- cgit v0.12