Observer pattern does not work using a widget

this is a resolved issue on Github so i’m obviously just being slow…

but i’m trying to watch a widget using the @observe decorator and can’t seem to get it working…

from traitlets import HasTraits, observe, Int, Unicode, Instance
import ipywidgets as widgets
class Foo(HasTraits):
    bar = Instance(klass=widgets.IntText, default_value=widgets.IntText())
    baz = Unicode()

    @observe('bar', "value")
    def _observe_bar(self, change):
        print('asdfasdf')
        print(change['old'])
        print(change['new'])
f = Foo()

then when i change the value of bar,

f.bar.value = 4

the observer isn’t called…

what am i missing?

thanks in advance

1 Like

That @observe is looking for two different traits on Foo, bar (which exists) and value) which does not.

If you wish to observe bar.value, and bar can change, your bar observer needs to delegate the value observing to the new bar instance (and clean up any old handlers)

    @observe("bar")
    def _observe_bar(self, change):
         if change.old:
             change.old.unobserve(self._on_bar_value, ["value"])
         if change.new:
             change.new.observe(self._on_bar_value, ["value"])
    
    def _on_bar_value(self, change):
        print('asdfasdf')
        print(change['old'])
        print(change['new'])
1 Like

thanks for the response -

i wish to watch bar.value, and bar cannot change. (i.e. use the decorator to watch the nested trait)

though it looks like this isn’t supported / isn’t the intended use case?

use the decorator to watch the nested trait

The API does not support that.

https://traitlets.readthedocs.io/en/stable/api.html#traitlets.observe

great - thanks very much for your help!