Temporarily disable a signal in a block
gergelypolonkai opened this issue · comments
I have an application that generates reports from a bunch of sources. When a report is generated, a Blinker signal report_created
is called, and one of the receivers sends an email to subscribers of that report type.
It sometimes happens, however, that we want to (re/)generate a large amount of reports. In such cases we don’t want email sending to happen. However, if an actual report gets generated meanwhile by the normal means, i want the receiver to be called, so i can’t just disconnect that receiver.
What i could imagine is something like this:
with report_created.disable():
generate_a_lot_of_reports()
As far as i understand, this is not possible in the current Blinker version, but please correct me if i’m wrong. Also, if this use case seems valid (ie. not a unicorn case, when only my project needs it) i’m willing to dig deeper and submit a PR for this.
As a workaround, this seems to work, there might be unexpected side effects, e.g. in a threaded environment:
from contextlib import contextmanager
def disable_signal(signal):
original_receivers = signal.receivers
signal.receivers = {}
try:
yield
finally:
signal.receivers = original_receivers
Done in #84