Getting issubcluss error on /docs in Fastapi
Output of python -c "import pydantic.utils; print(pydantic.utils.version_info())":
pydantic version: 1.4
pydantic compiled: False
install path: /Users/philippk/anaconda3/envs/py37/lib/python3.7/site-packages/pydantic
python version: 3.7.3 | packaged by conda-forge | (default, Dec 6 2019, 08:36:57) [Clang 9.0.0 (tags/RELEASE_900/final)]
platform: Darwin-19.2.0-x86_64-i386-64bit
optional deps. installed: ['typing-extensions']
(py37) ZG00021:se-sestimate philippk$ docker run -it -p 80:80 -e ENVKEY -e SNOWFLAKE_PASSWORD='dummy' -e SNOWFLAKE_ACCOUNT='zillow' -e SNOWFLAKE_USER='philippk' -e SNOWFLAKE_WAREHOUSE='LOOKER_WH' -e SNOWFLAKE_DATABASE='FEATURESTORE' -e AWS_ACCESS_KEY_ID -e AWS_SECRET_ACCESS_KEY -e AWS_SESSION_TOKEN -e AWS_SECURITY_TOKEN --entrypoint /bin/bash se-sestimate:local-api
root@d50a194c1238:/app# python -c "import pydantic.utils; print(pydantic.utils.version_info())"
pydantic version: 1.4
pydantic compiled: True
install path: /usr/local/lib/python3.7/site-packages/pydantic
python version: 3.7.4 (default, Sep 12 2019, 15:40:15) [GCC 8.3.0]
platform: Linux-4.19.76-linuxkit-x86_64-with-debian-10.1
optional deps. installed: []
Here is the code of request_models:
from typing import List
from pydantic import BaseModel
from enum import Enum
from datetime import date
class ModelName(str, Enum):
repeated_sale = "repeated_sale"
main = "main"
dummy = "dummy"
class Inference(BaseModel):
price: int
model: ModelName
model_version: float
date: date
@app.get("/infer", response_model=Inference)
def infer(
params: dict,
model: ModelName,
v: Optional[float] = None,
date: Optional["date"] = None,
) -> Inference:
"""attempts to pull predictions from snowflake"""
result = app.model_registry.pull(model=model, v=v, date=date).predict(params)
return {"model": model, "v": v, **result}
this results in:
File "/Users/philippk/anaconda3/envs/py37/lib/python3.7/site-packages/pydantic/schema.py", line 657, in field_singleton_schema
if issubclass(field_type, Enum):
TypeError: issubclass() arg 1 must be a class
So, I was able to fix this by changing Optional["date"] to Optional[date] in the signature of infer. The problem is that the forward ref inside the Optional isn't getting resolved first.
I'm not sure whether the problem should be considered to lie in fastapi or pydantic, but it appears to be stemming from an inability for pydantic.schema.field_schema to handle a field with type Optional[ForwardRef("date")] (presumably it would struggle to handle fields with any ForwardRefs).
@samuelcolvin Should FastAPI be taking responsibility for ensuring fields don't have forward refs in their types?
Does update_forward_refs fix this?
If so, I think the problem is on the FastAPI side.
Otherwise, we might be able to have a crack at resolving it in pydantic.
Simple example of the issue. Try to access /docs on FastAPI
from typing import Set
from fastapi import FastAPI
from pydantic import BaseModel
app = FastAPI()
class A(BaseModel):
b: 'B' # if this line is commented out, /docs works fine
class B(BaseModel):
a: A
@app.get("/")
def test(a: A):
return a
I just experience the same bug. update_forward_refs does not solve it.
Simple example of the issue. Try to access /docs on FastAPI
A.update_forward_refs() does work for me:
from fastapi import FastAPI
from pydantic import BaseModel
app = FastAPI()
class A(BaseModel):
b: 'B'
class B(BaseModel):
a: A
A.update_forward_refs() # This fixes the issubclass crash
# B.update_forward_refs() # This does not make a difference
@app.get("/")
def hello(a: A):
return a
if __name__ == "__main__":
import uvicorn
uvicorn.run(app, host="0.0.0.0", port=8001)
Hello
I feel like this issue should be closed as the other issues are not really related.
The issubclass issue is now solved since we use lenient_issubclass.
The second issue comes from how __annotations__ works.
When writing
class A:
date: Optional[date] = None
the __annotations__ is {'date': <class 'NoneType'>}, which leads to errors!
Unfortunately it has nothing to do with _pydantic_ and this is a tricky error.
This doesn't happen if we use Optional['date'] = None or Optional[date] without default value.
Using from __future__ import annotations also works as it does the same trick (use ForwardRef...) so I feel like this error should be solved once the new annotations system is supported and the default one.
And for this we already have some open issues. Don't know if we need to open a new one 🤷♂️
@PrettyWood has this fix released? I'm still getting the error without .update_forward_refs()
This will be fixed by #2221 which I'm about to merge and should get released very soon.
@thiras since you're obviously eager for a fix, it would be really helpful if you could try #2221 and let us know if it fixes your problem or not.
Most helpful comment
I just experience the same bug. update_forward_refs does not solve it.