Skip to content

Commit 6edd157

Browse files
miss-islingtonedvilmebrettcannonStanFromIreland
authored
[3.14] gh-130698: Convert sys.ps1 and sys.ps2 to strings before PyREPL use (GH-158828) (#160546)
(cherry picked from commit dec26ce) Co-authored-by: Eduardo Villalpando Mello <eduardovil@microsoft.com> Co-authored-by: Brett Cannon <brett@python.org> Co-authored-by: Stan Ulbrych <stan@python.org>
1 parent e9bf2cf commit 6edd157

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
@@ -136,9 +136,14 @@ def maybe_run_command(statement: str) -> bool:
136136
sys.stdout.flush()
137137
except Exception:
138138
pass
139-
140-
ps1 = getattr(sys, "ps1", ">>> ")
141-
ps2 = getattr(sys, "ps2", "... ")
139+
try:
140+
ps1 = str(getattr(sys, "ps1", ">>> "))
141+
except Exception:
142+
ps1 = ">>> "
143+
try:
144+
ps2 = str(getattr(sys, "ps2", "... "))
145+
except Exception:
146+
ps2 = "... "
142147
try:
143148
statement = multiline_input(more_lines, ps1, ps2)
144149
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)