##// END OF EJS Templates
Add some tests for the 4-5 int/float form in interact()
Gordon Ball -
Show More
@@ -1,482 +1,560 b''
1 1 """Test interact and interactive."""
2 2
3 3 #-----------------------------------------------------------------------------
4 4 # Copyright (C) 2014 The IPython Development Team
5 5 #
6 6 # Distributed under the terms of the BSD License. The full license is in
7 7 # the file COPYING, distributed as part of this software.
8 8 #-----------------------------------------------------------------------------
9 9
10 10 #-----------------------------------------------------------------------------
11 11 # Imports
12 12 #-----------------------------------------------------------------------------
13 13
14 14 from __future__ import print_function
15 15
16 16 from collections import OrderedDict
17 17
18 18 import nose.tools as nt
19 19 import IPython.testing.tools as tt
20 20
21 21 # from IPython.core.getipython import get_ipython
22 22 from IPython.html import widgets
23 23 from IPython.html.widgets import interact, interactive, Widget, interaction
24 24 from IPython.utils.py3compat import annotate
25 25
26 26 #-----------------------------------------------------------------------------
27 27 # Utility stuff
28 28 #-----------------------------------------------------------------------------
29 29
30 30 class DummyComm(object):
31 31 comm_id = 'a-b-c-d'
32 32 def send(self, *args, **kwargs):
33 33 pass
34 34
35 35 def close(self, *args, **kwargs):
36 36 pass
37 37
38 38 _widget_attrs = {}
39 39 displayed = []
40 40
41 41 def setup():
42 42 _widget_attrs['comm'] = Widget.comm
43 43 Widget.comm = DummyComm()
44 44 _widget_attrs['_ipython_display_'] = Widget._ipython_display_
45 45 def raise_not_implemented(*args, **kwargs):
46 46 raise NotImplementedError()
47 47 Widget._ipython_display_ = raise_not_implemented
48 48
49 49 def teardown():
50 50 for attr, value in _widget_attrs.items():
51 51 setattr(Widget, attr, value)
52 52
53 53 def f(**kwargs):
54 54 pass
55 55
56 56 def clear_display():
57 57 global displayed
58 58 displayed = []
59 59
60 60 def record_display(*args):
61 61 displayed.extend(args)
62 62
63 63 #-----------------------------------------------------------------------------
64 64 # Actual tests
65 65 #-----------------------------------------------------------------------------
66 66
67 67 def check_widget(w, **d):
68 68 """Check a single widget against a dict"""
69 69 for attr, expected in d.items():
70 70 if attr == 'cls':
71 71 nt.assert_is(w.__class__, expected)
72 72 else:
73 73 value = getattr(w, attr)
74 74 nt.assert_equal(value, expected,
75 75 "%s.%s = %r != %r" % (w.__class__.__name__, attr, value, expected)
76 76 )
77 77
78 78 def check_widgets(container, **to_check):
79 79 """Check that widgets are created as expected"""
80 80 # build a widget dictionary, so it matches
81 81 widgets = {}
82 82 for w in container.children:
83 83 widgets[w.description] = w
84 84
85 85 for key, d in to_check.items():
86 86 nt.assert_in(key, widgets)
87 87 check_widget(widgets[key], **d)
88 88
89 89
90 90 def test_single_value_string():
91 91 a = u'hello'
92 92 c = interactive(f, a=a)
93 93 w = c.children[0]
94 94 check_widget(w,
95 95 cls=widgets.TextWidget,
96 96 description='a',
97 97 value=a,
98 98 )
99 99
100 100 def test_single_value_bool():
101 101 for a in (True, False):
102 102 c = interactive(f, a=a)
103 103 w = c.children[0]
104 104 check_widget(w,
105 105 cls=widgets.CheckboxWidget,
106 106 description='a',
107 107 value=a,
108 108 )
109 109
110 110 def test_single_value_dict():
111 111 for d in [
112 112 dict(a=5),
113 113 dict(a=5, b='b', c=dict),
114 114 ]:
115 115 c = interactive(f, d=d)
116 116 w = c.children[0]
117 117 check_widget(w,
118 118 cls=widgets.DropdownWidget,
119 119 description='d',
120 120 values=d,
121 121 value=next(iter(d.values())),
122 122 )
123 123
124 124 def test_single_value_float():
125 125 for a in (2.25, 1.0, -3.5):
126 126 c = interactive(f, a=a)
127 127 w = c.children[0]
128 128 check_widget(w,
129 129 cls=widgets.FloatSliderWidget,
130 130 description='a',
131 131 value=a,
132 132 min= -a if a > 0 else 3*a,
133 133 max= 3*a if a > 0 else -a,
134 134 step=0.1,
135 135 readout=True,
136 136 )
137 137
138 138 def test_single_value_int():
139 139 for a in (1, 5, -3):
140 140 c = interactive(f, a=a)
141 141 nt.assert_equal(len(c.children), 1)
142 142 w = c.children[0]
143 143 check_widget(w,
144 144 cls=widgets.IntSliderWidget,
145 145 description='a',
146 146 value=a,
147 147 min= -a if a > 0 else 3*a,
148 148 max= 3*a if a > 0 else -a,
149 149 step=1,
150 150 readout=True,
151 151 )
152 152
153 153 def test_list_tuple_2_int():
154 154 with nt.assert_raises(ValueError):
155 155 c = interactive(f, tup=(1,1))
156 156 with nt.assert_raises(ValueError):
157 157 c = interactive(f, tup=(1,-1))
158 158 for min, max in [ (0,1), (1,10), (1,2), (-5,5), (-20,-19) ]:
159 159 c = interactive(f, tup=(min, max), lis=[min, max])
160 160 nt.assert_equal(len(c.children), 2)
161 161 d = dict(
162 162 cls=widgets.IntSliderWidget,
163 163 min=min,
164 164 max=max,
165 165 step=1,
166 166 readout=True,
167 167 )
168 168 check_widgets(c, tup=d, lis=d)
169 169
170 170 def test_list_tuple_3_int():
171 171 with nt.assert_raises(ValueError):
172 172 c = interactive(f, tup=(1,2,0))
173 173 with nt.assert_raises(ValueError):
174 174 c = interactive(f, tup=(1,2,-1))
175 175 for min, max, step in [ (0,2,1), (1,10,2), (1,100,2), (-5,5,4), (-100,-20,4) ]:
176 176 c = interactive(f, tup=(min, max, step), lis=[min, max, step])
177 177 nt.assert_equal(len(c.children), 2)
178 178 d = dict(
179 179 cls=widgets.IntSliderWidget,
180 180 min=min,
181 181 max=max,
182 182 step=step,
183 183 readout=True,
184 184 )
185 185 check_widgets(c, tup=d, lis=d)
186 186
187 187 def test_list_tuple_2_float():
188 188 with nt.assert_raises(ValueError):
189 189 c = interactive(f, tup=(1.0,1.0))
190 190 with nt.assert_raises(ValueError):
191 191 c = interactive(f, tup=(0.5,-0.5))
192 192 for min, max in [ (0.5, 1.5), (1.1,10.2), (1,2.2), (-5.,5), (-20,-19.) ]:
193 193 c = interactive(f, tup=(min, max), lis=[min, max])
194 194 nt.assert_equal(len(c.children), 2)
195 195 d = dict(
196 196 cls=widgets.FloatSliderWidget,
197 197 min=min,
198 198 max=max,
199 199 step=.1,
200 200 readout=True,
201 201 )
202 202 check_widgets(c, tup=d, lis=d)
203 203
204 204 def test_list_tuple_3_float():
205 205 with nt.assert_raises(ValueError):
206 206 c = interactive(f, tup=(1,2,0.0))
207 207 with nt.assert_raises(ValueError):
208 208 c = interactive(f, tup=(-1,-2,1.))
209 209 with nt.assert_raises(ValueError):
210 210 c = interactive(f, tup=(1,2.,-1.))
211 211 for min, max, step in [ (0.,2,1), (1,10.,2), (1,100,2.), (-5.,5.,4), (-100,-20.,4.) ]:
212 212 c = interactive(f, tup=(min, max, step), lis=[min, max, step])
213 213 nt.assert_equal(len(c.children), 2)
214 214 d = dict(
215 215 cls=widgets.FloatSliderWidget,
216 216 min=min,
217 217 max=max,
218 218 step=step,
219 219 readout=True,
220 220 )
221 221 check_widgets(c, tup=d, lis=d)
222 222
223 def test_list_tuple_4_int():
224 with nt.assert_raises(ValueError):
225 c = interactive(f, tup=(4, 3, 2, 1))
226 with nt.assert_raises(ValueError):
227 c = interactive(f, tup=(1, 2, 3, 2))
228 with nt.assert_raises(ValueError):
229 c = interactive(f, tup=(2, 1, 3, 4))
230 for min, low, high, max in [(0, 1, 2, 3), (0, 0, 0, 0), (1, 2, 2, 3), (-2, -1, 1, 2)]:
231 c = interactive(f, tup=(min, low, high, max), lis=[min, low, high, max])
232 nt.assert_equal(len(c.children), 2)
233 d = dict(
234 cls=widgets.IntRangeSliderWidget,
235 min=min,
236 max=max,
237 value=(low, high),
238 range=True,
239 readout=True
240 )
241 check_widgets(c, tup=d, lis=d)
242
243 def test_list_tuple_5_int():
244 with nt.assert_raises(ValueError):
245 c = interactive(f, tup=(1, 2, 3, 4, 0))
246 with nt.assert_raises(ValueError):
247 c = interactive(f, tup=(1, 2, 3, 4, -1))
248 for min, low, high, max, step in [(0, 1, 2, 3, 1), (0, 0, 0, 0, 1), (1, 2, 2, 3, 2), (-2, -1, 1, 2, 3)]:
249 c = interactive(f, tup=(min, low, high, max, step), lis=[min, low, high, max, step])
250 nt.assert_equal(len(c.children), 2)
251 d = dict(
252 cls=widgets.IntRangeSliderWidget,
253 min=min,
254 max=max,
255 value=(low, high),
256 step=step,
257 range=True,
258 readout=True
259 )
260 check_widgets(c, tup=d, lis=d)
261
262 def test_list_tuple_4_float():
263 with nt.assert_raises(ValueError):
264 c = interactive(f, tup=(4, 3., 2, 1))
265 with nt.assert_raises(ValueError):
266 c = interactive(f, tup=(1, 2, 3, 2.))
267 with nt.assert_raises(ValueError):
268 c = interactive(f, tup=(2, 1., 3, 4))
269 for min, low, high, max in [(0, 1., 2, 3), (0, 0, 0., 0), (1., 2., 2., 3.1415), (-2.5, -1, 1, 2.5)]:
270 c = interactive(f, tup=(min, low, high, max), lis=[min, low, high, max])
271 nt.assert_equal(len(c.children), 2)
272 d = dict(
273 cls=widgets.FloatRangeSliderWidget,
274 min=min,
275 max=max,
276 value=(low, high),
277 range=True,
278 readout=True
279 )
280 check_widgets(c, tup=d, lis=d)
281
282 def test_list_tuple_5_float():
283 with nt.assert_raises(ValueError):
284 c = interactive(f, tup=(1, 2., 3., 4, 0))
285 with nt.assert_raises(ValueError):
286 c = interactive(f, tup=(1, 2, 3., 4., -0.5))
287 for min, low, high, max, step in [(0, 1, 2, 3, 0.01), (0, 0, 0, 0, 0.1), (1, 2, 2, 3, 2.718), (-2, -1.5, 1.5, 2, 2)]:
288 c = interactive(f, tup=(min, low, high, max, step), lis=[min, low, high, max, step])
289 nt.assert_equal(len(c.children), 2)
290 d = dict(
291 cls=widgets.FloatRangeSliderWidget,
292 min=min,
293 max=max,
294 value=(low, high),
295 step=step,
296 range=True,
297 readout=True
298 )
299 check_widgets(c, tup=d, lis=d)
300
223 301 def test_list_tuple_str():
224 302 values = ['hello', 'there', 'guy']
225 303 first = values[0]
226 304 dvalues = OrderedDict((v,v) for v in values)
227 305 c = interactive(f, tup=tuple(values), lis=list(values))
228 306 nt.assert_equal(len(c.children), 2)
229 307 d = dict(
230 308 cls=widgets.DropdownWidget,
231 309 value=first,
232 310 values=dvalues
233 311 )
234 312 check_widgets(c, tup=d, lis=d)
235 313
236 314 def test_list_tuple_invalid():
237 315 for bad in [
238 316 (),
239 317 (5, 'hi'),
240 318 ('hi', 5),
241 319 ({},),
242 320 (None,),
243 321 ]:
244 322 with nt.assert_raises(ValueError):
245 323 print(bad) # because there is no custom message in assert_raises
246 324 c = interactive(f, tup=bad)
247 325
248 326 def test_defaults():
249 327 @annotate(n=10)
250 328 def f(n, f=4.5, g=1):
251 329 pass
252 330
253 331 c = interactive(f)
254 332 check_widgets(c,
255 333 n=dict(
256 334 cls=widgets.IntSliderWidget,
257 335 value=10,
258 336 ),
259 337 f=dict(
260 338 cls=widgets.FloatSliderWidget,
261 339 value=4.5,
262 340 ),
263 341 g=dict(
264 342 cls=widgets.IntSliderWidget,
265 343 value=1,
266 344 ),
267 345 )
268 346
269 347 def test_default_values():
270 348 @annotate(n=10, f=(0, 10.), g=5, h={'a': 1, 'b': 2}, j=['hi', 'there'])
271 349 def f(n, f=4.5, g=1, h=2, j='there'):
272 350 pass
273 351
274 352 c = interactive(f)
275 353 check_widgets(c,
276 354 n=dict(
277 355 cls=widgets.IntSliderWidget,
278 356 value=10,
279 357 ),
280 358 f=dict(
281 359 cls=widgets.FloatSliderWidget,
282 360 value=4.5,
283 361 ),
284 362 g=dict(
285 363 cls=widgets.IntSliderWidget,
286 364 value=5,
287 365 ),
288 366 h=dict(
289 367 cls=widgets.DropdownWidget,
290 368 values={'a': 1, 'b': 2},
291 369 value=2
292 370 ),
293 371 j=dict(
294 372 cls=widgets.DropdownWidget,
295 373 values={'hi':'hi', 'there':'there'},
296 374 value='there'
297 375 ),
298 376 )
299 377
300 378 def test_default_out_of_bounds():
301 379 @annotate(f=(0, 10.), h={'a': 1}, j=['hi', 'there'])
302 380 def f(f='hi', h=5, j='other'):
303 381 pass
304 382
305 383 c = interactive(f)
306 384 check_widgets(c,
307 385 f=dict(
308 386 cls=widgets.FloatSliderWidget,
309 387 value=5.,
310 388 ),
311 389 h=dict(
312 390 cls=widgets.DropdownWidget,
313 391 values={'a': 1},
314 392 value=1,
315 393 ),
316 394 j=dict(
317 395 cls=widgets.DropdownWidget,
318 396 values={'hi':'hi', 'there':'there'},
319 397 value='hi',
320 398 ),
321 399 )
322 400
323 401 def test_annotations():
324 402 @annotate(n=10, f=widgets.FloatTextWidget())
325 403 def f(n, f):
326 404 pass
327 405
328 406 c = interactive(f)
329 407 check_widgets(c,
330 408 n=dict(
331 409 cls=widgets.IntSliderWidget,
332 410 value=10,
333 411 ),
334 412 f=dict(
335 413 cls=widgets.FloatTextWidget,
336 414 ),
337 415 )
338 416
339 417 def test_priority():
340 418 @annotate(annotate='annotate', kwarg='annotate')
341 419 def f(kwarg='default', annotate='default', default='default'):
342 420 pass
343 421
344 422 c = interactive(f, kwarg='kwarg')
345 423 check_widgets(c,
346 424 kwarg=dict(
347 425 cls=widgets.TextWidget,
348 426 value='kwarg',
349 427 ),
350 428 annotate=dict(
351 429 cls=widgets.TextWidget,
352 430 value='annotate',
353 431 ),
354 432 )
355 433
356 434 @nt.with_setup(clear_display)
357 435 def test_decorator_kwarg():
358 436 with tt.monkeypatch(interaction, 'display', record_display):
359 437 @interact(a=5)
360 438 def foo(a):
361 439 pass
362 440 nt.assert_equal(len(displayed), 1)
363 441 w = displayed[0].children[0]
364 442 check_widget(w,
365 443 cls=widgets.IntSliderWidget,
366 444 value=5,
367 445 )
368 446
369 447 @nt.with_setup(clear_display)
370 448 def test_decorator_no_call():
371 449 with tt.monkeypatch(interaction, 'display', record_display):
372 450 @interact
373 451 def foo(a='default'):
374 452 pass
375 453 nt.assert_equal(len(displayed), 1)
376 454 w = displayed[0].children[0]
377 455 check_widget(w,
378 456 cls=widgets.TextWidget,
379 457 value='default',
380 458 )
381 459
382 460 @nt.with_setup(clear_display)
383 461 def test_call_interact():
384 462 def foo(a='default'):
385 463 pass
386 464 with tt.monkeypatch(interaction, 'display', record_display):
387 465 ifoo = interact(foo)
388 466 nt.assert_equal(len(displayed), 1)
389 467 w = displayed[0].children[0]
390 468 check_widget(w,
391 469 cls=widgets.TextWidget,
392 470 value='default',
393 471 )
394 472
395 473 @nt.with_setup(clear_display)
396 474 def test_call_interact_kwargs():
397 475 def foo(a='default'):
398 476 pass
399 477 with tt.monkeypatch(interaction, 'display', record_display):
400 478 ifoo = interact(foo, a=10)
401 479 nt.assert_equal(len(displayed), 1)
402 480 w = displayed[0].children[0]
403 481 check_widget(w,
404 482 cls=widgets.IntSliderWidget,
405 483 value=10,
406 484 )
407 485
408 486 @nt.with_setup(clear_display)
409 487 def test_call_decorated_on_trait_change():
410 488 """test calling @interact decorated functions"""
411 489 d = {}
412 490 with tt.monkeypatch(interaction, 'display', record_display):
413 491 @interact
414 492 def foo(a='default'):
415 493 d['a'] = a
416 494 return a
417 495 nt.assert_equal(len(displayed), 1)
418 496 w = displayed[0].children[0]
419 497 check_widget(w,
420 498 cls=widgets.TextWidget,
421 499 value='default',
422 500 )
423 501 # test calling the function directly
424 502 a = foo('hello')
425 503 nt.assert_equal(a, 'hello')
426 504 nt.assert_equal(d['a'], 'hello')
427 505
428 506 # test that setting trait values calls the function
429 507 w.value = 'called'
430 508 nt.assert_equal(d['a'], 'called')
431 509
432 510 @nt.with_setup(clear_display)
433 511 def test_call_decorated_kwargs_on_trait_change():
434 512 """test calling @interact(foo=bar) decorated functions"""
435 513 d = {}
436 514 with tt.monkeypatch(interaction, 'display', record_display):
437 515 @interact(a='kwarg')
438 516 def foo(a='default'):
439 517 d['a'] = a
440 518 return a
441 519 nt.assert_equal(len(displayed), 1)
442 520 w = displayed[0].children[0]
443 521 check_widget(w,
444 522 cls=widgets.TextWidget,
445 523 value='kwarg',
446 524 )
447 525 # test calling the function directly
448 526 a = foo('hello')
449 527 nt.assert_equal(a, 'hello')
450 528 nt.assert_equal(d['a'], 'hello')
451 529
452 530 # test that setting trait values calls the function
453 531 w.value = 'called'
454 532 nt.assert_equal(d['a'], 'called')
455 533
456 534 def test_fixed():
457 535 c = interactive(f, a=widgets.fixed(5), b='text')
458 536 nt.assert_equal(len(c.children), 1)
459 537 w = c.children[0]
460 538 check_widget(w,
461 539 cls=widgets.TextWidget,
462 540 value='text',
463 541 description='b',
464 542 )
465 543
466 544 def test_default_description():
467 545 c = interactive(f, b='text')
468 546 w = c.children[0]
469 547 check_widget(w,
470 548 cls=widgets.TextWidget,
471 549 value='text',
472 550 description='b',
473 551 )
474 552
475 553 def test_custom_description():
476 554 c = interactive(f, b=widgets.TextWidget(value='text', description='foo'))
477 555 w = c.children[0]
478 556 check_widget(w,
479 557 cls=widgets.TextWidget,
480 558 value='text',
481 559 description='foo',
482 560 )
General Comments 0
You need to be logged in to leave comments. Login now