##// END OF EJS Templates
test widget interaction (Python)
MinRK -
Show More
@@ -11,12 +11,392 b''
11 # Imports
11 # Imports
12 #-----------------------------------------------------------------------------
12 #-----------------------------------------------------------------------------
13
13
14 from __future__ import print_function
15
16 from collections import OrderedDict
17
14 import nose.tools as nt
18 import nose.tools as nt
19 import IPython.testing.tools as tt
20
21 # from IPython.core.getipython import get_ipython
22 from IPython.html import widgets
23 from IPython.html.widgets import interact, interactive, Widget, interaction
24 from IPython.utils.py3compat import annotate
25 # from IPython.utils.capture import capture_output
26
27 #-----------------------------------------------------------------------------
28 # Utility stuff
29 #-----------------------------------------------------------------------------
30
31 class DummyComm(object):
32 comm_id = 'a-b-c-d'
33 def send(self, *args, **kwargs):
34 pass
35
36 def close(self, *args, **kwargs):
37 pass
38
39 _widget_attrs = {}
40 displayed = []
41
42 def setup():
43 _widget_attrs['comm'] = Widget.comm
44 Widget.comm = DummyComm()
45 _widget_attrs['_ipython_display_'] = Widget._ipython_display_
46 def raise_not_implemented(*args, **kwargs):
47 raise NotImplementedError()
48 Widget._ipython_display_ = raise_not_implemented
49
50 def teardown():
51 for attr, value in _widget_attrs.items():
52 setattr(Widget, attr, value)
15
53
16 from IPython.html.widgets import interact, interactive
54 def f(**kwargs):
17 from IPython.html.widgets import interaction
55 pass
56
57 def clear_display():
58 global displayed
59 displayed = []
60
61 def record_display(*args):
62 displayed.extend(args)
18
63
19 #-----------------------------------------------------------------------------
64 #-----------------------------------------------------------------------------
20 # Test functions
65 # Actual tests
21 #-----------------------------------------------------------------------------
66 #-----------------------------------------------------------------------------
22
67
68 def check_widget(w, **d):
69 """Check a single widget against a dict"""
70 for attr, expected in d.items():
71 if attr == 'cls':
72 nt.assert_is(w.__class__, expected)
73 else:
74 value = getattr(w, attr)
75 nt.assert_equal(value, expected,
76 "%s.%s = %r != %r" % (w.__class__.__name__, attr, value, expected)
77 )
78
79 def check_widgets(container, **to_check):
80 """Check that widgets are created as expected"""
81 # build a widget dictionary, so it matches
82 widgets = {}
83 for w in container.children:
84 widgets[w.description] = w
85
86 for key, d in to_check.items():
87 nt.assert_in(key, widgets)
88 check_widget(widgets[key], **d)
89
90
91 def test_single_value_string():
92 a = u'hello'
93 c = interactive(f, a=a)
94 w = c.children[0]
95 check_widget(w,
96 cls=widgets.TextWidget,
97 description='a',
98 value=a,
99 )
100
101 def test_single_value_bool():
102 for a in (True, False):
103 c = interactive(f, a=a)
104 w = c.children[0]
105 check_widget(w,
106 cls=widgets.CheckboxWidget,
107 description='a',
108 value=a,
109 )
110
111 def test_single_value_dict():
112 for d in [
113 dict(a=5),
114 dict(a=5, b='b', c=dict),
115 ]:
116 c = interactive(f, d=d)
117 w = c.children[0]
118 check_widget(w,
119 cls=widgets.DropdownWidget,
120 description='d',
121 values=d,
122 value=next(iter(d.values())),
123 )
124
125 def test_single_value_float():
126 for a in (2.25, 1.0, -3.5):
127 c = interactive(f, a=a)
128 w = c.children[0]
129 check_widget(w,
130 cls=widgets.FloatSliderWidget,
131 description='a',
132 value=a,
133 min= -a if a > 0 else 3*a,
134 max= 3*a if a > 0 else -a,
135 step=0.1,
136 )
137
138 def test_single_value_int():
139 for a in (1, 5, -3):
140 c = interactive(f, a=a)
141 nt.assert_equal(len(c.children), 1)
142 w = c.children[0]
143 check_widget(w,
144 cls=widgets.IntSliderWidget,
145 description='a',
146 value=a,
147 min= -a if a > 0 else 3*a,
148 max= 3*a if a > 0 else -a,
149 step=1,
150 )
151
152 def test_list_tuple_2_int():
153 with nt.assert_raises(ValueError):
154 c = interactive(f, tup=(1,1))
155 with nt.assert_raises(ValueError):
156 c = interactive(f, tup=(1,-1))
157 for min, max in [ (0,1), (1,10), (1,2), (-5,5), (-20,-19) ]:
158 c = interactive(f, tup=(min, max), lis=[min, max])
159 nt.assert_equal(len(c.children), 2)
160 d = dict(
161 cls=widgets.IntSliderWidget,
162 min=min,
163 max=max,
164 step=1,
165 )
166 check_widgets(c, tup=d, lis=d)
167
168 def test_list_tuple_3_int():
169 with nt.assert_raises(ValueError):
170 c = interactive(f, tup=(1,2,0))
171 with nt.assert_raises(ValueError):
172 c = interactive(f, tup=(1,2,-1))
173 for min, max, step in [ (0,2,1), (1,10,2), (1,100,2), (-5,5,4), (-100,-20,4) ]:
174 c = interactive(f, tup=(min, max, step), lis=[min, max, step])
175 nt.assert_equal(len(c.children), 2)
176 d = dict(
177 cls=widgets.IntSliderWidget,
178 min=min,
179 max=max,
180 step=step,
181 )
182 check_widgets(c, tup=d, lis=d)
183
184 def test_list_tuple_2_float():
185 with nt.assert_raises(ValueError):
186 c = interactive(f, tup=(1.0,1.0))
187 with nt.assert_raises(ValueError):
188 c = interactive(f, tup=(0.5,-0.5))
189 for min, max in [ (0.5, 1.5), (1.1,10.2), (1,2.2), (-5.,5), (-20,-19.) ]:
190 c = interactive(f, tup=(min, max), lis=[min, max])
191 nt.assert_equal(len(c.children), 2)
192 d = dict(
193 cls=widgets.FloatSliderWidget,
194 min=min,
195 max=max,
196 step=.1,
197 )
198 check_widgets(c, tup=d, lis=d)
199
200 def test_list_tuple_3_float():
201 with nt.assert_raises(ValueError):
202 c = interactive(f, tup=(1,2,0.0))
203 with nt.assert_raises(ValueError):
204 c = interactive(f, tup=(-1,-2,1.))
205 with nt.assert_raises(ValueError):
206 c = interactive(f, tup=(1,2.,-1.))
207 for min, max, step in [ (0.,2,1), (1,10.,2), (1,100,2.), (-5.,5.,4), (-100,-20.,4.) ]:
208 c = interactive(f, tup=(min, max, step), lis=[min, max, step])
209 nt.assert_equal(len(c.children), 2)
210 d = dict(
211 cls=widgets.FloatSliderWidget,
212 min=min,
213 max=max,
214 step=step,
215 )
216 check_widgets(c, tup=d, lis=d)
217
218 def test_list_tuple_str():
219 values = ['hello', 'there', 'guy']
220 first = values[0]
221 dvalues = OrderedDict((v,v) for v in values)
222 c = interactive(f, tup=tuple(values), lis=list(values))
223 nt.assert_equal(len(c.children), 2)
224 d = dict(
225 cls=widgets.DropdownWidget,
226 value=first,
227 values=dvalues
228 )
229 check_widgets(c, tup=d, lis=d)
230
231 def test_list_tuple_invalid():
232 for bad in [
233 (),
234 (5, 'hi'),
235 ('hi', 5),
236 ({},),
237 (None,),
238 ]:
239 with nt.assert_raises(ValueError):
240 print(bad) # because there is no custom message in assert_raises
241 c = interactive(f, tup=bad)
242
243 def test_defaults():
244 @annotate(n=10)
245 def f(n, f=4.5):
246 pass
247
248 c = interactive(f)
249 check_widgets(c,
250 n=dict(
251 cls=widgets.IntSliderWidget,
252 value=10,
253 ),
254 f=dict(
255 cls=widgets.FloatSliderWidget,
256 value=4.5,
257 ),
258 )
259
260 def test_annotations():
261 @annotate(n=10, f=widgets.FloatTextWidget())
262 def f(n, f):
263 pass
264
265 c = interactive(f)
266 check_widgets(c,
267 n=dict(
268 cls=widgets.IntSliderWidget,
269 value=10,
270 ),
271 f=dict(
272 cls=widgets.FloatTextWidget,
273 ),
274 )
275
276 def test_priority():
277 @annotate(annotate='annotate', kwarg='annotate')
278 def f(kwarg='default', annotate='default', default='default'):
279 pass
280
281 c = interactive(f, kwarg='kwarg')
282 check_widgets(c,
283 kwarg=dict(
284 cls=widgets.TextWidget,
285 value='kwarg',
286 ),
287 annotate=dict(
288 cls=widgets.TextWidget,
289 value='annotate',
290 ),
291 )
292
293 @nt.with_setup(clear_display)
294 def test_decorator_kwarg():
295 with tt.monkeypatch(interaction, 'display', record_display):
296 @interact(a=5)
297 def foo(a):
298 pass
299 nt.assert_equal(len(displayed), 1)
300 w = displayed[0].children[0]
301 check_widget(w,
302 cls=widgets.IntSliderWidget,
303 value=5,
304 )
305
306 @nt.with_setup(clear_display)
307 def test_decorator_no_call():
308 with tt.monkeypatch(interaction, 'display', record_display):
309 @interact
310 def foo(a='default'):
311 pass
312 nt.assert_equal(len(displayed), 1)
313 w = displayed[0].children[0]
314 check_widget(w,
315 cls=widgets.TextWidget,
316 value='default',
317 )
318
319 @nt.with_setup(clear_display)
320 def test_call_interact():
321 def foo(a='default'):
322 pass
323 with tt.monkeypatch(interaction, 'display', record_display):
324 ifoo = interact(foo)
325 nt.assert_equal(len(displayed), 1)
326 w = displayed[0].children[0]
327 check_widget(w,
328 cls=widgets.TextWidget,
329 value='default',
330 )
331
332 @nt.with_setup(clear_display)
333 def test_call_interact_kwargs():
334 def foo(a='default'):
335 pass
336 with tt.monkeypatch(interaction, 'display', record_display):
337 ifoo = interact(foo, a=10)
338 nt.assert_equal(len(displayed), 1)
339 w = displayed[0].children[0]
340 check_widget(w,
341 cls=widgets.IntSliderWidget,
342 value=10,
343 )
344
345 @nt.with_setup(clear_display)
346 def test_call_decorated_on_trait_change():
347 """test calling @interact decorated functions"""
348 d = {}
349 with tt.monkeypatch(interaction, 'display', record_display):
350 @interact
351 def foo(a='default'):
352 d['a'] = a
353 return a
354 nt.assert_equal(len(displayed), 1)
355 w = displayed[0].children[0]
356 check_widget(w,
357 cls=widgets.TextWidget,
358 value='default',
359 )
360 # test calling the function directly
361 a = foo('hello')
362 nt.assert_equal(a, 'hello')
363 nt.assert_equal(d['a'], 'hello')
364
365 # test that setting trait values calls the function
366 w.value = 'called'
367 nt.assert_equal(d['a'], 'called')
368
369 @nt.with_setup(clear_display)
370 def test_call_decorated_kwargs_on_trait_change():
371 """test calling @interact(foo=bar) decorated functions"""
372 d = {}
373 with tt.monkeypatch(interaction, 'display', record_display):
374 @interact(a='kwarg')
375 def foo(a='default'):
376 d['a'] = a
377 return a
378 nt.assert_equal(len(displayed), 1)
379 w = displayed[0].children[0]
380 check_widget(w,
381 cls=widgets.TextWidget,
382 value='kwarg',
383 )
384 # test calling the function directly
385 a = foo('hello')
386 nt.assert_equal(a, 'hello')
387 nt.assert_equal(d['a'], 'hello')
388
389 # test that setting trait values calls the function
390 w.value = 'called'
391 nt.assert_equal(d['a'], 'called')
392
393 def test_fixed():
394 c = interactive(f, a=widgets.fixed(5), b='text')
395 nt.assert_equal(len(c.children), 1)
396 w = c.children[0]
397 check_widget(w,
398 cls=widgets.TextWidget,
399 value='text',
400 description='b',
401 )
402
General Comments 0
You need to be logged in to leave comments. Login now