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

Exceptions prevent all connected receivers from being called.

htoothrot opened this issue · comments

I would like a way of ensuring all receivers are called, even if one misbehaves.

Happy to do a PR if you can give some direction.

Example below (and of course the order of receivers is not specified).

>>> import blinker
... sig = blinker.signal('asignal')
... def a(sender):
...     print (sender)
...     print ('a done')
... def bad(sender):
...     print (sender)
...     1/0
...     print ('never done')
... def c(sender):
...     print (sender)
...     print ('c done')
... sig.connect(a)
... sig.connect(bad)
... sig.connect(c)
... sig.send('THESENDERSTRING')
THESENDERSTRING
a done
THESENDERSTRING
Traceback (most recent call last):
  File "<pyshell#2>", line 16, in <module>
    sig.send('THESENDERSTRING')
  File "D:\Python27\lib\site-packages\blinker\base.py", line 267, in send
    for receiver in self.receivers_for(sender)]
  File "<pyshell#1>", line 8, in bad
    1/0
ZeroDivisionError: integer division or modulo by zero
>>> 

This is very simple to implement. However it's notably absent from Blinker, which otherwise mostly follows the Django signal API at the point when Blinker was born. The reason is that I haven't seen a need for this, or an instance when the quashing & reporting adds value to a design vs failing fast. The omission of send_robust is opinionated design in Blinker.

All that said I'm happy to be shown otherwise, and such a use case could be easily implemented, or at least some refactoring done in the sending code such that a subclass could reasonably implement send_robust on its own.

My use case is one of plugins. A badly behaving plugin should not be able to interfere with another.

That being said, I simply subclassed NamedSignal, reimplemented send(), and then created my own Namespace class which used my RobustNamedSignal.