Package: mediatr
mediatr_pyThis is an async implementation of Mediator pattern with pipline behaviors.It is a port ofMediatrfrom .Net C#Requirements:Python >= 3.6Usage:installmediatr:pip install mediatrDefine your request classclassGetArrayQuery():def__init__(self,items_count:int):self.items_count=items_countDefine your handler class or functionimportMediatorfrommediatr@Mediator.handlerasyncdefget_array_handler(request:GetArrayQuery):items=list()foriinrange(0,request.items_count):items.append(i)returnitems# or just Mediator.register_handler(get_array_handler)or class:@Mediator.handlerclassGetArrayQueryHandler():defhandle(self,request:GetArrayQuery):items=list()foriinrange(0,request.items_count):items.append(i)returnitems# or just Mediator.register_handler(GetArrayQueryHandler)Run mediatorimportMediatorfrommediatrmediator=Mediator()request=GetArrayQuery(5)result=awaitmediator.send_async(request)# result = mediator.send(request) in synchronous modeprint(result)//[0,1,2,3,4]If you are using synchronousmediator.send(request)method, try to define synchronous handlers and behaviorsIn another case useasynciomodule for manual manage of event loop in synchronous codeRun mediator statically, without instanceimportMediatorfrommediatrrequest=GetArrayQuery(5)result=awaitMediator.send_async(request)# or:result=Mediator.send(request)#in synchronous mode. Async handlers and behaviors will not blocking!print(result)//[0,1,2,3,4]Note that instantiation ofMediator(handler_class_manager = my_manager_func)is useful if you have custom handlers creation. For example using an injector.
By default class handlers are instantiated with simple init:SomeRequestHandler(). handlers or behaviors as functions are executed directly.Using behaviorsYou can define behavior class with method 'handle' or function:@Mediator.behaviorasyncdefget_array_query_behavior(request:GetArrayQuery,next):#behavior only for GetArrayQuery or derived classesarray1=awaitnext()array1.append(5)returnarray1@Mediator.behaviordefcommon_behavior(request:object,next):#behavior for all requests because issubclass(GetArrayQuery,object)==Truerequest.timestamp='123'returnnext()# ...mediator=Mediator()request=GetArrayQuery(5)result=awaitmediator.send_async(request)print(result)//[0,1,2,3,4,5]print(request.timestamp)//'123'Using custom handler (behavior) factory for handlers (behaviors) as classesIf your handlers or behaviors registered as functions, it just executes them.In case with handlers or behaviors, declared as classes with methodhandleMediator uses function, that instantiates handlers or behaviors:defdefault_handler_class_manager(HandlerCls:type,is_behavior:bool=False):returnHandlerCls()For example, if you want to instantiate them with dependency injector or custom, pass your own factory function to Mediator:defmy_class_handler_manager(handler_class,is_behavior=False):ifis_behavior:# custom logicpassreturninjector.get(handler_class)mediator=Mediator(handler_class_manager=my_class_handler_manager)PS:Thenextfunction in behavior isasync, so if you want to take results or if your behavior is async, usemiddle_results = await next()Handler may be async too, if you need.Using with generic typing support (version >= 1.2):frommediatrimportMediator,GenericQueryclassUserModel(BaseModel):# For example sqlalchemy ORM entityid=Column(String,primary_key=True)name=Column(String)classFetchUserQuery(GenericQuery[UserModel])def__init__(self,user_id:str):self.user_id=user_idmediator=Mediator()request=FetchUserQuery(user_id="123456")user=mediator.send(request)# type of response will be a UserModel# -------------------------------------------------------------classFetchUserQueryHandler():defhandle(self,request:FetchUserQuery):db_session=Session()#sqlalchemy sessionreturndb_session.query(UserModel).filter(UserModel.id==request.user_id).one()# or handler as simple function:deffetch_user_query_handler(request:FetchUserQuery):db_session=Session()#sqlalchemy sessionreturndb_session.query(UserModel).filter(UserModel.id==request.user_id).one()Please give a star if the library is useful for you :smiley: