2
2
import unittest
3
3
import sys
4
4
import os
5
+ from contextlib import contextmanager
5
6
6
- from curtsies .formatstringarray import FormatStringTest , fsarray
7
+ try :
8
+ from unittest import skip
9
+ except ImportError :
10
+ def skip (f ):
11
+ return lambda self : None
7
12
13
+ from curtsies .formatstringarray import FormatStringTest , fsarray
8
14
from curtsies .fmtfuncs import *
15
+ from curtsies .events import RefreshRequestEvent
9
16
10
17
from bpython import config
11
18
from bpython .curtsiesfrontend .repl import Repl
12
19
from bpython .repl import History
20
+ from bpython .curtsiesfrontend .repl import INCONSISTENT_HISTORY_MSG , CONTIGUITY_BROKEN_MSG
13
21
14
22
def setup_config ():
15
23
config_struct = config .Struct ()
@@ -30,6 +38,9 @@ def assert_paint(self, screen, cursor_row_col):
30
38
def assert_paint_ignoring_formatting (self , screen , cursor_row_col ):
31
39
array , cursor_pos = self .repl .paint ()
32
40
self .assertFSArraysEqualIgnoringFormatting (array , screen )
41
+ self .assertEqual (cursor_pos , cursor_row_col )
42
+
43
+ class TestCurtsiesPaintingSimple (TestCurtsiesPainting ):
33
44
34
45
def test_startup (self ):
35
46
screen = fsarray ([cyan ('>>> ' ), cyan ('Welcome to' )])
@@ -48,7 +59,7 @@ def test_run_line(self):
48
59
[self .repl .add_normal_character (c ) for c in '1 + 1' ]
49
60
self .repl .on_enter ()
50
61
screen = fsarray ([u'>>> 1 + 1' , '2' , 'Welcome to' ])
51
- self .assert_paint_ignoring_formatting (screen , (0 , 9 ))
62
+ self .assert_paint_ignoring_formatting (screen , (1 , 1 ))
52
63
finally :
53
64
sys .stdout = orig_stdout
54
65
@@ -62,4 +73,137 @@ def test_completion(self):
62
73
u'└───────────────────────┘' ,
63
74
u'' ,
64
75
u'Welcome to bpython! Press <F1> f' ]
65
- self .assert_paint_ignoring_formatting (screen , (0 , 9 ))
76
+ self .assert_paint_ignoring_formatting (screen , (0 , 4 ))
77
+
78
+ @contextmanager
79
+ def output_to_repl (repl ):
80
+ old_out , old_err = sys .stdout , sys .stderr
81
+ try :
82
+ sys .stdout , sys .stderr = repl .stdout , repl .stderr
83
+ yield
84
+ finally :
85
+ sys .stdout , sys .stderr = old_out , old_err
86
+
87
+ class TestCurtsiesRewindRedraw (TestCurtsiesPainting ):
88
+ def refresh (self , when = 'now' ):
89
+ self .refresh_requests .append (RefreshRequestEvent (when = when ))
90
+
91
+ def send_refreshes (self ):
92
+ while self .refresh_requests :
93
+ self .repl .process_event (self .refresh_requests .pop ())
94
+
95
+ def enter (self , line = None ):
96
+ """Enter a line of text, avoiding autocompletion windows
97
+
98
+ autocomplete could still happen if the entered line has
99
+ autocompletion that would happen then, but intermediate
100
+ stages won't happen"""
101
+ if line is not None :
102
+ self .repl .current_line = line
103
+ with output_to_repl (self .repl ):
104
+ self .repl .on_enter ()
105
+ self .send_refreshes ()
106
+
107
+ def undo (self ):
108
+ with output_to_repl (self .repl ):
109
+ self .repl .undo ()
110
+ self .send_refreshes ()
111
+
112
+ def setUp (self ):
113
+ self .refresh_requests = []
114
+ self .repl = Repl (banner = '' , config = setup_config (), request_refresh = self .refresh )
115
+ self .repl .rl_history = History () # clear history
116
+ self .repl .height , self .repl .width = (5 , 32 )
117
+
118
+ def test_rewind (self ):
119
+ self .repl .current_line = '1 + 1'
120
+ self .enter ()
121
+ screen = [u'>>> 1 + 1' ,
122
+ u'2' ,
123
+ u'>>> ' ]
124
+ self .assert_paint_ignoring_formatting (screen , (2 , 4 ))
125
+ self .repl .undo ()
126
+ screen = [u'>>> ' ]
127
+ self .assert_paint_ignoring_formatting (screen , (0 , 4 ))
128
+
129
+ @skip ('wrong message' )
130
+ def test_rewind_contiguity_loss (self ):
131
+ self .enter ('1 + 1' )
132
+ self .enter ('2 + 2' )
133
+ self .enter ('def foo(x):' )
134
+ self .repl .current_line = ' return x + 1'
135
+ screen = [u'>>> 1 + 1' ,
136
+ u'2' ,
137
+ u'>>> 2 + 2' ,
138
+ u'4' ,
139
+ u'>>> def foo(x):' ,
140
+ u'... return x + 1' ]
141
+ self .assert_paint_ignoring_formatting (screen , (5 , 8 ))
142
+ self .repl .scroll_offset = 1
143
+ self .assert_paint_ignoring_formatting (screen [1 :], (4 , 8 ))
144
+ self .undo ()
145
+ screen = [u'2' ,
146
+ u'>>> 2 + 2' ,
147
+ u'4' ,
148
+ u'>>> ' ]
149
+ self .assert_paint_ignoring_formatting (screen , (3 , 4 ))
150
+ self .undo ()
151
+ screen = [u'2' ,
152
+ u'>>> ' ]
153
+ self .assert_paint_ignoring_formatting (screen , (1 , 4 ))
154
+ self .undo ()
155
+ screen = [CONTIGUITY_BROKEN_MSG [:self .repl .width ],
156
+ u'>>> ' ,
157
+ u'' ,
158
+ u'' ,
159
+ u'' ,
160
+ u' ' ] #TODO why is that there? Necessary?
161
+ self .assert_paint_ignoring_formatting (screen , (1 , 4 ))
162
+ screen = [u'>>> ' ]
163
+ self .assert_paint_ignoring_formatting (screen , (0 , 4 ))
164
+
165
+ def test_inconsistent_history_doesnt_happen_if_onscreen (self ):
166
+ self .enter ("1 + 1" )
167
+ screen = [u">>> 1 + 1" ,
168
+ u'2' ,
169
+ u'>>> ' ]
170
+ self .assert_paint_ignoring_formatting (screen , (2 , 4 ))
171
+ self .enter ("2 + 2" )
172
+ screen = [u">>> 1 + 1" ,
173
+ u'2' ,
174
+ u'>>> 2 + 2' ,
175
+ u'4' ,
176
+ u'>>> ' ]
177
+ self .assert_paint_ignoring_formatting (screen , (4 , 4 ))
178
+ self .repl .display_lines [0 ] = self .repl .display_lines [0 ] * 2
179
+ self .undo ()
180
+ screen = [u">>> 1 + 1" ,
181
+ u'2' ,
182
+ u'>>> ' ]
183
+ self .assert_paint_ignoring_formatting (screen , (2 , 4 ))
184
+
185
+ @skip ('why is everything moved up?' )
186
+ def test_rewind_inconsistent_history (self ):
187
+ self .enter ("1 + 1" )
188
+ self .enter ("2 + 2" )
189
+ self .enter ("3 + 3" )
190
+ screen = [u">>> 1 + 1" ,
191
+ u'2' ,
192
+ u'>>> 2 + 2' ,
193
+ u'4' ,
194
+ u'>>> 3 + 3' ,
195
+ u'6' ,
196
+ u'>>> ' ]
197
+ self .assert_paint_ignoring_formatting (screen , (6 , 4 ))
198
+ self .repl .scroll_offset += len (screen ) - self .repl .height
199
+ self .assert_paint_ignoring_formatting (screen [2 :], (4 , 4 ))
200
+ self .repl .display_lines [0 ] = self .repl .display_lines [0 ] * 2
201
+ self .undo ()
202
+ screen = [INCONSISTENT_HISTORY_MSG [:self .repl .width ],
203
+ u'>>> 2 + 2' ,
204
+ u'4' ,
205
+ u'>>> ' ,
206
+ u'' ,
207
+ u'' ]
208
+ self .assert_paint_ignoring_formatting (screen , (5 , 4 ))
209
+
0 commit comments