Skip to content

Commit dec26ce

Browse files
edvilmebrettcannonStanFromIreland
authored
gh-130698: Convert sys.ps1 and sys.ps2 to strings before PyREPL use (#158828)
Co-authored-by: Brett Cannon <brett@python.org> Co-authored-by: Stan Ulbrych <stan@python.org>
1 parent eacae21 commit dec26ce

3 files changed

Lines changed: 54 additions & 5 deletions

File tree

‎Lib/_pyrepl/simple_interact.py‎

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -134,9 +134,14 @@ def maybe_run_command(statement: str) -> bool:
134134
sys.stdout.flush()
135135
except Exception:
136136
pass
137-
138-
ps1 = getattr(sys, "ps1", ">>> ")
139-
ps2 = getattr(sys, "ps2", "... ")
137+
try:
138+
ps1 = str(getattr(sys, "ps1", ">>> "))
139+
except Exception:
140+
ps1 = ">>> "
141+
try:
142+
ps2 = str(getattr(sys, "ps2", "... "))
143+
except Exception:
144+
ps2 = "... "
140145
try:
141146
statement = multiline_input(more_lines, ps1, ps2)
142147
except EOFError:

‎Lib/test/test_pyrepl/test_interact.py‎

Lines changed: 44 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,58 @@
11
import contextlib
22
import io
3+
import sys
34
import warnings
45
import unittest
5-
from unittest.mock import patch
6+
from unittest.mock import ANY, patch
67
from textwrap import dedent
78

89
from test.support import force_not_colorized
910

1011
from _pyrepl.console import InteractiveColoredConsole
11-
from _pyrepl.simple_interact import _more_lines
12+
from _pyrepl.simple_interact import (
13+
_more_lines,
14+
run_multiline_interactive_console,
15+
)
1216

1317
class TestSimpleInteract(unittest.TestCase):
18+
def test_prompts_are_converted_to_strings(self):
19+
console = InteractiveColoredConsole()
20+
21+
class Prompt:
22+
def __init__(self, value):
23+
self.value = value
24+
25+
def __str__(self):
26+
return self.value
27+
28+
with (
29+
patch.object(sys, "ps1", Prompt("primary"), create=True),
30+
patch.object(sys, "ps2", Prompt("secondary"), create=True),
31+
patch("_pyrepl.readline._setup"),
32+
patch(
33+
"_pyrepl.simple_interact.multiline_input", side_effect=EOFError
34+
) as multiline_input,
35+
):
36+
run_multiline_interactive_console(console)
37+
38+
multiline_input.assert_called_once_with(ANY, "primary", "secondary")
39+
40+
def test_ps1_str_error_uses_default_prompt(self):
41+
class Prompt:
42+
def __str__(self):
43+
return 1 / 0
44+
45+
with (
46+
patch.object(sys, "ps1", Prompt(), create=True),
47+
patch("_pyrepl.readline._setup"),
48+
patch(
49+
"_pyrepl.simple_interact.multiline_input", side_effect=EOFError
50+
) as multiline_input,
51+
):
52+
run_multiline_interactive_console(InteractiveColoredConsole())
53+
54+
multiline_input.assert_called_once_with(ANY, ">>> ", ANY)
55+
1456
def test_multiple_statements(self):
1557
namespace = {}
1658
code = dedent("""\
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
Fix PyREPL to convert :data:`sys.ps1` and :data:`sys.ps2` to strings before
2+
use, and fall back to the default prompts if the conversion raises.

0 commit comments

Comments
 (0)