##// END OF EJS Templates
Final changes traitlet -> trait for review
Dav Clark -
Show More
@@ -27,7 +27,7 b' from weakref import WeakValueDictionary'
27 27 from IPython.utils.importstring import import_item
28 28 from IPython.config.loader import Config
29 29 from IPython.utils.traitlets import (
30 HasTraits, TraitletError, MetaHasTraits, Instance, This
30 HasTraits, TraitError, MetaHasTraits, Instance, This
31 31 )
32 32
33 33
@@ -186,7 +186,7 b' class Component(HasTraits):'
186 186
187 187 __metaclass__ = MetaComponent
188 188
189 # Traitlets are fun!
189 # Traits are fun!
190 190 config = Instance(Config,(),{})
191 191 parent = This()
192 192 root = This()
@@ -250,7 +250,7 b' class Component(HasTraits):'
250 250 self.created = datetime.datetime.now()
251 251
252 252 #-------------------------------------------------------------------------
253 # Static traitlet notifiations
253 # Static trait notifiations
254 254 #-------------------------------------------------------------------------
255 255
256 256 def _parent_changed(self, name, old, new):
@@ -276,12 +276,12 b' class Component(HasTraits):'
276 276 def _config_changed(self, name, old, new):
277 277 """Update all the class traits having ``config=True`` as metadata.
278 278
279 For any class traitlet with a ``config`` metadata attribute that is
280 ``True``, we update the traitlet with the value of the corresponding
279 For any class trait with a ``config`` metadata attribute that is
280 ``True``, we update the trait with the value of the corresponding
281 281 config entry.
282 282 """
283 # Get all traitlets with a config metadata entry that is True
284 traitlets = self.traits(config=True)
283 # Get all traits with a config metadata entry that is True
284 traits = self.traits(config=True)
285 285
286 286 # We auto-load config section for this class as well as any parent
287 287 # classes that are Component subclasses. This starts with Component
@@ -295,7 +295,7 b' class Component(HasTraits):'
295 295 # dynamically create the section with name self.__class__.__name__.
296 296 if new._has_section(sname):
297 297 my_config = new[sname]
298 for k, v in traitlets.items():
298 for k, v in traits.items():
299 299 try:
300 300 config_value = my_config[k]
301 301 except KeyError:
@@ -165,7 +165,7 b' def get_default_editor():'
165 165 class SeparateStr(Str):
166 166 """A Str subclass to validate separate_in, separate_out, etc.
167 167
168 This is a Str based traitlet that converts '0'->'' and '\\n'->'\n'.
168 This is a Str based trait that converts '0'->'' and '\\n'->'\n'.
169 169 """
170 170
171 171 def validate(self, obj, value):
@@ -246,7 +246,7 b' class InteractiveShell(Component, Magic):'
246 246
247 247 screen_length = Int(0, config=True)
248 248
249 # Use custom TraitletTypes that convert '0'->'' and '\\n'->'\n'
249 # Use custom TraitTypes that convert '0'->'' and '\\n'->'\n'
250 250 separate_in = SeparateStr('\n', config=True)
251 251 separate_out = SeparateStr('', config=True)
252 252 separate_out2 = SeparateStr('', config=True)
@@ -269,7 +269,7 b' class InteractiveShell(Component, Magic):'
269 269 banner1=None, banner2=None, display_banner=None,
270 270 custom_exceptions=((),None)):
271 271
272 # This is where traitlets with a config_key argument are updated
272 # This is where traits with a config_key argument are updated
273 273 # from the values on config.
274 274 super(InteractiveShell, self).__init__(parent, config=config)
275 275
@@ -323,7 +323,7 b' class InteractiveShell(Component, Magic):'
323 323 return self
324 324
325 325 #-------------------------------------------------------------------------
326 # Traitlet changed handlers
326 # Trait changed handlers
327 327 #-------------------------------------------------------------------------
328 328
329 329 def _banner1_changed(self):
@@ -24,7 +24,7 b' from unittest import TestCase'
24 24
25 25 from IPython.core.component import Component, ComponentError
26 26 from IPython.utils.traitlets import (
27 TraitletError, Int, Float, Str
27 TraitError, Int, Float, Str
28 28 )
29 29 from IPython.config.loader import Config
30 30
@@ -109,7 +109,7 b' class TestComponent(TestCase):'
109 109
110 110 def test_subclass_parent(self):
111 111 c1 = Component(None)
112 self.assertRaises(TraitletError, setattr, c1, 'parent', 10)
112 self.assertRaises(TraitError, setattr, c1, 'parent', 10)
113 113
114 114 class MyComponent(Component):
115 115 pass
@@ -29,8 +29,8 b' import os'
29 29 from unittest import TestCase
30 30
31 31 from IPython.utils.traitlets import (
32 HasTraits, MetaHasTraits, TraitletType, Any,
33 Int, Long, Float, Complex, Str, Unicode, Bool, TraitletError,
32 HasTraits, MetaHasTraits, TraitType, Any,
33 Int, Long, Float, Complex, Str, Unicode, Bool, TraitError,
34 34 Undefined, Type, This, Instance
35 35 )
36 36
@@ -40,9 +40,9 b' from IPython.utils.traitlets import ('
40 40 #-----------------------------------------------------------------------------
41 41
42 42
43 class HasTraitletsStub(HasTraits):
43 class HasTraitsStub(HasTraits):
44 44
45 def _notify_traitlet(self, name, old, new):
45 def _notify_trait(self, name, old, new):
46 46 self._notify_name = name
47 47 self._notify_old = old
48 48 self._notify_new = new
@@ -53,17 +53,17 b' class HasTraitletsStub(HasTraits):'
53 53 #-----------------------------------------------------------------------------
54 54
55 55
56 class TestTraitletType(TestCase):
56 class TestTraitType(TestCase):
57 57
58 58 def test_get_undefined(self):
59 59 class A(HasTraits):
60 a = TraitletType
60 a = TraitType
61 61 a = A()
62 62 self.assertEquals(a.a, Undefined)
63 63
64 64 def test_set(self):
65 class A(HasTraitletsStub):
66 a = TraitletType
65 class A(HasTraitsStub):
66 a = TraitType
67 67
68 68 a = A()
69 69 a.a = 10
@@ -73,10 +73,10 b' class TestTraitletType(TestCase):'
73 73 self.assertEquals(a._notify_new, 10)
74 74
75 75 def test_validate(self):
76 class MyTT(TraitletType):
76 class MyTT(TraitType):
77 77 def validate(self, inst, value):
78 78 return -1
79 class A(HasTraitletsStub):
79 class A(HasTraitsStub):
80 80 tt = MyTT
81 81
82 82 a = A()
@@ -84,7 +84,7 b' class TestTraitletType(TestCase):'
84 84 self.assertEquals(a.tt, -1)
85 85
86 86 def test_default_validate(self):
87 class MyIntTT(TraitletType):
87 class MyIntTT(TraitType):
88 88 def validate(self, obj, value):
89 89 if isinstance(value, int):
90 90 return value
@@ -97,10 +97,10 b' class TestTraitletType(TestCase):'
97 97 # Defaults are validated when the HasTraits is instantiated
98 98 class B(HasTraits):
99 99 tt = MyIntTT('bad default')
100 self.assertRaises(TraitletError, B)
100 self.assertRaises(TraitError, B)
101 101
102 102 def test_is_valid_for(self):
103 class MyTT(TraitletType):
103 class MyTT(TraitType):
104 104 def is_valid_for(self, value):
105 105 return True
106 106 class A(HasTraits):
@@ -111,7 +111,7 b' class TestTraitletType(TestCase):'
111 111 self.assertEquals(a.tt, 10)
112 112
113 113 def test_value_for(self):
114 class MyTT(TraitletType):
114 class MyTT(TraitType):
115 115 def value_for(self, value):
116 116 return 20
117 117 class A(HasTraits):
@@ -123,15 +123,15 b' class TestTraitletType(TestCase):'
123 123
124 124 def test_info(self):
125 125 class A(HasTraits):
126 tt = TraitletType
126 tt = TraitType
127 127 a = A()
128 128 self.assertEquals(A.tt.info(), 'any value')
129 129
130 130 def test_error(self):
131 131 class A(HasTraits):
132 tt = TraitletType
132 tt = TraitType
133 133 a = A()
134 self.assertRaises(TraitletError, A.tt.error, a, 10)
134 self.assertRaises(TraitError, A.tt.error, a, 10)
135 135
136 136
137 137 class TestHasTraitsMeta(TestCase):
@@ -204,8 +204,8 b' class TestHasTraitsNotify(TestCase):'
204 204 self.assert_(('a',0,10) in self._notify1)
205 205 a.b = 10.0
206 206 self.assert_(('b',0.0,10.0) in self._notify1)
207 self.assertRaises(TraitletError,setattr,a,'a','bad string')
208 self.assertRaises(TraitletError,setattr,a,'b','bad string')
207 self.assertRaises(TraitError,setattr,a,'a','bad string')
208 self.assertRaises(TraitError,setattr,a,'b','bad string')
209 209 self._notify1 = []
210 210 a.on_trait_change(self.notify1,remove=True)
211 211 a.a = 20
@@ -224,7 +224,7 b' class TestHasTraitsNotify(TestCase):'
224 224 self.assertEquals(len(self._notify1),0)
225 225 a.a = 10
226 226 self.assert_(('a',0,10) in self._notify1)
227 self.assertRaises(TraitletError,setattr,a,'a','bad string')
227 self.assertRaises(TraitError,setattr,a,'a','bad string')
228 228
229 229 def test_subclass(self):
230 230
@@ -324,7 +324,7 b' class TestHasTraitsNotify(TestCase):'
324 324 self.assertEquals(self.cb,('a',1000,10000))
325 325 a.on_trait_change(callback3, 'a', remove=True)
326 326
327 self.assertEquals(len(a._traitlet_notifiers['a']),0)
327 self.assertEquals(len(a._trait_notifiers['a']),0)
328 328
329 329
330 330 class TestHasTraits(TestCase):
@@ -356,17 +356,17 b' class TestHasTraits(TestCase):'
356 356 j = Int(0)
357 357 a = A()
358 358 self.assertEquals(a.traits(), dict(i=A.i, f=A.f, j=A.j))
359 traitlets = a.traits(config_key='VALUE1', other_thing='VALUE2')
360 self.assertEquals(traitlets, dict(i=A.i))
359 traits = a.traits(config_key='VALUE1', other_thing='VALUE2')
360 self.assertEquals(traits, dict(i=A.i))
361 361
362 362 # This passes, but it shouldn't because I am replicating a bug in
363 363 # traits.
364 traitlets = a.traits(config_key=lambda v: True)
365 self.assertEquals(traitlets, dict(i=A.i, f=A.f, j=A.j))
364 traits = a.traits(config_key=lambda v: True)
365 self.assertEquals(traits, dict(i=A.i, f=A.f, j=A.j))
366 366
367 367
368 368 #-----------------------------------------------------------------------------
369 # Tests for specific traitlet types
369 # Tests for specific trait types
370 370 #-----------------------------------------------------------------------------
371 371
372 372
@@ -383,7 +383,7 b' class TestType(TestCase):'
383 383
384 384 a.klass = B
385 385 self.assertEquals(a.klass, B)
386 self.assertRaises(TraitletError, setattr, a, 'klass', 10)
386 self.assertRaises(TraitError, setattr, a, 'klass', 10)
387 387
388 388 def test_value(self):
389 389
@@ -394,8 +394,8 b' class TestType(TestCase):'
394 394
395 395 a = A()
396 396 self.assertEquals(a.klass, B)
397 self.assertRaises(TraitletError, setattr, a, 'klass', C)
398 self.assertRaises(TraitletError, setattr, a, 'klass', object)
397 self.assertRaises(TraitError, setattr, a, 'klass', C)
398 self.assertRaises(TraitError, setattr, a, 'klass', object)
399 399 a.klass = B
400 400
401 401 def test_allow_none(self):
@@ -407,7 +407,7 b' class TestType(TestCase):'
407 407
408 408 a = A()
409 409 self.assertEquals(a.klass, B)
410 self.assertRaises(TraitletError, setattr, a, 'klass', None)
410 self.assertRaises(TraitError, setattr, a, 'klass', None)
411 411 a.klass = C
412 412 self.assertEquals(a.klass, C)
413 413
@@ -434,7 +434,7 b' class TestType(TestCase):'
434 434 class C(HasTraits):
435 435 klass = Type(None, B, allow_none=False)
436 436
437 self.assertRaises(TraitletError, C)
437 self.assertRaises(TraitError, C)
438 438
439 439 def test_str_klass(self):
440 440
@@ -446,7 +446,7 b' class TestType(TestCase):'
446 446 a.klass = Struct
447 447 self.assertEquals(a.klass, Struct)
448 448
449 self.assertRaises(TraitletError, setattr, a, 'klass', 10)
449 self.assertRaises(TraitError, setattr, a, 'klass', 10)
450 450
451 451 class TestInstance(TestCase):
452 452
@@ -464,9 +464,9 b' class TestInstance(TestCase):'
464 464 self.assert_(isinstance(a.inst, Foo))
465 465 a.inst = Bar()
466 466 self.assert_(isinstance(a.inst, Foo))
467 self.assertRaises(TraitletError, setattr, a, 'inst', Foo)
468 self.assertRaises(TraitletError, setattr, a, 'inst', Bar)
469 self.assertRaises(TraitletError, setattr, a, 'inst', Bah())
467 self.assertRaises(TraitError, setattr, a, 'inst', Foo)
468 self.assertRaises(TraitError, setattr, a, 'inst', Bar)
469 self.assertRaises(TraitError, setattr, a, 'inst', Bah())
470 470
471 471 def test_unique_default_value(self):
472 472 class Foo(object): pass
@@ -507,7 +507,7 b' class TestInstance(TestCase):'
507 507 class A(HasTraits):
508 508 inst = Instance(Foo, allow_none=False)
509 509
510 self.assertRaises(TraitletError, A)
510 self.assertRaises(TraitError, A)
511 511
512 512 def test_instance(self):
513 513 class Foo(object): pass
@@ -516,7 +516,7 b' class TestInstance(TestCase):'
516 516 class A(HasTraits):
517 517 inst = Instance(Foo())
518 518
519 self.assertRaises(TraitletError, inner)
519 self.assertRaises(TraitError, inner)
520 520
521 521
522 522 class TestThis(TestCase):
@@ -530,7 +530,7 b' class TestThis(TestCase):'
530 530 g = Foo()
531 531 f.this = g
532 532 self.assertEquals(f.this, g)
533 self.assertRaises(TraitletError, setattr, f, 'this', 10)
533 self.assertRaises(TraitError, setattr, f, 'this', 10)
534 534
535 535 def test_this_inst(self):
536 536 class Foo(HasTraits):
@@ -561,10 +561,10 b' class TestThis(TestCase):'
561 561 b = Bar()
562 562 f.t = b
563 563 self.assertEquals(f.t, b)
564 self.assertRaises(TraitletError, setattr, b, 't', f)
564 self.assertRaises(TraitError, setattr, b, 't', f)
565 565
566 class TraitletTestBase(TestCase):
567 """A best testing class for basic traitlet types."""
566 class TraitTestBase(TestCase):
567 """A best testing class for basic trait types."""
568 568
569 569 def assign(self, value):
570 570 self.obj.value = value
@@ -581,33 +581,33 b' class TraitletTestBase(TestCase):'
581 581 def test_bad_values(self):
582 582 if hasattr(self, '_bad_values'):
583 583 for value in self._bad_values:
584 self.assertRaises(TraitletError, self.assign, value)
584 self.assertRaises(TraitError, self.assign, value)
585 585
586 586 def test_default_value(self):
587 587 if hasattr(self, '_default_value'):
588 588 self.assertEquals(self._default_value, self.obj.value)
589 589
590 590
591 class AnyTraitlet(HasTraits):
591 class AnyTrait(HasTraits):
592 592
593 593 value = Any
594 594
595 class AnyTraitTest(TraitletTestBase):
595 class AnyTraitTest(TraitTestBase):
596 596
597 obj = AnyTraitlet()
597 obj = AnyTrait()
598 598
599 599 _default_value = None
600 600 _good_values = [10.0, 'ten', u'ten', [10], {'ten': 10},(10,), None, 1j]
601 601 _bad_values = []
602 602
603 603
604 class IntTraitlet(HasTraits):
604 class IntTrait(HasTraits):
605 605
606 606 value = Int(99)
607 607
608 class TestInt(TraitletTestBase):
608 class TestInt(TraitTestBase):
609 609
610 obj = IntTraitlet()
610 obj = IntTrait()
611 611 _default_value = 99
612 612 _good_values = [10, -10]
613 613 _bad_values = ['ten', u'ten', [10], {'ten': 10},(10,), None, 1j, 10L,
@@ -615,13 +615,13 b' class TestInt(TraitletTestBase):'
615 615 u'-10L', u'10.1', u'-10.1', '10', '-10', u'10', u'-10']
616 616
617 617
618 class LongTraitlet(HasTraits):
618 class LongTrait(HasTraits):
619 619
620 620 value = Long(99L)
621 621
622 class TestLong(TraitletTestBase):
622 class TestLong(TraitTestBase):
623 623
624 obj = LongTraitlet()
624 obj = LongTrait()
625 625
626 626 _default_value = 99L
627 627 _good_values = [10, -10, 10L, -10L]
@@ -631,13 +631,13 b' class TestLong(TraitletTestBase):'
631 631 u'-10.1']
632 632
633 633
634 class FloatTraitlet(HasTraits):
634 class FloatTrait(HasTraits):
635 635
636 636 value = Float(99.0)
637 637
638 class TestFloat(TraitletTestBase):
638 class TestFloat(TraitTestBase):
639 639
640 obj = FloatTraitlet()
640 obj = FloatTrait()
641 641
642 642 _default_value = 99.0
643 643 _good_values = [10, -10, 10.1, -10.1]
@@ -646,13 +646,13 b' class TestFloat(TraitletTestBase):'
646 646 u'-10', u'10L', u'-10L', u'10.1', u'-10.1']
647 647
648 648
649 class ComplexTraitlet(HasTraits):
649 class ComplexTrait(HasTraits):
650 650
651 651 value = Complex(99.0-99.0j)
652 652
653 class TestComplex(TraitletTestBase):
653 class TestComplex(TraitTestBase):
654 654
655 obj = ComplexTraitlet()
655 obj = ComplexTrait()
656 656
657 657 _default_value = 99.0-99.0j
658 658 _good_values = [10, -10, 10.1, -10.1, 10j, 10+10j, 10-10j,
@@ -660,13 +660,13 b' class TestComplex(TraitletTestBase):'
660 660 _bad_values = [10L, -10L, u'10L', u'-10L', 'ten', [10], {'ten': 10},(10,), None]
661 661
662 662
663 class StringTraitlet(HasTraits):
663 class StringTrait(HasTraits):
664 664
665 665 value = Str('string')
666 666
667 class TestString(TraitletTestBase):
667 class TestString(TraitTestBase):
668 668
669 obj = StringTraitlet()
669 obj = StringTrait()
670 670
671 671 _default_value = 'string'
672 672 _good_values = ['10', '-10', '10L',
@@ -675,13 +675,13 b' class TestString(TraitletTestBase):'
675 675 ['ten'],{'ten': 10},(10,), None, u'string']
676 676
677 677
678 class UnicodeTraitlet(HasTraits):
678 class UnicodeTrait(HasTraits):
679 679
680 680 value = Unicode(u'unicode')
681 681
682 class TestUnicode(TraitletTestBase):
682 class TestUnicode(TraitTestBase):
683 683
684 obj = UnicodeTraitlet()
684 obj = UnicodeTrait()
685 685
686 686 _default_value = u'unicode'
687 687 _good_values = ['10', '-10', '10L', '-10L', '10.1',
@@ -17,7 +17,7 b" We don't support:"
17 17 * Delegation
18 18 * Automatic GUI generation
19 19 * A full set of trait types. Most importantly, we don't provide container
20 traitlets (list, dict, tuple) that can trigger notifications if their
20 traits (list, dict, tuple) that can trigger notifications if their
21 21 contents change.
22 22 * API compatibility with enthought.traits
23 23
@@ -86,16 +86,9 b' NoDefaultSpecified = NoDefaultSpecified()'
86 86 class Undefined ( object ): pass
87 87 Undefined = Undefined()
88 88
89 # The following allows us to test specifically for a TraitletError, or more
90 # generally for a TraitError if we are going for compatability with Enthought
91 # Traits
92 89 class TraitError(Exception):
93 90 pass
94 91
95 class TraitletError(TraitError):
96 pass
97
98
99 92 #-----------------------------------------------------------------------------
100 93 # Utilities
101 94 #-----------------------------------------------------------------------------
@@ -168,25 +161,25 b' class _SimpleTest:'
168 161
169 162
170 163 #-----------------------------------------------------------------------------
171 # Base TraitletType for all traitlets
164 # Base TraitType for all traits
172 165 #-----------------------------------------------------------------------------
173 166
174 167
175 class TraitletType(object):
176 """A base class for all traitlet descriptors.
168 class TraitType(object):
169 """A base class for all trait descriptors.
177 170
178 171 Notes
179 172 -----
180 Our implementation of traitlets is based on Python's descriptor
173 Our implementation of traits is based on Python's descriptor
181 174 prototol. This class is the base class for all such descriptors. The
182 175 only magic we use is a custom metaclass for the main :class:`HasTraits`
183 176 class that does the following:
184 177
185 1. Sets the :attr:`name` attribute of every :class:`TraitletType`
178 1. Sets the :attr:`name` attribute of every :class:`TraitType`
186 179 instance in the class dict to the name of the attribute.
187 2. Sets the :attr:`this_class` attribute of every :class:`TraitletType`
188 instance in the class dict to the *class* that declared the traitlet.
189 This is used by the :class:`This` traitlet to allow subclasses to
180 2. Sets the :attr:`this_class` attribute of every :class:`TraitType`
181 instance in the class dict to the *class* that declared the trait.
182 This is used by the :class:`This` trait to allow subclasses to
190 183 accept superclasses for :class:`This` values.
191 184 """
192 185
@@ -196,7 +189,7 b' class TraitletType(object):'
196 189 info_text = 'any value'
197 190
198 191 def __init__(self, default_value=NoDefaultSpecified, **metadata):
199 """Create a TraitletType.
192 """Create a TraitType.
200 193 """
201 194 if default_value is not NoDefaultSpecified:
202 195 self.default_value = default_value
@@ -250,10 +243,10 b' class TraitletType(object):'
250 243 """
251 244 dv = self.get_default_value()
252 245 newdv = self._validate(obj, dv)
253 obj._traitlet_values[self.name] = newdv
246 obj._trait_values[self.name] = newdv
254 247
255 248 def __get__(self, obj, cls=None):
256 """Get the value of the traitlet by self.name for the instance.
249 """Get the value of the trait by self.name for the instance.
257 250
258 251 Default values are instantiated when :meth:`HasTraits.__new__`
259 252 is called. Thus by the time this method gets called either the
@@ -264,11 +257,11 b' class TraitletType(object):'
264 257 return self
265 258 else:
266 259 try:
267 value = obj._traitlet_values[self.name]
260 value = obj._trait_values[self.name]
268 261 except:
269 262 # HasTraits should call set_default_value to populate
270 263 # this. So this should never be reached.
271 raise TraitletError('Unexpected error in TraitletType: '
264 raise TraitError('Unexpected error in TraitType: '
272 265 'default value not set properly')
273 266 else:
274 267 return value
@@ -277,8 +270,8 b' class TraitletType(object):'
277 270 new_value = self._validate(obj, value)
278 271 old_value = self.__get__(obj)
279 272 if old_value != new_value:
280 obj._traitlet_values[self.name] = new_value
281 obj._notify_traitlet(self.name, old_value, new_value)
273 obj._trait_values[self.name] = new_value
274 obj._notify_trait(self.name, old_value, new_value)
282 275
283 276 def _validate(self, obj, value):
284 277 if hasattr(self, 'validate'):
@@ -288,7 +281,7 b' class TraitletType(object):'
288 281 if valid:
289 282 return value
290 283 else:
291 raise TraitletError('invalid value for type: %r' % value)
284 raise TraitError('invalid value for type: %r' % value)
292 285 elif hasattr(self, 'value_for'):
293 286 return self.value_for(value)
294 287 else:
@@ -299,13 +292,13 b' class TraitletType(object):'
299 292
300 293 def error(self, obj, value):
301 294 if obj is not None:
302 e = "The '%s' traitlet of %s instance must be %s, but a value of %s was specified." \
295 e = "The '%s' trait of %s instance must be %s, but a value of %s was specified." \
303 296 % (self.name, class_of(obj),
304 297 self.info(), repr_type(value))
305 298 else:
306 e = "The '%s' traitlet must be %s, but a value of %r was specified." \
299 e = "The '%s' trait must be %s, but a value of %r was specified." \
307 300 % (self.name, self.info(), repr_type(value))
308 raise TraitletError(e)
301 raise TraitError(e)
309 302
310 303 def get_metadata(self, key):
311 304 return getattr(self, '_metadata', {}).get(key, None)
@@ -322,21 +315,21 b' class TraitletType(object):'
322 315 class MetaHasTraits(type):
323 316 """A metaclass for HasTraits.
324 317
325 This metaclass makes sure that any TraitletType class attributes are
318 This metaclass makes sure that any TraitType class attributes are
326 319 instantiated and sets their name attribute.
327 320 """
328 321
329 322 def __new__(mcls, name, bases, classdict):
330 323 """Create the HasTraits class.
331 324
332 This instantiates all TraitletTypes in the class dict and sets their
325 This instantiates all TraitTypes in the class dict and sets their
333 326 :attr:`name` attribute.
334 327 """
335 328 for k,v in classdict.iteritems():
336 if isinstance(v, TraitletType):
329 if isinstance(v, TraitType):
337 330 v.name = k
338 331 elif inspect.isclass(v):
339 if issubclass(v, TraitletType):
332 if issubclass(v, TraitType):
340 333 vinst = v()
341 334 vinst.name = k
342 335 classdict[k] = vinst
@@ -345,11 +338,11 b' class MetaHasTraits(type):'
345 338 def __init__(cls, name, bases, classdict):
346 339 """Finish initializing the HasTraits class.
347 340
348 This sets the :attr:`this_class` attribute of each TraitletType in the
341 This sets the :attr:`this_class` attribute of each TraitType in the
349 342 class dict to the newly created class ``cls``.
350 343 """
351 344 for k, v in classdict.iteritems():
352 if isinstance(v, TraitletType):
345 if isinstance(v, TraitType):
353 346 v.this_class = cls
354 347 super(MetaHasTraits, cls).__init__(name, bases, classdict)
355 348
@@ -365,25 +358,25 b' class HasTraits(object):'
365 358 inst = new_meth(cls)
366 359 else:
367 360 inst = new_meth(cls, *args, **kw)
368 inst._traitlet_values = {}
369 inst._traitlet_notifiers = {}
370 # Here we tell all the TraitletType instances to set their default
361 inst._trait_values = {}
362 inst._trait_notifiers = {}
363 # Here we tell all the TraitType instances to set their default
371 364 # values on the instance.
372 365 for key in dir(cls):
373 366 value = getattr(cls, key)
374 if isinstance(value, TraitletType):
367 if isinstance(value, TraitType):
375 368 value.instance_init(inst)
376 369 return inst
377 370
378 371 # def __init__(self):
379 # self._traitlet_values = {}
380 # self._traitlet_notifiers = {}
372 # self._trait_values = {}
373 # self._trait_notifiers = {}
381 374
382 def _notify_traitlet(self, name, old_value, new_value):
375 def _notify_trait(self, name, old_value, new_value):
383 376
384 377 # First dynamic ones
385 callables = self._traitlet_notifiers.get(name,[])
386 more_callables = self._traitlet_notifiers.get('anytrait',[])
378 callables = self._trait_notifiers.get(name,[])
379 more_callables = self._trait_notifiers.get('anytrait',[])
387 380 callables.extend(more_callables)
388 381
389 382 # Now static ones
@@ -416,25 +409,25 b' class HasTraits(object):'
416 409 elif nargs + offset == 3:
417 410 c(name, old_value, new_value)
418 411 else:
419 raise TraitletError('a traitlet changed callback '
412 raise TraitError('a trait changed callback '
420 413 'must have 0-3 arguments.')
421 414 else:
422 raise TraitletError('a traitlet changed callback '
415 raise TraitError('a trait changed callback '
423 416 'must be callable.')
424 417
425 418
426 419 def _add_notifiers(self, handler, name):
427 if not self._traitlet_notifiers.has_key(name):
420 if not self._trait_notifiers.has_key(name):
428 421 nlist = []
429 self._traitlet_notifiers[name] = nlist
422 self._trait_notifiers[name] = nlist
430 423 else:
431 nlist = self._traitlet_notifiers[name]
424 nlist = self._trait_notifiers[name]
432 425 if handler not in nlist:
433 426 nlist.append(handler)
434 427
435 428 def _remove_notifiers(self, handler, name):
436 if self._traitlet_notifiers.has_key(name):
437 nlist = self._traitlet_notifiers[name]
429 if self._trait_notifiers.has_key(name):
430 nlist = self._trait_notifiers[name]
438 431 try:
439 432 index = nlist.index(handler)
440 433 except ValueError:
@@ -443,24 +436,24 b' class HasTraits(object):'
443 436 del nlist[index]
444 437
445 438 def on_trait_change(self, handler, name=None, remove=False):
446 """Setup a handler to be called when a traitlet changes.
439 """Setup a handler to be called when a trait changes.
447 440
448 This is used to setup dynamic notifications of traitlet changes.
441 This is used to setup dynamic notifications of trait changes.
449 442
450 443 Static handlers can be created by creating methods on a HasTraits
451 subclass with the naming convention '_[traitletname]_changed'. Thus,
452 to create static handler for the traitlet 'a', create the method
444 subclass with the naming convention '_[traitname]_changed'. Thus,
445 to create static handler for the trait 'a', create the method
453 446 _a_changed(self, name, old, new) (fewer arguments can be used, see
454 447 below).
455 448
456 449 Parameters
457 450 ----------
458 451 handler : callable
459 A callable that is called when a traitlet changes. Its
452 A callable that is called when a trait changes. Its
460 453 signature can be handler(), handler(name), handler(name, new)
461 454 or handler(name, old, new).
462 455 name : list, str, None
463 If None, the handler will apply to all traitlets. If a list
456 If None, the handler will apply to all traits. If a list
464 457 of str, handler will apply to all names in the list. If a
465 458 str, the handler will apply just to that name.
466 459 remove : bool
@@ -477,61 +470,61 b' class HasTraits(object):'
477 470 self._add_notifiers(handler, n)
478 471
479 472 def trait_names(self, **metadata):
480 """Get a list of all the names of this classes traitlets."""
473 """Get a list of all the names of this classes traits."""
481 474 return self.traits(**metadata).keys()
482 475
483 476 def traits(self, **metadata):
484 """Get a list of all the traitlets of this class.
477 """Get a list of all the traits of this class.
485 478
486 The TraitletTypes returned don't know anything about the values
487 that the various HasTraitlet's instances are holding.
479 The TraitTypes returned don't know anything about the values
480 that the various HasTrait's instances are holding.
488 481
489 482 This follows the same algorithm as traits does and does not allow
490 483 for any simple way of specifying merely that a metadata name
491 484 exists, but has any value. This is because get_metadata returns
492 485 None if a metadata key doesn't exist.
493 486 """
494 traitlets = dict([memb for memb in inspect.getmembers(self.__class__) if \
495 isinstance(memb[1], TraitletType)])
487 traits = dict([memb for memb in inspect.getmembers(self.__class__) if \
488 isinstance(memb[1], TraitType)])
496 489
497 490 if len(metadata) == 0:
498 return traitlets
491 return traits
499 492
500 493 for meta_name, meta_eval in metadata.items():
501 494 if type(meta_eval) is not FunctionType:
502 495 metadata[meta_name] = _SimpleTest(meta_eval)
503 496
504 497 result = {}
505 for name, traitlet in traitlets.items():
498 for name, trait in traits.items():
506 499 for meta_name, meta_eval in metadata.items():
507 if not meta_eval(traitlet.get_metadata(meta_name)):
500 if not meta_eval(trait.get_metadata(meta_name)):
508 501 break
509 502 else:
510 result[name] = traitlet
503 result[name] = trait
511 504
512 505 return result
513 506
514 def trait_metadata(self, traitletname, key):
515 """Get metadata values for traitlet by key."""
507 def trait_metadata(self, traitname, key):
508 """Get metadata values for trait by key."""
516 509 try:
517 traitlet = getattr(self.__class__, traitletname)
510 trait = getattr(self.__class__, traitname)
518 511 except AttributeError:
519 raise TraitletError("Class %s does not have a traitlet named %s" %
520 (self.__class__.__name__, traitletname))
512 raise TraitError("Class %s does not have a trait named %s" %
513 (self.__class__.__name__, traitname))
521 514 else:
522 return traitlet.get_metadata(key)
515 return trait.get_metadata(key)
523 516
524 517 #-----------------------------------------------------------------------------
525 # Actual TraitletTypes implementations/subclasses
518 # Actual TraitTypes implementations/subclasses
526 519 #-----------------------------------------------------------------------------
527 520
528 521 #-----------------------------------------------------------------------------
529 # TraitletTypes subclasses for handling classes and instances of classes
522 # TraitTypes subclasses for handling classes and instances of classes
530 523 #-----------------------------------------------------------------------------
531 524
532 525
533 class ClassBasedTraitletType(TraitletType):
534 """A traitlet with error reporting for Type, Instance and This."""
526 class ClassBasedTraitType(TraitType):
527 """A trait with error reporting for Type, Instance and This."""
535 528
536 529 def error(self, obj, value):
537 530 kind = type(value)
@@ -540,16 +533,16 b' class ClassBasedTraitletType(TraitletType):'
540 533 else:
541 534 msg = '%s (i.e. %s)' % ( str( kind )[1:-1], repr( value ) )
542 535
543 super(ClassBasedTraitletType, self).error(obj, msg)
536 super(ClassBasedTraitType, self).error(obj, msg)
544 537
545 538
546 class Type(ClassBasedTraitletType):
547 """A traitlet whose value must be a subclass of a specified class."""
539 class Type(ClassBasedTraitType):
540 """A trait whose value must be a subclass of a specified class."""
548 541
549 542 def __init__ (self, default_value=None, klass=None, allow_none=True, **metadata ):
550 """Construct a Type traitlet
543 """Construct a Type trait
551 544
552 A Type traitlet specifies that its values must be subclasses of
545 A Type trait specifies that its values must be subclasses of
553 546 a particular class.
554 547
555 548 If only ``default_value`` is given, it is used for the ``klass`` as
@@ -563,7 +556,7 b' class Type(ClassBasedTraitletType):'
563 556 The string is resolved into real class, when the parent
564 557 :class:`HasTraits` class is instantiated.
565 558 klass : class, str, None
566 Values of this traitlet must be a subclass of klass. The klass
559 Values of this trait must be a subclass of klass. The klass
567 560 may be specified in a string like: 'foo.bar.MyClass'.
568 561 The string is resolved into real class, when the parent
569 562 :class:`HasTraits` class is instantiated.
@@ -578,7 +571,7 b' class Type(ClassBasedTraitletType):'
578 571 klass = default_value
579 572
580 573 if not (inspect.isclass(klass) or isinstance(klass, basestring)):
581 raise TraitletError("A Type traitlet must specify a class.")
574 raise TraitError("A Type trait must specify a class.")
582 575
583 576 self.klass = klass
584 577 self._allow_none = allow_none
@@ -632,7 +625,7 b' class DefaultValueGenerator(object):'
632 625 return klass(*self.args, **self.kw)
633 626
634 627
635 class Instance(ClassBasedTraitletType):
628 class Instance(ClassBasedTraitType):
636 629 """A trait whose value must be an instance of a specified class.
637 630
638 631 The value can also be an instance of a subclass of the specified class.
@@ -640,9 +633,9 b' class Instance(ClassBasedTraitletType):'
640 633
641 634 def __init__(self, klass=None, args=None, kw=None,
642 635 allow_none=True, **metadata ):
643 """Construct an Instance traitlet.
636 """Construct an Instance trait.
644 637
645 This traitlet allows values that are instances of a particular
638 This trait allows values that are instances of a particular
646 639 class or its sublclasses. Our implementation is quite different
647 640 from that of enthough.traits as we don't allow instances to be used
648 641 for klass and we handle the ``args`` and ``kw`` arguments differently.
@@ -650,7 +643,7 b' class Instance(ClassBasedTraitletType):'
650 643 Parameters
651 644 ----------
652 645 klass : class, str
653 The class that forms the basis for the traitlet. Class names
646 The class that forms the basis for the trait. Class names
654 647 can also be specified as strings, like 'foo.bar.Bar'.
655 648 args : tuple
656 649 Positional arguments for generating the default value.
@@ -670,7 +663,7 b' class Instance(ClassBasedTraitletType):'
670 663 self._allow_none = allow_none
671 664
672 665 if (klass is None) or (not (inspect.isclass(klass) or isinstance(klass, basestring))):
673 raise TraitletError('The klass argument must be a class'
666 raise TraitError('The klass argument must be a class'
674 667 ' you gave: %r' % klass)
675 668 self.klass = klass
676 669
@@ -686,9 +679,9 b' class Instance(ClassBasedTraitletType):'
686 679 kw = {}
687 680
688 681 if not isinstance(kw, dict):
689 raise TraitletError("The 'kw' argument must be a dict or None.")
682 raise TraitError("The 'kw' argument must be a dict or None.")
690 683 if not isinstance(args, tuple):
691 raise TraitletError("The 'args' argument must be a tuple or None.")
684 raise TraitError("The 'args' argument must be a tuple or None.")
692 685
693 686 default_value = DefaultValueGenerator(*args, **kw)
694 687
@@ -738,11 +731,11 b' class Instance(ClassBasedTraitletType):'
738 731 return dv
739 732
740 733
741 class This(ClassBasedTraitletType):
742 """A traitlet for instances of the class containing this trait.
734 class This(ClassBasedTraitType):
735 """A trait for instances of the class containing this trait.
743 736
744 737 Because how how and when class bodies are executed, the ``This``
745 traitlet can only have a default value of None. This, and because we
738 trait can only have a default value of None. This, and because we
746 739 always validate default values, ``allow_none`` is *always* true.
747 740 """
748 741
@@ -754,7 +747,7 b' class This(ClassBasedTraitletType):'
754 747 def validate(self, obj, value):
755 748 # What if value is a superclass of obj.__class__? This is
756 749 # complicated if it was the superclass that defined the This
757 # traitlet.
750 # trait.
758 751 if isinstance(value, self.this_class) or (value is None):
759 752 return value
760 753 else:
@@ -762,17 +755,17 b' class This(ClassBasedTraitletType):'
762 755
763 756
764 757 #-----------------------------------------------------------------------------
765 # Basic TraitletTypes implementations/subclasses
758 # Basic TraitTypes implementations/subclasses
766 759 #-----------------------------------------------------------------------------
767 760
768 761
769 class Any(TraitletType):
762 class Any(TraitType):
770 763 default_value = None
771 764 info_text = 'any value'
772 765
773 766
774 class Int(TraitletType):
775 """A integer traitlet."""
767 class Int(TraitType):
768 """A integer trait."""
776 769
777 770 evaluate = int
778 771 default_value = 0
@@ -784,7 +777,7 b' class Int(TraitletType):'
784 777 self.error(obj, value)
785 778
786 779 class CInt(Int):
787 """A casting version of the int traitlet."""
780 """A casting version of the int trait."""
788 781
789 782 def validate(self, obj, value):
790 783 try:
@@ -793,8 +786,8 b' class CInt(Int):'
793 786 self.error(obj, value)
794 787
795 788
796 class Long(TraitletType):
797 """A long integer traitlet."""
789 class Long(TraitType):
790 """A long integer trait."""
798 791
799 792 evaluate = long
800 793 default_value = 0L
@@ -809,7 +802,7 b' class Long(TraitletType):'
809 802
810 803
811 804 class CLong(Long):
812 """A casting version of the long integer traitlet."""
805 """A casting version of the long integer trait."""
813 806
814 807 def validate(self, obj, value):
815 808 try:
@@ -818,8 +811,8 b' class CLong(Long):'
818 811 self.error(obj, value)
819 812
820 813
821 class Float(TraitletType):
822 """A float traitlet."""
814 class Float(TraitType):
815 """A float trait."""
823 816
824 817 evaluate = float
825 818 default_value = 0.0
@@ -834,7 +827,7 b' class Float(TraitletType):'
834 827
835 828
836 829 class CFloat(Float):
837 """A casting version of the float traitlet."""
830 """A casting version of the float trait."""
838 831
839 832 def validate(self, obj, value):
840 833 try:
@@ -842,8 +835,8 b' class CFloat(Float):'
842 835 except:
843 836 self.error(obj, value)
844 837
845 class Complex(TraitletType):
846 """A traitlet for complex numbers."""
838 class Complex(TraitType):
839 """A trait for complex numbers."""
847 840
848 841 evaluate = complex
849 842 default_value = 0.0 + 0.0j
@@ -858,7 +851,7 b' class Complex(TraitletType):'
858 851
859 852
860 853 class CComplex(Complex):
861 """A casting version of the complex number traitlet."""
854 """A casting version of the complex number trait."""
862 855
863 856 def validate (self, obj, value):
864 857 try:
@@ -867,8 +860,8 b' class CComplex(Complex):'
867 860 self.error(obj, value)
868 861
869 862
870 class Str(TraitletType):
871 """A traitlet for strings."""
863 class Str(TraitType):
864 """A trait for strings."""
872 865
873 866 evaluate = lambda x: x
874 867 default_value = ''
@@ -881,7 +874,7 b' class Str(TraitletType):'
881 874
882 875
883 876 class CStr(Str):
884 """A casting version of the string traitlet."""
877 """A casting version of the string trait."""
885 878
886 879 def validate(self, obj, value):
887 880 try:
@@ -893,8 +886,8 b' class CStr(Str):'
893 886 self.error(obj, value)
894 887
895 888
896 class Unicode(TraitletType):
897 """A traitlet for unicode strings."""
889 class Unicode(TraitType):
890 """A trait for unicode strings."""
898 891
899 892 evaluate = unicode
900 893 default_value = u''
@@ -909,7 +902,7 b' class Unicode(TraitletType):'
909 902
910 903
911 904 class CUnicode(Unicode):
912 """A casting version of the unicode traitlet."""
905 """A casting version of the unicode trait."""
913 906
914 907 def validate(self, obj, value):
915 908 try:
@@ -918,8 +911,8 b' class CUnicode(Unicode):'
918 911 self.error(obj, value)
919 912
920 913
921 class Bool(TraitletType):
922 """A boolean (True, False) traitlet."""
914 class Bool(TraitType):
915 """A boolean (True, False) trait."""
923 916 evaluate = bool
924 917 default_value = False
925 918 info_text = 'a boolean'
@@ -931,7 +924,7 b' class Bool(TraitletType):'
931 924
932 925
933 926 class CBool(Bool):
934 """A casting version of the boolean traitlet."""
927 """A casting version of the boolean trait."""
935 928
936 929 def validate(self, obj, value):
937 930 try:
@@ -940,7 +933,7 b' class CBool(Bool):'
940 933 self.error(obj, value)
941 934
942 935
943 class Enum(TraitletType):
936 class Enum(TraitType):
944 937 """An enum that whose value must be in a given sequence."""
945 938
946 939 def __init__(self, values, default_value=None, allow_none=True, **metadata):
@@ -985,7 +978,7 b' class List(Instance):'
985 978 """An instance of a Python list."""
986 979
987 980 def __init__(self, default_value=None, allow_none=True, **metadata):
988 """Create a list traitlet type from a list or tuple.
981 """Create a list trait type from a list or tuple.
989 982
990 983 The default value is created by doing ``list(default_value)``,
991 984 which creates a copy of the ``default_value``.
General Comments 0
You need to be logged in to leave comments. Login now