11import curses
2+ import itertools
23import os
34import rlcompleter
45import sys
@@ -41,6 +42,11 @@ def multiline_input(reader, namespace=None):
4142 reader .paste_mode = False
4243
4344
45+ def code_to_events (code ):
46+ for c in code :
47+ yield Event (evt = 'key' , data = c , raw = bytearray (c .encode ('utf-8' )))
48+
49+
4450class FakeConsole (Console ):
4551 def __init__ (self , events , encoding = "utf-8" ):
4652 self .events = iter (events )
@@ -62,25 +68,14 @@ def prepare_reader(self, events):
6268 return reader , console
6369
6470 def test_up_arrow (self ):
65- events = [
66- Event (evt = "key" , data = "d" , raw = bytearray (b"d" )),
67- Event (evt = "key" , data = "e" , raw = bytearray (b"e" )),
68- Event (evt = "key" , data = "f" , raw = bytearray (b"f" )),
69- Event (evt = "key" , data = " " , raw = bytearray (b" " )),
70- Event (evt = "key" , data = "f" , raw = bytearray (b"f" )),
71- Event (evt = "key" , data = "(" , raw = bytearray (b"(" )),
72- Event (evt = "key" , data = ")" , raw = bytearray (b")" )),
73- Event (evt = "key" , data = ":" , raw = bytearray (b":" )),
74- Event (evt = "key" , data = "\n " , raw = bytearray (b"\n " )),
75- Event (evt = "key" , data = " " , raw = bytearray (b" " )),
76- Event (evt = "key" , data = " " , raw = bytearray (b" " )),
77- Event (evt = "key" , data = "." , raw = bytearray (b"." )),
78- Event (evt = "key" , data = "." , raw = bytearray (b"." )),
79- Event (evt = "key" , data = "." , raw = bytearray (b"." )),
80- Event (evt = "key" , data = "\n " , raw = bytearray (b"\n " )),
71+ code = (
72+ 'def f():\n '
73+ ' ...\n '
74+ )
75+ events = itertools .chain (code_to_events (code ), [
8176 Event (evt = "key" , data = "up" , raw = bytearray (b"\x1b OA" )),
8277 Event (evt = "key" , data = "\n " , raw = bytearray (b"\n " )),
83- ]
78+ ])
8479
8580 reader , console = self .prepare_reader (events )
8681
@@ -90,25 +85,14 @@ def test_up_arrow(self):
9085 console .move_cursor .assert_called_with (1 , 3 )
9186
9287 def test_down_arrow (self ):
93- events = [
94- Event (evt = "key" , data = "d" , raw = bytearray (b"d" )),
95- Event (evt = "key" , data = "e" , raw = bytearray (b"e" )),
96- Event (evt = "key" , data = "f" , raw = bytearray (b"f" )),
97- Event (evt = "key" , data = " " , raw = bytearray (b" " )),
98- Event (evt = "key" , data = "f" , raw = bytearray (b"f" )),
99- Event (evt = "key" , data = "(" , raw = bytearray (b"(" )),
100- Event (evt = "key" , data = ")" , raw = bytearray (b")" )),
101- Event (evt = "key" , data = ":" , raw = bytearray (b":" )),
102- Event (evt = "key" , data = "\n " , raw = bytearray (b"\n " )),
103- Event (evt = "key" , data = " " , raw = bytearray (b" " )),
104- Event (evt = "key" , data = " " , raw = bytearray (b" " )),
105- Event (evt = "key" , data = "." , raw = bytearray (b"." )),
106- Event (evt = "key" , data = "." , raw = bytearray (b"." )),
107- Event (evt = "key" , data = "." , raw = bytearray (b"." )),
108- Event (evt = "key" , data = "\n " , raw = bytearray (b"\n " )),
88+ code = (
89+ 'def f():\n '
90+ ' ...\n '
91+ )
92+ events = itertools .chain (code_to_events (code ), [
10993 Event (evt = "key" , data = "down" , raw = bytearray (b"\x1b OB" )),
11094 Event (evt = "key" , data = "\n " , raw = bytearray (b"\n " )),
111- ]
95+ ])
11296
11397 reader , console = self .prepare_reader (events )
11498
@@ -118,15 +102,10 @@ def test_down_arrow(self):
118102 console .move_cursor .assert_called_with (1 , 5 )
119103
120104 def test_left_arrow (self ):
121- events = [
122- Event (evt = "key" , data = "1" , raw = bytearray (b"1" )),
123- Event (evt = "key" , data = "1" , raw = bytearray (b"1" )),
124- Event (evt = "key" , data = "+" , raw = bytearray (b"+" )),
125- Event (evt = "key" , data = "1" , raw = bytearray (b"1" )),
126- Event (evt = "key" , data = "1" , raw = bytearray (b"1" )),
105+ events = itertools .chain (code_to_events ('11+11' ), [
127106 Event (evt = "key" , data = "left" , raw = bytearray (b"\x1b OD" )),
128107 Event (evt = "key" , data = "\n " , raw = bytearray (b"\n " )),
129- ]
108+ ])
130109
131110 reader , console = self .prepare_reader (events )
132111
@@ -139,15 +118,10 @@ def test_left_arrow(self):
139118 )
140119
141120 def test_right_arrow (self ):
142- events = [
143- Event (evt = "key" , data = "1" , raw = bytearray (b"1" )),
144- Event (evt = "key" , data = "1" , raw = bytearray (b"1" )),
145- Event (evt = "key" , data = "+" , raw = bytearray (b"+" )),
146- Event (evt = "key" , data = "1" , raw = bytearray (b"1" )),
147- Event (evt = "key" , data = "1" , raw = bytearray (b"1" )),
121+ events = itertools .chain (code_to_events ('11+11' ), [
148122 Event (evt = "key" , data = "right" , raw = bytearray (b"\x1b OC" )),
149123 Event (evt = "key" , data = "\n " , raw = bytearray (b"\n " )),
150- ]
124+ ])
151125
152126 reader , console = self .prepare_reader (events )
153127
@@ -169,35 +143,13 @@ def prepare_reader(self, events):
169143 return reader
170144
171145 def test_basic (self ):
172- events = [
173- Event (evt = "key" , data = "1" , raw = bytearray (b"1" )),
174- Event (evt = "key" , data = "+" , raw = bytearray (b"+" )),
175- Event (evt = "key" , data = "1" , raw = bytearray (b"1" )),
176- Event (evt = "key" , data = "\n " , raw = bytearray (b"\n " )),
177- ]
178- reader = self .prepare_reader (events )
146+ reader = self .prepare_reader (code_to_events ('1+1\n ' ))
179147
180148 output = multiline_input (reader )
181149 self .assertEqual (output , "1+1" )
182150
183151 def test_multiline_edit (self ):
184- events = [
185- Event (evt = "key" , data = "d" , raw = bytearray (b"d" )),
186- Event (evt = "key" , data = "e" , raw = bytearray (b"e" )),
187- Event (evt = "key" , data = "f" , raw = bytearray (b"f" )),
188- Event (evt = "key" , data = " " , raw = bytearray (b" " )),
189- Event (evt = "key" , data = "f" , raw = bytearray (b"f" )),
190- Event (evt = "key" , data = "(" , raw = bytearray (b"(" )),
191- Event (evt = "key" , data = ")" , raw = bytearray (b")" )),
192- Event (evt = "key" , data = ":" , raw = bytearray (b":" )),
193- Event (evt = "key" , data = "\n " , raw = bytearray (b"\n " )),
194- Event (evt = "key" , data = " " , raw = bytearray (b" " )),
195- Event (evt = "key" , data = " " , raw = bytearray (b" " )),
196- Event (evt = "key" , data = "." , raw = bytearray (b"." )),
197- Event (evt = "key" , data = "." , raw = bytearray (b"." )),
198- Event (evt = "key" , data = "." , raw = bytearray (b"." )),
199- Event (evt = "key" , data = "\n " , raw = bytearray (b"\n " )),
200- Event (evt = "key" , data = "\n " , raw = bytearray (b"\n " )),
152+ events = itertools .chain (code_to_events ('def f():\n ...\n \n ' ), [
201153 Event (evt = "key" , data = "up" , raw = bytearray (b"\x1b OA" )),
202154 Event (evt = "key" , data = "up" , raw = bytearray (b"\x1b OA" )),
203155 Event (evt = "key" , data = "up" , raw = bytearray (b"\x1b OA" )),
@@ -209,7 +161,7 @@ def test_multiline_edit(self):
209161 Event (evt = "key" , data = "down" , raw = bytearray (b"\x1b OB" )),
210162 Event (evt = "key" , data = "down" , raw = bytearray (b"\x1b OB" )),
211163 Event (evt = "key" , data = "\n " , raw = bytearray (b"\n " )),
212- ]
164+ ])
213165 reader = self .prepare_reader (events )
214166
215167 output = multiline_input (reader )
@@ -218,22 +170,14 @@ def test_multiline_edit(self):
218170 self .assertEqual (output , "def g():\n ...\n " )
219171
220172 def test_history_navigation_with_up_arrow (self ):
221- events = [
222- Event (evt = "key" , data = "1" , raw = bytearray (b"1" )),
223- Event (evt = "key" , data = "+" , raw = bytearray (b"+" )),
224- Event (evt = "key" , data = "1" , raw = bytearray (b"1" )),
225- Event (evt = "key" , data = "\n " , raw = bytearray (b"\n " )),
226- Event (evt = "key" , data = "2" , raw = bytearray (b"1" )),
227- Event (evt = "key" , data = "+" , raw = bytearray (b"+" )),
228- Event (evt = "key" , data = "2" , raw = bytearray (b"1" )),
229- Event (evt = "key" , data = "\n " , raw = bytearray (b"\n " )),
173+ events = itertools .chain (code_to_events ('1+1\n 2+2\n ' ), [
230174 Event (evt = "key" , data = "up" , raw = bytearray (b"\x1b OA" )),
231175 Event (evt = "key" , data = "\n " , raw = bytearray (b"\n " )),
232176 Event (evt = "key" , data = "up" , raw = bytearray (b"\x1b OA" )),
233177 Event (evt = "key" , data = "up" , raw = bytearray (b"\x1b OA" )),
234178 Event (evt = "key" , data = "up" , raw = bytearray (b"\x1b OA" )),
235179 Event (evt = "key" , data = "\n " , raw = bytearray (b"\n " )),
236- ]
180+ ])
237181
238182 reader = self .prepare_reader (events )
239183
@@ -247,46 +191,26 @@ def test_history_navigation_with_up_arrow(self):
247191 self .assertEqual (output , "1+1" )
248192
249193 def test_history_navigation_with_down_arrow (self ):
250- events = [
251- Event (evt = "key" , data = "1" , raw = bytearray (b"1" )),
252- Event (evt = "key" , data = "+" , raw = bytearray (b"+" )),
253- Event (evt = "key" , data = "1" , raw = bytearray (b"1" )),
254- Event (evt = "key" , data = "\n " , raw = bytearray (b"\n " )),
255- Event (evt = "key" , data = "2" , raw = bytearray (b"1" )),
256- Event (evt = "key" , data = "+" , raw = bytearray (b"+" )),
257- Event (evt = "key" , data = "2" , raw = bytearray (b"1" )),
258- Event (evt = "key" , data = "\n " , raw = bytearray (b"\n " )),
194+ events = itertools .chain (code_to_events ('1+1\n 2+2\n ' ), [
259195 Event (evt = "key" , data = "up" , raw = bytearray (b"\x1b OA" )),
260196 Event (evt = "key" , data = "up" , raw = bytearray (b"\x1b OA" )),
261197 Event (evt = "key" , data = "\n " , raw = bytearray (b"\n " )),
262198 Event (evt = "key" , data = "down" , raw = bytearray (b"\x1b OB" )),
263199 Event (evt = "key" , data = "down" , raw = bytearray (b"\x1b OB" )),
264- ]
200+ ])
265201
266202 reader = self .prepare_reader (events )
267203
268204 output = multiline_input (reader )
269205 self .assertEqual (output , "1+1" )
270206
271207 def test_history_search (self ):
272- events = [
273- Event (evt = "key" , data = "1" , raw = bytearray (b"1" )),
274- Event (evt = "key" , data = "+" , raw = bytearray (b"+" )),
275- Event (evt = "key" , data = "1" , raw = bytearray (b"1" )),
276- Event (evt = "key" , data = "\n " , raw = bytearray (b"\n " )),
277- Event (evt = "key" , data = "2" , raw = bytearray (b"2" )),
278- Event (evt = "key" , data = "+" , raw = bytearray (b"+" )),
279- Event (evt = "key" , data = "2" , raw = bytearray (b"2" )),
280- Event (evt = "key" , data = "\n " , raw = bytearray (b"\n " )),
281- Event (evt = "key" , data = "3" , raw = bytearray (b"3" )),
282- Event (evt = "key" , data = "+" , raw = bytearray (b"+" )),
283- Event (evt = "key" , data = "3" , raw = bytearray (b"3" )),
284- Event (evt = "key" , data = "\n " , raw = bytearray (b"\n " )),
208+ events = itertools .chain (code_to_events ('1+1\n 2+2\n 3+3\n ' ), [
285209 Event (evt = "key" , data = "\x12 " , raw = bytearray (b"\x12 " )),
286210 Event (evt = "key" , data = "1" , raw = bytearray (b"1" )),
287211 Event (evt = "key" , data = "\n " , raw = bytearray (b"\n " )),
288212 Event (evt = "key" , data = "\n " , raw = bytearray (b"\n " )),
289- ]
213+ ])
290214
291215 reader = self .prepare_reader (events )
292216
@@ -309,18 +233,7 @@ def prepare_reader(self, events, namespace):
309233 return reader
310234
311235 def test_simple_completion (self ):
312- events = [
313- Event (evt = "key" , data = "o" , raw = bytearray (b"o" )),
314- Event (evt = "key" , data = "s" , raw = bytearray (b"s" )),
315- Event (evt = "key" , data = "." , raw = bytearray (b"." )),
316- Event (evt = "key" , data = "g" , raw = bytearray (b"g" )),
317- Event (evt = "key" , data = "e" , raw = bytearray (b"e" )),
318- Event (evt = "key" , data = "t" , raw = bytearray (b"t" )),
319- Event (evt = "key" , data = "e" , raw = bytearray (b"e" )),
320- Event (evt = "key" , data = "n" , raw = bytearray (b"n" )),
321- Event (evt = "key" , data = "\t " , raw = bytearray (b"\t " )),
322- Event (evt = "key" , data = "\n " , raw = bytearray (b"\n " )),
323- ]
236+ events = code_to_events ('os.geten\t \n ' )
324237
325238 namespace = {"os" : os }
326239 reader = self .prepare_reader (events , namespace )
@@ -329,19 +242,7 @@ def test_simple_completion(self):
329242 self .assertEqual (output , "os.getenv" )
330243
331244 def test_completion_with_many_options (self ):
332- events = [
333- Event (evt = "key" , data = "o" , raw = bytearray (b"o" )),
334- Event (evt = "key" , data = "s" , raw = bytearray (b"s" )),
335- Event (evt = "key" , data = "." , raw = bytearray (b"." )),
336- Event (evt = "key" , data = "\t " , raw = bytearray (b"\t " )),
337- Event (evt = "key" , data = "\t " , raw = bytearray (b"\t " )),
338- Event (evt = "key" , data = "O" , raw = bytearray (b"O" )),
339- Event (evt = "key" , data = "_" , raw = bytearray (b"_" )),
340- Event (evt = "key" , data = "A" , raw = bytearray (b"A" )),
341- Event (evt = "key" , data = "S" , raw = bytearray (b"S" )),
342- Event (evt = "key" , data = "\t " , raw = bytearray (b"\t " )),
343- Event (evt = "key" , data = "\n " , raw = bytearray (b"\n " )),
344- ]
245+ events = code_to_events ('os.\t \t O_AS\t \n ' )
345246
346247 namespace = {"os" : os }
347248 reader = self .prepare_reader (events , namespace )
@@ -350,36 +251,17 @@ def test_completion_with_many_options(self):
350251 self .assertEqual (output , "os.O_ASYNC" )
351252
352253 def test_empty_namespace_completion (self ):
353- events = [
354- Event (evt = "key" , data = "o" , raw = bytearray (b"o" )),
355- Event (evt = "key" , data = "s" , raw = bytearray (b"s" )),
356- Event (evt = "key" , data = "." , raw = bytearray (b"." )),
357- Event (evt = "key" , data = "g" , raw = bytearray (b"g" )),
358- Event (evt = "key" , data = "e" , raw = bytearray (b"e" )),
359- Event (evt = "key" , data = "t" , raw = bytearray (b"t" )),
360- Event (evt = "key" , data = "e" , raw = bytearray (b"e" )),
361- Event (evt = "key" , data = "n" , raw = bytearray (b"n" )),
362- Event (evt = "key" , data = "\t " , raw = bytearray (b"\t " )),
363- Event (evt = "key" , data = "\n " , raw = bytearray (b"\n " )),
364- ]
365-
254+ events = code_to_events ('os.geten\t \n ' )
366255 namespace = {}
367256 reader = self .prepare_reader (events , namespace )
368257
369258 output = multiline_input (reader , namespace )
370259 self .assertEqual (output , "os.geten" )
371260
372261 def test_global_namespace_completion (self ):
373- events = [
374- Event (evt = "key" , data = "p" , raw = bytearray (b"p" )),
375- Event (evt = "key" , data = "y" , raw = bytearray (b"y" )),
376- Event (evt = "key" , data = "\t " , raw = bytearray (b"\t " )),
377- Event (evt = "key" , data = "\n " , raw = bytearray (b"\n " )),
378- ]
379-
262+ events = code_to_events ('py\t \n ' )
380263 namespace = {"python" : None }
381264 reader = self .prepare_reader (events , namespace )
382-
383265 output = multiline_input (reader , namespace )
384266 self .assertEqual (output , "python" )
385267
@@ -488,5 +370,58 @@ def test_push_unrecognized_escape_sequence(self):
488370 self .assertEqual (eq .events [2 ].data , "Z" )
489371
490372
373+ class TestPasteEvent (TestCase ):
374+ def setUp (self ) -> None :
375+ curses .setupterm ()
376+ return super ().setUp ()
377+
378+ def prepare_reader (self , events ):
379+ console = FakeConsole (events )
380+ reader = ReadlineAlikeReader (console )
381+ reader .config = ReadlineConfig ()
382+ reader .config .readline_completer = None
383+ return reader
384+
385+ def test_paste (self ):
386+ code = (
387+ 'def a():\n '
388+ ' for x in range(10):\n '
389+ ' if x%2:\n '
390+ ' print(x)\n '
391+ ' else:\n '
392+ ' pass\n \n '
393+ )
394+
395+ events = itertools .chain ([
396+ Event (evt = 'key' , data = 'f3' , raw = bytearray (b'\x1b OR' )),
397+ ], code_to_events (code ))
398+ reader = self .prepare_reader (events )
399+ output = multiline_input (reader )
400+ self .assertEqual (output , code [:- 1 ])
401+
402+ def test_paste_not_in_paste_mode (self ):
403+ input_code = (
404+ 'def a():\n '
405+ ' for x in range(10):\n '
406+ ' if x%2:\n '
407+ ' print(x)\n '
408+ ' else:\n '
409+ ' pass\n \n '
410+ )
411+
412+ output_code = (
413+ 'def a():\n '
414+ ' for x in range(10):\n '
415+ ' if x%2:\n '
416+ ' print(x)\n '
417+ ' else:'
418+ )
419+
420+ events = code_to_events (input_code )
421+ reader = self .prepare_reader (events )
422+ output = multiline_input (reader )
423+ self .assertEqual (output , output_code )
424+
425+
491426if __name__ == "__main__" :
492427 unittest .main ()
0 commit comments