-
-
Notifications
You must be signed in to change notification settings - Fork 8.8k
Description
First Check
- I added a very descriptive title to this issue.
- I used the GitHub search to find a similar issue and didn't find it.
- I searched the FastAPI documentation, with the integrated search.
- I already searched in Google "How to X in FastAPI" and didn't find any information.
- I already read and followed all the tutorial in the docs and didn't find an answer.
- I already checked if it is not related to FastAPI but to Pydantic.
- I already checked if it is not related to FastAPI but to Swagger UI.
- I already checked if it is not related to FastAPI but to ReDoc.
Commit to Help
- I commit to help with one of those options 👆
Example Code
from __future__ import annotations
from fastapi import FastAPI, Depends
app = FastAPI()
CoolType = int
def get_cool_type() -> int:
return 123
class MyClass:
def __init__(self, val: CoolType = Depends(get_cool_type)):
self.val = val
def get_my_class(val: CoolType = Depends(get_cool_type)):
return MyClass
@app.get("/")
def my_view(mycls: MyClass = Depends()):
return mycls.val
@app.get("/test2")
def my_view_working(mycls: MyClass = Depends(get_my_class)):
return mycls.valDescription
Run the example app, and you will get a NameError because CoolType cannot be resolved. If you comment out the first view, the program will work correctly. The second view just uses a function to construct and return MyClass instead using MyClass as a dependency directly.
A possible root of the problem is in fastapi.dependency.utils:get_typed_signature:
def get_typed_signature(call: Callable[..., Any]) -> inspect.Signature:
signature = inspect.signature(call)
globalns = getattr(call, "__globals__", {})
...To resolve the annotations, this function uses the dependency's __globals__ property to look up the names. When call is a function, this works just fine. When call is a class, it doesn't have a __globals__, so we get an empty namespace as a fallback.
However, when we specify a class as a dependency, what we really care about is MyClass.__init__. This is a function, and it has a __globals__ containing all the types we need to resolve its dependencies.
A possible fix for this would be to make this function check if call is a class and use it's __init__ method instead.
Operating System
Linux
Operating System Details
No response
FastAPI Version
0.73.0
Python Version
Python 3.10.2
Additional Context
Also using pydantic 1.9.0
See also this related issue: #1654