ipython / traitlets

A lightweight Traits like module
https://traitlets.readthedocs.io/
BSD 3-Clause "New" or "Revised" License
612 stars 200 forks source link

Should there be a way to disable trait notifications? #907

Open loicdtx opened 1 month ago

loicdtx commented 1 month ago

I recently had to completely disable trait notification during instantiation of a HasTraits child class. Holding with hold_trait_notifications wasn't sufficient; the notifications release when exiting the context manager was modifying attributes I didn't want to change.

I used a snippet found in the source code to implement the following context manager.

import contextlib

from traitlets import HasTraits, Bunch

@contextlib.contextmanager
def disable_trait_notifications(self):
    """Temporatilly disable trait notifications."""
    def ignore(change: Bunch) -> None:
        pass
    original_notify_change = self.notify_change
    self.notify_change = ignore
    try:
        yield
    finally:
        self.notify_change = original_notify_change

# Monkey patch HasTraits
HasTraits.disable_trait_notifications = disable_trait_notifications

Wondering if it would make sense to have this as part of the API. Hope I'm not suggesting an anti pattern :sweat_smile:

rmorshea commented 1 month ago

One relatively straightforward way to enable this behavior would be for hold_trait_notifications to yield the "cache" of notifications received during the context. Implementing a mute_trait_notifications method would then just involve calling cache.clear() before the context exited:

with obj.hold_trait_notifications() as cache:
    ...  # do stuff
    cache.clear()

I'm not currently an active maintainer, but I don't think a change like this would be very controversial if you wanted to make a PR - very small and backwards compatible. We'd just want a test to ensure that future changes to hold_trait_notifications() don't break this expectation about being able to mute notifications.