pallets-eco / blinker

A fast Python in-process signal/event dispatching system.

Home Page:https://blinker.readthedocs.io

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

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