enthought/traits — pull request #79 by pberkes (2013-09-25 20:56:06+00:00)
Title: Refactor traits notifiers; add trait change event hooks

* Completely cover the traits notification code with tests
* Refactor the notification code to remove code duplication and get rid of the never ending sequence of `code_0`, `code_1`, ... methods
* Add hooks to trace global trait change notification events

This is a major refactoring of the traits notification system, made to add a single feature: the possibility to add hooks to listen to dispatched events.

Although this might seem a minor feature, it turns out to be very useful during testing and debugging. With a prototype version of this I was able to detect a cycle in trait notifications that was making my application very slow. The hooks could also be used to collect information during runtime and create a graph of object dependencies based on change emitters and listeners.

For example, this code:
https://gist.github.com/pberkes/6705859

produces this output:
```
--> 'baz' changed from 0.0 to 4.0 in 'Foo'
CALLING: '_on_baz_change_notification' in change_events_hooks_example.py
----> 'bar' changed from 3.0 to 4.0 in 'Foo'
CALLING: '_bar_changed' in change_events_hooks_example.py
<---- EXIT: '_bar_changed'
----> 'bar' changed from 3.0 to 4.0 in 'Foo'
CALLING: '_on_bar_change_notification' in change_events_hooks_example.py
<---- EXIT: '_on_bar_change_notification'
<-- EXIT: '_on_baz_change_notification'

--> 'fuz' changed from 0.0 to 7.0 in 'Foo'
CALLING: '_on_fuz_change_notification' in change_events_hooks_example.py
----> 'bar' changed from 4.0 to 5.0 in 'Foo'
CALLING: '_bar_changed' in change_events_hooks_example.py
<---- EXIT: '_bar_changed'
----> 'bar' changed from 4.0 to 5.0 in 'Foo'
CALLING: '_on_bar_change_notification' in change_events_hooks_example.py
<---- EXIT: '_on_bar_change_notification'
<-- EXIT: '_on_fuz_change_notification' [EXCEPTION: Crash]

Exception occurred in traits notification handler.
Please check the log file for details.
Exception occurred in traits notification handler for object: <__main__.Foo object at 0x100768950>, trait: fuz, old value: 0.0, new value: 7.0
Traceback (most recent call last):
File "/Users/pberkes/egit/meta-geophysics/meta-ETS/traits/traits/trait_notifiers.py", line 515, in _dispatch_change_event
self.dispatch( handler, *args )
File "/Users/pberkes/egit/meta-geophysics/meta-ETS/traits/traits/trait_notifiers.py", line 478, in dispatch
handler( *args )
File "change_events_hooks_example.py", line 82, in _on_fuz_change_notification
raise Exception('Crash')
Exception: Crash
```

Showing the nested chain of events triggered by a traits change.