##// END OF EJS Templates
try..finally for tearing down test
zah -
Show More
@@ -1,1125 +1,1127 b''
1 1 # encoding: utf-8
2 2 """Tests for IPython.utils.traitlets."""
3 3
4 4 # Copyright (c) IPython Development Team.
5 5 # Distributed under the terms of the Modified BSD License.
6 6 #
7 7 # Adapted from enthought.traits, Copyright (c) Enthought, Inc.,
8 8 # also under the terms of the Modified BSD License.
9 9
10 10 import pickle
11 11 import re
12 12 import sys
13 13 from unittest import TestCase
14 14
15 15 import nose.tools as nt
16 16 from nose import SkipTest
17 17
18 18 from IPython.utils.traitlets import (
19 19 HasTraits, MetaHasTraits, TraitType, AllowNone, Any, CBytes, Dict,
20 20 Int, Long, Integer, Float, Complex, Bytes, Unicode, TraitError,
21 21 Undefined, Type, This, Instance, TCPAddress, List, Tuple,
22 22 ObjectName, DottedObjectName, CRegExp, link
23 23 )
24 24 from IPython.utils import py3compat
25 25 from IPython.testing.decorators import skipif
26 26
27 27 #-----------------------------------------------------------------------------
28 28 # Helper classes for testing
29 29 #-----------------------------------------------------------------------------
30 30
31 31
32 32 class HasTraitsStub(HasTraits):
33 33
34 34 def _notify_trait(self, name, old, new):
35 35 self._notify_name = name
36 36 self._notify_old = old
37 37 self._notify_new = new
38 38
39 39
40 40 #-----------------------------------------------------------------------------
41 41 # Test classes
42 42 #-----------------------------------------------------------------------------
43 43
44 44
45 45 class TestTraitType(TestCase):
46 46
47 47 def test_get_undefined(self):
48 48 class A(HasTraits):
49 49 a = TraitType
50 50 a = A()
51 51 self.assertEqual(a.a, Undefined)
52 52
53 53 def test_set(self):
54 54 class A(HasTraitsStub):
55 55 a = TraitType
56 56
57 57 a = A()
58 58 a.a = 10
59 59 self.assertEqual(a.a, 10)
60 60 self.assertEqual(a._notify_name, 'a')
61 61 self.assertEqual(a._notify_old, Undefined)
62 62 self.assertEqual(a._notify_new, 10)
63 63
64 64 def test_validate(self):
65 65 class MyTT(TraitType):
66 66 def validate(self, inst, value):
67 67 return -1
68 68 class A(HasTraitsStub):
69 69 tt = MyTT
70 70
71 71 a = A()
72 72 a.tt = 10
73 73 self.assertEqual(a.tt, -1)
74 74
75 75 def test_default_validate(self):
76 76 class MyIntTT(AllowNone):
77 77 def validate(self, obj, value):
78 78 if isinstance(value, int):
79 79 return value
80 80 self.error(obj, value)
81 81 class A(HasTraits):
82 82 tt = MyIntTT(10)
83 83 a = A()
84 84 self.assertEqual(a.tt, 10)
85 85
86 86 # Defaults are validated when the HasTraits is instantiated
87 87 class B(HasTraits):
88 88 tt = MyIntTT('bad default')
89 89 self.assertRaises(TraitError, B)
90 90
91 91 def test_is_valid_for(self):
92 92 class MyTT(TraitType):
93 93 def is_valid_for(self, value):
94 94 return True
95 95 class A(HasTraits):
96 96 tt = MyTT
97 97
98 98 a = A()
99 99 a.tt = 10
100 100 self.assertEqual(a.tt, 10)
101 101
102 102 def test_value_for(self):
103 103 class MyTT(TraitType):
104 104 def value_for(self, value):
105 105 return 20
106 106 class A(HasTraits):
107 107 tt = MyTT
108 108
109 109 a = A()
110 110 a.tt = 10
111 111 self.assertEqual(a.tt, 20)
112 112
113 113 def test_info(self):
114 114 class A(HasTraits):
115 115 tt = TraitType
116 116 a = A()
117 117 self.assertEqual(A.tt.info(), 'any value')
118 118
119 119 def test_error(self):
120 120 class A(HasTraits):
121 121 tt = TraitType
122 122 a = A()
123 123 self.assertRaises(TraitError, A.tt.error, a, 10)
124 124
125 125 def test_dynamic_initializer(self):
126 126 class A(HasTraits):
127 127 x = Int(10)
128 128 def _x_default(self):
129 129 return 11
130 130 class B(A):
131 131 x = Int(20)
132 132 class C(A):
133 133 def _x_default(self):
134 134 return 21
135 135
136 136 a = A()
137 137 self.assertEqual(a._trait_values, {})
138 138 self.assertEqual(list(a._trait_dyn_inits.keys()), ['x'])
139 139 self.assertEqual(a.x, 11)
140 140 self.assertEqual(a._trait_values, {'x': 11})
141 141 b = B()
142 142 self.assertEqual(b._trait_values, {'x': 20})
143 143 self.assertEqual(list(a._trait_dyn_inits.keys()), ['x'])
144 144 self.assertEqual(b.x, 20)
145 145 c = C()
146 146 self.assertEqual(c._trait_values, {})
147 147 self.assertEqual(list(a._trait_dyn_inits.keys()), ['x'])
148 148 self.assertEqual(c.x, 21)
149 149 self.assertEqual(c._trait_values, {'x': 21})
150 150 # Ensure that the base class remains unmolested when the _default
151 151 # initializer gets overridden in a subclass.
152 152 a = A()
153 153 c = C()
154 154 self.assertEqual(a._trait_values, {})
155 155 self.assertEqual(list(a._trait_dyn_inits.keys()), ['x'])
156 156 self.assertEqual(a.x, 11)
157 157 self.assertEqual(a._trait_values, {'x': 11})
158 158
159 159
160 160
161 161 class TestHasTraitsMeta(TestCase):
162 162
163 163 def test_metaclass(self):
164 164 self.assertEqual(type(HasTraits), MetaHasTraits)
165 165
166 166 class A(HasTraits):
167 167 a = Int
168 168
169 169 a = A()
170 170 self.assertEqual(type(a.__class__), MetaHasTraits)
171 171 self.assertEqual(a.a,0)
172 172 a.a = 10
173 173 self.assertEqual(a.a,10)
174 174
175 175 class B(HasTraits):
176 176 b = Int()
177 177
178 178 b = B()
179 179 self.assertEqual(b.b,0)
180 180 b.b = 10
181 181 self.assertEqual(b.b,10)
182 182
183 183 class C(HasTraits):
184 184 c = Int(30)
185 185
186 186 c = C()
187 187 self.assertEqual(c.c,30)
188 188 c.c = 10
189 189 self.assertEqual(c.c,10)
190 190
191 191 def test_this_class(self):
192 192 class A(HasTraits):
193 193 t = This()
194 194 tt = This()
195 195 class B(A):
196 196 tt = This()
197 197 ttt = This()
198 198 self.assertEqual(A.t.this_class, A)
199 199 self.assertEqual(B.t.this_class, A)
200 200 self.assertEqual(B.tt.this_class, B)
201 201 self.assertEqual(B.ttt.this_class, B)
202 202
203 203 class TestHasTraitsNotify(TestCase):
204 204
205 205 def setUp(self):
206 206 self._notify1 = []
207 207 self._notify2 = []
208 208
209 209 def notify1(self, name, old, new):
210 210 self._notify1.append((name, old, new))
211 211
212 212 def notify2(self, name, old, new):
213 213 self._notify2.append((name, old, new))
214 214
215 215 def test_notify_all(self):
216 216
217 217 class A(HasTraits):
218 218 a = Int
219 219 b = Float
220 220
221 221 a = A()
222 222 a.on_trait_change(self.notify1)
223 223 a.a = 0
224 224 self.assertEqual(len(self._notify1),0)
225 225 a.b = 0.0
226 226 self.assertEqual(len(self._notify1),0)
227 227 a.a = 10
228 228 self.assertTrue(('a',0,10) in self._notify1)
229 229 a.b = 10.0
230 230 self.assertTrue(('b',0.0,10.0) in self._notify1)
231 231 self.assertRaises(TraitError,setattr,a,'a','bad string')
232 232 self.assertRaises(TraitError,setattr,a,'b','bad string')
233 233 self._notify1 = []
234 234 a.on_trait_change(self.notify1,remove=True)
235 235 a.a = 20
236 236 a.b = 20.0
237 237 self.assertEqual(len(self._notify1),0)
238 238
239 239 def test_notify_one(self):
240 240
241 241 class A(HasTraits):
242 242 a = Int
243 243 b = Float
244 244
245 245 a = A()
246 246 a.on_trait_change(self.notify1, 'a')
247 247 a.a = 0
248 248 self.assertEqual(len(self._notify1),0)
249 249 a.a = 10
250 250 self.assertTrue(('a',0,10) in self._notify1)
251 251 self.assertRaises(TraitError,setattr,a,'a','bad string')
252 252
253 253 def test_subclass(self):
254 254
255 255 class A(HasTraits):
256 256 a = Int
257 257
258 258 class B(A):
259 259 b = Float
260 260
261 261 b = B()
262 262 self.assertEqual(b.a,0)
263 263 self.assertEqual(b.b,0.0)
264 264 b.a = 100
265 265 b.b = 100.0
266 266 self.assertEqual(b.a,100)
267 267 self.assertEqual(b.b,100.0)
268 268
269 269 def test_notify_subclass(self):
270 270
271 271 class A(HasTraits):
272 272 a = Int
273 273
274 274 class B(A):
275 275 b = Float
276 276
277 277 b = B()
278 278 b.on_trait_change(self.notify1, 'a')
279 279 b.on_trait_change(self.notify2, 'b')
280 280 b.a = 0
281 281 b.b = 0.0
282 282 self.assertEqual(len(self._notify1),0)
283 283 self.assertEqual(len(self._notify2),0)
284 284 b.a = 10
285 285 b.b = 10.0
286 286 self.assertTrue(('a',0,10) in self._notify1)
287 287 self.assertTrue(('b',0.0,10.0) in self._notify2)
288 288
289 289 def test_static_notify(self):
290 290
291 291 class A(HasTraits):
292 292 a = Int
293 293 _notify1 = []
294 294 def _a_changed(self, name, old, new):
295 295 self._notify1.append((name, old, new))
296 296
297 297 a = A()
298 298 a.a = 0
299 299 # This is broken!!!
300 300 self.assertEqual(len(a._notify1),0)
301 301 a.a = 10
302 302 self.assertTrue(('a',0,10) in a._notify1)
303 303
304 304 class B(A):
305 305 b = Float
306 306 _notify2 = []
307 307 def _b_changed(self, name, old, new):
308 308 self._notify2.append((name, old, new))
309 309
310 310 b = B()
311 311 b.a = 10
312 312 b.b = 10.0
313 313 self.assertTrue(('a',0,10) in b._notify1)
314 314 self.assertTrue(('b',0.0,10.0) in b._notify2)
315 315
316 316 def test_notify_args(self):
317 317
318 318 def callback0():
319 319 self.cb = ()
320 320 def callback1(name):
321 321 self.cb = (name,)
322 322 def callback2(name, new):
323 323 self.cb = (name, new)
324 324 def callback3(name, old, new):
325 325 self.cb = (name, old, new)
326 326
327 327 class A(HasTraits):
328 328 a = Int
329 329
330 330 a = A()
331 331 a.on_trait_change(callback0, 'a')
332 332 a.a = 10
333 333 self.assertEqual(self.cb,())
334 334 a.on_trait_change(callback0, 'a', remove=True)
335 335
336 336 a.on_trait_change(callback1, 'a')
337 337 a.a = 100
338 338 self.assertEqual(self.cb,('a',))
339 339 a.on_trait_change(callback1, 'a', remove=True)
340 340
341 341 a.on_trait_change(callback2, 'a')
342 342 a.a = 1000
343 343 self.assertEqual(self.cb,('a',1000))
344 344 a.on_trait_change(callback2, 'a', remove=True)
345 345
346 346 a.on_trait_change(callback3, 'a')
347 347 a.a = 10000
348 348 self.assertEqual(self.cb,('a',1000,10000))
349 349 a.on_trait_change(callback3, 'a', remove=True)
350 350
351 351 self.assertEqual(len(a._trait_notifiers['a']),0)
352 352
353 353 def test_notify_only_once(self):
354 354
355 355 class A(HasTraits):
356 356 listen_to = ['a']
357 357
358 358 a = Int(0)
359 359 b = 0
360 360
361 361 def __init__(self, **kwargs):
362 362 super(A, self).__init__(**kwargs)
363 363 self.on_trait_change(self.listener1, ['a'])
364 364
365 365 def listener1(self, name, old, new):
366 366 self.b += 1
367 367
368 368 class B(A):
369 369
370 370 c = 0
371 371 d = 0
372 372
373 373 def __init__(self, **kwargs):
374 374 super(B, self).__init__(**kwargs)
375 375 self.on_trait_change(self.listener2)
376 376
377 377 def listener2(self, name, old, new):
378 378 self.c += 1
379 379
380 380 def _a_changed(self, name, old, new):
381 381 self.d += 1
382 382
383 383 b = B()
384 384 b.a += 1
385 385 self.assertEqual(b.b, b.c)
386 386 self.assertEqual(b.b, b.d)
387 387 b.a += 1
388 388 self.assertEqual(b.b, b.c)
389 389 self.assertEqual(b.b, b.d)
390 390
391 391
392 392 class TestHasTraits(TestCase):
393 393
394 394 def test_trait_names(self):
395 395 class A(HasTraits):
396 396 i = Int
397 397 f = Float
398 398 a = A()
399 399 self.assertEqual(sorted(a.trait_names()),['f','i'])
400 400 self.assertEqual(sorted(A.class_trait_names()),['f','i'])
401 401
402 402 def test_trait_metadata(self):
403 403 class A(HasTraits):
404 404 i = Int(config_key='MY_VALUE')
405 405 a = A()
406 406 self.assertEqual(a.trait_metadata('i','config_key'), 'MY_VALUE')
407 407
408 408 def test_traits(self):
409 409 class A(HasTraits):
410 410 i = Int
411 411 f = Float
412 412 a = A()
413 413 self.assertEqual(a.traits(), dict(i=A.i, f=A.f))
414 414 self.assertEqual(A.class_traits(), dict(i=A.i, f=A.f))
415 415
416 416 def test_traits_metadata(self):
417 417 class A(HasTraits):
418 418 i = Int(config_key='VALUE1', other_thing='VALUE2')
419 419 f = Float(config_key='VALUE3', other_thing='VALUE2')
420 420 j = Int(0)
421 421 a = A()
422 422 self.assertEqual(a.traits(), dict(i=A.i, f=A.f, j=A.j))
423 423 traits = a.traits(config_key='VALUE1', other_thing='VALUE2')
424 424 self.assertEqual(traits, dict(i=A.i))
425 425
426 426 # This passes, but it shouldn't because I am replicating a bug in
427 427 # traits.
428 428 traits = a.traits(config_key=lambda v: True)
429 429 self.assertEqual(traits, dict(i=A.i, f=A.f, j=A.j))
430 430
431 431 def test_init(self):
432 432 class A(HasTraits):
433 433 i = Int()
434 434 x = Float()
435 435 a = A(i=1, x=10.0)
436 436 self.assertEqual(a.i, 1)
437 437 self.assertEqual(a.x, 10.0)
438 438
439 439 def test_positional_args(self):
440 440 class A(HasTraits):
441 441 i = Int(0)
442 442 def __init__(self, i):
443 443 super(A, self).__init__()
444 444 self.i = i
445 445
446 446 a = A(5)
447 447 self.assertEqual(a.i, 5)
448 448 # should raise TypeError if no positional arg given
449 449 self.assertRaises(TypeError, A)
450 450
451 451 #-----------------------------------------------------------------------------
452 452 # Tests for specific trait types
453 453 #-----------------------------------------------------------------------------
454 454
455 455
456 456 class TestType(TestCase):
457 457
458 458 def test_default(self):
459 459
460 460 class B(object): pass
461 461 class A(HasTraits):
462 462 klass = Type
463 463
464 464 a = A()
465 465 self.assertEqual(a.klass, None)
466 466
467 467 a.klass = B
468 468 self.assertEqual(a.klass, B)
469 469 self.assertRaises(TraitError, setattr, a, 'klass', 10)
470 470
471 471 def test_value(self):
472 472
473 473 class B(object): pass
474 474 class C(object): pass
475 475 class A(HasTraits):
476 476 klass = Type(B)
477 477
478 478 a = A()
479 479 self.assertEqual(a.klass, B)
480 480 self.assertRaises(TraitError, setattr, a, 'klass', C)
481 481 self.assertRaises(TraitError, setattr, a, 'klass', object)
482 482 a.klass = B
483 483
484 484 def test_allow_none(self):
485 485
486 486 class B(object): pass
487 487 class C(B): pass
488 488 class A(HasTraits):
489 489 klass = Type(B, allow_none=False)
490 490
491 491 a = A()
492 492 self.assertEqual(a.klass, B)
493 493 self.assertRaises(TraitError, setattr, a, 'klass', None)
494 494 a.klass = C
495 495 self.assertEqual(a.klass, C)
496 496
497 497 def test_validate_klass(self):
498 498
499 499 class A(HasTraits):
500 500 klass = Type('no strings allowed')
501 501
502 502 self.assertRaises(ImportError, A)
503 503
504 504 class A(HasTraits):
505 505 klass = Type('rub.adub.Duck')
506 506
507 507 self.assertRaises(ImportError, A)
508 508
509 509 def test_validate_default(self):
510 510
511 511 class B(object): pass
512 512 class A(HasTraits):
513 513 klass = Type('bad default', B)
514 514
515 515 self.assertRaises(ImportError, A)
516 516
517 517 class C(HasTraits):
518 518 klass = Type(None, B, allow_none=False)
519 519
520 520 self.assertRaises(TraitError, C)
521 521
522 522 def test_str_klass(self):
523 523
524 524 class A(HasTraits):
525 525 klass = Type('IPython.utils.ipstruct.Struct')
526 526
527 527 from IPython.utils.ipstruct import Struct
528 528 a = A()
529 529 a.klass = Struct
530 530 self.assertEqual(a.klass, Struct)
531 531
532 532 self.assertRaises(TraitError, setattr, a, 'klass', 10)
533 533
534 534 class TestInstance(TestCase):
535 535
536 536 def test_basic(self):
537 537 class Foo(object): pass
538 538 class Bar(Foo): pass
539 539 class Bah(object): pass
540 540
541 541 class A(HasTraits):
542 542 inst = Instance(Foo)
543 543
544 544 a = A()
545 545 self.assertTrue(a.inst is None)
546 546 a.inst = Foo()
547 547 self.assertTrue(isinstance(a.inst, Foo))
548 548 a.inst = Bar()
549 549 self.assertTrue(isinstance(a.inst, Foo))
550 550 self.assertRaises(TraitError, setattr, a, 'inst', Foo)
551 551 self.assertRaises(TraitError, setattr, a, 'inst', Bar)
552 552 self.assertRaises(TraitError, setattr, a, 'inst', Bah())
553 553
554 554 def test_unique_default_value(self):
555 555 class Foo(object): pass
556 556 class A(HasTraits):
557 557 inst = Instance(Foo,(),{})
558 558
559 559 a = A()
560 560 b = A()
561 561 self.assertTrue(a.inst is not b.inst)
562 562
563 563 def test_args_kw(self):
564 564 class Foo(object):
565 565 def __init__(self, c): self.c = c
566 566 class Bar(object): pass
567 567 class Bah(object):
568 568 def __init__(self, c, d):
569 569 self.c = c; self.d = d
570 570
571 571 class A(HasTraits):
572 572 inst = Instance(Foo, (10,))
573 573 a = A()
574 574 self.assertEqual(a.inst.c, 10)
575 575
576 576 class B(HasTraits):
577 577 inst = Instance(Bah, args=(10,), kw=dict(d=20))
578 578 b = B()
579 579 self.assertEqual(b.inst.c, 10)
580 580 self.assertEqual(b.inst.d, 20)
581 581
582 582 class C(HasTraits):
583 583 inst = Instance(Foo)
584 584 c = C()
585 585 self.assertTrue(c.inst is None)
586 586
587 587 def test_bad_default(self):
588 588 class Foo(object): pass
589 589
590 590 class A(HasTraits):
591 591 inst = Instance(Foo, allow_none=False)
592 592
593 593 self.assertRaises(TraitError, A)
594 594
595 595 def test_instance(self):
596 596 class Foo(object): pass
597 597
598 598 def inner():
599 599 class A(HasTraits):
600 600 inst = Instance(Foo())
601 601
602 602 self.assertRaises(TraitError, inner)
603 603
604 604
605 605 class TestThis(TestCase):
606 606
607 607 def test_this_class(self):
608 608 class Foo(HasTraits):
609 609 this = This
610 610
611 611 f = Foo()
612 612 self.assertEqual(f.this, None)
613 613 g = Foo()
614 614 f.this = g
615 615 self.assertEqual(f.this, g)
616 616 self.assertRaises(TraitError, setattr, f, 'this', 10)
617 617
618 618 def test_this_inst(self):
619 619 class Foo(HasTraits):
620 620 this = This()
621 621
622 622 f = Foo()
623 623 f.this = Foo()
624 624 self.assertTrue(isinstance(f.this, Foo))
625 625
626 626 def test_subclass(self):
627 627 class Foo(HasTraits):
628 628 t = This()
629 629 class Bar(Foo):
630 630 pass
631 631 f = Foo()
632 632 b = Bar()
633 633 f.t = b
634 634 b.t = f
635 635 self.assertEqual(f.t, b)
636 636 self.assertEqual(b.t, f)
637 637
638 638 def test_subclass_override(self):
639 639 class Foo(HasTraits):
640 640 t = This()
641 641 class Bar(Foo):
642 642 t = This()
643 643 f = Foo()
644 644 b = Bar()
645 645 f.t = b
646 646 self.assertEqual(f.t, b)
647 647 self.assertRaises(TraitError, setattr, b, 't', f)
648 648
649 649 class TraitTestBase(TestCase):
650 650 """A best testing class for basic trait types."""
651 651
652 652 def assign(self, value):
653 653 self.obj.value = value
654 654
655 655 def coerce(self, value):
656 656 return value
657 657
658 658 def test_good_values(self):
659 659 if hasattr(self, '_good_values'):
660 660 for value in self._good_values:
661 661 self.assign(value)
662 662 self.assertEqual(self.obj.value, self.coerce(value))
663 663
664 664 def test_bad_values(self):
665 665 if hasattr(self, '_bad_values'):
666 666 for value in self._bad_values:
667 667 try:
668 668 self.assertRaises(TraitError, self.assign, value)
669 669 except AssertionError:
670 670 assert False, value
671 671
672 672 def test_default_value(self):
673 673 if hasattr(self, '_default_value'):
674 674 self.assertEqual(self._default_value, self.obj.value)
675 675
676 676 def test_allow_none(self):
677 677 if (hasattr(self, '_bad_values') and hasattr(self, '_good_values') and
678 678 None in self._bad_values):
679 679 trait=self.obj.traits()['value']
680 680 if isinstance(trait, AllowNone) and not trait._allow_none:
681 try:
681 682 trait._allow_none = True
682 683 self._bad_values.remove(None)
683 684 #skip coerce. Allow None casts None to None.
684 685 self.assign(None)
685 686 self.assertEqual(self.obj.value,None)
686 687 self.test_good_values()
687 688 self.test_bad_values()
689 finally:
688 690 #tear down
689 691 trait._allow_none = False
690 692 self._bad_values.append(None)
691 693
692 694
693 695 def tearDown(self):
694 696 # restore default value after tests, if set
695 697 if hasattr(self, '_default_value'):
696 698 self.obj.value = self._default_value
697 699
698 700
699 701 class AnyTrait(HasTraits):
700 702
701 703 value = Any
702 704
703 705 class AnyTraitTest(TraitTestBase):
704 706
705 707 obj = AnyTrait()
706 708
707 709 _default_value = None
708 710 _good_values = [10.0, 'ten', u'ten', [10], {'ten': 10},(10,), None, 1j]
709 711 _bad_values = []
710 712
711 713
712 714 class IntTrait(HasTraits):
713 715
714 716 value = Int(99)
715 717
716 718 class TestInt(TraitTestBase):
717 719
718 720 obj = IntTrait()
719 721 _default_value = 99
720 722 _good_values = [10, -10]
721 723 _bad_values = ['ten', u'ten', [10], {'ten': 10},(10,), None, 1j,
722 724 10.1, -10.1, '10L', '-10L', '10.1', '-10.1', u'10L',
723 725 u'-10L', u'10.1', u'-10.1', '10', '-10', u'10', u'-10']
724 726 if not py3compat.PY3:
725 727 _bad_values.extend([long(10), long(-10), 10*sys.maxint, -10*sys.maxint])
726 728
727 729
728 730 class LongTrait(HasTraits):
729 731
730 732 value = Long(99 if py3compat.PY3 else long(99))
731 733
732 734 class TestLong(TraitTestBase):
733 735
734 736 obj = LongTrait()
735 737
736 738 _default_value = 99 if py3compat.PY3 else long(99)
737 739 _good_values = [10, -10]
738 740 _bad_values = ['ten', u'ten', [10], {'ten': 10},(10,),
739 741 None, 1j, 10.1, -10.1, '10', '-10', '10L', '-10L', '10.1',
740 742 '-10.1', u'10', u'-10', u'10L', u'-10L', u'10.1',
741 743 u'-10.1']
742 744 if not py3compat.PY3:
743 745 # maxint undefined on py3, because int == long
744 746 _good_values.extend([long(10), long(-10), 10*sys.maxint, -10*sys.maxint])
745 747 _bad_values.extend([[long(10)], (long(10),)])
746 748
747 749 @skipif(py3compat.PY3, "not relevant on py3")
748 750 def test_cast_small(self):
749 751 """Long casts ints to long"""
750 752 self.obj.value = 10
751 753 self.assertEqual(type(self.obj.value), long)
752 754
753 755
754 756 class IntegerTrait(HasTraits):
755 757 value = Integer(1)
756 758
757 759 class TestInteger(TestLong):
758 760 obj = IntegerTrait()
759 761 _default_value = 1
760 762
761 763 def coerce(self, n):
762 764 return int(n)
763 765
764 766 @skipif(py3compat.PY3, "not relevant on py3")
765 767 def test_cast_small(self):
766 768 """Integer casts small longs to int"""
767 769 if py3compat.PY3:
768 770 raise SkipTest("not relevant on py3")
769 771
770 772 self.obj.value = long(100)
771 773 self.assertEqual(type(self.obj.value), int)
772 774
773 775
774 776 class FloatTrait(HasTraits):
775 777
776 778 value = Float(99.0)
777 779
778 780 class TestFloat(TraitTestBase):
779 781
780 782 obj = FloatTrait()
781 783
782 784 _default_value = 99.0
783 785 _good_values = [10, -10, 10.1, -10.1]
784 786 _bad_values = ['ten', u'ten', [10], {'ten': 10},(10,), None,
785 787 1j, '10', '-10', '10L', '-10L', '10.1', '-10.1', u'10',
786 788 u'-10', u'10L', u'-10L', u'10.1', u'-10.1']
787 789 if not py3compat.PY3:
788 790 _bad_values.extend([long(10), long(-10)])
789 791
790 792
791 793 class ComplexTrait(HasTraits):
792 794
793 795 value = Complex(99.0-99.0j)
794 796
795 797 class TestComplex(TraitTestBase):
796 798
797 799 obj = ComplexTrait()
798 800
799 801 _default_value = 99.0-99.0j
800 802 _good_values = [10, -10, 10.1, -10.1, 10j, 10+10j, 10-10j,
801 803 10.1j, 10.1+10.1j, 10.1-10.1j]
802 804 _bad_values = [u'10L', u'-10L', 'ten', [10], {'ten': 10},(10,), None]
803 805 if not py3compat.PY3:
804 806 _bad_values.extend([long(10), long(-10)])
805 807
806 808
807 809 class BytesTrait(HasTraits):
808 810
809 811 value = Bytes(b'string')
810 812
811 813 class TestBytes(TraitTestBase):
812 814
813 815 obj = BytesTrait()
814 816
815 817 _default_value = b'string'
816 818 _good_values = [b'10', b'-10', b'10L',
817 819 b'-10L', b'10.1', b'-10.1', b'string']
818 820 _bad_values = [10, -10, 10.1, -10.1, 1j, [10],
819 821 ['ten'],{'ten': 10},(10,), None, u'string']
820 822 if not py3compat.PY3:
821 823 _bad_values.extend([long(10), long(-10)])
822 824
823 825
824 826 class UnicodeTrait(HasTraits):
825 827
826 828 value = Unicode(u'unicode')
827 829
828 830 class TestUnicode(TraitTestBase):
829 831
830 832 obj = UnicodeTrait()
831 833
832 834 _default_value = u'unicode'
833 835 _good_values = ['10', '-10', '10L', '-10L', '10.1',
834 836 '-10.1', '', u'', 'string', u'string', u"€"]
835 837 _bad_values = [10, -10, 10.1, -10.1, 1j,
836 838 [10], ['ten'], [u'ten'], {'ten': 10},(10,), None]
837 839 if not py3compat.PY3:
838 840 _bad_values.extend([long(10), long(-10)])
839 841
840 842
841 843 class ObjectNameTrait(HasTraits):
842 844 value = ObjectName("abc")
843 845
844 846 class TestObjectName(TraitTestBase):
845 847 obj = ObjectNameTrait()
846 848
847 849 _default_value = "abc"
848 850 _good_values = ["a", "gh", "g9", "g_", "_G", u"a345_"]
849 851 _bad_values = [1, "", u"€", "9g", "!", "#abc", "aj@", "a.b", "a()", "a[0]",
850 852 None, object(), object]
851 853 if sys.version_info[0] < 3:
852 854 _bad_values.append(u"ΓΎ")
853 855 else:
854 856 _good_values.append(u"ΓΎ") # ΓΎ=1 is valid in Python 3 (PEP 3131).
855 857
856 858
857 859 class DottedObjectNameTrait(HasTraits):
858 860 value = DottedObjectName("a.b")
859 861
860 862 class TestDottedObjectName(TraitTestBase):
861 863 obj = DottedObjectNameTrait()
862 864
863 865 _default_value = "a.b"
864 866 _good_values = ["A", "y.t", "y765.__repr__", "os.path.join", u"os.path.join"]
865 867 _bad_values = [1, u"abc.€", "_.@", ".", ".abc", "abc.", ".abc.", None]
866 868 if sys.version_info[0] < 3:
867 869 _bad_values.append(u"t.ΓΎ")
868 870 else:
869 871 _good_values.append(u"t.ΓΎ")
870 872
871 873
872 874 class TCPAddressTrait(HasTraits):
873 875
874 876 value = TCPAddress()
875 877
876 878 class TestTCPAddress(TraitTestBase):
877 879
878 880 obj = TCPAddressTrait()
879 881
880 882 _default_value = ('127.0.0.1',0)
881 883 _good_values = [('localhost',0),('192.168.0.1',1000),('www.google.com',80)]
882 884 _bad_values = [(0,0),('localhost',10.0),('localhost',-1), None]
883 885
884 886 class ListTrait(HasTraits):
885 887
886 888 value = List(Int)
887 889
888 890 class TestList(TraitTestBase):
889 891
890 892 obj = ListTrait()
891 893
892 894 _default_value = []
893 895 _good_values = [[], [1], list(range(10)), (1,2)]
894 896 _bad_values = [10, [1,'a'], 'a']
895 897
896 898 def coerce(self, value):
897 899 if value is not None:
898 900 value = list(value)
899 901 return value
900 902
901 903 class LenListTrait(HasTraits):
902 904
903 905 value = List(Int, [0], minlen=1, maxlen=2)
904 906
905 907 class TestLenList(TraitTestBase):
906 908
907 909 obj = LenListTrait()
908 910
909 911 _default_value = [0]
910 912 _good_values = [[1], [1,2], (1,2)]
911 913 _bad_values = [10, [1,'a'], 'a', [], list(range(3))]
912 914
913 915 def coerce(self, value):
914 916 if value is not None:
915 917 value = list(value)
916 918 return value
917 919
918 920 class TupleTrait(HasTraits):
919 921
920 922 value = Tuple(Int)
921 923
922 924 class TestTupleTrait(TraitTestBase):
923 925
924 926 obj = TupleTrait()
925 927
926 928 _default_value = None
927 929 _good_values = [(1,), None, (0,), [1]]
928 930 _bad_values = [10, (1,2), ('a'), ()]
929 931
930 932 def coerce(self, value):
931 933 if value is not None:
932 934 value = tuple(value)
933 935 return value
934 936
935 937 def test_invalid_args(self):
936 938 self.assertRaises(TypeError, Tuple, 5)
937 939 self.assertRaises(TypeError, Tuple, default_value='hello')
938 940 t = Tuple(Int, CBytes, default_value=(1,5))
939 941
940 942 class LooseTupleTrait(HasTraits):
941 943
942 944 value = Tuple((1,2,3))
943 945
944 946 class TestLooseTupleTrait(TraitTestBase):
945 947
946 948 obj = LooseTupleTrait()
947 949
948 950 _default_value = (1,2,3)
949 951 _good_values = [(1,), None, [1], (0,), tuple(range(5)), tuple('hello'), ('a',5), ()]
950 952 _bad_values = [10, 'hello', {}]
951 953
952 954 def coerce(self, value):
953 955 if value is not None:
954 956 value = tuple(value)
955 957 return value
956 958
957 959 def test_invalid_args(self):
958 960 self.assertRaises(TypeError, Tuple, 5)
959 961 self.assertRaises(TypeError, Tuple, default_value='hello')
960 962 t = Tuple(Int, CBytes, default_value=(1,5))
961 963
962 964
963 965 class MultiTupleTrait(HasTraits):
964 966
965 967 value = Tuple(Int, Bytes, default_value=[99,b'bottles'])
966 968
967 969 class TestMultiTuple(TraitTestBase):
968 970
969 971 obj = MultiTupleTrait()
970 972
971 973 _default_value = (99,b'bottles')
972 974 _good_values = [(1,b'a'), (2,b'b')]
973 975 _bad_values = ((),10, b'a', (1,b'a',3), (b'a',1), (1, u'a'))
974 976
975 977 class CRegExpTrait(HasTraits):
976 978
977 979 value = CRegExp(r'')
978 980
979 981 class TestCRegExp(TraitTestBase):
980 982
981 983 def coerce(self, value):
982 984 return re.compile(value)
983 985
984 986 obj = CRegExpTrait()
985 987
986 988 _default_value = re.compile(r'')
987 989 _good_values = [r'\d+', re.compile(r'\d+')]
988 990 _bad_values = [r'(', None, ()]
989 991
990 992 class DictTrait(HasTraits):
991 993 value = Dict()
992 994
993 995 def test_dict_assignment():
994 996 d = dict()
995 997 c = DictTrait()
996 998 c.value = d
997 999 d['a'] = 5
998 1000 nt.assert_equal(d, c.value)
999 1001 nt.assert_true(c.value is d)
1000 1002
1001 1003 class TestLink(TestCase):
1002 1004 def test_connect_same(self):
1003 1005 """Verify two traitlets of the same type can be linked together using link."""
1004 1006
1005 1007 # Create two simple classes with Int traitlets.
1006 1008 class A(HasTraits):
1007 1009 value = Int()
1008 1010 a = A(value=9)
1009 1011 b = A(value=8)
1010 1012
1011 1013 # Conenct the two classes.
1012 1014 c = link((a, 'value'), (b, 'value'))
1013 1015
1014 1016 # Make sure the values are the same at the point of linking.
1015 1017 self.assertEqual(a.value, b.value)
1016 1018
1017 1019 # Change one of the values to make sure they stay in sync.
1018 1020 a.value = 5
1019 1021 self.assertEqual(a.value, b.value)
1020 1022 b.value = 6
1021 1023 self.assertEqual(a.value, b.value)
1022 1024
1023 1025 def test_link_different(self):
1024 1026 """Verify two traitlets of different types can be linked together using link."""
1025 1027
1026 1028 # Create two simple classes with Int traitlets.
1027 1029 class A(HasTraits):
1028 1030 value = Int()
1029 1031 class B(HasTraits):
1030 1032 count = Int()
1031 1033 a = A(value=9)
1032 1034 b = B(count=8)
1033 1035
1034 1036 # Conenct the two classes.
1035 1037 c = link((a, 'value'), (b, 'count'))
1036 1038
1037 1039 # Make sure the values are the same at the point of linking.
1038 1040 self.assertEqual(a.value, b.count)
1039 1041
1040 1042 # Change one of the values to make sure they stay in sync.
1041 1043 a.value = 5
1042 1044 self.assertEqual(a.value, b.count)
1043 1045 b.count = 4
1044 1046 self.assertEqual(a.value, b.count)
1045 1047
1046 1048 def test_unlink(self):
1047 1049 """Verify two linked traitlets can be unlinked."""
1048 1050
1049 1051 # Create two simple classes with Int traitlets.
1050 1052 class A(HasTraits):
1051 1053 value = Int()
1052 1054 a = A(value=9)
1053 1055 b = A(value=8)
1054 1056
1055 1057 # Connect the two classes.
1056 1058 c = link((a, 'value'), (b, 'value'))
1057 1059 a.value = 4
1058 1060 c.unlink()
1059 1061
1060 1062 # Change one of the values to make sure they don't stay in sync.
1061 1063 a.value = 5
1062 1064 self.assertNotEqual(a.value, b.value)
1063 1065
1064 1066 def test_callbacks(self):
1065 1067 """Verify two linked traitlets have their callbacks called once."""
1066 1068
1067 1069 # Create two simple classes with Int traitlets.
1068 1070 class A(HasTraits):
1069 1071 value = Int()
1070 1072 class B(HasTraits):
1071 1073 count = Int()
1072 1074 a = A(value=9)
1073 1075 b = B(count=8)
1074 1076
1075 1077 # Register callbacks that count.
1076 1078 callback_count = []
1077 1079 def a_callback(name, old, new):
1078 1080 callback_count.append('a')
1079 1081 a.on_trait_change(a_callback, 'value')
1080 1082 def b_callback(name, old, new):
1081 1083 callback_count.append('b')
1082 1084 b.on_trait_change(b_callback, 'count')
1083 1085
1084 1086 # Connect the two classes.
1085 1087 c = link((a, 'value'), (b, 'count'))
1086 1088
1087 1089 # Make sure b's count was set to a's value once.
1088 1090 self.assertEqual(''.join(callback_count), 'b')
1089 1091 del callback_count[:]
1090 1092
1091 1093 # Make sure a's value was set to b's count once.
1092 1094 b.count = 5
1093 1095 self.assertEqual(''.join(callback_count), 'ba')
1094 1096 del callback_count[:]
1095 1097
1096 1098 # Make sure b's count was set to a's value once.
1097 1099 a.value = 4
1098 1100 self.assertEqual(''.join(callback_count), 'ab')
1099 1101 del callback_count[:]
1100 1102
1101 1103 class Pickleable(HasTraits):
1102 1104 i = Int()
1103 1105 j = Int()
1104 1106
1105 1107 def _i_default(self):
1106 1108 return 1
1107 1109
1108 1110 def _i_changed(self, name, old, new):
1109 1111 self.j = new
1110 1112
1111 1113 def test_pickle_hastraits():
1112 1114 c = Pickleable()
1113 1115 for protocol in range(pickle.HIGHEST_PROTOCOL + 1):
1114 1116 p = pickle.dumps(c, protocol)
1115 1117 c2 = pickle.loads(p)
1116 1118 nt.assert_equal(c2.i, c.i)
1117 1119 nt.assert_equal(c2.j, c.j)
1118 1120
1119 1121 c.i = 5
1120 1122 for protocol in range(pickle.HIGHEST_PROTOCOL + 1):
1121 1123 p = pickle.dumps(c, protocol)
1122 1124 c2 = pickle.loads(p)
1123 1125 nt.assert_equal(c2.i, c.i)
1124 1126 nt.assert_equal(c2.j, c.j)
1125 1127
General Comments 0
You need to be logged in to leave comments. Login now