Uh oh!
There was an error while loading.Please reload this page.
- Notifications
You must be signed in to change notification settings - Fork8.7k
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 toPydantic.
- I already checked if it is not related to FastAPI but toSwagger UI.
- I already checked if it is not related to FastAPI but toReDoc.
Commit to Help
- I commit to help with one of those options 👆
Example Code
# This needs to be in two files because the nature of the bug involves different globalns# entries for a decorated function versus the module of the original function.# If you put the code here into two files (func.py and main.py) in a directory, then the# bug can be reproduced by running:# PYTHONPATH=.:$PYTHONPATH python ./main.py# This should cause an exception `NameError: name 'MyModel' is not defined`# func.pyfrompydanticimportBaseModeldeffoo(obj:"MyModel")->"MyModel":returnobjclassMyModel(BaseModel):x:int# main.pyimportfunctools,typingfromfastapiimportFastAPIfrompydanticimportBaseModelfromfuncimportfooapp=FastAPI()defdeco(func):@functools.wraps(func)defpassthrough(*args,**kwargs):returnfunc(*args,**kwargs)returnpassthroughdecorated=deco(foo)assertissubclass(typing.get_type_hints(decorated)["obj"],BaseModel)assertdecorated.__annotations__==foo.__annotations__assertisinstance(decorated.__annotations__["obj"],str)method=app.post('/endpoint')(decorated)
Description
Using a decorator employingfunctools.wraps or a similar causes aNameError infastapi/dependencies/utils.py inget_typed_annotation. The implementation there differs from the implementation intyping, which dereferences the__wrapped__ attribute to find the namespace the original function was defined in. This allows forward references to be handled correctly:
https://github.com/python/cpython/blob/576dd901170af30fc50b0a7f07a388b38fd724a9/Lib/typing.py#L2314-L2315
In the "Example Code" section, my example includes assertions showing thattyping.get_type_hints handles this situation correctly. I believe this can be fixed either by using the same implementation as typing uses, or by callingtyping.get_type_hints, and only doing special FastAPI-specific logic if that fails.
Operating System
macOS
Operating System Details
I first saw this on Ubuntu Linux with python 3.8, then later reproduced it on my Macbook in python 3.9. The example code was tested on the Mac.
I do not believe the bug is related to operating systems. I think it's a bug in how pure python code handles type annotations.
FastAPI Version
0.78.0
Python Version
Python 3.9.1
Additional Context
This bug is unlikely to come up in most ordinary code, but is likely to come up when using metaprogramming or decorators (especially in programmatically adding endpoints). The context I found it in was in a in-house workflow framework we are building at my job. The framework uses some decorators to alter the type signature of methods, and passes them to FastAPI to expose task endpoints. This leads to the above error.
I definitely understand that such an odd use case is probably not high priority for the maintainers, but I hope you'll be willing to review a PR from me fixing the bug.
Thank you for all your work on FastAPI! It is an amazingly well-made piece of software.