Skip to content

Commit db0c5b7

Browse files
authored
bpo-43776: Remove list call from args in Popen repr (pythonGH-25338)
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
1 parent f9bedb6 commit db0c5b7

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
@@ -1003,7 +1003,7 @@ def __init__(self, args, bufsize=-1, executable=None,
10031003
def __repr__(self):
10041004
obj_repr = (
10051005
f"<{self.__class__.__name__}: "
1006-
f"returncode: {self.returncode} args: {list(self.args)!r}>"
1006+
f"returncode: {self.returncode} args: {self.args!r}>"
10071007
)
10081008
if len(obj_repr) > 80:
10091009
obj_repr = obj_repr[:76] + "...>"

Lib/test/test_subprocess.py

Lines changed: 18 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
import gc
2424
import textwrap
2525
import json
26+
import pathlib
2627
from test.support.os_helper import FakePath
2728

2829
try:
@@ -1442,28 +1443,23 @@ def test_communicate_epipe(self):
14421443
p.communicate(b"x" * 2**20)
14431444

14441445
def test_repr(self):
1445-
# Run a command that waits for user input, to check the repr() of
1446-
# a Proc object while and after the sub-process runs.
1447-
code = 'import sys; input(); sys.exit(57)'
1448-
cmd = [sys.executable, '-c', code]
1449-
result = "<Popen: returncode: {}"
1450-
1451-
with subprocess.Popen(
1452-
cmd, stdin=subprocess.PIPE, universal_newlines=True) as proc:
1453-
self.assertIsNone(proc.returncode)
1454-
self.assertTrue(
1455-
repr(proc).startswith(result.format(proc.returncode)) and
1456-
repr(proc).endswith('>')
1457-
)
1458-
1459-
proc.communicate(input='exit...\n')
1460-
proc.wait()
1461-
1462-
self.assertIsNotNone(proc.returncode)
1463-
self.assertTrue(
1464-
repr(proc).startswith(result.format(proc.returncode)) and
1465-
repr(proc).endswith('>')
1466-
)
1446+
path_cmd = pathlib.Path("my-tool.py")
1447+
pathlib_cls = path_cmd.__class__.__name__
1448+
1449+
cases = [
1450+
("ls", True, 123, "<Popen: returncode: 123 args: 'ls'>"),
1451+
('a' * 100, True, 0,
1452+
"<Popen: returncode: 0 args: 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa...>"),
1453+
(["ls"], False, None, "<Popen: returncode: None args: ['ls']>"),
1454+
(["ls", '--my-opts', 'a' * 100], False, None,
1455+
"<Popen: returncode: None args: ['ls', '--my-opts', 'aaaaaaaaaaaaaaaaaaaaaaaa...>"),
1456+
(path_cmd, False, 7, f"<Popen: returncode: 7 args: {pathlib_cls}('my-tool.py')>")
1457+
]
1458+
with unittest.mock.patch.object(subprocess.Popen, '_execute_child'):
1459+
for cmd, shell, code, sx in cases:
1460+
p = subprocess.Popen(cmd, shell=shell)
1461+
p.returncode = code
1462+
self.assertEqual(repr(p), sx)
14671463

14681464
def test_communicate_epipe_only_stdin(self):
14691465
# 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)