Package: backend-utils
backend-utilsUseful python tools for backend servicesDocumentationToolsSingleton- metaclass to make singletonsfrombackend_utils.toolsimportSingletonclassA(metaclass=Singleton):passprint(id(A())==id(A()))# TrueStrEnum- subclasses that create variants usingauto()will have values equal to their namesfromenumimportautofrombackend_utils.toolsimportStrEnumclassBit(StrEnum):one=auto()two=auto()print(Bit.one.value)# 'one'print(Bit.two.value)# 'two'ServerRouter,compile_routers,register_routers- build routers
for fastapi appfromfastapiimportFastAPI,APIRouterfrombackend_utils.serverimport(Router,compile_routers,register_routers)router=APIRouter()routers=[Router(router=router,tags=['Users'],prefix='/users'),]compiled_routers=compile_routers(routers=routers,root_prefix='/api/v1')app=FastAPI()register_routers(app=app,routers=[*compiled_routers])This code will compile routers:/api/v1/users/*HttpRequestMethods- enum for http methodsBaseRequester- base class for http clients. You can specifyURL,TIMEOUT,MIDDLEWARE.
Useself.make_request()to make http requestsimportosimportasynciofromtypingimportOptionalimporthttpxfrombackend_utils.httpimportBaseRequester,RequestMethodsclassJsonPlaceholder(BaseRequester):URL=os.getenv('JSONPLACEHOLDER_URL','https://jsonplaceholder.typicode.com')TIMEOUT=10asyncdefget_todo(self,todo_id:int)->Optional[httpx.Response]:returnawaitself.make_request(method=RequestMethods.GET,uri=f'/todos/{todo_id}',)if__name__=='__main__':jp=JsonPlaceholder()asyncio.run(jp.get_todo(todo_id=1))You also can validate response with pydantic modelsimportosimportasynciofromtypingimportOptionalfrompydanticimportBaseModel,Fieldfrombackend_utils.httpimportBaseRequester,RequestMethodsclassGetTodo(BaseModel):user_id:int=Field(...,alias='userId')id:inttitle:strcompleted:boolclassJsonPlaceholder(BaseRequester):asyncdefget_todo_model(self,todo_id:int)->Optional[GetTodo]:url=os.getenv('JSONPLACEHOLDER_URL','https://jsonplaceholder.typicode.com')returnawaitself.make_request(method=RequestMethods.GET,url=f'{url}/todos/{todo_id}',response_model=GetTodo,timeout=5.5)if__name__=='__main__':jp=JsonPlaceholder()asyncio.run(jp.get_todo_model(todo_id=1))So it will returnGetTodomodel orNoneif request failedBaseMiddleware- base class for http request middleware.
Available methods:before_request(self, request: httpx.Request)after_request(self, request: httpx.Request, response: httpx.Response):on_request_error(self, request: httpx.Request, error: httpx.HTTPError)on_request_status_error(self, request: httpx.Request)on_validation_error(self, response: httpx.Response, error: [ValidationError, json.decoder.JSONDecodeError])For example middleware to print request timeimportosimporttimeimportasynciofromtypingimportOptionalimporthttpxfrombackend_utils.httpimportBaseRequester,RequestMethods,BaseMiddlewareclassPrintRequestTime(BaseMiddleware):asyncdefbefore_request(self,request:httpx.Request):request.start_time=time.perf_counter()asyncdefafter_request(self,request:httpx.Request,response:httpx.Response):request_time=time.perf_counter()-request.start_timeprint(request_time)classJsonPlaceholder(BaseRequester):URL=os.getenv('JSONPLACEHOLDER_URL','https://jsonplaceholder.typicode.com')MIDDLEWARES=[PrintRequestTime()]asyncdefget_todo(self,todo_id:int)->Optional[httpx.Response]:returnawaitself.make_request(method=RequestMethods.GET,uri=f'/todos/{todo_id}',)if__name__=='__main__':jp=JsonPlaceholder()asyncio.run(jp.get_todo(todo_id=1))