Skip to content

Commit 5a8ddcc

Browse files
gpsheadmpkocher
andauthored
[3.9] bpo-43776: Remove list call from args in Popen repr (pythonGH-25338) (pythonGH-26510)
Removes the `list` call in the Popen `repr`. Current implementation: For cmd = `python --version`, with `shell=True`. ```bash <Popen: returncode: None args: ['p', 'y', 't', 'h', 'o', 'n', ' ', '-', '-',...> ``` For `shell=False` and args=`['python', '--version']`, the output is correct: ```bash <Popen: returncode: None args: ['python', '--version']> ``` With the new changes the `repr` yields: For cmd = `python --version`, with `shell=True`: ```bash <Popen: returncode: None args: 'python --version'> ``` For `shell=False` and args=`['python', '--version']`, the output: ```bash <Popen: returncode: None args: ['python', '--version']> ``` Automerge-Triggered-By: GH:gpshead. (cherry picked from commit db0c5b7) Co-authored-by: M. Kocher <[email protected]> Co-authored-by: M. Kocher <[email protected]>
1 parent 5df4abd commit 5a8ddcc

File tree

3 files changed

+20
-23
lines changed

3 files changed

+20
-23
lines changed

Lib/subprocess.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -989,7 +989,7 @@ def __init__(self, args, bufsize=-1, executable=None,
989989
def __repr__(self):
990990
obj_repr = (
991991
f"<{self.__class__.__name__}: "
992-
f"returncode: {self.returncode} args: {list(self.args)!r}>"
992+
f"returncode: {self.returncode} args: {self.args!r}>"
993993
)
994994
if len(obj_repr) > 80:
995995
obj_repr = obj_repr[:76] + "...>"

Lib/test/test_subprocess.py

Lines changed: 18 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
import gc
2121
import textwrap
2222
import json
23+
import pathlib
2324
from test.support import FakePath
2425

2526
try:
@@ -1373,28 +1374,23 @@ def test_communicate_epipe(self):
13731374
p.communicate(b"x" * 2**20)
13741375

13751376
def test_repr(self):
1376-
# Run a command that waits for user input, to check the repr() of
1377-
# a Proc object while and after the sub-process runs.
1378-
code = 'import sys; input(); sys.exit(57)'
1379-
cmd = [sys.executable, '-c', code]
1380-
result = "<Popen: returncode: {}"
1381-
1382-
with subprocess.Popen(
1383-
cmd, stdin=subprocess.PIPE, universal_newlines=True) as proc:
1384-
self.assertIsNone(proc.returncode)
1385-
self.assertTrue(
1386-
repr(proc).startswith(result.format(proc.returncode)) and
1387-
repr(proc).endswith('>')
1388-
)
1389-
1390-
proc.communicate(input='exit...\n')
1391-
proc.wait()
1392-
1393-
self.assertIsNotNone(proc.returncode)
1394-
self.assertTrue(
1395-
repr(proc).startswith(result.format(proc.returncode)) and
1396-
repr(proc).endswith('>')
1397-
)
1377+
path_cmd = pathlib.Path("my-tool.py")
1378+
pathlib_cls = path_cmd.__class__.__name__
1379+
1380+
cases = [
1381+
("ls", True, 123, "<Popen: returncode: 123 args: 'ls'>"),
1382+
('a' * 100, True, 0,
1383+
"<Popen: returncode: 0 args: 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa...>"),
1384+
(["ls"], False, None, "<Popen: returncode: None args: ['ls']>"),
1385+
(["ls", '--my-opts', 'a' * 100], False, None,
1386+
"<Popen: returncode: None args: ['ls', '--my-opts', 'aaaaaaaaaaaaaaaaaaaaaaaa...>"),
1387+
(path_cmd, False, 7, f"<Popen: returncode: 7 args: {pathlib_cls}('my-tool.py')>")
1388+
]
1389+
with unittest.mock.patch.object(subprocess.Popen, '_execute_child'):
1390+
for cmd, shell, code, sx in cases:
1391+
p = subprocess.Popen(cmd, shell=shell)
1392+
p.returncode = code
1393+
self.assertEqual(repr(p), sx)
13981394

13991395
def test_communicate_epipe_only_stdin(self):
14001396
# Issue 10963: communicate() should hide EPIPE
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
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.

0 commit comments

Comments
 (0)