Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Commit fe92193

Browse filesBrowse files
authored
gh-111201: Add tests for unix console class in pyrepl (#118653)
1 parent 9257731 commit fe92193
Copy full SHA for fe92193

File tree

1 file changed

+290
-2
lines changed
Filter options

1 file changed

+290
-2
lines changed

‎Lib/test/test_pyrepl.py

Copy file name to clipboardExpand all lines: Lib/test/test_pyrepl.py
+290-2Lines changed: 290 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
from code import InteractiveConsole
88
from functools import partial
99
from unittest import TestCase
10-
from unittest.mock import MagicMock, patch
10+
from unittest.mock import MagicMock, call, patch, ANY
1111

1212
from test.support import requires
1313
from test.support.import_helper import import_module
@@ -22,6 +22,7 @@
2222
from _pyrepl.console import Console, Event
2323
from _pyrepl.readline import ReadlineAlikeReader, ReadlineConfig
2424
from _pyrepl.simple_interact import _strip_final_indent
25+
from _pyrepl.unix_console import UnixConsole
2526
from _pyrepl.unix_eventqueue import EventQueue
2627
from _pyrepl.input import KeymapTranslator
2728
from _pyrepl.keymap import parse_keys, compile_keymap
@@ -105,7 +106,8 @@ def handle_all_events(
105106

106107

107108
handle_events_narrow_console = partial(
108-
handle_all_events, prepare_console=partial(prepare_mock_console, width=10)
109+
handle_all_events,
110+
prepare_console=partial(prepare_mock_console, width=10),
109111
)
110112

111113

@@ -1198,5 +1200,291 @@ def test_nested_multiple_keymaps(self):
11981200
self.assertEqual(result, {b"a": {b"b": {b"c": "action"}}})
11991201

12001202

1203+
def unix_console(events, **kwargs):
1204+
console = UnixConsole()
1205+
console.get_event = MagicMock(side_effect=events)
1206+
1207+
height = kwargs.get("height", 25)
1208+
width = kwargs.get("width", 80)
1209+
console.getheightwidth = MagicMock(side_effect=lambda: (height, width))
1210+
1211+
console.prepare()
1212+
for key, val in kwargs.items():
1213+
setattr(console, key, val)
1214+
return console
1215+
1216+
1217+
handle_events_unix_console = partial(
1218+
handle_all_events,
1219+
prepare_console=partial(unix_console),
1220+
)
1221+
handle_events_narrow_unix_console = partial(
1222+
handle_all_events,
1223+
prepare_console=partial(unix_console, width=5),
1224+
)
1225+
handle_events_short_unix_console = partial(
1226+
handle_all_events,
1227+
prepare_console=partial(unix_console, height=1),
1228+
)
1229+
handle_events_unix_console_height_3 = partial(
1230+
handle_all_events, prepare_console=partial(unix_console, height=3)
1231+
)
1232+
1233+
1234+
TERM_CAPABILITIES = {
1235+
"bel": b"\x07",
1236+
"civis": b"\x1b[?25l",
1237+
"clear": b"\x1b[H\x1b[2J",
1238+
"cnorm": b"\x1b[?12l\x1b[?25h",
1239+
"cub": b"\x1b[%p1%dD",
1240+
"cub1": b"\x08",
1241+
"cud": b"\x1b[%p1%dB",
1242+
"cud1": b"\n",
1243+
"cuf": b"\x1b[%p1%dC",
1244+
"cuf1": b"\x1b[C",
1245+
"cup": b"\x1b[%i%p1%d;%p2%dH",
1246+
"cuu": b"\x1b[%p1%dA",
1247+
"cuu1": b"\x1b[A",
1248+
"dch1": b"\x1b[P",
1249+
"dch": b"\x1b[%p1%dP",
1250+
"el": b"\x1b[K",
1251+
"hpa": b"\x1b[%i%p1%dG",
1252+
"ich": b"\x1b[%p1%d@",
1253+
"ich1": None,
1254+
"ind": b"\n",
1255+
"pad": None,
1256+
"ri": b"\x1bM",
1257+
"rmkx": b"\x1b[?1l\x1b>",
1258+
"smkx": b"\x1b[?1h\x1b=",
1259+
}
1260+
1261+
1262+
@patch("_pyrepl.curses.tigetstr", lambda s: TERM_CAPABILITIES.get(s))
1263+
@patch(
1264+
"_pyrepl.curses.tparm",
1265+
lambda s, *args: s + b":" + b",".join(str(i).encode() for i in args),
1266+
)
1267+
@patch("_pyrepl.curses.setupterm", lambda a, b: None)
1268+
@patch(
1269+
"termios.tcgetattr",
1270+
lambda _: [
1271+
27394,
1272+
3,
1273+
19200,
1274+
536872399,
1275+
38400,
1276+
38400,
1277+
[
1278+
b"\x04",
1279+
b"\xff",
1280+
b"\xff",
1281+
b"\x7f",
1282+
b"\x17",
1283+
b"\x15",
1284+
b"\x12",
1285+
b"\x00",
1286+
b"\x03",
1287+
b"\x1c",
1288+
b"\x1a",
1289+
b"\x19",
1290+
b"\x11",
1291+
b"\x13",
1292+
b"\x16",
1293+
b"\x0f",
1294+
b"\x01",
1295+
b"\x00",
1296+
b"\x14",
1297+
b"\x00",
1298+
],
1299+
],
1300+
)
1301+
@patch("termios.tcsetattr", lambda a, b, c: None)
1302+
@patch("os.write")
1303+
class TestConsole(TestCase):
1304+
def test_simple_addition(self, _os_write):
1305+
code = "12+34"
1306+
events = code_to_events(code)
1307+
_, _ = handle_events_unix_console(events)
1308+
_os_write.assert_any_call(ANY, b"1")
1309+
_os_write.assert_any_call(ANY, b"2")
1310+
_os_write.assert_any_call(ANY, b"+")
1311+
_os_write.assert_any_call(ANY, b"3")
1312+
_os_write.assert_any_call(ANY, b"4")
1313+
1314+
def test_wrap(self, _os_write):
1315+
code = "12+34"
1316+
events = code_to_events(code)
1317+
_, _ = handle_events_narrow_unix_console(events)
1318+
_os_write.assert_any_call(ANY, b"1")
1319+
_os_write.assert_any_call(ANY, b"2")
1320+
_os_write.assert_any_call(ANY, b"+")
1321+
_os_write.assert_any_call(ANY, b"3")
1322+
_os_write.assert_any_call(ANY, b"\\")
1323+
_os_write.assert_any_call(ANY, b"\n")
1324+
_os_write.assert_any_call(ANY, b"4")
1325+
1326+
def test_cursor_left(self, _os_write):
1327+
code = "1"
1328+
events = itertools.chain(
1329+
code_to_events(code),
1330+
[Event(evt="key", data="left", raw=bytearray(b"\x1bOD"))],
1331+
)
1332+
_, _ = handle_events_unix_console(events)
1333+
_os_write.assert_any_call(ANY, TERM_CAPABILITIES["cub"] + b":1")
1334+
1335+
def test_cursor_left_right(self, _os_write):
1336+
code = "1"
1337+
events = itertools.chain(
1338+
code_to_events(code),
1339+
[
1340+
Event(evt="key", data="left", raw=bytearray(b"\x1bOD")),
1341+
Event(evt="key", data="right", raw=bytearray(b"\x1bOC")),
1342+
],
1343+
)
1344+
_, _ = handle_events_unix_console(events)
1345+
_os_write.assert_any_call(ANY, TERM_CAPABILITIES["cub"] + b":1")
1346+
_os_write.assert_any_call(ANY, TERM_CAPABILITIES["cuf"] + b":1")
1347+
1348+
def test_cursor_up(self, _os_write):
1349+
code = "1\n2+3"
1350+
events = itertools.chain(
1351+
code_to_events(code),
1352+
[Event(evt="key", data="up", raw=bytearray(b"\x1bOA"))],
1353+
)
1354+
_, _ = handle_events_unix_console(events)
1355+
_os_write.assert_any_call(ANY, TERM_CAPABILITIES["cuu"] + b":1")
1356+
1357+
def test_cursor_up_down(self, _os_write):
1358+
code = "1\n2+3"
1359+
events = itertools.chain(
1360+
code_to_events(code),
1361+
[
1362+
Event(evt="key", data="up", raw=bytearray(b"\x1bOA")),
1363+
Event(evt="key", data="down", raw=bytearray(b"\x1bOB")),
1364+
],
1365+
)
1366+
_, _ = handle_events_unix_console(events)
1367+
_os_write.assert_any_call(ANY, TERM_CAPABILITIES["cuu"] + b":1")
1368+
_os_write.assert_any_call(ANY, TERM_CAPABILITIES["cud"] + b":1")
1369+
1370+
def test_cursor_back_write(self, _os_write):
1371+
events = itertools.chain(
1372+
code_to_events("1"),
1373+
[Event(evt="key", data="left", raw=bytearray(b"\x1bOD"))],
1374+
code_to_events("2"),
1375+
)
1376+
_, _ = handle_events_unix_console(events)
1377+
_os_write.assert_any_call(ANY, b"1")
1378+
_os_write.assert_any_call(ANY, TERM_CAPABILITIES["cub"] + b":1")
1379+
_os_write.assert_any_call(ANY, b"2")
1380+
1381+
def test_multiline_function_move_up_short_terminal(self, _os_write):
1382+
# fmt: off
1383+
code = (
1384+
"def f():\n"
1385+
" foo"
1386+
)
1387+
# fmt: on
1388+
1389+
events = itertools.chain(
1390+
code_to_events(code),
1391+
[
1392+
Event(evt="key", data="up", raw=bytearray(b"\x1bOA")),
1393+
Event(evt="scroll", data=None),
1394+
],
1395+
)
1396+
_, _ = handle_events_short_unix_console(events)
1397+
_os_write.assert_any_call(ANY, TERM_CAPABILITIES["ri"] + b":")
1398+
1399+
def test_multiline_function_move_up_down_short_terminal(self, _os_write):
1400+
# fmt: off
1401+
code = (
1402+
"def f():\n"
1403+
" foo"
1404+
)
1405+
# fmt: on
1406+
1407+
events = itertools.chain(
1408+
code_to_events(code),
1409+
[
1410+
Event(evt="key", data="up", raw=bytearray(b"\x1bOA")),
1411+
Event(evt="scroll", data=None),
1412+
Event(evt="key", data="down", raw=bytearray(b"\x1bOB")),
1413+
Event(evt="scroll", data=None),
1414+
],
1415+
)
1416+
_, _ = handle_events_short_unix_console(events)
1417+
_os_write.assert_any_call(ANY, TERM_CAPABILITIES["ri"] + b":")
1418+
_os_write.assert_any_call(ANY, TERM_CAPABILITIES["ind"] + b":")
1419+
1420+
def test_resize_bigger_on_multiline_function(self, _os_write):
1421+
# fmt: off
1422+
code = (
1423+
"def f():\n"
1424+
" foo"
1425+
)
1426+
# fmt: on
1427+
1428+
events = itertools.chain(code_to_events(code))
1429+
reader, console = handle_events_short_unix_console(events)
1430+
1431+
console.height = 2
1432+
console.getheightwidth = MagicMock(lambda _: (2, 80))
1433+
1434+
def same_reader(_):
1435+
return reader
1436+
1437+
def same_console(events):
1438+
console.get_event = MagicMock(side_effect=events)
1439+
return console
1440+
1441+
_, _ = handle_all_events(
1442+
[Event(evt="resize", data=None)],
1443+
prepare_reader=same_reader,
1444+
prepare_console=same_console,
1445+
)
1446+
_os_write.assert_has_calls(
1447+
[
1448+
call(ANY, TERM_CAPABILITIES["ri"] + b":"),
1449+
call(ANY, TERM_CAPABILITIES["cup"] + b":0,0"),
1450+
call(ANY, b"def f():"),
1451+
]
1452+
)
1453+
1454+
def test_resize_smaller_on_multiline_function(self, _os_write):
1455+
# fmt: off
1456+
code = (
1457+
"def f():\n"
1458+
" foo"
1459+
)
1460+
# fmt: on
1461+
1462+
events = itertools.chain(code_to_events(code))
1463+
reader, console = handle_events_unix_console_height_3(events)
1464+
1465+
console.height = 1
1466+
console.getheightwidth = MagicMock(lambda _: (1, 80))
1467+
1468+
def same_reader(_):
1469+
return reader
1470+
1471+
def same_console(events):
1472+
console.get_event = MagicMock(side_effect=events)
1473+
return console
1474+
1475+
_, _ = handle_all_events(
1476+
[Event(evt="resize", data=None)],
1477+
prepare_reader=same_reader,
1478+
prepare_console=same_console,
1479+
)
1480+
_os_write.assert_has_calls(
1481+
[
1482+
call(ANY, TERM_CAPABILITIES["ind"] + b":"),
1483+
call(ANY, TERM_CAPABILITIES["cup"] + b":0,0"),
1484+
call(ANY, b" foo"),
1485+
]
1486+
)
1487+
1488+
12011489
if __name__ == "__main__":
12021490
unittest.main()

0 commit comments

Comments
0 (0)
Morty Proxy This is a proxified and sanitized view of the page, visit original site.