1

The following examples both work just fine, the only issue is that mypy is complaing about create_operation. Specifically I'm getting these errors:

  • Variable "model" is not valid as a type
  • model? has no attribute "dict"

Especially the second error doesn't make sense to me since pydantic.BaseModel definitely has a dict method. Is there a better way to annotate this?

from typing import Type
from pydantic import BaseModel
from fastapi import FastAPI, testclient

app = FastAPI()
client = testclient.TestClient(app)


class A(BaseModel):
    foo: str


# regular way of creating an endpoint
@app.post("/foo")
def post(data: A):
    assert data.dict() == {"foo": "1"}


# creating an endpoint programmatically
def create_operation(model: Type[BaseModel]):
     @app.post("/bar")
     def post(data: model):
         assert data.dict() == {"foo": "1"}


create_operation(A)

assert client.post("/foo", json={"foo": 1}).status_code == 200
assert client.post("/bar", json={"foo": 1}).status_code == 200
bad_coder
  • 11,289
  • 20
  • 44
  • 72
charlemagne
  • 284
  • 2
  • 10
  • I believe the problem lies in the type of the model of the endpoint. On personal level, what does the `from typing import Type` do? I've never seen it and I'm curious. Thanks – lsabi Mar 04 '21 at 21:07
  • Yes, that is indeed the problem. The question is how to solve it. For `typing.Type` see the [documentation](https://docs.python.org/3/library/typing.html#typing.Type) – charlemagne Mar 04 '21 at 21:51
  • Ooo I see. Then I guess that the problem is `Type[BaseModel]` because `BaseModel` should be some sort of abstract class, while `fastapi` under hood needs to get a dictionary representation of the class in order to validate it. Could you try creating a new class that inherits from `Basemodel` and is used as base class for the others as type of the function parameter? – lsabi Mar 04 '21 at 22:08
  • As I said, the code runs just fine and without errors. It's just that when I check it with mypy I'm having troubles. In fact in the actual code I'm using, it *is* a subclass of `pydantic.BaseModel`. That doesn't make a difference. – charlemagne Mar 04 '21 at 23:41
  • I understand that, but since mypy checks at compile time, my guess is that it expects a certain type as parameter, which does not happen. At runtime, python does not complain because it doesn't assume any type, but mypy does, so it complains – lsabi Mar 05 '21 at 08:10
  • Variables with type `Type[...]` [cannot be used](https://mypy.readthedocs.io/en/latest/common_issues.html#variables-vs-type-aliases) for annotations from `mypy` point of view. – alex_noname Mar 05 '21 at 08:20
  • I know they can't, but `Type[BaseModel]` is in fact the correct annotation for the function. It's just that FastAPI only allows the definition of the body parameter in this type annotation way. – charlemagne Mar 05 '21 at 10:36
  • You can use a Generic type. – Yagiz Degirmenci Mar 07 '21 at 13:05

0 Answers0