Package: signalbus
SignalbusSimple and small library to broadcast signals with typing supportFeatures:Async supportFull typing support (get errors)Small (around 100 lines of code) and fastYou may incapsulate some logic inside a signalWhy another library?Other signals library don't have a good typing support.Installation$ pip install signalbusUsagefromsignalbusimportcreate_signal# Create a signals# Just define a (generator) function and wrap it with `signalbus.create_signal`@create_signaldeforder_changed(order_status:str,*,order_id:int):#"""The function contains the signal code.Feel free to do some operations before and after the sending.Pay attention to the function's paramsAll receivers for the signal have to be able to accept the same params.Typing libraries will show you errors."""# first, you have to get `emit` to be able to send the signalemit=yield# then send the signal to the receivers (you may want to skip it in some cases)res:list=emit(order_status,order_id=order_id)# you may check the results, do some additional work, etc# Register a receiver for the signal# The receiver has to have the same params (types will be checked)@order_changed.registerdefnotify_user(order_status:str,*,order_id:int):...@order_changed.registerdefupdate_stats(order_status:str,*,order_id:int):...# To send the signal just call it like a function with all required paramsorder_changed('done',order_id=42)Async SignalsEverything is almost the same except async/awaitfromsignalbusimportcreate_signal@create_signalasyncdeforder_changed(order_status:str,*,order_id:int):emit=yieldres:list=awaitemit(order_status,order_id=order_id)# Receiver has to be async too@order_changed.registerasyncdefnotify_user(order_status:str,*,order_id:int):...@order_changed.registerasyncdefupdate_stats(order_status:str,*,order_id:int):...# Do not forget to await the signalawaitorder_changed('done',order_id=42)Filter signals by argumentsYou may set any arguments to filter a receiver with the register function. The
receiver would be called only when corresponding arguments match.Let's consider the following example:fromsignalbusimportcreate_signal@create_signalasyncdeforder_changed(order_status:str,*,order_id:int):emit=yieldres:list=awaitemit(order_status,order_id=order_id)# pay attention to that we define an attribute in register@order_changed.register('done')asyncdefnotify_user(order_status:str,*,order_id:int):...@order_changed.registerasyncdefupdate_stats(order_status:str,*,order_id:int):...awaitorder_changed('done',order_id=42)# both the receivers above will be calledawaitorder_changed('cancel',order_id=42)# only update stats will be calledMypy supportFor better typing with mypy, you have to set correct returning type for your signals:fromsignalbusimportcreate_signalfromtypingimportGenerator,AsyncGenerator@create_signaldefsync_signal()->Generator:emit=yieldres:list=awaitemit()@create_signalasyncdefasync_signal()->AsyncGenerator:emit=yieldres:list=awaitemit()No need to do it with Pyright, because the Pyright calculates the types correctlyBug trackerIf you have any suggestions, bug reports or annoyances please report them to
the issue tracker athttps://github.com/klen/signalbus/issuesContributingDevelopment of The library happens at:https://github.com/klen/signalbusLicenseLicensed under aMIT license