|
| 1 | +.. _global-dispatcher: |
| 2 | + |
| 3 | +Global Dispatcher |
| 4 | +================= |
| 5 | + |
| 6 | +.. currentmodule:: pydispatch |
| 7 | + |
| 8 | +.. versionadded:: 0.2.2 |
| 9 | + |
| 10 | +At the module-level, most of the functionality of :class:`~.dispatch.Dispatcher` |
| 11 | +can be used directly as a `singleton`_ instance. Note that this interface only |
| 12 | +supports event dispatching (not :ref:`properties`). |
| 13 | + |
| 14 | +When used this way, the concept is similar to the `Signals Framework`_ found in Django. |
| 15 | + |
| 16 | +Basic Usage |
| 17 | +----------- |
| 18 | + |
| 19 | +Events can be registered using :func:`register_event`, connected to callbacks |
| 20 | +using :func:`bind` and dispatched with the :func:`emit` function. |
| 21 | + |
| 22 | +>>> import pydispatch |
| 23 | + |
| 24 | +>>> def my_callback(message, **kwargs): |
| 25 | +... print(f'my_callback: "{message}"') |
| 26 | + |
| 27 | +>>> # register 'event_a' as an event and bind it to my_callback |
| 28 | +>>> pydispatch.register_event('event_a') |
| 29 | +>>> pydispatch.bind(event_a=my_callback) |
| 30 | + |
| 31 | +>>> # emit the event |
| 32 | +>>> pydispatch.emit('event_a', 'hello') |
| 33 | +my_callback: "hello" |
| 34 | + |
| 35 | +>>> # unbind the callback |
| 36 | +>>> pydispatch.unbind(my_callback) |
| 37 | +>>> pydispatch.emit('event_a', 'still there?') |
| 38 | + |
| 39 | +>>> # (Nothing printed) |
| 40 | + |
| 41 | + |
| 42 | +The @receiver Decorator |
| 43 | +----------------------- |
| 44 | + |
| 45 | +To simplify binding callbacks to events, the :func:`~decorators.receiver` decorator may be used. |
| 46 | + |
| 47 | +>>> from pydispatch import receiver |
| 48 | + |
| 49 | +>>> @receiver('event_a') |
| 50 | +... def my_callback(message, **kwargs): |
| 51 | +... print(f'my_callback: "{message}"') |
| 52 | + |
| 53 | +>>> pydispatch.emit('event_a', 'hello again!') |
| 54 | +my_callback: "hello again!" |
| 55 | + |
| 56 | +Note that there is currently no way to :func:`unbind` a callback defined in this way. |
| 57 | + |
| 58 | + |
| 59 | +Arguments |
| 60 | +^^^^^^^^^ |
| 61 | + |
| 62 | +If the event name has not been registered beforehand, the ``cache`` and ``auto_register`` |
| 63 | +arguments to :func:`~decorators.receiver` may be used |
| 64 | + |
| 65 | +cache |
| 66 | +""""" |
| 67 | + |
| 68 | +The ``cache`` argument stores the callback and will bind it to the event |
| 69 | +once it is registered. |
| 70 | + |
| 71 | +>>> # No event named 'foo' exists yet |
| 72 | +>>> @receiver('foo', cache=True) |
| 73 | +... def on_foo(message, **kwargs): |
| 74 | +... print(f'on_foo: "{message}"') |
| 75 | + |
| 76 | +>>> # on_foo will be connected after the call to register_event |
| 77 | +>>> pydispatch.register_event('foo') |
| 78 | +>>> pydispatch.emit('foo', 'bar') |
| 79 | +on_foo: "bar" |
| 80 | + |
| 81 | +auto_register |
| 82 | +""""""""""""" |
| 83 | + |
| 84 | +The ``auto_register`` argument will immediately register the event if it does not exist |
| 85 | + |
| 86 | +>>> @receiver('bar', auto_register=True) |
| 87 | +... def on_bar(message, **kwargs): |
| 88 | +... print(f'on_bar: "{message}"') |
| 89 | + |
| 90 | +>>> pydispatch.emit('bar', 'baz') |
| 91 | +on_bar: "baz" |
| 92 | + |
| 93 | + |
| 94 | +Async Support |
| 95 | +^^^^^^^^^^^^^ |
| 96 | + |
| 97 | +If the decorated callback is a :term:`coroutine function` or method, |
| 98 | +the :class:`EventLoop <asyncio.BaseEventLoop>` returned by |
| 99 | +:func:`asyncio.get_event_loop` will be used as the ``loop`` argument to |
| 100 | +:func:`bind_async`. |
| 101 | + |
| 102 | +This will in most cases be the desired behavior unless multiple event loops |
| 103 | +(in separate threads) are being used. |
| 104 | + |
| 105 | + |
| 106 | + |
| 107 | +.. _singleton: https://en.wikipedia.org/wiki/Singleton_pattern |
| 108 | +.. _Signals Framework: https://docs.djangoproject.com/en/4.2/topics/signals/ |
0 commit comments