Package: pyeventdispatcher
PyEventDispatchermasterdevelopPyPIPythonLicencePyEventDispatcher allows your application components to communicate with each
other by sending events and listening to them.
Inspiration for this library was Symfony'sevent-dispatchercomponent.DisclaimerLibrary is in very early stage of development. A lot of things can change or might not work as expected, which includes breaking changes.Easiest examplefrompyeventdispatcherimportdispatch,Event,registerregister("foo.bar",lambdaevent:print(f"{event.name}::{event.data}"))dispatch(Event("foo.bar","some data"))# foo.bar::some dataInstallationpipinstallpyeventdispatcherListenersAnycallablecan be registered as listener,
the only requirements is that it takes one parameter,event.Below function is simplest example of listener you can define:defmy_listener(event):print(event.name)Registering global listenerThere is several ways of registering your global listener, you can mix styles or keep one across whole application.registerfunctionfrompyeventdispatcherimportregisterdefmy_func(event):print(event.name)register("foo.bar",my_func)register("bar.foo",my_func,-100)listendecoratorfrompyeventdispatcherimportlisten@listen("foo.bar",("bar.foo",-100))defmy_func(event):print(event.name)By extendingEventSubscriberclassfrompyeventdispatcherimportEventSubscriber,register_event_subscribersclassMySubscriber(EventSubscriber):EVENTS={"foo.bar":"execute_one","bar.foo":("execute_two",-100)}@staticmethoddefexecute_one(event):print(event.name)@staticmethoddefexecute_two(event):print(event.name)register_event_subscribers()# Register your classesLocal listenersIn most of the cases your application will only need one global registration of listeners that is used across
whole application.Buf if you need, you can initialise as many instances of EventDispatcher as you wish. Everyone of them will have
local registry of listeners.frompyeventdispatcherimportEventDispatcher,register# Register listener in  global registryregister("foo.bar",lambdaevent:print("global listener"))# Initialise instances of local EventDispatcherpy_event_dispatcher_1=EventDispatcher()py_event_dispatcher_1.register("foo.bar",lambdaevent:print("event dispatcher 1"))py_event_dispatcher_2=EventDispatcher()py_event_dispatcher_2.register("foo.bar",lambdaevent:print("event dispatcher 2"))Registering listeners with execution priorityListeners are executed in order of priority parameter's value, which by default is set to "0".You can change priority of registered listener to define in which order it will be executed.frompyeventdispatcherimportregisterregister("foo.bar",lambdaevent:print("second"))register("foo.bar",lambdaevent:print("first "),-100)# first secondDispatching an eventWhen you dispatch your event, every registered listener that listens for occurrence of specified event,
will be called with event object as parameter.Dispatching global eventfrompyeventdispatcherimportdispatch,Event,registerregister("foo.bar",lambdaevent:print(event.name))dispatch(Event("foo.bar",{"id":1}))Dispatching local eventfrompyeventdispatcherimportEventDispatcher,Event,registerregister("foo.bar",lambdaevent:print(f"{event.name}::global"))# Initialise separated instancepy_event_dispatcher=EventDispatcher()py_event_dispatcher.register("foo.bar",lambdaevent:print(f"{event.name}::local"))# Dispatch event to both global and local listenerspy_event_dispatcher.dispatch(Event("foo.bar"))# foo.bar::global# foo.bar::local# Dispatch event to local listeners onlypy_event_dispatcher.dispatch(Event("foo.bar"),False)# foo.bar::localStopping propagationSometimes you might want to stop propagation of event, for that you just have to setevent.stoptoTrue,In example below onlyfirst_listenerwill be executed.frompyeventdispatcherimportregisterdeffirst_listener(event):event.stop=Trueprint("first_listener")defsecond_listener(event):print("first_listener")register("foo.bar",first_listener)register("foo.bar",second_listener)# first_listener