Picon
Gravatar

[Traits] feature request

Hi Dave Morrill,

I see from the implementation (from trunk) that the CHasTraits class 
defines a _trait_change_notify method that is used in the trait_set 
method to disable/enable notifications.  Unfortunately, there is no way 
to determine from Python if this flag has been set or not.  This is 
needed if you want to create a Property trait that does the right thing 
in its set method.  For example:

class Test(HasTraits):
     x = Property(Float)
     _x = Float
     def _get_x(self):
	return self._x
     def _set_x(self, value):
	old = self._x
	self._x = value
	if old != new:
	    self.trait_property_changed('x', old, new)

Clearly, this will break the trait_set method when 
trait_change_notify=False.  I propose to add a 
_get_trait_change_notify() to the ctraits.c to be able to get this so 
users can write:

  if self._get_trait_change_notify():
      ...

etc. to work around this.

Attached is a working patch with a test case.  This change doesn't break 
any existing code.

Could you please check this in?  Thanks!

Thanks.
prabhu

Index: enthought/traits/ctraits.c
===================================================================
--- enthought/traits/ctraits.c	(revision 21706)
+++ enthought/traits/ctraits.c	(working copy)
@@ -1474,6 +1474,24 @@
 }

 /*-----------------------------------------------------------------------------
+|  Returns whether or not trait change notification is enabled for the object:
++----------------------------------------------------------------------------*/
+
+static PyObject *
+_has_get_traits_change_notify ( has_traits_object * obj, PyObject * args ) {
+ 
+    if ( !PyArg_ParseTuple( args, "" ) )
+        return NULL;
+   
+    if ( ( obj->flags & HASTRAITS_NO_NOTIFY ) == 0 ) {
+        Py_RETURN_TRUE;
+    }
+    else {
+        Py_RETURN_FALSE;
+    }
+}
+
+/*-----------------------------------------------------------------------------
 |  Enables/Disables trait change notifications when this object is assigned to 
 |  a trait:
 +----------------------------------------------------------------------------*/
@@ -1623,6 +1641,9 @@
 	{ "_trait_change_notify", (PyCFunction) _has_traits_change_notify,
       METH_VARARGS,
       PyDoc_STR( "_trait_change_notify(boolean)" ) },
+	{ "_get_trait_change_notify", (PyCFunction) _has_get_traits_change_notify,
+      METH_VARARGS,
+      PyDoc_STR( "_get_trait_change_notify() -> bool" ) },
 	{ "_trait_veto_notify", (PyCFunction) _has_traits_veto_notify,
       METH_VARARGS,
       PyDoc_STR( "_trait_veto_notify(boolean)" ) },
from enthought.traits.api import HasTraits, Float, Property, Int

import unittest

class Test(HasTraits):
    x = Float
    _test = Int(0)
    def _x_changed(self, value):
        self._test += 1

class TestTraitChangeNotify(unittest.TestCase):
    def test_trait_change_notify(self):
        "Test if _get/_trait_change_notify work."
        t = Test()
        t.x = 10.0
        self.assertEqual(t._test, 1)
        self.assertEqual(t._get_trait_change_notify(), True)
        # Turn off notification.
        t._trait_change_notify(False)
        self.assertEqual(t._get_trait_change_notify(), False)
        t.x = 20.0
        self.assertEqual(t._test, 1)
        # Turn it back on.
        t._trait_change_notify(True)
        self.assertEqual(t._get_trait_change_notify(), True)
        t.x = 30.0
        self.assertEqual(t._test, 2)

if __name__ == '__main__':
    unittest.main()
_______________________________________________
Enthought-dev mailing list
Enthought-dev@...
https://mail.enthought.com/mailman/listinfo/enthought-dev

Gmane