##// END OF EJS Templates
Tests for the default klass attribute of the Instance traitlet
Jason Grout -
Show More
@@ -1,1153 +1,1174 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, 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(TraitType):
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 def test_set_str_klass(self):
535 535
536 536 class A(HasTraits):
537 537 klass = Type()
538 538
539 539 a = A(klass='IPython.utils.ipstruct.Struct')
540 540 from IPython.utils.ipstruct import Struct
541 541 self.assertEqual(a.klass, Struct)
542 542
543 543 class TestInstance(TestCase):
544 544
545 545 def test_basic(self):
546 546 class Foo(object): pass
547 547 class Bar(Foo): pass
548 548 class Bah(object): pass
549 549
550 550 class A(HasTraits):
551 551 inst = Instance(Foo)
552 552
553 553 a = A()
554 554 self.assertTrue(a.inst is None)
555 555 a.inst = Foo()
556 556 self.assertTrue(isinstance(a.inst, Foo))
557 557 a.inst = Bar()
558 558 self.assertTrue(isinstance(a.inst, Foo))
559 559 self.assertRaises(TraitError, setattr, a, 'inst', Foo)
560 560 self.assertRaises(TraitError, setattr, a, 'inst', Bar)
561 561 self.assertRaises(TraitError, setattr, a, 'inst', Bah())
562 562
563 def test_default_klass(self):
564 class Foo(object): pass
565 class Bar(Foo): pass
566 class Bah(object): pass
567
568 class FooInstance(Instance):
569 klass = Foo
570
571 class A(HasTraits):
572 inst = FooInstance()
573
574 a = A()
575 self.assertTrue(a.inst is None)
576 a.inst = Foo()
577 self.assertTrue(isinstance(a.inst, Foo))
578 a.inst = Bar()
579 self.assertTrue(isinstance(a.inst, Foo))
580 self.assertRaises(TraitError, setattr, a, 'inst', Foo)
581 self.assertRaises(TraitError, setattr, a, 'inst', Bar)
582 self.assertRaises(TraitError, setattr, a, 'inst', Bah())
583
563 584 def test_unique_default_value(self):
564 585 class Foo(object): pass
565 586 class A(HasTraits):
566 587 inst = Instance(Foo,(),{})
567 588
568 589 a = A()
569 590 b = A()
570 591 self.assertTrue(a.inst is not b.inst)
571 592
572 593 def test_args_kw(self):
573 594 class Foo(object):
574 595 def __init__(self, c): self.c = c
575 596 class Bar(object): pass
576 597 class Bah(object):
577 598 def __init__(self, c, d):
578 599 self.c = c; self.d = d
579 600
580 601 class A(HasTraits):
581 602 inst = Instance(Foo, (10,))
582 603 a = A()
583 604 self.assertEqual(a.inst.c, 10)
584 605
585 606 class B(HasTraits):
586 607 inst = Instance(Bah, args=(10,), kw=dict(d=20))
587 608 b = B()
588 609 self.assertEqual(b.inst.c, 10)
589 610 self.assertEqual(b.inst.d, 20)
590 611
591 612 class C(HasTraits):
592 613 inst = Instance(Foo)
593 614 c = C()
594 615 self.assertTrue(c.inst is None)
595 616
596 617 def test_bad_default(self):
597 618 class Foo(object): pass
598 619
599 620 class A(HasTraits):
600 621 inst = Instance(Foo, allow_none=False)
601 622
602 623 self.assertRaises(TraitError, A)
603 624
604 625 def test_instance(self):
605 626 class Foo(object): pass
606 627
607 628 def inner():
608 629 class A(HasTraits):
609 630 inst = Instance(Foo())
610 631
611 632 self.assertRaises(TraitError, inner)
612 633
613 634
614 635 class TestThis(TestCase):
615 636
616 637 def test_this_class(self):
617 638 class Foo(HasTraits):
618 639 this = This
619 640
620 641 f = Foo()
621 642 self.assertEqual(f.this, None)
622 643 g = Foo()
623 644 f.this = g
624 645 self.assertEqual(f.this, g)
625 646 self.assertRaises(TraitError, setattr, f, 'this', 10)
626 647
627 648 def test_this_inst(self):
628 649 class Foo(HasTraits):
629 650 this = This()
630 651
631 652 f = Foo()
632 653 f.this = Foo()
633 654 self.assertTrue(isinstance(f.this, Foo))
634 655
635 656 def test_subclass(self):
636 657 class Foo(HasTraits):
637 658 t = This()
638 659 class Bar(Foo):
639 660 pass
640 661 f = Foo()
641 662 b = Bar()
642 663 f.t = b
643 664 b.t = f
644 665 self.assertEqual(f.t, b)
645 666 self.assertEqual(b.t, f)
646 667
647 668 def test_subclass_override(self):
648 669 class Foo(HasTraits):
649 670 t = This()
650 671 class Bar(Foo):
651 672 t = This()
652 673 f = Foo()
653 674 b = Bar()
654 675 f.t = b
655 676 self.assertEqual(f.t, b)
656 677 self.assertRaises(TraitError, setattr, b, 't', f)
657 678
658 679 class TraitTestBase(TestCase):
659 680 """A best testing class for basic trait types."""
660 681
661 682 def assign(self, value):
662 683 self.obj.value = value
663 684
664 685 def coerce(self, value):
665 686 return value
666 687
667 688 def test_good_values(self):
668 689 if hasattr(self, '_good_values'):
669 690 for value in self._good_values:
670 691 self.assign(value)
671 692 self.assertEqual(self.obj.value, self.coerce(value))
672 693
673 694 def test_bad_values(self):
674 695 if hasattr(self, '_bad_values'):
675 696 for value in self._bad_values:
676 697 try:
677 698 self.assertRaises(TraitError, self.assign, value)
678 699 except AssertionError:
679 700 assert False, value
680 701
681 702 def test_default_value(self):
682 703 if hasattr(self, '_default_value'):
683 704 self.assertEqual(self._default_value, self.obj.value)
684 705
685 706 def test_allow_none(self):
686 707 if (hasattr(self, '_bad_values') and hasattr(self, '_good_values') and
687 708 None in self._bad_values):
688 709 trait=self.obj.traits()['value']
689 710 try:
690 711 trait.allow_none = True
691 712 self._bad_values.remove(None)
692 713 #skip coerce. Allow None casts None to None.
693 714 self.assign(None)
694 715 self.assertEqual(self.obj.value,None)
695 716 self.test_good_values()
696 717 self.test_bad_values()
697 718 finally:
698 719 #tear down
699 720 trait.allow_none = False
700 721 self._bad_values.append(None)
701 722
702 723 def tearDown(self):
703 724 # restore default value after tests, if set
704 725 if hasattr(self, '_default_value'):
705 726 self.obj.value = self._default_value
706 727
707 728
708 729 class AnyTrait(HasTraits):
709 730
710 731 value = Any
711 732
712 733 class AnyTraitTest(TraitTestBase):
713 734
714 735 obj = AnyTrait()
715 736
716 737 _default_value = None
717 738 _good_values = [10.0, 'ten', u'ten', [10], {'ten': 10},(10,), None, 1j]
718 739 _bad_values = []
719 740
720 741
721 742 class IntTrait(HasTraits):
722 743
723 744 value = Int(99)
724 745
725 746 class TestInt(TraitTestBase):
726 747
727 748 obj = IntTrait()
728 749 _default_value = 99
729 750 _good_values = [10, -10]
730 751 _bad_values = ['ten', u'ten', [10], {'ten': 10},(10,), None, 1j,
731 752 10.1, -10.1, '10L', '-10L', '10.1', '-10.1', u'10L',
732 753 u'-10L', u'10.1', u'-10.1', '10', '-10', u'10', u'-10']
733 754 if not py3compat.PY3:
734 755 _bad_values.extend([long(10), long(-10), 10*sys.maxint, -10*sys.maxint])
735 756
736 757
737 758 class LongTrait(HasTraits):
738 759
739 760 value = Long(99 if py3compat.PY3 else long(99))
740 761
741 762 class TestLong(TraitTestBase):
742 763
743 764 obj = LongTrait()
744 765
745 766 _default_value = 99 if py3compat.PY3 else long(99)
746 767 _good_values = [10, -10]
747 768 _bad_values = ['ten', u'ten', [10], {'ten': 10},(10,),
748 769 None, 1j, 10.1, -10.1, '10', '-10', '10L', '-10L', '10.1',
749 770 '-10.1', u'10', u'-10', u'10L', u'-10L', u'10.1',
750 771 u'-10.1']
751 772 if not py3compat.PY3:
752 773 # maxint undefined on py3, because int == long
753 774 _good_values.extend([long(10), long(-10), 10*sys.maxint, -10*sys.maxint])
754 775 _bad_values.extend([[long(10)], (long(10),)])
755 776
756 777 @skipif(py3compat.PY3, "not relevant on py3")
757 778 def test_cast_small(self):
758 779 """Long casts ints to long"""
759 780 self.obj.value = 10
760 781 self.assertEqual(type(self.obj.value), long)
761 782
762 783
763 784 class IntegerTrait(HasTraits):
764 785 value = Integer(1)
765 786
766 787 class TestInteger(TestLong):
767 788 obj = IntegerTrait()
768 789 _default_value = 1
769 790
770 791 def coerce(self, n):
771 792 return int(n)
772 793
773 794 @skipif(py3compat.PY3, "not relevant on py3")
774 795 def test_cast_small(self):
775 796 """Integer casts small longs to int"""
776 797 if py3compat.PY3:
777 798 raise SkipTest("not relevant on py3")
778 799
779 800 self.obj.value = long(100)
780 801 self.assertEqual(type(self.obj.value), int)
781 802
782 803
783 804 class FloatTrait(HasTraits):
784 805
785 806 value = Float(99.0)
786 807
787 808 class TestFloat(TraitTestBase):
788 809
789 810 obj = FloatTrait()
790 811
791 812 _default_value = 99.0
792 813 _good_values = [10, -10, 10.1, -10.1]
793 814 _bad_values = ['ten', u'ten', [10], {'ten': 10},(10,), None,
794 815 1j, '10', '-10', '10L', '-10L', '10.1', '-10.1', u'10',
795 816 u'-10', u'10L', u'-10L', u'10.1', u'-10.1']
796 817 if not py3compat.PY3:
797 818 _bad_values.extend([long(10), long(-10)])
798 819
799 820
800 821 class ComplexTrait(HasTraits):
801 822
802 823 value = Complex(99.0-99.0j)
803 824
804 825 class TestComplex(TraitTestBase):
805 826
806 827 obj = ComplexTrait()
807 828
808 829 _default_value = 99.0-99.0j
809 830 _good_values = [10, -10, 10.1, -10.1, 10j, 10+10j, 10-10j,
810 831 10.1j, 10.1+10.1j, 10.1-10.1j]
811 832 _bad_values = [u'10L', u'-10L', 'ten', [10], {'ten': 10},(10,), None]
812 833 if not py3compat.PY3:
813 834 _bad_values.extend([long(10), long(-10)])
814 835
815 836
816 837 class BytesTrait(HasTraits):
817 838
818 839 value = Bytes(b'string')
819 840
820 841 class TestBytes(TraitTestBase):
821 842
822 843 obj = BytesTrait()
823 844
824 845 _default_value = b'string'
825 846 _good_values = [b'10', b'-10', b'10L',
826 847 b'-10L', b'10.1', b'-10.1', b'string']
827 848 _bad_values = [10, -10, 10.1, -10.1, 1j, [10],
828 849 ['ten'],{'ten': 10},(10,), None, u'string']
829 850 if not py3compat.PY3:
830 851 _bad_values.extend([long(10), long(-10)])
831 852
832 853
833 854 class UnicodeTrait(HasTraits):
834 855
835 856 value = Unicode(u'unicode')
836 857
837 858 class TestUnicode(TraitTestBase):
838 859
839 860 obj = UnicodeTrait()
840 861
841 862 _default_value = u'unicode'
842 863 _good_values = ['10', '-10', '10L', '-10L', '10.1',
843 864 '-10.1', '', u'', 'string', u'string', u"€"]
844 865 _bad_values = [10, -10, 10.1, -10.1, 1j,
845 866 [10], ['ten'], [u'ten'], {'ten': 10},(10,), None]
846 867 if not py3compat.PY3:
847 868 _bad_values.extend([long(10), long(-10)])
848 869
849 870
850 871 class ObjectNameTrait(HasTraits):
851 872 value = ObjectName("abc")
852 873
853 874 class TestObjectName(TraitTestBase):
854 875 obj = ObjectNameTrait()
855 876
856 877 _default_value = "abc"
857 878 _good_values = ["a", "gh", "g9", "g_", "_G", u"a345_"]
858 879 _bad_values = [1, "", u"€", "9g", "!", "#abc", "aj@", "a.b", "a()", "a[0]",
859 880 None, object(), object]
860 881 if sys.version_info[0] < 3:
861 882 _bad_values.append(u"ΓΎ")
862 883 else:
863 884 _good_values.append(u"ΓΎ") # ΓΎ=1 is valid in Python 3 (PEP 3131).
864 885
865 886
866 887 class DottedObjectNameTrait(HasTraits):
867 888 value = DottedObjectName("a.b")
868 889
869 890 class TestDottedObjectName(TraitTestBase):
870 891 obj = DottedObjectNameTrait()
871 892
872 893 _default_value = "a.b"
873 894 _good_values = ["A", "y.t", "y765.__repr__", "os.path.join", u"os.path.join"]
874 895 _bad_values = [1, u"abc.€", "_.@", ".", ".abc", "abc.", ".abc.", None]
875 896 if sys.version_info[0] < 3:
876 897 _bad_values.append(u"t.ΓΎ")
877 898 else:
878 899 _good_values.append(u"t.ΓΎ")
879 900
880 901
881 902 class TCPAddressTrait(HasTraits):
882 903
883 904 value = TCPAddress()
884 905
885 906 class TestTCPAddress(TraitTestBase):
886 907
887 908 obj = TCPAddressTrait()
888 909
889 910 _default_value = ('127.0.0.1',0)
890 911 _good_values = [('localhost',0),('192.168.0.1',1000),('www.google.com',80)]
891 912 _bad_values = [(0,0),('localhost',10.0),('localhost',-1), None]
892 913
893 914 class ListTrait(HasTraits):
894 915
895 916 value = List(Int)
896 917
897 918 class TestList(TraitTestBase):
898 919
899 920 obj = ListTrait()
900 921
901 922 _default_value = []
902 923 _good_values = [[], [1], list(range(10)), (1,2)]
903 924 _bad_values = [10, [1,'a'], 'a']
904 925
905 926 def coerce(self, value):
906 927 if value is not None:
907 928 value = list(value)
908 929 return value
909 930
910 931 class Foo(object):
911 932 pass
912 933
913 934 class InstanceListTrait(HasTraits):
914 935
915 936 value = List(Instance(__name__+'.Foo'))
916 937
917 938 class TestInstanceList(TraitTestBase):
918 939
919 940 obj = InstanceListTrait()
920 941
921 942 def test_klass(self):
922 943 """Test that the instance klass is properly assigned."""
923 944 self.assertIs(self.obj.traits()['value']._trait.klass, Foo)
924 945
925 946 _default_value = []
926 947 _good_values = [[Foo(), Foo(), None], None]
927 948 _bad_values = [['1', 2,], '1', [Foo]]
928 949
929 950 class LenListTrait(HasTraits):
930 951
931 952 value = List(Int, [0], minlen=1, maxlen=2)
932 953
933 954 class TestLenList(TraitTestBase):
934 955
935 956 obj = LenListTrait()
936 957
937 958 _default_value = [0]
938 959 _good_values = [[1], [1,2], (1,2)]
939 960 _bad_values = [10, [1,'a'], 'a', [], list(range(3))]
940 961
941 962 def coerce(self, value):
942 963 if value is not None:
943 964 value = list(value)
944 965 return value
945 966
946 967 class TupleTrait(HasTraits):
947 968
948 969 value = Tuple(Int(allow_none=True))
949 970
950 971 class TestTupleTrait(TraitTestBase):
951 972
952 973 obj = TupleTrait()
953 974
954 975 _default_value = None
955 976 _good_values = [(1,), None, (0,), [1], (None,)]
956 977 _bad_values = [10, (1,2), ('a'), ()]
957 978
958 979 def coerce(self, value):
959 980 if value is not None:
960 981 value = tuple(value)
961 982 return value
962 983
963 984 def test_invalid_args(self):
964 985 self.assertRaises(TypeError, Tuple, 5)
965 986 self.assertRaises(TypeError, Tuple, default_value='hello')
966 987 t = Tuple(Int, CBytes, default_value=(1,5))
967 988
968 989 class LooseTupleTrait(HasTraits):
969 990
970 991 value = Tuple((1,2,3))
971 992
972 993 class TestLooseTupleTrait(TraitTestBase):
973 994
974 995 obj = LooseTupleTrait()
975 996
976 997 _default_value = (1,2,3)
977 998 _good_values = [(1,), None, [1], (0,), tuple(range(5)), tuple('hello'), ('a',5), ()]
978 999 _bad_values = [10, 'hello', {}]
979 1000
980 1001 def coerce(self, value):
981 1002 if value is not None:
982 1003 value = tuple(value)
983 1004 return value
984 1005
985 1006 def test_invalid_args(self):
986 1007 self.assertRaises(TypeError, Tuple, 5)
987 1008 self.assertRaises(TypeError, Tuple, default_value='hello')
988 1009 t = Tuple(Int, CBytes, default_value=(1,5))
989 1010
990 1011
991 1012 class MultiTupleTrait(HasTraits):
992 1013
993 1014 value = Tuple(Int, Bytes, default_value=[99,b'bottles'])
994 1015
995 1016 class TestMultiTuple(TraitTestBase):
996 1017
997 1018 obj = MultiTupleTrait()
998 1019
999 1020 _default_value = (99,b'bottles')
1000 1021 _good_values = [(1,b'a'), (2,b'b')]
1001 1022 _bad_values = ((),10, b'a', (1,b'a',3), (b'a',1), (1, u'a'))
1002 1023
1003 1024 class CRegExpTrait(HasTraits):
1004 1025
1005 1026 value = CRegExp(r'')
1006 1027
1007 1028 class TestCRegExp(TraitTestBase):
1008 1029
1009 1030 def coerce(self, value):
1010 1031 return re.compile(value)
1011 1032
1012 1033 obj = CRegExpTrait()
1013 1034
1014 1035 _default_value = re.compile(r'')
1015 1036 _good_values = [r'\d+', re.compile(r'\d+')]
1016 1037 _bad_values = [r'(', None, ()]
1017 1038
1018 1039 class DictTrait(HasTraits):
1019 1040 value = Dict()
1020 1041
1021 1042 def test_dict_assignment():
1022 1043 d = dict()
1023 1044 c = DictTrait()
1024 1045 c.value = d
1025 1046 d['a'] = 5
1026 1047 nt.assert_equal(d, c.value)
1027 1048 nt.assert_true(c.value is d)
1028 1049
1029 1050 class TestLink(TestCase):
1030 1051 def test_connect_same(self):
1031 1052 """Verify two traitlets of the same type can be linked together using link."""
1032 1053
1033 1054 # Create two simple classes with Int traitlets.
1034 1055 class A(HasTraits):
1035 1056 value = Int()
1036 1057 a = A(value=9)
1037 1058 b = A(value=8)
1038 1059
1039 1060 # Conenct the two classes.
1040 1061 c = link((a, 'value'), (b, 'value'))
1041 1062
1042 1063 # Make sure the values are the same at the point of linking.
1043 1064 self.assertEqual(a.value, b.value)
1044 1065
1045 1066 # Change one of the values to make sure they stay in sync.
1046 1067 a.value = 5
1047 1068 self.assertEqual(a.value, b.value)
1048 1069 b.value = 6
1049 1070 self.assertEqual(a.value, b.value)
1050 1071
1051 1072 def test_link_different(self):
1052 1073 """Verify two traitlets of different types can be linked together using link."""
1053 1074
1054 1075 # Create two simple classes with Int traitlets.
1055 1076 class A(HasTraits):
1056 1077 value = Int()
1057 1078 class B(HasTraits):
1058 1079 count = Int()
1059 1080 a = A(value=9)
1060 1081 b = B(count=8)
1061 1082
1062 1083 # Conenct the two classes.
1063 1084 c = link((a, 'value'), (b, 'count'))
1064 1085
1065 1086 # Make sure the values are the same at the point of linking.
1066 1087 self.assertEqual(a.value, b.count)
1067 1088
1068 1089 # Change one of the values to make sure they stay in sync.
1069 1090 a.value = 5
1070 1091 self.assertEqual(a.value, b.count)
1071 1092 b.count = 4
1072 1093 self.assertEqual(a.value, b.count)
1073 1094
1074 1095 def test_unlink(self):
1075 1096 """Verify two linked traitlets can be unlinked."""
1076 1097
1077 1098 # Create two simple classes with Int traitlets.
1078 1099 class A(HasTraits):
1079 1100 value = Int()
1080 1101 a = A(value=9)
1081 1102 b = A(value=8)
1082 1103
1083 1104 # Connect the two classes.
1084 1105 c = link((a, 'value'), (b, 'value'))
1085 1106 a.value = 4
1086 1107 c.unlink()
1087 1108
1088 1109 # Change one of the values to make sure they don't stay in sync.
1089 1110 a.value = 5
1090 1111 self.assertNotEqual(a.value, b.value)
1091 1112
1092 1113 def test_callbacks(self):
1093 1114 """Verify two linked traitlets have their callbacks called once."""
1094 1115
1095 1116 # Create two simple classes with Int traitlets.
1096 1117 class A(HasTraits):
1097 1118 value = Int()
1098 1119 class B(HasTraits):
1099 1120 count = Int()
1100 1121 a = A(value=9)
1101 1122 b = B(count=8)
1102 1123
1103 1124 # Register callbacks that count.
1104 1125 callback_count = []
1105 1126 def a_callback(name, old, new):
1106 1127 callback_count.append('a')
1107 1128 a.on_trait_change(a_callback, 'value')
1108 1129 def b_callback(name, old, new):
1109 1130 callback_count.append('b')
1110 1131 b.on_trait_change(b_callback, 'count')
1111 1132
1112 1133 # Connect the two classes.
1113 1134 c = link((a, 'value'), (b, 'count'))
1114 1135
1115 1136 # Make sure b's count was set to a's value once.
1116 1137 self.assertEqual(''.join(callback_count), 'b')
1117 1138 del callback_count[:]
1118 1139
1119 1140 # Make sure a's value was set to b's count once.
1120 1141 b.count = 5
1121 1142 self.assertEqual(''.join(callback_count), 'ba')
1122 1143 del callback_count[:]
1123 1144
1124 1145 # Make sure b's count was set to a's value once.
1125 1146 a.value = 4
1126 1147 self.assertEqual(''.join(callback_count), 'ab')
1127 1148 del callback_count[:]
1128 1149
1129 1150 class Pickleable(HasTraits):
1130 1151 i = Int()
1131 1152 j = Int()
1132 1153
1133 1154 def _i_default(self):
1134 1155 return 1
1135 1156
1136 1157 def _i_changed(self, name, old, new):
1137 1158 self.j = new
1138 1159
1139 1160 def test_pickle_hastraits():
1140 1161 c = Pickleable()
1141 1162 for protocol in range(pickle.HIGHEST_PROTOCOL + 1):
1142 1163 p = pickle.dumps(c, protocol)
1143 1164 c2 = pickle.loads(p)
1144 1165 nt.assert_equal(c2.i, c.i)
1145 1166 nt.assert_equal(c2.j, c.j)
1146 1167
1147 1168 c.i = 5
1148 1169 for protocol in range(pickle.HIGHEST_PROTOCOL + 1):
1149 1170 p = pickle.dumps(c, protocol)
1150 1171 c2 = pickle.loads(p)
1151 1172 nt.assert_equal(c2.i, c.i)
1152 1173 nt.assert_equal(c2.j, c.j)
1153 1174
General Comments 0
You need to be logged in to leave comments. Login now