Get all callbacks associated with a widget

Is there a way to get all callbacks associated with a widget?

My use case is that I need to change the options of a Select widget based on user-interaction. When I make those changes from within the code, I want to disable the callbacks associated with the Select widget I’m changing. I do this by applying the remove_on_change() function, after which I make the changes to the widget, and then I apply the on_change() function to re-add the callback. The callback is a lambda function (since I’m using extra arguments to call the function between the attr, old, new parameters), so I can’t just remove the original name of the function. So, I want to get all callbacks associated with the widget, and remove them all.

I’m able to do this with:

for callback in myWidget._callbacks['value']:
    myWidget.remove_on_change('value', callback)

I’d like to keep to the practice of not calling “private” attributes like _callbacks. However, I don’t see any other way to access them. Is there a method to do this that I’m not seeing?

There isn’t. No-one has ever asked about it before, and in general removing callbacks seems uncommon, so it’s never been a priority (or even thought of, AFAIK). Currently callbacks are removed by value, so if you expect to need to remove them later, then the only supported method would be to store off our own references to them to use to remove later (you can certainly do that, even with the lambdas).

I would definitely not count on the private _callbacks attribute to remain stable. I’ve been doing some fairly intensive refactoring to support maintainability lately, and I will be getting to the callback mixin classes soon. If this use case is important to you, I’d suggest making a GitHub development discussion about it. E.g. it’s possible that on_change could return handles that could stored and used later for removal, instead of needing to remove the callback by value. Or at a minimum, supported API for exposing all the callbacks.

The other present alternative is to simply add a single “controller” callback and have that one callback do or not do whatever you need to happen, as appropriate.

Ah, I didn’t think about defining lambdas that call the callbacks as their own named function. That will do the trick.