Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Mypy + FastAPI response_model

I've been tasked with handling the update from Mypy 0.770 to 0.870 in our FastAPI project, and this has produced an error that I can't quite wrap my head around. My endpoint can return two different models based on some condition, and this was denoted as follows the endpont decorator:

@router.get("/", response_model=Union[Model1, Model2])

Mypy 0.870 now complains about this, stating that

Argument "response_model" to "get" of "APIRouter" has incompatible type "object"; expected "Optional[Type[Any]]"

Setting it to single types, such as Model1 or even str removes the error. Any however, does not work.

Now, looking into the get method, I see that the response_model argument is typed as Type[Any], which I assume must be a pointer.

How I can define non-simple return models for my API, and make Mypy happy?

edit: I tried to reproduce the problem in a smaller frame, but couldn't. The following code works fine:

from typing import Any, Type, Union


def test1(var, response_model: Type[Any]):
    print(f"Accepted Type[Any], {var}")

def test2(var, response_model: Union[dict, set]):
    print(f"Accepted Union, {var}")

def main():
    test1('test1', response_model=Union[dict, set])
    test2('test2', response_model=Union[dict, set])

if __name__ == '__main__':
    main()
like image 789
oyblix Avatar asked Nov 07 '22 07:11

oyblix


1 Answers

This is a compatibility issue introduced in newer versions of mypy. There is an open issue on Github about this topic: https://github.com/tiangolo/fastapi/issues/2279

In the discussion they provide the following workarounds:

  • Using a different approach to create a type alias:

    NewModel = TypeVar('NewModel',Model1,Model2)

  • Creating a new Pydantic Model :

    class NewModel(BaseModel):
         __root__: Union[Model1, Model2]
    
like image 181
vianmixt Avatar answered Nov 14 '22 23:11

vianmixt