6 Sep 07:33
Re: [Traits] dirty trait metadata
Robert Kern wrote:
>> Is there a simple way of doing this? I know that I could achieve this
>> if I implemented x as a Property(Array) but is there an easier way?
>
> I don't think so. The comparison logic is in C
> (ctraits.c:setattr_trait), and there are no hooks for this.
>
> If you only need coarse-grained notifications, you might consider
> using an updated Event. This:
OK, so I came up with a new trait type that does this nicely with
minimal fuss and also does the validation right. Attached is the code
along with a complete test case. A quick example:
ArrayOrNone = Either(None, Array)
class Data(HasTraits):
x = ShadowProperty(ArrayOrNone)
# Test attribute.
_test = Any
def _x_changed(self, value):
self._test = value.copy()
This automatically builds the shadow _x trait and always calls back
_x_changed. The ShadowProperty can be made smarter so it optionally
checks to see if the value changed and only then fire the handler but
thats easy to do. I'll likely do it. I think this is a common enough
use case this solves (the shadow getter/setter stuff) that this may be a
worthy addition to traits. Maybe it is already there somewhere?
cheers,
prabhu
from enthought.traits.api import (TraitType, Instance, CTrait)
from enthought.traits.traits import trait_cast
import numpy
class ShadowProperty(TraitType):
trait_type = Instance(CTrait)
def __init__(self, trait_type, **metadata):
self.trait_type = trait_cast(trait_type)
super(ShadowProperty, self).__init__(**metadata)
def validate(self, object, name, value):
value = self.trait_type.validate(object, name, value)
return value
def get(self, object, name):
shadow = self._get_shadow(name)
d = object.__dict__
if shadow in d:
return d[shadow]
else:
return None
def set(self, object, name, value):
old = self.get(object, name)
shadow = self._get_shadow(name)
object.__dict__[shadow] = value
# Fire a trait property changed.
object.trait_property_changed(name, old, value)
def _get_shadow(self, name):
return '_' + name
# -------------- test ---
from enthought.traits.api import HasTraits, Either, Array, Any, TraitError
import unittest
ArrayOrNone = Either(None, Array)
class Data(HasTraits):
x = ShadowProperty(ArrayOrNone)
# Test attribute.
_test = Any
def _x_changed(self, value):
self._test = value.copy()
class TestShadowProperty(unittest.TestCase):
def test_shadow_property(self):
"Test if the shadow property trait type works correctly."
x = numpy.linspace(0, 1)
d = Data(x=x)
self.assertEqual(numpy.all(d.x == x), True)
self.assertEqual(numpy.all(d._x == x), True)
self.assertEqual(numpy.all(d._test == x), True)
x *= 2
d.x = x
self.assertEqual(numpy.all(d.x == x), True)
self.assertEqual(numpy.all(d._x == x), True)
self.assertEqual(numpy.all(d._test == x), True)
def test_type_checking(self):
"Test if the validation works correctly."
x = numpy.linspace(0, 1)
d = Data(x=x)
self.assertRaises(TraitError, d.__setattr__, 'x', 'hey')
if __name__ == '__main__':
unittest.main()
_______________________________________________ Enthought-dev mailing list Enthought-dev@... https://mail.enthought.com/mailman/listinfo/enthought-dev
RSS Feed