Skip to content

Commit 7f16b4b

Browse files
committed
improve tests
1 parent 64ff638 commit 7f16b4b

File tree

1 file changed

+39
-23
lines changed

1 file changed

+39
-23
lines changed

Lib/test/test_pyrepl/test_interact.py

Lines changed: 39 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
from unittest.mock import patch
66
from textwrap import dedent
77

8-
from test.support import force_not_colorized
8+
from test.support import captured_stdout, force_not_colorized
99

1010
from _pyrepl.console import InteractiveColoredConsole
1111
from _pyrepl.simple_interact import _more_lines
@@ -134,11 +134,7 @@ def test_runsource_shows_syntax_error_for_failed_compilation(self):
134134
def test_runsource_shows_syntax_error_for_failed_symtable_checks(self):
135135
# Some checks cannot be performed by AST parsing only.
136136
# See https://github.com/python/cpython/issues/137376.
137-
console = InteractiveColoredConsole()
138-
source = "x = 1; global x; x = 2"
139-
with patch.object(console, "showsyntaxerror") as mock_showsyntaxerror:
140-
console.runsource(source)
141-
mock_showsyntaxerror.assert_called_once()
137+
self._test_runsource_error("x = 1; global x; x = 2")
142138

143139
def test_runsource_survives_null_bytes(self):
144140
console = InteractiveColoredConsole()
@@ -162,26 +158,46 @@ def test_no_active_future(self):
162158
self.assertEqual(f.getvalue(), "{'x': <class 'int'>}\n")
163159

164160
def test_future_annotations(self):
165-
console = InteractiveColoredConsole()
166-
source = dedent("""\
167-
from __future__ import annotations
168-
def g(x: int): ...
169-
print(g.__annotations__)
170-
""")
171-
f = io.StringIO()
172-
with contextlib.redirect_stdout(f):
173-
result = console.runsource(source)
174-
self.assertFalse(result)
175-
self.assertEqual(f.getvalue(), "{'x': 'int'}\n")
161+
self._test_runsource_future(
162+
"from __future__ import annotations",
163+
["def g(x: int): ...", "print(g.__annotations__)"],
164+
"{'x': 'int'}\n",
165+
)
176166

177167
def test_future_barry_as_flufl(self):
168+
self._test_runsource_future(
169+
"from __future__ import barry_as_FLUFL",
170+
["""print("black" <> 'blue')"""],
171+
"True\n",
172+
)
173+
174+
def _test_runsource_error(self, buggy_source):
178175
console = InteractiveColoredConsole()
179-
f = io.StringIO()
180-
with contextlib.redirect_stdout(f):
181-
result = console.runsource("from __future__ import barry_as_FLUFL\n")
182-
result = console.runsource("""print("black" <> 'blue')\n""")
183-
self.assertFalse(result)
184-
self.assertEqual(f.getvalue(), "True\n")
176+
with patch.object(console, "showsyntaxerror") as handler:
177+
result = console.runsource(buggy_source)
178+
handler.assert_called_once()
179+
180+
def _test_runsource_future(self, future_statement, statements, expected):
181+
"""Run future_statement + statements.
182+
183+
This checks whether a standalone future statement remains active
184+
for the entire session lifetime.
185+
"""
186+
with self.subTest("standalone source"):
187+
console = InteractiveColoredConsole()
188+
source = "\n".join([future_statement, *statements])
189+
with captured_stdout() as stdout:
190+
result = console.runsource(source)
191+
self.assertFalse(result)
192+
self.assertEqual(stdout.getvalue(), expected)
193+
194+
with self.subTest("__future__ executed separtely"):
195+
console = InteractiveColoredConsole()
196+
with captured_stdout() as stdout:
197+
result = console.runsource(future_statement)
198+
result = console.runsource("\n".join(statements))
199+
self.assertFalse(result)
200+
self.assertEqual(stdout.getvalue(), expected)
185201

186202

187203
class TestMoreLines(unittest.TestCase):

0 commit comments

Comments
 (0)