1import unittest
2try:
3    # Python3 version
4    import unittest.mock as mock
5except ImportError:
6    # Python2, rely on PyPi
7    import mock
8
9from urwid.tests.util import SelectableText
10import urwid
11
12
13class FrameTest(unittest.TestCase):
14    def ftbtest(self, desc, focus_part, header_rows, footer_rows, size,
15            focus, top, bottom):
16        class FakeWidget:
17            def __init__(self, rows, want_focus):
18                self.ret_rows = rows
19                self.want_focus = want_focus
20            def rows(self, size, focus=False):
21                assert self.want_focus == focus
22                return self.ret_rows
23        header = footer = None
24        if header_rows:
25            header = FakeWidget(header_rows,
26                focus and focus_part == 'header')
27        if footer_rows:
28            footer = FakeWidget(footer_rows,
29                focus and focus_part == 'footer')
30
31        f = urwid.Frame(None, header, footer, focus_part)
32
33        rval = f.frame_top_bottom(size, focus)
34        exp = (top, bottom), (header_rows, footer_rows)
35        assert exp == rval, "%s expected %r but got %r"%(
36            desc,exp,rval)
37
38    def test(self):
39        self.ftbtest("simple", 'body', 0, 0, (9, 10), True, 0, 0)
40        self.ftbtest("simple h", 'body', 3, 0, (9, 10), True, 3, 0)
41        self.ftbtest("simple f", 'body', 0, 3, (9, 10), True, 0, 3)
42        self.ftbtest("simple hf", 'body', 3, 3, (9, 10), True, 3, 3)
43        self.ftbtest("almost full hf", 'body', 4, 5, (9, 10),
44            True, 4, 5)
45        self.ftbtest("full hf", 'body', 5, 5, (9, 10),
46            True, 4, 5)
47        self.ftbtest("x full h+1f", 'body', 6, 5, (9, 10),
48            False, 4, 5)
49        self.ftbtest("full h+1f", 'body', 6, 5, (9, 10),
50            True, 4, 5)
51        self.ftbtest("full hf+1", 'body', 5, 6, (9, 10),
52            True, 3, 6)
53        self.ftbtest("F full h+1f", 'footer', 6, 5, (9, 10),
54            True, 5, 5)
55        self.ftbtest("F full hf+1", 'footer', 5, 6, (9, 10),
56            True, 4, 6)
57        self.ftbtest("F full hf+5", 'footer', 5, 11, (9, 10),
58            True, 0, 10)
59        self.ftbtest("full hf+5", 'body', 5, 11, (9, 10),
60            True, 0, 9)
61        self.ftbtest("H full hf+1", 'header', 5, 6, (9, 10),
62            True, 5, 5)
63        self.ftbtest("H full h+1f", 'header', 6, 5, (9, 10),
64            True, 6, 4)
65        self.ftbtest("H full h+5f", 'header', 11, 5, (9, 10),
66            True, 10, 0)
67
68
69class PileTest(unittest.TestCase):
70    def ktest(self, desc, l, focus_item, key,
71            rkey, rfocus, rpref_col):
72        p = urwid.Pile( l, focus_item )
73        rval = p.keypress( (20,), key )
74        assert rkey == rval, "%s key expected %r but got %r" %(
75            desc, rkey, rval)
76        new_focus = l.index(p.get_focus())
77        assert new_focus == rfocus, "%s focus expected %r but got %r" %(
78            desc, rfocus, new_focus)
79        new_pref = p.get_pref_col((20,))
80        assert new_pref == rpref_col, (
81            "%s pref_col expected %r but got %r" % (
82            desc, rpref_col, new_pref))
83
84    def test_select_change(self):
85        T,S,E = urwid.Text, SelectableText, urwid.Edit
86
87        self.ktest("simple up", [S("")], 0, "up", "up", 0, 0)
88        self.ktest("simple down", [S("")], 0, "down", "down", 0, 0)
89        self.ktest("ignore up", [T(""),S("")], 1, "up", "up", 1, 0)
90        self.ktest("ignore down", [S(""),T("")], 0, "down",
91            "down", 0, 0)
92        self.ktest("step up", [S(""),S("")], 1, "up", None, 0, 0)
93        self.ktest("step down", [S(""),S("")], 0, "down",
94            None, 1, 0)
95        self.ktest("skip step up", [S(""),T(""),S("")], 2, "up",
96            None, 0, 0)
97        self.ktest("skip step down", [S(""),T(""),S("")], 0, "down",
98            None, 2, 0)
99        self.ktest("pad skip step up", [T(""),S(""),T(""),S("")], 3,
100            "up", None, 1, 0)
101        self.ktest("pad skip step down", [S(""),T(""),S(""),T("")], 0,
102            "down", None, 2, 0)
103        self.ktest("padi skip step up", [S(""),T(""),S(""),T(""),S("")],
104            4, "up", None, 2, 0)
105        self.ktest("padi skip step down", [S(""),T(""),S(""),T(""),
106            S("")], 0, "down", None, 2, 0)
107        e = E("","abcd", edit_pos=1)
108        e.keypress((20,),"right") # set a pref_col
109        self.ktest("pref step up", [S(""),T(""),e], 2, "up",
110            None, 0, 2)
111        self.ktest("pref step down", [e,T(""),S("")], 0, "down",
112            None, 2, 2)
113        z = E("","1234")
114        self.ktest("prefx step up", [z,T(""),e], 2, "up",
115            None, 0, 2)
116        assert z.get_pref_col((20,)) == 2
117        z = E("","1234")
118        self.ktest("prefx step down", [e,T(""),z], 0, "down",
119            None, 2, 2)
120        assert z.get_pref_col((20,)) == 2
121
122    def test_init_with_a_generator(self):
123        urwid.Pile(urwid.Text(c) for c in "ABC")
124
125    def test_change_focus_with_mouse(self):
126        p = urwid.Pile([urwid.Edit(), urwid.Edit()])
127        self.assertEqual(p.focus_position, 0)
128        p.mouse_event((10,), 'button press', 1, 1, 1, True)
129        self.assertEqual(p.focus_position, 1)
130
131    def test_zero_weight(self):
132        p = urwid.Pile([
133            urwid.SolidFill('a'),
134            ('weight', 0, urwid.SolidFill('d')),
135            ])
136        p.render((5, 4))
137
138    def test_mouse_event_in_empty_pile(self):
139        p = urwid.Pile([])
140        p.mouse_event((5,), 'button press', 1, 1, 1, False)
141        p.mouse_event((5,), 'button press', 1, 1, 1, True)
142
143
144class ColumnsTest(unittest.TestCase):
145    def cwtest(self, desc, l, divide, size, exp, focus_column=0):
146        c = urwid.Columns(l, divide, focus_column)
147        rval = c.column_widths( size )
148        assert rval == exp, "%s expected %s, got %s"%(desc,exp,rval)
149
150    def test_widths(self):
151        x = urwid.Text("") # sample "column"
152        self.cwtest( "simple 1", [x], 0, (20,), [20] )
153        self.cwtest( "simple 2", [x,x], 0, (20,), [10,10] )
154        self.cwtest( "simple 2+1", [x,x], 1, (20,), [10,9] )
155        self.cwtest( "simple 3+1", [x,x,x], 1, (20,), [6,6,6] )
156        self.cwtest( "simple 3+2", [x,x,x], 2, (20,), [5,6,5] )
157        self.cwtest( "simple 3+2", [x,x,x], 2, (21,), [6,6,5] )
158        self.cwtest( "simple 4+1", [x,x,x,x], 1, (25,), [6,5,6,5] )
159        self.cwtest( "squish 4+1", [x,x,x,x], 1, (7,), [1,1,1,1] )
160        self.cwtest( "squish 4+1", [x,x,x,x], 1, (6,), [1,2,1] )
161        self.cwtest( "squish 4+1", [x,x,x,x], 1, (4,), [2,1] )
162
163        self.cwtest( "fixed 3", [('fixed',4,x),('fixed',6,x),
164            ('fixed',2,x)], 1, (25,), [4,6,2] )
165        self.cwtest( "fixed 3 cut", [('fixed',4,x),('fixed',6,x),
166            ('fixed',2,x)], 1, (13,), [4,6] )
167        self.cwtest( "fixed 3 cut2", [('fixed',4,x),('fixed',6,x),
168            ('fixed',2,x)], 1, (10,), [4] )
169
170        self.cwtest( "mixed 4", [('weight',2,x),('fixed',5,x),
171            x, ('weight',3,x)], 1, (14,), [2,5,1,3] )
172        self.cwtest( "mixed 4 a", [('weight',2,x),('fixed',5,x),
173            x, ('weight',3,x)], 1, (12,), [1,5,1,2] )
174        self.cwtest( "mixed 4 b", [('weight',2,x),('fixed',5,x),
175            x, ('weight',3,x)], 1, (10,), [2,5,1] )
176        self.cwtest( "mixed 4 c", [('weight',2,x),('fixed',5,x),
177            x, ('weight',3,x)], 1, (20,), [4,5,2,6] )
178
179    def test_widths_focus_end(self):
180        x = urwid.Text("") # sample "column"
181        self.cwtest("end simple 2", [x,x], 0, (20,), [10,10], 1)
182        self.cwtest("end simple 2+1", [x,x], 1, (20,), [10,9], 1)
183        self.cwtest("end simple 3+1", [x,x,x], 1, (20,), [6,6,6], 2)
184        self.cwtest("end simple 3+2", [x,x,x], 2, (20,), [5,6,5], 2)
185        self.cwtest("end simple 3+2", [x,x,x], 2, (21,), [6,6,5], 2)
186        self.cwtest("end simple 4+1", [x,x,x,x], 1, (25,), [6,5,6,5], 3)
187        self.cwtest("end squish 4+1", [x,x,x,x], 1, (7,), [1,1,1,1], 3)
188        self.cwtest("end squish 4+1", [x,x,x,x], 1, (6,), [0,1,2,1], 3)
189        self.cwtest("end squish 4+1", [x,x,x,x], 1, (4,), [0,0,2,1], 3)
190
191        self.cwtest("end fixed 3", [('fixed',4,x),('fixed',6,x),
192            ('fixed',2,x)], 1, (25,), [4,6,2], 2)
193        self.cwtest("end fixed 3 cut", [('fixed',4,x),('fixed',6,x),
194            ('fixed',2,x)], 1, (13,), [0,6,2], 2)
195        self.cwtest("end fixed 3 cut2", [('fixed',4,x),('fixed',6,x),
196            ('fixed',2,x)], 1, (8,), [0,0,2], 2)
197
198        self.cwtest("end mixed 4", [('weight',2,x),('fixed',5,x),
199            x, ('weight',3,x)], 1, (14,), [2,5,1,3], 3)
200        self.cwtest("end mixed 4 a", [('weight',2,x),('fixed',5,x),
201            x, ('weight',3,x)], 1, (12,), [1,5,1,2], 3)
202        self.cwtest("end mixed 4 b", [('weight',2,x),('fixed',5,x),
203            x, ('weight',3,x)], 1, (10,), [0,5,1,2], 3)
204        self.cwtest("end mixed 4 c", [('weight',2,x),('fixed',5,x),
205            x, ('weight',3,x)], 1, (20,), [4,5,2,6], 3)
206
207    def mctest(self, desc, l, divide, size, col, row, exp, f_col, pref_col):
208        c = urwid.Columns( l, divide )
209        rval = c.move_cursor_to_coords( size, col, row )
210        assert rval == exp, "%s expected %r, got %r"%(desc,exp,rval)
211        assert c.focus_col == f_col, "%s expected focus_col %s got %s"%(
212            desc, f_col, c.focus_col)
213        pc = c.get_pref_col( size )
214        assert pc == pref_col, "%s expected pref_col %s, got %s"%(
215            desc, pref_col, pc)
216
217    def test_move_cursor(self):
218        e, s, x = urwid.Edit("",""),SelectableText(""), urwid.Text("")
219        self.mctest("nothing selectbl",[x,x,x],1,(20,),9,0,False,0,None)
220        self.mctest("dead on",[x,s,x],1,(20,),9,0,True,1,9)
221        self.mctest("l edge",[x,s,x],1,(20,),6,0,True,1,6)
222        self.mctest("r edge",[x,s,x],1,(20,),13,0,True,1,13)
223        self.mctest("l off",[x,s,x],1,(20,),2,0,True,1,2)
224        self.mctest("r off",[x,s,x],1,(20,),17,0,True,1,17)
225        self.mctest("l off 2",[x,x,s],1,(20,),2,0,True,2,2)
226        self.mctest("r off 2",[s,x,x],1,(20,),17,0,True,0,17)
227
228        self.mctest("l between",[s,s,x],1,(20,),6,0,True,0,6)
229        self.mctest("r between",[x,s,s],1,(20,),13,0,True,1,13)
230        self.mctest("l between 2l",[s,s,x],2,(22,),6,0,True,0,6)
231        self.mctest("r between 2l",[x,s,s],2,(22,),14,0,True,1,14)
232        self.mctest("l between 2r",[s,s,x],2,(22,),7,0,True,1,7)
233        self.mctest("r between 2r",[x,s,s],2,(22,),15,0,True,2,15)
234
235        # unfortunate pref_col shifting
236        self.mctest("l e edge",[x,e,x],1,(20,),6,0,True,1,7)
237        self.mctest("r e edge",[x,e,x],1,(20,),13,0,True,1,12)
238
239        # 'left'/'right' special cases
240        self.mctest("right", [e, e, e], 0, (12,), 'right', 0, True, 2, 'right')
241        self.mctest("left", [e, e, e], 0, (12,), 'left', 0, True, 0, 'left')
242
243    def test_init_with_a_generator(self):
244        urwid.Columns(urwid.Text(c) for c in "ABC")
245
246    def test_old_attributes(self):
247        c = urwid.Columns([urwid.Text(u'a'), urwid.SolidFill(u'x')],
248            box_columns=[1])
249        self.assertEqual(c.box_columns, [1])
250        c.box_columns=[]
251        self.assertEqual(c.box_columns, [])
252
253    def test_box_column(self):
254        c = urwid.Columns([urwid.Filler(urwid.Edit()),urwid.Text('')],
255            box_columns=[0])
256        c.keypress((10,), 'x')
257        c.get_cursor_coords((10,))
258        c.move_cursor_to_coords((10,), 0, 0)
259        c.mouse_event((10,), 'foo', 1, 0, 0, True)
260        c.get_pref_col((10,))
261
262
263
264class OverlayTest(unittest.TestCase):
265    def test_old_params(self):
266        o1 = urwid.Overlay(urwid.SolidFill(u'X'), urwid.SolidFill(u'O'),
267            ('fixed left', 5), ('fixed right', 4),
268            ('fixed top', 3), ('fixed bottom', 2),)
269        self.assertEqual(o1.contents[1][1], (
270            'left', None, 'relative', 100, None, 5, 4,
271            'top', None, 'relative', 100, None, 3, 2))
272        o2 = urwid.Overlay(urwid.SolidFill(u'X'), urwid.SolidFill(u'O'),
273            ('fixed right', 5), ('fixed left', 4),
274            ('fixed bottom', 3), ('fixed top', 2),)
275        self.assertEqual(o2.contents[1][1], (
276            'right', None, 'relative', 100, None, 4, 5,
277            'bottom', None, 'relative', 100, None, 2, 3))
278
279    def test_get_cursor_coords(self):
280        self.assertEqual(urwid.Overlay(urwid.Filler(urwid.Edit()),
281            urwid.SolidFill(u'B'),
282            'right', 1, 'bottom', 1).get_cursor_coords((2,2)), (1,1))
283
284
285class GridFlowTest(unittest.TestCase):
286    def test_cell_width(self):
287        gf = urwid.GridFlow([], 5, 0, 0, 'left')
288        self.assertEqual(gf.cell_width, 5)
289
290    def test_basics(self):
291        repr(urwid.GridFlow([], 5, 0, 0, 'left')) # should not fail
292
293    def test_v_sep(self):
294        gf = urwid.GridFlow([urwid.Text("test")], 10, 3, 1, "center")
295        self.assertEqual(gf.rows((40,), False), 1)
296
297    def test_keypress_v_sep_0(self):
298        """
299        Ensure proper keypress handling when v_sep is 0.
300        https://github.com/urwid/urwid/issues/387
301        """
302        call_back = mock.Mock()
303        button = urwid.Button("test", call_back)
304        gf = urwid.GridFlow([button], 10, 3, v_sep=0, align="center")
305        self.assertEqual(gf.keypress((20,), "enter"), None)
306        call_back.assert_called_with(button)
307
308
309class WidgetSquishTest(unittest.TestCase):
310    def wstest(self, w):
311        c = w.render((80,0), focus=False)
312        assert c.rows() == 0
313        c = w.render((80,0), focus=True)
314        assert c.rows() == 0
315        c = w.render((80,1), focus=False)
316        assert c.rows() == 1
317        c = w.render((0, 25), focus=False)
318        c = w.render((1, 25), focus=False)
319
320    def fwstest(self, w):
321        def t(cols, focus):
322            wrows = w.rows((cols,), focus)
323            c = w.render((cols,), focus)
324            assert c.rows() == wrows, (c.rows(), wrows)
325            if focus and hasattr(w, 'get_cursor_coords'):
326                gcc = w.get_cursor_coords((cols,))
327                assert c.cursor == gcc, (c.cursor, gcc)
328        t(0, False)
329        t(1, False)
330        t(0, True)
331        t(1, True)
332
333    def test_listbox(self):
334        self.wstest(urwid.ListBox(urwid.SimpleListWalker([])))
335        self.wstest(urwid.ListBox(urwid.SimpleListWalker([urwid.Text("hello")])))
336
337    def test_bargraph(self):
338        self.wstest(urwid.BarGraph(['foo','bar']))
339
340    def test_graphvscale(self):
341        self.wstest(urwid.GraphVScale([(0,"hello")], 1))
342        self.wstest(urwid.GraphVScale([(5,"hello")], 1))
343
344    def test_solidfill(self):
345        self.wstest(urwid.SolidFill())
346
347    def test_filler(self):
348        self.wstest(urwid.Filler(urwid.Text("hello")))
349
350    def test_overlay(self):
351        self.wstest(urwid.Overlay(
352            urwid.BigText("hello",urwid.Thin6x6Font()),
353            urwid.SolidFill(),
354            'center', None, 'middle', None))
355        self.wstest(urwid.Overlay(
356            urwid.Text("hello"), urwid.SolidFill(),
357            'center',  ('relative', 100), 'middle', None))
358
359    def test_frame(self):
360        self.wstest(urwid.Frame(urwid.SolidFill()))
361        self.wstest(urwid.Frame(urwid.SolidFill(),
362            header=urwid.Text("hello")))
363        self.wstest(urwid.Frame(urwid.SolidFill(),
364            header=urwid.Text("hello"),
365            footer=urwid.Text("hello")))
366
367    def test_pile(self):
368        self.wstest(urwid.Pile([urwid.SolidFill()]))
369        self.wstest(urwid.Pile([('flow', urwid.Text("hello"))]))
370        self.wstest(urwid.Pile([]))
371
372    def test_columns(self):
373        self.wstest(urwid.Columns([urwid.SolidFill()]))
374        self.wstest(urwid.Columns([(4, urwid.SolidFill())]))
375
376    def test_buttons(self):
377        self.fwstest(urwid.Button(u"hello"))
378        self.fwstest(urwid.RadioButton([], u"hello"))
379
380
381class CommonContainerTest(unittest.TestCase):
382    def test_pile(self):
383        t1 = urwid.Text(u'one')
384        t2 = urwid.Text(u'two')
385        t3 = urwid.Text(u'three')
386        sf = urwid.SolidFill('x')
387        p = urwid.Pile([])
388        self.assertEqual(p.focus, None)
389        self.assertRaises(IndexError, lambda: getattr(p, 'focus_position'))
390        self.assertRaises(IndexError, lambda: setattr(p, 'focus_position',
391            None))
392        self.assertRaises(IndexError, lambda: setattr(p, 'focus_position', 0))
393        p.contents = [(t1, ('pack', None)), (t2, ('pack', None)),
394            (sf, ('given', 3)), (t3, ('pack', None))]
395        p.focus_position = 1
396        del p.contents[0]
397        self.assertEqual(p.focus_position, 0)
398        p.contents[0:0] = [(t3, ('pack', None)), (t2, ('pack', None))]
399        p.contents.insert(3, (t1, ('pack', None)))
400        self.assertEqual(p.focus_position, 2)
401        self.assertRaises(urwid.PileError, lambda: p.contents.append(t1))
402        self.assertRaises(urwid.PileError, lambda: p.contents.append((t1, None)))
403        self.assertRaises(urwid.PileError, lambda: p.contents.append((t1, 'given')))
404
405        p = urwid.Pile([t1, t2])
406        self.assertEqual(p.focus, t1)
407        self.assertEqual(p.focus_position, 0)
408        p.focus_position = 1
409        self.assertEqual(p.focus, t2)
410        self.assertEqual(p.focus_position, 1)
411        p.focus_position = 0
412        self.assertRaises(IndexError, lambda: setattr(p, 'focus_position', -1))
413        self.assertRaises(IndexError, lambda: setattr(p, 'focus_position', 2))
414        # old methods:
415        p.set_focus(0)
416        self.assertRaises(IndexError, lambda: p.set_focus(-1))
417        self.assertRaises(IndexError, lambda: p.set_focus(2))
418        p.set_focus(t2)
419        self.assertEqual(p.focus_position, 1)
420        self.assertRaises(ValueError, lambda: p.set_focus('nonexistant'))
421        self.assertEqual(p.widget_list, [t1, t2])
422        self.assertEqual(p.item_types, [('weight', 1), ('weight', 1)])
423        p.widget_list = [t2, t1]
424        self.assertEqual(p.widget_list, [t2, t1])
425        self.assertEqual(p.contents, [(t2, ('weight', 1)), (t1, ('weight', 1))])
426        self.assertEqual(p.focus_position, 1) # focus unchanged
427        p.item_types = [('flow', None), ('weight', 2)]
428        self.assertEqual(p.item_types, [('flow', None), ('weight', 2)])
429        self.assertEqual(p.contents, [(t2, ('pack', None)), (t1, ('weight', 2))])
430        self.assertEqual(p.focus_position, 1) # focus unchanged
431        p.widget_list = [t1]
432        self.assertEqual(len(p.contents), 1)
433        self.assertEqual(p.focus_position, 0)
434        p.widget_list.extend([t2, t1])
435        self.assertEqual(len(p.contents), 3)
436        self.assertEqual(p.item_types, [
437            ('flow', None), ('weight', 1), ('weight', 1)])
438        p.item_types[:] = [('weight', 2)]
439        self.assertEqual(len(p.contents), 1)
440
441    def test_columns(self):
442        t1 = urwid.Text(u'one')
443        t2 = urwid.Text(u'two')
444        t3 = urwid.Text(u'three')
445        sf = urwid.SolidFill('x')
446        c = urwid.Columns([])
447        self.assertEqual(c.focus, None)
448        self.assertRaises(IndexError, lambda: getattr(c, 'focus_position'))
449        self.assertRaises(IndexError, lambda: setattr(c, 'focus_position',
450            None))
451        self.assertRaises(IndexError, lambda: setattr(c, 'focus_position', 0))
452        c.contents = [
453            (t1, ('pack', None, False)),
454            (t2, ('weight', 1, False)),
455            (sf, ('weight', 2, True)),
456            (t3, ('given', 10, False))]
457        c.focus_position = 1
458        del c.contents[0]
459        self.assertEqual(c.focus_position, 0)
460        c.contents[0:0] = [
461            (t3, ('given', 10, False)),
462            (t2, ('weight', 1, False))]
463        c.contents.insert(3, (t1, ('pack', None, False)))
464        self.assertEqual(c.focus_position, 2)
465        self.assertRaises(urwid.ColumnsError, lambda: c.contents.append(t1))
466        self.assertRaises(urwid.ColumnsError, lambda: c.contents.append((t1, None)))
467        self.assertRaises(urwid.ColumnsError, lambda: c.contents.append((t1, 'given')))
468
469        c = urwid.Columns([t1, t2])
470        self.assertEqual(c.focus, t1)
471        self.assertEqual(c.focus_position, 0)
472        c.focus_position = 1
473        self.assertEqual(c.focus, t2)
474        self.assertEqual(c.focus_position, 1)
475        c.focus_position = 0
476        self.assertRaises(IndexError, lambda: setattr(c, 'focus_position', -1))
477        self.assertRaises(IndexError, lambda: setattr(c, 'focus_position', 2))
478        # old methods:
479        c = urwid.Columns([t1, ('weight', 3, t2), sf], box_columns=[2])
480        c.set_focus(0)
481        self.assertRaises(IndexError, lambda: c.set_focus(-1))
482        self.assertRaises(IndexError, lambda: c.set_focus(3))
483        c.set_focus(t2)
484        self.assertEqual(c.focus_position, 1)
485        self.assertRaises(ValueError, lambda: c.set_focus('nonexistant'))
486        self.assertEqual(c.widget_list, [t1, t2, sf])
487        self.assertEqual(c.column_types, [
488            ('weight', 1), ('weight', 3), ('weight', 1)])
489        self.assertEqual(c.box_columns, [2])
490        c.widget_list = [t2, t1, sf]
491        self.assertEqual(c.widget_list, [t2, t1, sf])
492        self.assertEqual(c.box_columns, [2])
493
494        self.assertEqual(c.contents, [
495            (t2, ('weight', 1, False)),
496            (t1, ('weight', 3, False)),
497            (sf, ('weight', 1, True))])
498        self.assertEqual(c.focus_position, 1) # focus unchanged
499        c.column_types = [
500            ('flow', None), # use the old name
501            ('weight', 2),
502            ('fixed', 5)]
503        self.assertEqual(c.column_types, [
504            ('flow', None),
505            ('weight', 2),
506            ('fixed', 5)])
507        self.assertEqual(c.contents, [
508            (t2, ('pack', None, False)),
509            (t1, ('weight', 2, False)),
510            (sf, ('given', 5, True))])
511        self.assertEqual(c.focus_position, 1) # focus unchanged
512        c.widget_list = [t1]
513        self.assertEqual(len(c.contents), 1)
514        self.assertEqual(c.focus_position, 0)
515        c.widget_list.extend([t2, t1])
516        self.assertEqual(len(c.contents), 3)
517        self.assertEqual(c.column_types, [
518            ('flow', None), ('weight', 1), ('weight', 1)])
519        c.column_types[:] = [('weight', 2)]
520        self.assertEqual(len(c.contents), 1)
521
522    def test_list_box(self):
523        lb = urwid.ListBox(urwid.SimpleFocusListWalker([]))
524        self.assertEqual(lb.focus, None)
525        self.assertRaises(IndexError, lambda: getattr(lb, 'focus_position'))
526        self.assertRaises(IndexError, lambda: setattr(lb, 'focus_position',
527            None))
528        self.assertRaises(IndexError, lambda: setattr(lb, 'focus_position', 0))
529
530        t1 = urwid.Text(u'one')
531        t2 = urwid.Text(u'two')
532        lb = urwid.ListBox(urwid.SimpleListWalker([t1, t2]))
533        self.assertEqual(lb.focus, t1)
534        self.assertEqual(lb.focus_position, 0)
535        lb.focus_position = 1
536        self.assertEqual(lb.focus, t2)
537        self.assertEqual(lb.focus_position, 1)
538        lb.focus_position = 0
539        self.assertRaises(IndexError, lambda: setattr(lb, 'focus_position', -1))
540        self.assertRaises(IndexError, lambda: setattr(lb, 'focus_position', 2))
541
542    def test_grid_flow(self):
543        gf = urwid.GridFlow([], 5, 1, 0, 'left')
544        self.assertEqual(gf.focus, None)
545        self.assertEqual(gf.contents, [])
546        self.assertRaises(IndexError, lambda: getattr(gf, 'focus_position'))
547        self.assertRaises(IndexError, lambda: setattr(gf, 'focus_position',
548            None))
549        self.assertRaises(IndexError, lambda: setattr(gf, 'focus_position', 0))
550        self.assertEqual(gf.options(), ('given', 5))
551        self.assertEqual(gf.options(width_amount=9), ('given', 9))
552        self.assertRaises(urwid.GridFlowError, lambda: gf.options(
553            'pack', None))
554
555        t1 = urwid.Text(u'one')
556        t2 = urwid.Text(u'two')
557        gf = urwid.GridFlow([t1, t2], 5, 1, 0, 'left')
558        self.assertEqual(gf.focus, t1)
559        self.assertEqual(gf.focus_position, 0)
560        self.assertEqual(gf.contents, [(t1, ('given', 5)), (t2, ('given', 5))])
561        gf.focus_position = 1
562        self.assertEqual(gf.focus, t2)
563        self.assertEqual(gf.focus_position, 1)
564        gf.contents.insert(0, (t2, ('given', 5)))
565        self.assertEqual(gf.focus_position, 2)
566        self.assertRaises(urwid.GridFlowError, lambda: gf.contents.append(()))
567        self.assertRaises(urwid.GridFlowError, lambda: gf.contents.insert(1,
568            (t1, ('pack', None))))
569        gf.focus_position = 0
570        self.assertRaises(IndexError, lambda: setattr(gf, 'focus_position', -1))
571        self.assertRaises(IndexError, lambda: setattr(gf, 'focus_position', 3))
572        # old methods:
573        gf.set_focus(0)
574        self.assertRaises(IndexError, lambda: gf.set_focus(-1))
575        self.assertRaises(IndexError, lambda: gf.set_focus(3))
576        gf.set_focus(t1)
577        self.assertEqual(gf.focus_position, 1)
578        self.assertRaises(ValueError, lambda: gf.set_focus('nonexistant'))
579
580    def test_overlay(self):
581        s1 = urwid.SolidFill(u'1')
582        s2 = urwid.SolidFill(u'2')
583        o = urwid.Overlay(s1, s2,
584            'center', ('relative', 50), 'middle', ('relative', 50))
585        self.assertEqual(o.focus, s1)
586        self.assertEqual(o.focus_position, 1)
587        self.assertRaises(IndexError, lambda: setattr(o, 'focus_position',
588            None))
589        self.assertRaises(IndexError, lambda: setattr(o, 'focus_position', 2))
590
591        self.assertEqual(o.contents[0], (s2,
592            urwid.Overlay._DEFAULT_BOTTOM_OPTIONS))
593        self.assertEqual(o.contents[1], (s1, (
594            'center', None, 'relative', 50, None, 0, 0,
595            'middle', None, 'relative', 50, None, 0, 0)))
596
597    def test_frame(self):
598        s1 = urwid.SolidFill(u'1')
599
600        f = urwid.Frame(s1)
601        self.assertEqual(f.focus, s1)
602        self.assertEqual(f.focus_position, 'body')
603        self.assertRaises(IndexError, lambda: setattr(f, 'focus_position',
604            None))
605        self.assertRaises(IndexError, lambda: setattr(f, 'focus_position',
606            'header'))
607
608        t1 = urwid.Text(u'one')
609        t2 = urwid.Text(u'two')
610        t3 = urwid.Text(u'three')
611        f = urwid.Frame(s1, t1, t2, 'header')
612        self.assertEqual(f.focus, t1)
613        self.assertEqual(f.focus_position, 'header')
614        f.focus_position = 'footer'
615        self.assertEqual(f.focus, t2)
616        self.assertEqual(f.focus_position, 'footer')
617        self.assertRaises(IndexError, lambda: setattr(f, 'focus_position', -1))
618        self.assertRaises(IndexError, lambda: setattr(f, 'focus_position', 2))
619        del f.contents['footer']
620        self.assertEqual(f.footer, None)
621        self.assertEqual(f.focus_position, 'body')
622        f.contents.update(footer=(t3, None), header=(t2, None))
623        self.assertEqual(f.header, t2)
624        self.assertEqual(f.footer, t3)
625        def set1():
626            f.contents['body'] = t1
627        self.assertRaises(urwid.FrameError, set1)
628        def set2():
629            f.contents['body'] = (t1, 'given')
630        self.assertRaises(urwid.FrameError, set2)
631
632    def test_focus_path(self):
633        # big tree of containers
634        t = urwid.Text(u'x')
635        e = urwid.Edit(u'?')
636        c = urwid.Columns([t, e, t, t])
637        p = urwid.Pile([t, t, c, t])
638        a = urwid.AttrMap(p, 'gets ignored')
639        s = urwid.SolidFill(u'/')
640        o = urwid.Overlay(e, s, 'center', 'pack', 'middle', 'pack')
641        lb = urwid.ListBox(urwid.SimpleFocusListWalker([t, a, o, t]))
642        lb.focus_position = 1
643        g = urwid.GridFlow([t, t, t, t, e, t], 10, 0, 0, 'left')
644        g.focus_position = 4
645        f = urwid.Frame(lb, header=t, footer=g)
646
647        self.assertEqual(f.get_focus_path(), ['body', 1, 2, 1])
648        f.set_focus_path(['footer']) # same as f.focus_position = 'footer'
649        self.assertEqual(f.get_focus_path(), ['footer', 4])
650        f.set_focus_path(['body', 1, 2, 2])
651        self.assertEqual(f.get_focus_path(), ['body', 1, 2, 2])
652        self.assertRaises(IndexError, lambda: f.set_focus_path([0, 1, 2]))
653        self.assertRaises(IndexError, lambda: f.set_focus_path(['body', 2, 2]))
654        f.set_focus_path(['body', 2]) # focus the overlay
655        self.assertEqual(f.get_focus_path(), ['body', 2, 1])
656