Skip to content

Commit a443e54

Browse files
pablogsalambv
andauthored
gh-111201: Add more tests to test_pyrepl to cover key translation (#118705)
Co-authored-by: Łukasz Langa <[email protected]>
1 parent fe67af1 commit a443e54

File tree

1 file changed

+181
-8
lines changed

1 file changed

+181
-8
lines changed

Lib/test/test_pyrepl.py

Lines changed: 181 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,8 @@
2323
from _pyrepl.readline import ReadlineAlikeReader, ReadlineConfig
2424
from _pyrepl.simple_interact import _strip_final_indent
2525
from _pyrepl.unix_eventqueue import EventQueue
26-
from _pyrepl.simple_interact import InteractiveColoredConsole
26+
from _pyrepl.input import KeymapTranslator
27+
from _pyrepl.keymap import parse_keys, compile_keymap
2728

2829

2930
def more_lines(unicodetext, namespace=None):
@@ -617,10 +618,10 @@ def test_updown_arrow_with_completion_menu(self):
617618
events = itertools.chain(
618619
code_to_events(code),
619620
[
620-
Event(evt='key', data='up', raw=bytearray(b'\x1bOA')),
621+
Event(evt="key", data="up", raw=bytearray(b"\x1bOA")),
621622
Event(evt="key", data="down", raw=bytearray(b"\x1bOB")),
622623
],
623-
code_to_events("\n")
624+
code_to_events("\n"),
624625
)
625626
reader = self.prepare_reader(events, namespace=namespace)
626627
output = multiline_input(reader, namespace)
@@ -1017,13 +1018,185 @@ def test_setpos_fromxy_in_wrapped_line(self):
10171018
self.assertEqual(reader.pos, 9)
10181019

10191020
def test_up_arrow_after_ctrl_r(self):
1020-
events = iter([
1021-
Event(evt='key', data='\x12', raw=bytearray(b'\x12')),
1022-
Event(evt='key', data='up', raw=bytearray(b'\x1bOA')),
1023-
])
1021+
events = iter(
1022+
[
1023+
Event(evt="key", data="\x12", raw=bytearray(b"\x12")),
1024+
Event(evt="key", data="up", raw=bytearray(b"\x1bOA")),
1025+
]
1026+
)
10241027

10251028
reader, _ = handle_all_events(events)
10261029
self.assert_screen_equals(reader, "")
10271030

1028-
if __name__ == '__main__':
1031+
1032+
class KeymapTranslatorTests(unittest.TestCase):
1033+
def test_push_single_key(self):
1034+
keymap = [("a", "command_a")]
1035+
translator = KeymapTranslator(keymap)
1036+
evt = Event("key", "a")
1037+
translator.push(evt)
1038+
result = translator.get()
1039+
self.assertEqual(result, ("command_a", ["a"]))
1040+
1041+
def test_push_multiple_keys(self):
1042+
keymap = [("ab", "command_ab")]
1043+
translator = KeymapTranslator(keymap)
1044+
evt1 = Event("key", "a")
1045+
evt2 = Event("key", "b")
1046+
translator.push(evt1)
1047+
translator.push(evt2)
1048+
result = translator.get()
1049+
self.assertEqual(result, ("command_ab", ["a", "b"]))
1050+
1051+
def test_push_invalid_key(self):
1052+
keymap = [("a", "command_a")]
1053+
translator = KeymapTranslator(keymap)
1054+
evt = Event("key", "b")
1055+
translator.push(evt)
1056+
result = translator.get()
1057+
self.assertEqual(result, (None, ["b"]))
1058+
1059+
def test_push_invalid_key_with_stack(self):
1060+
keymap = [("ab", "command_ab")]
1061+
translator = KeymapTranslator(keymap)
1062+
evt1 = Event("key", "a")
1063+
evt2 = Event("key", "c")
1064+
translator.push(evt1)
1065+
translator.push(evt2)
1066+
result = translator.get()
1067+
self.assertEqual(result, (None, ["a", "c"]))
1068+
1069+
def test_push_character_key(self):
1070+
keymap = [("a", "command_a")]
1071+
translator = KeymapTranslator(keymap)
1072+
evt = Event("key", "a")
1073+
translator.push(evt)
1074+
result = translator.get()
1075+
self.assertEqual(result, ("command_a", ["a"]))
1076+
1077+
def test_push_character_key_with_stack(self):
1078+
keymap = [("ab", "command_ab")]
1079+
translator = KeymapTranslator(keymap)
1080+
evt1 = Event("key", "a")
1081+
evt2 = Event("key", "b")
1082+
evt3 = Event("key", "c")
1083+
translator.push(evt1)
1084+
translator.push(evt2)
1085+
translator.push(evt3)
1086+
result = translator.get()
1087+
self.assertEqual(result, ("command_ab", ["a", "b"]))
1088+
1089+
def test_push_transition_key(self):
1090+
keymap = [("a", {"b": "command_ab"})]
1091+
translator = KeymapTranslator(keymap)
1092+
evt1 = Event("key", "a")
1093+
evt2 = Event("key", "b")
1094+
translator.push(evt1)
1095+
translator.push(evt2)
1096+
result = translator.get()
1097+
self.assertEqual(result, ("command_ab", ["a", "b"]))
1098+
1099+
def test_push_transition_key_interrupted(self):
1100+
keymap = [("a", {"b": "command_ab"})]
1101+
translator = KeymapTranslator(keymap)
1102+
evt1 = Event("key", "a")
1103+
evt2 = Event("key", "c")
1104+
evt3 = Event("key", "b")
1105+
translator.push(evt1)
1106+
translator.push(evt2)
1107+
translator.push(evt3)
1108+
result = translator.get()
1109+
self.assertEqual(result, (None, ["a", "c"]))
1110+
1111+
def test_push_invalid_key_with_unicode_category(self):
1112+
keymap = [("a", "command_a")]
1113+
translator = KeymapTranslator(keymap)
1114+
evt = Event("key", "\u0003") # Control character
1115+
translator.push(evt)
1116+
result = translator.get()
1117+
self.assertEqual(result, (None, ["\u0003"]))
1118+
1119+
def test_empty(self):
1120+
keymap = [("a", "command_a")]
1121+
translator = KeymapTranslator(keymap)
1122+
self.assertTrue(translator.empty())
1123+
evt = Event("key", "a")
1124+
translator.push(evt)
1125+
self.assertFalse(translator.empty())
1126+
translator.get()
1127+
self.assertTrue(translator.empty())
1128+
1129+
1130+
class TestParseKeys(unittest.TestCase):
1131+
def test_single_character(self):
1132+
self.assertEqual(parse_keys("a"), ["a"])
1133+
self.assertEqual(parse_keys("b"), ["b"])
1134+
self.assertEqual(parse_keys("1"), ["1"])
1135+
1136+
def test_escape_sequences(self):
1137+
self.assertEqual(parse_keys("\\n"), ["\n"])
1138+
self.assertEqual(parse_keys("\\t"), ["\t"])
1139+
self.assertEqual(parse_keys("\\\\"), ["\\"])
1140+
self.assertEqual(parse_keys("\\'"), ["'"])
1141+
self.assertEqual(parse_keys('\\"'), ['"'])
1142+
1143+
def test_control_sequences(self):
1144+
self.assertEqual(parse_keys("\\C-a"), ["\x01"])
1145+
self.assertEqual(parse_keys("\\C-b"), ["\x02"])
1146+
self.assertEqual(parse_keys("\\C-c"), ["\x03"])
1147+
1148+
def test_meta_sequences(self):
1149+
self.assertEqual(parse_keys("\\M-a"), ["\033", "a"])
1150+
self.assertEqual(parse_keys("\\M-b"), ["\033", "b"])
1151+
self.assertEqual(parse_keys("\\M-c"), ["\033", "c"])
1152+
1153+
def test_keynames(self):
1154+
self.assertEqual(parse_keys("\\<up>"), ["up"])
1155+
self.assertEqual(parse_keys("\\<down>"), ["down"])
1156+
self.assertEqual(parse_keys("\\<left>"), ["left"])
1157+
self.assertEqual(parse_keys("\\<right>"), ["right"])
1158+
1159+
def test_combinations(self):
1160+
self.assertEqual(parse_keys("\\C-a\\n\\<up>"), ["\x01", "\n", "up"])
1161+
self.assertEqual(parse_keys("\\M-a\\t\\<down>"), ["\033", "a", "\t", "down"])
1162+
1163+
1164+
class TestCompileKeymap(unittest.TestCase):
1165+
def test_empty_keymap(self):
1166+
keymap = {}
1167+
result = compile_keymap(keymap)
1168+
self.assertEqual(result, {})
1169+
1170+
def test_single_keymap(self):
1171+
keymap = {b"a": "action"}
1172+
result = compile_keymap(keymap)
1173+
self.assertEqual(result, {b"a": "action"})
1174+
1175+
def test_nested_keymap(self):
1176+
keymap = {b"a": {b"b": "action"}}
1177+
result = compile_keymap(keymap)
1178+
self.assertEqual(result, {b"a": {b"b": "action"}})
1179+
1180+
def test_empty_value(self):
1181+
keymap = {b"a": {b"": "action"}}
1182+
result = compile_keymap(keymap)
1183+
self.assertEqual(result, {b"a": {b"": "action"}})
1184+
1185+
def test_multiple_empty_values(self):
1186+
keymap = {b"a": {b"": "action1", b"b": "action2"}}
1187+
result = compile_keymap(keymap)
1188+
self.assertEqual(result, {b"a": {b"": "action1", b"b": "action2"}})
1189+
1190+
def test_multiple_keymaps(self):
1191+
keymap = {b"a": {b"b": "action1", b"c": "action2"}}
1192+
result = compile_keymap(keymap)
1193+
self.assertEqual(result, {b"a": {b"b": "action1", b"c": "action2"}})
1194+
1195+
def test_nested_multiple_keymaps(self):
1196+
keymap = {b"a": {b"b": {b"c": "action"}}}
1197+
result = compile_keymap(keymap)
1198+
self.assertEqual(result, {b"a": {b"b": {b"c": "action"}}})
1199+
1200+
1201+
if __name__ == "__main__":
10291202
unittest.main()

0 commit comments

Comments
 (0)