☰Read-only archive⌕
Looking for help with Bokeh?

This is a read-only archive. Ask questions and join the conversation on GitHub.

Visit Community Support on GitHub →
Archived discussions · Captured October 28, 2026

Boomerang update avoidance

Community Support
Steve_Maxwell
Steve_Maxwell

Hi, I’m unclear on exactly what object to give the setter property of a widget when avoiding “boomerang” updates. In particular, I have a server-side function that checks on the state of a variable that is not part of the bokeh app and then uses the update method to synchronize the state of a toggle.

To avoid triggering my_toggle.on_change, I think I need to acquire my_server_session and use it in:

doc.add_next_tick_callback(lambda: my_toggle.update(active=False,setter=my_server_session))

Is that right? And if so, how is my_server_session acquired?
Thanks!

⌁   Link to post
Bryan
Bryan

setter is a deep implementation detail and should really never be used or set by users directly. It may even go away in the future. This is why there essentially no documentation for it. Callbacks for widgets can be removed, so your best approach is probably to remove the callback that you don’t want to fire, make your update, and then add it back.

⌁   Link to post
Steve_Maxwell
Steve_Maxwell

Thanks, @Bryan. I wonder if adding a context manager to bokeh like

with suspend_callbacks(my_widget):
   mess_with_my_widget_state()

would be a good idea?

where the context manager is defined by

class suspend_callbacks(object):
    def __init__(self, my_widget):
        self._widget = my_widget

    def __enter__(self):
        self._suspended_callbacks = self._widget._callbacks.copy() # not sure if copy required...
        self._widget._callbacks = {} #delete all callbacks from widget


    def __exit__(self,exc_type, exc_value, exc_traceback):
        self._widget._callbacks = self._suspended_callbacks.copy() # restore callbacks again, not sure re copy

I implemented this in my code and it seems to work, although it is accessing a private variable and I’m sure there’s a way to do it that’s more consistent with your user-facing api.

⌁   Link to post
Bryan
Bryan

Context manager seems nice but I would try to use remove_on_change rather than mucking with _callbacks directly. Private attrs might be changed at any point in the future, so just FYI. If you need to use _callbacks for now I would advise to open a GitHub Issue so we can consider what minimal public supported API additions might be warranted to help with this situation.

⌁   Link to post
_jm
_jm

Not sure if this would work in your use case, but I leveraged the tags property on a shared data source among widgets to provide conceptually similar control in one of my apps.

Here’s snippet of a relevant part of a callback in case it helps.

    def radial_eq_cb(self, attr, old, new):
        """Set radial equalizer
        """
        _methodname = self.radial_eq_cb.__name__

        s = self.equalizer().ui.sources.radial

        if s.tags:
            s.tags = []
            return

        s.tags = ['cb']

        if new:
            c = new[0] // self.equalizer().num_levels
            if c < self.equalizer().num_eq:
                # Set selected equalizer
                self.equalizer().sel0[c] = new[0]
                eq_index = new[0] % self.equalizer().num_levels
⌁   Link to post

End of archived discussion · Replies are disabled