From 39e74b164b6cc39a095269abcd1b70700c8b5d6b 2011-02-15 18:13:18 From: Robert Kern Date: 2011-02-15 18:13:18 Subject: [PATCH] BUG: Do not store class-specific state on TraitTypes since they may be shared through subclassing. --- diff --git a/IPython/utils/tests/test_traitlets.py b/IPython/utils/tests/test_traitlets.py index 16baab7..724d631 100755 --- a/IPython/utils/tests/test_traitlets.py +++ b/IPython/utils/tests/test_traitlets.py @@ -142,15 +142,27 @@ class TestTraitType(TestCase): a = A() self.assertEquals(a._trait_values, {}) + self.assertEquals(a._trait_dyn_inits.keys(), ['x']) self.assertEquals(a.x, 11) self.assertEquals(a._trait_values, {'x': 11}) b = B() self.assertEquals(b._trait_values, {'x': 20}) + self.assertEquals(a._trait_dyn_inits.keys(), ['x']) self.assertEquals(b.x, 20) c = C() self.assertEquals(c._trait_values, {}) + self.assertEquals(a._trait_dyn_inits.keys(), ['x']) self.assertEquals(c.x, 21) self.assertEquals(c._trait_values, {'x': 21}) + # Ensure that the base class remains unmolested when the _default + # initializer gets overridden in a subclass. + a = A() + c = C() + self.assertEquals(a._trait_values, {}) + self.assertEquals(a._trait_dyn_inits.keys(), ['x']) + self.assertEquals(a.x, 11) + self.assertEquals(a._trait_values, {'x': 11}) + class TestHasTraitsMeta(TestCase): diff --git a/IPython/utils/traitlets.py b/IPython/utils/traitlets.py index a6bf9f8..b3a3012 100644 --- a/IPython/utils/traitlets.py +++ b/IPython/utils/traitlets.py @@ -262,7 +262,7 @@ class TraitType(object): obj._trait_values[self.name] = newdv return # Complete the dynamic initialization. - self.dynamic_initializer = cls.__dict__[meth_name] + obj._trait_dyn_inits[self.name] = cls.__dict__[meth_name] def __get__(self, obj, cls=None): """Get the value of the trait by self.name for the instance. @@ -279,8 +279,8 @@ class TraitType(object): value = obj._trait_values[self.name] except KeyError: # Check for a dynamic initializer. - if hasattr(self, 'dynamic_initializer'): - value = self.dynamic_initializer(obj) + if self.name in obj._trait_dyn_inits: + value = obj._trait_dyn_inits[self.name](obj) # FIXME: Do we really validate here? value = self._validate(obj, value) obj._trait_values[self.name] = value @@ -318,11 +318,6 @@ class TraitType(object): else: return value - def set_dynamic_initializer(self, method): - """ Set the dynamic initializer method, if any. - """ - self.dynamic_initializer = method - def info(self): return self.info_text @@ -399,6 +394,7 @@ class HasTraits(object): inst = new_meth(cls, **kw) inst._trait_values = {} inst._trait_notifiers = {} + inst._trait_dyn_inits = {} # Here we tell all the TraitType instances to set their default # values on the instance. for key in dir(cls):