Coverage for opt/mealie/lib/python3.12/site-packages/mealie/schema/make_dependable.py: 61%

16 statements  

« prev     ^ index     » next       coverage.py v7.10.6, created at 2025-11-25 17:29 +0000

1from inspect import signature 1a

2 

3from fastapi.exceptions import HTTPException, RequestValidationError 1a

4from pydantic import ValidationError 1a

5 

6 

7def format_exception(ex: Exception) -> str: 1a

8 return f"{ex.__class__.__name__}: {ex}" 

9 

10 

11def make_dependable(cls): 1a

12 """ 

13 Pydantic BaseModels are very powerful because we get lots of validations and type checking right out of the box. 

14 FastAPI can accept a BaseModel as a route Dependency and it will automatically handle things like documentation 

15 and error handling. However, if we define custom validators then the errors they raise are not handled, leading 

16 to HTTP 500's being returned. 

17 

18 To better understand this issue, you can visit https://github.com/tiangolo/fastapi/issues/1474 for context. 

19 

20 A workaround proposed there adds a classmethod which attempts to init the BaseModel and handles formatting of 

21 any raised ValidationErrors, custom or otherwise. However, this means essentially duplicating the class's 

22 signature. This function automates the creation of a workaround method with a matching signature so that you 

23 can avoid code duplication. 

24 

25 usage: 

26 async def fetch(thing_request: ThingRequest = Depends(make_dependable(ThingRequest))): 

27 """ 

28 

29 def init_cls_and_handle_errors(*args, **kwargs): 1a

30 try: 

31 signature(init_cls_and_handle_errors).bind(*args, **kwargs) 

32 return cls(*args, **kwargs) 

33 except (ValidationError, RequestValidationError) as e: 

34 for error in e.errors(): 

35 error["loc"] = ["query", *list(error["loc"])] 

36 raise HTTPException(422, detail=[format_exception(ex) for ex in e.errors()]) from None 

37 

38 init_cls_and_handle_errors.__signature__ = signature(cls) 1a

39 return init_cls_and_handle_errors 1a