class Action[ReqT, RespT](Protocol):
name: str
request_schema: Type[ReqT] # тип который мы будем принимать
response_schema: Type[RespT] # тип который мы будем возвращать
interact: Callable[[ReqT], Coroutine[Any, Any, RespT]]
def create_action_handler(action: Action):
# какой-то код
async def action_endpoint(entity_id: int, data: dict[str, Any]) -> Any:
# какой-то код
return await action.interact(server, data)
return action_endpoint
def add_action_route(router: APIRouter, action: Action):
handler = create_action_handler(action)
router.post(
f"/plugins/{action.name}",
response_model=action.response_schema, # установим схему для ответа
)(handler)
Схему для ответа я установил при регистрации нашего эндпоинта в
response_model
. А что делать с data
, тип которого должен быть не dict[str, Any]
а action.request_schema
handler = create_action_handler(action)
handler.__annotations__["data"] = action.request_schema
Но это не помогло - аннотации поменялись, а вот схема - нет
Зная это нам остается только одно - изменить signature перед регистрацией роута
sig = inspect.signature(handler) # достаем сигнатуру
new = []
for p in sig.parameters.values():
if p.name == "data": # находим нашу data
p = p.replace(annotation=action.request_schema) # меняем
new.append(p)
handler.__signature__ = sig.replace(parameters=new) # записываем новую сигнатуру
Вуаля! Теперь в OpenAPI будет указанная в
action.request_schema
схема #fastapi #рецепт
Please open Telegram to view this post
VIEW IN TELEGRAM
🤯4🔥3