11from functools import wraps
2- from typing import Any , Callable , Coroutine , Sequence , Type , TypeVar , cast
2+ from typing import Any , Callable , Coroutine , Type , TypeVar
33
44from fastapi import APIRouter , Response
55from fastapi .types import DecoratedCallable
66from loguru import logger
77from pydantic import BaseModel
88
9+ from app .exceptions .router import RouterTypeError
910from app .schemas .responses import APIResponse
1011
1112T = TypeVar ("T" , bound = BaseModel )
@@ -15,8 +16,9 @@ class CoreAPIRouter(APIRouter):
1516 def api_route ( # type: ignore
1617 self ,
1718 path : str ,
18- * args ,
19- response_model : Type [T ] | Type [Response ],
19+ * ,
20+ response_model : Type [T ],
21+ response_class : Type [Response ],
2022 status_code : int ,
2123 ** kwargs ,
2224 ) -> Callable [
@@ -27,30 +29,58 @@ def decorator(
2729 func : DecoratedCallable ,
2830 ) -> Callable [..., Coroutine [Any , Any , APIResponse [T ] | Response ]]:
2931 @wraps (func )
30- async def success (
32+ async def endpoint (
3133 * _args : tuple , ** _kwargs : dict
3234 ) -> APIResponse [T ] | Response :
3335 response : Any = await func (* _args , ** _kwargs )
34- # FIXME: 우선 response_model이 List와 같은 Sequence로 구성된 경우는 차후에 해결 (#24)
35- if isinstance (response , Sequence ):
36- pass
37- elif not isinstance (response , response_model ):
38- logger .warning (f"{ type (response )} : { response } " )
39- raise TypeError
40- if isinstance (response , (BaseModel , Sequence )):
41- return APIResponse [T ].success (
42- status = status_code , data = cast (T , response )
36+ if isinstance (response , response_class ):
37+ return response
38+ if isinstance (response , tuple ):
39+ # NOTE: 아래 두 변수는 차후 사용 시 추가
40+ # media_type: str | None = None,
41+ # background: BackgroundTask | None = None,
42+ content , headers = response
43+ return response_class (
44+ content = APIResponse [response_model ] # type: ignore[valid-type]
45+ .success (
46+ status = status_code ,
47+ data = content ,
48+ )
49+ .model_dump (mode = "json" ),
50+ status_code = status_code ,
51+ headers = headers ,
4352 )
44- return response
53+ if isinstance (response , (BaseModel , list )):
54+ return response_class (
55+ content = APIResponse [response_model ] # type: ignore[valid-type]
56+ .success (
57+ status = status_code ,
58+ data = response ,
59+ )
60+ .model_dump (mode = "json" ),
61+ status_code = status_code ,
62+ )
63+ logger .error (f"{ type (response )} : { response } " )
64+ raise RouterTypeError
4565
46- self .add_api_route (
47- path ,
48- success ,
49- * args ,
50- response_model = APIResponse [T ],
51- status_code = status_code ,
52- ** kwargs ,
53- )
54- return success
66+ if response_model is None :
67+ self .add_api_route (
68+ path = path ,
69+ endpoint = endpoint ,
70+ response_model = response_model ,
71+ response_class = response_class ,
72+ status_code = status_code ,
73+ ** kwargs ,
74+ )
75+ else :
76+ self .add_api_route (
77+ path = path ,
78+ endpoint = endpoint ,
79+ response_model = APIResponse [response_model ], # type: ignore[valid-type]
80+ response_class = response_class ,
81+ status_code = status_code ,
82+ ** kwargs ,
83+ )
84+ return endpoint
5585
5686 return decorator
0 commit comments