55from unittest import TestCase
66from unittest .mock import patch
77
8- from .support import FakeConsole , handle_all_events , handle_events_narrow_console
9- from .support import more_lines , multiline_input , code_to_events
8+ from .support import (
9+ FakeConsole ,
10+ handle_all_events ,
11+ handle_events_narrow_console ,
12+ more_lines ,
13+ multiline_input ,
14+ code_to_events ,
15+ )
1016from _pyrepl .console import Event
1117from _pyrepl .readline import ReadlineAlikeReader , ReadlineConfig
1218from _pyrepl .readline import multiline_input as readline_multiline_input
1319
1420
1521class TestCursorPosition (TestCase ):
22+ def prepare_reader (self , events ):
23+ console = FakeConsole (events )
24+ config = ReadlineConfig (readline_completer = None )
25+ reader = ReadlineAlikeReader (console = console , config = config )
26+ return reader
27+
1628 def test_up_arrow_simple (self ):
1729 # fmt: off
1830 code = (
19- ' def f():\n '
20- ' ...\n '
31+ " def f():\n "
32+ " ...\n "
2133 )
2234 # fmt: on
2335 events = itertools .chain (
@@ -34,8 +46,8 @@ def test_up_arrow_simple(self):
3446 def test_down_arrow_end_of_input (self ):
3547 # fmt: off
3648 code = (
37- ' def f():\n '
38- ' ...\n '
49+ " def f():\n "
50+ " ...\n "
3951 )
4052 # fmt: on
4153 events = itertools .chain (
@@ -300,6 +312,79 @@ def test_cursor_position_after_wrap_and_move_up(self):
300312 self .assertEqual (reader .pos , 10 )
301313 self .assertEqual (reader .cxy , (1 , 1 ))
302314
315+ def test_auto_indent_default (self ):
316+ # fmt: off
317+ input_code = (
318+ "def f():\n "
319+ "pass\n \n "
320+ )
321+
322+ output_code = (
323+ "def f():\n "
324+ " pass\n "
325+ " "
326+ )
327+ # fmt: on
328+
329+ def test_auto_indent_continuation (self ):
330+ # auto indenting according to previous user indentation
331+ # fmt: off
332+ events = itertools .chain (
333+ code_to_events ("def f():\n " ),
334+ # add backspace to delete default auto-indent
335+ [
336+ Event (evt = "key" , data = "backspace" , raw = bytearray (b"\x7f " )),
337+ ],
338+ code_to_events (
339+ " pass\n "
340+ "pass\n \n "
341+ ),
342+ )
343+
344+ output_code = (
345+ "def f():\n "
346+ " pass\n "
347+ " pass\n "
348+ " "
349+ )
350+ # fmt: on
351+
352+ reader = self .prepare_reader (events )
353+ output = multiline_input (reader )
354+ self .assertEqual (output , output_code )
355+
356+ def test_auto_indent_prev_block (self ):
357+ # auto indenting according to indentation in different block
358+ # fmt: off
359+ events = itertools .chain (
360+ code_to_events ("def f():\n " ),
361+ # add backspace to delete default auto-indent
362+ [
363+ Event (evt = "key" , data = "backspace" , raw = bytearray (b"\x7f " )),
364+ ],
365+ code_to_events (
366+ " pass\n "
367+ "pass\n \n "
368+ ),
369+ code_to_events (
370+ "def g():\n "
371+ "pass\n \n "
372+ ),
373+ )
374+
375+
376+ output_code = (
377+ "def g():\n "
378+ " pass\n "
379+ " "
380+ )
381+ # fmt: on
382+
383+ reader = self .prepare_reader (events )
384+ output1 = multiline_input (reader )
385+ output2 = multiline_input (reader )
386+ self .assertEqual (output2 , output_code )
387+
303388
304389class TestPyReplOutput (TestCase ):
305390 def prepare_reader (self , events ):
@@ -316,14 +401,12 @@ def test_basic(self):
316401
317402 def test_multiline_edit (self ):
318403 events = itertools .chain (
319- code_to_events ("def f():\n ...\n \n " ),
404+ code_to_events ("def f():\n ...\n \n " ),
320405 [
321406 Event (evt = "key" , data = "up" , raw = bytearray (b"\x1b OA" )),
322407 Event (evt = "key" , data = "up" , raw = bytearray (b"\x1b OA" )),
323408 Event (evt = "key" , data = "up" , raw = bytearray (b"\x1b OA" )),
324409 Event (evt = "key" , data = "right" , raw = bytearray (b"\x1b OC" )),
325- Event (evt = "key" , data = "right" , raw = bytearray (b"\x1b OC" )),
326- Event (evt = "key" , data = "right" , raw = bytearray (b"\x1b OC" )),
327410 Event (evt = "key" , data = "backspace" , raw = bytearray (b"\x7f " )),
328411 Event (evt = "key" , data = "g" , raw = bytearray (b"g" )),
329412 Event (evt = "key" , data = "down" , raw = bytearray (b"\x1b OB" )),
@@ -334,9 +417,9 @@ def test_multiline_edit(self):
334417 reader = self .prepare_reader (events )
335418
336419 output = multiline_input (reader )
337- self .assertEqual (output , "def f():\n ...\n " )
420+ self .assertEqual (output , "def f():\n ...\n " )
338421 output = multiline_input (reader )
339- self .assertEqual (output , "def g():\n ...\n " )
422+ self .assertEqual (output , "def g():\n ...\n " )
340423
341424 def test_history_navigation_with_up_arrow (self ):
342425 events = itertools .chain (
@@ -485,6 +568,7 @@ class Dummy:
485568 @property
486569 def test_func (self ):
487570 import warnings
571+
488572 warnings .warn ("warnings\n " )
489573 return None
490574
@@ -508,12 +592,12 @@ def prepare_reader(self, events):
508592 def test_paste (self ):
509593 # fmt: off
510594 code = (
511- ' def a():\n '
512- ' for x in range(10):\n '
513- ' if x%2:\n '
514- ' print(x)\n '
515- ' else:\n '
516- ' pass\n '
595+ " def a():\n "
596+ " for x in range(10):\n "
597+ " if x%2:\n "
598+ " print(x)\n "
599+ " else:\n "
600+ " pass\n "
517601 )
518602 # fmt: on
519603
@@ -534,10 +618,10 @@ def test_paste(self):
534618 def test_paste_mid_newlines (self ):
535619 # fmt: off
536620 code = (
537- ' def f():\n '
538- ' x = y\n '
539- ' \n '
540- ' y = z\n '
621+ " def f():\n "
622+ " x = y\n "
623+ " \n "
624+ " y = z\n "
541625 )
542626 # fmt: on
543627
@@ -558,16 +642,16 @@ def test_paste_mid_newlines(self):
558642 def test_paste_mid_newlines_not_in_paste_mode (self ):
559643 # fmt: off
560644 code = (
561- ' def f():\n '
562- ' x = y\n '
563- ' \n '
564- ' y = z\n \n '
645+ " def f():\n "
646+ " x = y\n "
647+ " \n "
648+ " y = z\n \n "
565649 )
566650
567651 expected = (
568- ' def f():\n '
569- ' x = y\n '
570- ' '
652+ " def f():\n "
653+ " x = y\n "
654+ " "
571655 )
572656 # fmt: on
573657
@@ -579,20 +663,20 @@ def test_paste_mid_newlines_not_in_paste_mode(self):
579663 def test_paste_not_in_paste_mode (self ):
580664 # fmt: off
581665 input_code = (
582- ' def a():\n '
583- ' for x in range(10):\n '
584- ' if x%2:\n '
585- ' print(x)\n '
586- ' else:\n '
587- ' pass\n \n '
666+ " def a():\n "
667+ " for x in range(10):\n "
668+ " if x%2:\n "
669+ " print(x)\n "
670+ " else:\n "
671+ " pass\n \n "
588672 )
589673
590674 output_code = (
591- ' def a():\n '
592- ' for x in range(10):\n '
593- ' if x%2:\n '
594- ' print(x)\n '
595- ' else:'
675+ " def a():\n "
676+ " for x in range(10):\n "
677+ " if x%2:\n "
678+ " print(x)\n "
679+ " else:"
596680 )
597681 # fmt: on
598682
@@ -605,25 +689,25 @@ def test_bracketed_paste(self):
605689 """Test that bracketed paste using \x1b [200~ and \x1b [201~ works."""
606690 # fmt: off
607691 input_code = (
608- ' def a():\n '
609- ' for x in range(10):\n '
610- ' \n '
611- ' if x%2:\n '
612- ' print(x)\n '
613- ' \n '
614- ' else:\n '
615- ' pass\n '
692+ " def a():\n "
693+ " for x in range(10):\n "
694+ " \n "
695+ " if x%2:\n "
696+ " print(x)\n "
697+ " \n "
698+ " else:\n "
699+ " pass\n "
616700 )
617701
618702 output_code = (
619- ' def a():\n '
620- ' for x in range(10):\n '
621- ' \n '
622- ' if x%2:\n '
623- ' print(x)\n '
624- ' \n '
625- ' else:\n '
626- ' pass\n '
703+ " def a():\n "
704+ " for x in range(10):\n "
705+ " \n "
706+ " if x%2:\n "
707+ " print(x)\n "
708+ " \n "
709+ " else:\n "
710+ " pass\n "
627711 )
628712 # fmt: on
629713
0 commit comments