Package: pyknot
py-knotThis repository offers a message bus system tailored for integration withpython-dependency-injector. It efficiently manages command and query dispatching and supports dependency injection, enhancing application decoupling, organization, and maintainability.InstallationThe source code is currently hosted on GitHub at:https://github.com/Retr0327/py-knotBinary installers for the latest released version are available at thePython Package Index (PyPI).pippipinstallpyknotpoetrypoetryaddpyknotUsage1. Fundamental ImplementationDefine messages:Create specific command or query messages by extendingCommandorQueryclasses.fromdataclassesimportdataclassfromknotimportCommandReturnType=dict[str,int]@dataclass(slots=True)classTestCommand(Command[ReturnType]):a:intb:intDefine handlers:ImplementCommandHandlerorQueryHandlerfor handling defined messages.fromdataclassesimportdataclassfromknotimportCommand,CommandHandlerReturnType=dict[str,int]@dataclass(slots=True)classTestCommand(Command[ReturnType]):a:intb:intclassTestCommandHandler(CommandHandler[TestCommand]):defhandle(self,message:TestCommand)->ReturnType:...# do somethingRegister handlers:Register handlers toMessageBusby usingregister_handlermethod.fromdataclassesimportdataclassfromknotimport(Command,CommandHandler,MessageBus,register_handlers,)ReturnType=dict[str,int]@dataclass(slots=True)classTestCommand(Command[ReturnType]):a:intb:intclassTestCommandHandler(CommandHandler[TestCommand]):defhandle(self,message:TestCommand)->ReturnType:...# do somethingmessages=register_handlers((TestCommandHandler,))message_bus=MessageBus(messages=messages)Dispatch Messages:UtilizeMessageBusto dispatch messages within your applicationfromdataclassesimportdataclassfromknotimport(Command,CommandHandler,MessageBus,register_handlers,)ReturnType=dict[str,int]@dataclass(slots=True)classTestCommand(Command[ReturnType]):a:intb:intclassTestCommandHandler(CommandHandler[TestCommand]):defhandle(self,message:TestCommand)->ReturnType:...# do somethingmessages=register_handlers((TestCommandHandler,))message_bus=MessageBus(messages=messages)message_bus.dispatch(TestCommand(a=1,b=2))2. Integration with Dependency Injectionplease make sure you have installedpython-dependency-injectorSet Up Dependency Injection Containerfromdataclassesimportdataclassfromdependency_injectorimport(containers,providers,)fromknotimport(Command,CommandHandler,MessageBus,register_handlers,)fromknot.plugins.diimporthandlers_to_factoriesReturnType=dict[str,int]@dataclass(slots=True)classTestCommand(Command[ReturnType]):a:intb:intclassTestCommandHandler(CommandHandler[TestCommand]):defhandle(self,message:TestCommand)->ReturnType:returnmessage.as_dict()messages=register_handlers((TestCommandHandler,))classMessageBusContainer(containers.DeclarativeContainer):message_bus=providers.Singleton(MessageBus,messages=providers.Dict(handlers_to_factories(messages)),)In this container, you'll manage your dependencies, including the message bus. The key function here ishandlers_to_factories, transforming the handlers into factory providers that are compatible with the dependency injection framework.Wire Dependencies and Dispatch CommandWire the dependencies and dispatch commands through the message bus, and inject the message bus to whereever you need it.fromdependency_injector.wiringimportinject,Provide@injectdeftest(message_bus:MessageBus=Provide["message_bus"],):returnmessage_bus.dispatch(TestCommand(a=1,b=2))if__name__=="__main__":container=MessageBusContainer()container.wire(modules=[__name__])test()3. Extension as a Celery Pluginplease ensure that your application is already configured to work withCelerypy-knotcan be extended to work seamlessly withCelery, enabling the dispatching of messages to a task queue. This extension is particularly useful for applications that require asynchronous processing or distributed task execution.ExtendMessageBusfor Celery IntegrationChange:fromknotimportMessageBustofromknot.plugins.celeryimportMessageBusWirequeue_dispatcher_moduleto the DI ContainerWiringqueue_dispatcher_moduleto the DI container makes thedispatch_queuemethod accessible as a dependency.fromdataclassesimportdataclassfromdependency_injectorimport(containers,providers,)fromdependency_injector.wiringimport(Provide,inject,)fromknotimport(Command,CommandHandler,register_handlers,)fromknot.plugins.celeryimport(MessageBus,queue_dispatcher_module,)fromknot.plugins.diimporthandlers_to_factoriesReturnType=dict[str,int]@dataclass(slots=True)classTestCommand(Command[ReturnType]):a:intb:intclassTestCommandHandler(CommandHandler[TestCommand]):defhandle(self,message:TestCommand)->ReturnType:returnmessage.as_dict()messages=register_handlers((TestCommandHandler,))classMessageBusContainer(containers.DeclarativeContainer):message_bus=providers.Singleton(MessageBus,messages=providers.Dict(handlers_to_factories(messages)),)@injectdeftest(message_bus:MessageBus=Provide["message_bus"],):returnmessage_bus.dispatch_queue(TestCommand(a="a",b="b"))if__name__=="__main__":container=MessageBusContainer()container.wire(modules=[__name__,queue_dispatcher_module])test()Contact MeIf you have any suggestion or question, please do not hesitate to email me atretr0327.dev@gmail.com.