Show More
@@ -129,6 +129,29 b' class TestTraitType(TestCase):' | |||||
129 | a = A() |
|
129 | a = A() | |
130 | self.assertRaises(TraitError, A.tt.error, a, 10) |
|
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 | class TestHasTraitsMeta(TestCase): |
|
156 | class TestHasTraitsMeta(TestCase): | |
134 |
|
157 |
@@ -248,9 +248,21 b' class TraitType(object):' | |||||
248 | default values must be delayed until the parent :class:`HasTraits` |
|
248 | default values must be delayed until the parent :class:`HasTraits` | |
249 | class has been instantiated. |
|
249 | class has been instantiated. | |
250 | """ |
|
250 | """ | |
|
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. | |||
251 | dv = self.get_default_value() |
|
260 | dv = self.get_default_value() | |
252 | newdv = self._validate(obj, dv) |
|
261 | newdv = self._validate(obj, dv) | |
253 | obj._trait_values[self.name] = newdv |
|
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 | def __get__(self, obj, cls=None): |
|
267 | def __get__(self, obj, cls=None): | |
256 | """Get the value of the trait by self.name for the instance. |
|
268 | """Get the value of the trait by self.name for the instance. | |
@@ -265,7 +277,19 b' class TraitType(object):' | |||||
265 | else: |
|
277 | else: | |
266 | try: |
|
278 | try: | |
267 | value = obj._trait_values[self.name] |
|
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 | # HasTraits should call set_default_value to populate |
|
293 | # HasTraits should call set_default_value to populate | |
270 | # this. So this should never be reached. |
|
294 | # this. So this should never be reached. | |
271 | raise TraitError('Unexpected error in TraitType: ' |
|
295 | raise TraitError('Unexpected error in TraitType: ' | |
@@ -294,6 +318,11 b' class TraitType(object):' | |||||
294 | else: |
|
318 | else: | |
295 | return value |
|
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 | def info(self): |
|
326 | def info(self): | |
298 | return self.info_text |
|
327 | return self.info_text | |
299 |
|
328 |
General Comments 0
You need to be logged in to leave comments.
Login now