Show More
@@ -129,6 +129,29 b' class TestTraitType(TestCase):' | |||
|
129 | 129 | a = A() |
|
130 | 130 | self.assertRaises(TraitError, A.tt.error, a, 10) |
|
131 | 131 | |
|
132 | def test_dynamic_initializer(self): | |
|
133 | class A(HasTraits): | |
|
134 | x = Int(10) | |
|
135 | def _x_default(self): | |
|
136 | return 11 | |
|
137 | class B(A): | |
|
138 | x = Int(20) | |
|
139 | class C(A): | |
|
140 | def _x_default(self): | |
|
141 | return 21 | |
|
142 | ||
|
143 | a = A() | |
|
144 | self.assertEquals(a._trait_values, {}) | |
|
145 | self.assertEquals(a.x, 11) | |
|
146 | self.assertEquals(a._trait_values, {'x': 11}) | |
|
147 | b = B() | |
|
148 | self.assertEquals(b._trait_values, {'x': 20}) | |
|
149 | self.assertEquals(b.x, 20) | |
|
150 | c = C() | |
|
151 | self.assertEquals(c._trait_values, {}) | |
|
152 | self.assertEquals(c.x, 21) | |
|
153 | self.assertEquals(c._trait_values, {'x': 21}) | |
|
154 | ||
|
132 | 155 | |
|
133 | 156 | class TestHasTraitsMeta(TestCase): |
|
134 | 157 |
@@ -248,9 +248,21 b' class TraitType(object):' | |||
|
248 | 248 | default values must be delayed until the parent :class:`HasTraits` |
|
249 | 249 | class has been instantiated. |
|
250 | 250 | """ |
|
251 | dv = self.get_default_value() | |
|
252 | newdv = self._validate(obj, dv) | |
|
253 | obj._trait_values[self.name] = newdv | |
|
251 | # Check for a deferred initializer defined in the same class as the | |
|
252 | # trait declaration or above. | |
|
253 | mro = type(obj).mro() | |
|
254 | meth_name = '_%s_default' % self.name | |
|
255 | for cls in mro[:mro.index(self.this_class)+1]: | |
|
256 | if meth_name in cls.__dict__: | |
|
257 | break | |
|
258 | else: | |
|
259 | # We didn't find one. Do static initialization. | |
|
260 | dv = self.get_default_value() | |
|
261 | newdv = self._validate(obj, dv) | |
|
262 | obj._trait_values[self.name] = newdv | |
|
263 | return | |
|
264 | # Complete the dynamic initialization. | |
|
265 | self.dynamic_initializer = cls.__dict__[meth_name] | |
|
254 | 266 | |
|
255 | 267 | def __get__(self, obj, cls=None): |
|
256 | 268 | """Get the value of the trait by self.name for the instance. |
@@ -265,7 +277,19 b' class TraitType(object):' | |||
|
265 | 277 | else: |
|
266 | 278 | try: |
|
267 | 279 | value = obj._trait_values[self.name] |
|
268 | except: | |
|
280 | except KeyError: | |
|
281 | # Check for a dynamic initializer. | |
|
282 | if hasattr(self, 'dynamic_initializer'): | |
|
283 | value = self.dynamic_initializer(obj) | |
|
284 | # FIXME: Do we really validate here? | |
|
285 | value = self._validate(obj, value) | |
|
286 | obj._trait_values[self.name] = value | |
|
287 | return value | |
|
288 | else: | |
|
289 | raise TraitError('Unexpected error in TraitType: ' | |
|
290 | 'both default value and dynamic initializer are ' | |
|
291 | 'absent.') | |
|
292 | except Exception: | |
|
269 | 293 | # HasTraits should call set_default_value to populate |
|
270 | 294 | # this. So this should never be reached. |
|
271 | 295 | raise TraitError('Unexpected error in TraitType: ' |
@@ -294,6 +318,11 b' class TraitType(object):' | |||
|
294 | 318 | else: |
|
295 | 319 | return value |
|
296 | 320 | |
|
321 | def set_dynamic_initializer(self, method): | |
|
322 | """ Set the dynamic initializer method, if any. | |
|
323 | """ | |
|
324 | self.dynamic_initializer = method | |
|
325 | ||
|
297 | 326 | def info(self): |
|
298 | 327 | return self.info_text |
|
299 | 328 |
General Comments 0
You need to be logged in to leave comments.
Login now