Skip to content
New issue

Have a question about this project?Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to ourterms of serviceand privacy statement.We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Pydantic v2, dataclasses, UUID, and__annotations__ #10007

Open
1 task done
tiangoloopened this issue Aug 4, 2023 · 17 comments
Open
1 task done

Pydantic v2, dataclasses, UUID, and__annotations__ #10007

tiangoloopened this issue Aug 4, 2023 · 17 comments
Labels
bug Something isn't working

Comments

@tiangolo
Copy link
Member

tiangolo commented Aug 4, 2023

Privileged issue

  • I'm@tiangoloor he asked me directly to create an issue here.

Issue Content

The combination of using:

  • Pydantic v2
  • dataclasses (instead of Pydantic models)
  • UUIDs
  • from future import __annotations__

seems to break in a strange way.

This was original reported in this discussion by@sanzoghenzo:#9709 (comment)

In particular the comment by@raddevonwith the minimal example by@fantix:

from__future__importannotations

importuuid
fromdataclassesimportdataclass,field
fromtypingimportList,Union

fromfastapiimportFastAPI


@dataclass
classItem:
id:uuid.UUID
name:str
price:float
tags:List[str]=field(default_factory=list)
description:Union[str,None]=None
tax:Union[float,None]=None


app=FastAPI()


@app.get("/items/next",response_model=Item)
asyncdefread_next_item():
return{
"name":"Island In The Moon",
"price":12.99,
"description":"A place to be be playin' and havin' fun",
"tags":["breater"],
}

Starting FastAPI with that breaks with an error of:

log
uvicorn main:app
Traceback (most recent call last):
File "/Users/user/code/fastapi/env3.10/lib/ Python 3.10/site-packages/pydantic/type_adapter.py", line 165, in __init__
core_schema = _getattr_no_parents(type, '__pydantic_core_schema__')
File "/Users/user/code/fastapi/env3.10/lib/ Python 3.10/site-packages/pydantic/type_adapter.py", line 97, in _getattr_no_parents
raise AttributeError(attribute)
AttributeError: __pydantic_core_schema__

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
File "/Users/user/code/fastapi/env3.10/lib/ Python 3.10/site-packages/pydantic/_internal/_generate_schema.py", line 625, in _resolve_forward_ref
obj = _typing_extra.evaluate_fwd_ref(obj, globalns=self._types_namespace)
File "/Users/user/code/fastapi/env3.10/lib/ Python 3.10/site-packages/pydantic/_internal/_typing_extra.py", line 423, in evaluate_fwd_ref
return ref._evaluate(globalns=globalns, localns=localns, recursive_guard=frozenset())
File "/Library/Frameworks/Python.framework/Versions/3.10/lib/ Python 3.10/typing.py", line 694, in _evaluate
eval(self.__forward_code__, globalns, localns),
File "<string>", line 1, in <module>
NameError: name 'uuid' is not defined

The above exception was the direct cause of the following exception:

Traceback (most recent call last):
File "/Users/user/code/fastapi/env3.10/bin/uvicorn", line 8, in <module>
sys.exit(main())
File "/Users/user/code/fastapi/env3.10/lib/ Python 3.10/site-packages/click/core.py", line 1130, in __call__
return self.main(*args, **kwargs)
File "/Users/user/code/fastapi/env3.10/lib/ Python 3.10/site-packages/click/core.py", line 1055, in main
rv = self.invoke(ctx)
File "/Users/user/code/fastapi/env3.10/lib/ Python 3.10/site-packages/click/core.py", line 1404, in invoke
return ctx.invoke(self.callback, **ctx.params)
File "/Users/user/code/fastapi/env3.10/lib/ Python 3.10/site-packages/click/core.py", line 760, in invoke
return __callback(*args, **kwargs)
File "/Users/user/code/fastapi/env3.10/lib/ Python 3.10/site-packages/uvicorn/main.py", line 410, in main
run(
File "/Users/user/code/fastapi/env3.10/lib/ Python 3.10/site-packages/uvicorn/main.py", line 578, in run
server.run()
File "/Users/user/code/fastapi/env3.10/lib/ Python 3.10/site-packages/uvicorn/server.py", line 61, in run
return asyncio.run(self.serve(sockets=sockets))
File "/Library/Frameworks/Python.framework/Versions/3.10/lib/ Python 3.10/asyncio/runners.py", line 44, in run
return loop.run_until_complete(main)
File "uvloop/loop.pyx", line 1517, in uvloop.loop.Loop.run_until_complete
File "/Users/user/code/fastapi/env3.10/lib/ Python 3.10/site-packages/uvicorn/server.py", line 68, in serve
config.load()
File "/Users/user/code/fastapi/env3.10/lib/ Python 3.10/site-packages/uvicorn/config.py", line 473, in load
self.loaded_app = import_from_string(self.app)
File "/Users/user/code/fastapi/env3.10/lib/ Python 3.10/site-packages/uvicorn/importer.py", line 21, in import_from_string
module = importlib.import_module(module_str)
File "/Library/Frameworks/Python.framework/Versions/3.10/lib/ Python 3.10/importlib/__init__.py", line 126, in import_module
return _bootstrap._gcd_import(name[level:], package, level)
File "<frozen importlib._bootstrap>", line 1050, in _gcd_import
File "<frozen importlib._bootstrap>", line 1027, in _find_and_load
File "<frozen importlib._bootstrap>", line 1006, in _find_and_load_unlocked
File "<frozen importlib._bootstrap>", line 688, in _load_unlocked
File "<frozen importlib._bootstrap_external>", line 883, in exec_module
File "<frozen importlib._bootstrap>", line 241, in _call_with_frames_removed
File "/Users/user/code/fastapi/main.py", line 24, in <module>
async def read_next_item():
File "/Users/user/code/fastapi/fastapi/routing.py", line 706, in decorator
self.add_api_route(
File "/Users/user/code/fastapi/fastapi/routing.py", line 645, in add_api_route
route = route_class(
File "/Users/user/code/fastapi/fastapi/routing.py", line 448, in __init__
self.response_field = create_response_field(
File "/Users/user/code/fastapi/fastapi/utils.py", line 99, in create_response_field
return ModelField(**kwargs) # type: ignore[arg-type]
File "<string>", line 6, in __init__
File "/Users/user/code/fastapi/fastapi/_compat.py", line 101, in __post_init__
self._type_adapter: TypeAdapter[Any] = TypeAdapter(
File "/Users/user/code/fastapi/env3.10/lib/ Python 3.10/site-packages/pydantic/type_adapter.py", line 167, in __init__
core_schema = _get_schema(type, config_wrapper, parent_depth=_parent_depth + 1)
File "/Users/user/code/fastapi/env3.10/lib/ Python 3.10/site-packages/pydantic/type_adapter.py", line 80, in _get_schema
schema = gen.generate_schema(type_)
File "/Users/user/code/fastapi/env3.10/lib/ Python 3.10/site-packages/pydantic/_internal/_generate_schema.py", line 425, in generate_schema
return self._annotated_schema(obj)
File "/Users/user/code/fastapi/env3.10/lib/ Python 3.10/site-packages/pydantic/_internal/_generate_schema.py", line 1464, in _annotated_schema
schema = self._apply_annotations(source_type, annotations)
File "/Users/user/code/fastapi/env3.10/lib/ Python 3.10/site-packages/pydantic/_internal/_generate_schema.py", line 1586, in _apply_annotations
schema = get_inner_schema(source_type)
File "/Users/user/code/fastapi/env3.10/lib/ Python 3.10/site-packages/pydantic/_internal/_schema_generation_shared.py", line 82, in __call__
schema = self._handler(__source_type)
File "/Users/user/code/fastapi/env3.10/lib/ Python 3.10/site-packages/pydantic/_internal/_generate_schema.py", line 1679, in new_handler
schema = metadata_get_schema(source, get_inner_schema)
File "/Users/user/code/fastapi/env3.10/lib/ Python 3.10/site-packages/pydantic/_internal/_generate_schema.py", line 1675, in <lambda>
lambda source, handler: handler(source)
File "/Users/user/code/fastapi/env3.10/lib/ Python 3.10/site-packages/pydantic/_internal/_schema_generation_shared.py", line 82, in __call__
schema = self._handler(__source_type)
File "/Users/user/code/fastapi/env3.10/lib/ Python 3.10/site-packages/pydantic/_internal/_generate_schema.py", line 1550, in inner_handler
schema = self._generate_schema(obj)
File "/Users/user/code/fastapi/env3.10/lib/ Python 3.10/site-packages/pydantic/_internal/_generate_schema.py", line 689, in _generate_schema
return self.match_type(obj)
File "/Users/user/code/fastapi/env3.10/lib/ Python 3.10/site-packages/pydantic/_internal/_generate_schema.py", line 763, in match_type
return self._dataclass_schema(obj, None)
File "/Users/user/code/fastapi/env3.10/lib/ Python 3.10/site-packages/pydantic/_internal/_generate_schema.py", line 1317, in _dataclass_schema
args = sorted(
File "/Users/user/code/fastapi/env3.10/lib/ Python 3.10/site-packages/pydantic/_internal/_generate_schema.py", line 1318, in <genexpr>
(self._generate_dc_field_schema(k, v, decorators) for k, v in fields.items()),
File "/Users/user/code/fastapi/env3.10/lib/ Python 3.10/site-packages/pydantic/_internal/_generate_schema.py", line 865, in _generate_dc_field_schema
common_field = self._common_field_schema(name, field_info, decorators)
File "/Users/user/code/fastapi/env3.10/lib/ Python 3.10/site-packages/pydantic/_internal/_generate_schema.py", line 900, in _common_field_schema
schema = self._apply_annotations(
File "/Users/user/code/fastapi/env3.10/lib/ Python 3.10/site-packages/pydantic/_internal/_generate_schema.py", line 1586, in _apply_annotations
schema = get_inner_schema(source_type)
File "/Users/user/code/fastapi/env3.10/lib/ Python 3.10/site-packages/pydantic/_internal/_schema_generation_shared.py", line 82, in __call__
schema = self._handler(__source_type)
File "/Users/user/code/fastapi/env3.10/lib/ Python 3.10/site-packages/pydantic/_internal/_generate_schema.py", line 1550, in inner_handler
schema = self._generate_schema(obj)
File "/Users/user/code/fastapi/env3.10/lib/ Python 3.10/site-packages/pydantic/_internal/_generate_schema.py", line 679, in _generate_schema
return self.generate_schema(self._resolve_forward_ref(obj))
File "/Users/user/code/fastapi/env3.10/lib/ Python 3.10/site-packages/pydantic/_internal/_generate_schema.py", line 627, in _resolve_forward_ref
raise PydanticUndefinedAnnotation.from_name_error(e) from e
pydantic.errors.PydanticUndefinedAnnotation: name 'uuid' is not defined

For further information visit https://errors.pydantic.dev/2.1.1/u/undefined-annotation

I still don't know if it's about which of these multiple interacting parts, I'm creating this issue to keep track of it.

@tiangolo tiangolo added the bug Something isn't working label Aug 4, 2023
@MaquinaTech
Copy link

Maybe using an id of type str can solve the problem...

class Item:
id: str # Using string instead of uuid.UUID
name: str
price: float
tags: List[str] = field(default_factory=list)
description: Union[str, None] = None
tax: Union[float, None] = None

@xouyang1
Copy link

xouyang1 commented Aug 6, 2023

It looks like forward references are resolved from namespaces built from the previous 2 frames
https://github /pydantic/pydantic/blob/adc657a8b9f0b5191c180fc51005c0bf1fe529db/pydantic/type_adapter.py#L76

@harunyasar
Copy link

harunyasar commented Aug 9, 2023

You could use Pydantic's dataclass extension. It doesn't just give you the same data validation features but also fix your issue.

from__future__importannotations

fromtypingimportList,Union
importuuid

frompydantic.dataclassesimportdataclass,Field

@dataclass
classItem:
id:uuid.UUID
name:str
price:float
tags:List[str]=Field(default_factory=list)
description:Union[str,None]=None
tax:Union[float,None]=None

item=Item(
id=uuid.uuid4(),
name="John",
price=666.66,
)

print(item)

# Item(id=UUID('c399d5c9-c2bf-4e5f-94f9-21a7a5f78610'), name='John', price=666.66, tags=[], description=None, tax=None)

@tiangolo
Copy link
Member Author

tiangolo commented Aug 14, 2023

This would need to be handled on the Pydantic side (or at least require some input/changes from them).pydantic/pydantic#7111

As@harunyasarmentions, there's a simple workaround, to use Pydantic's flavor ofdataclassesinstead of the standard library ones.

frompydantic.dataclassesimportdataclass

I understand this is one of the things that begs for PEP 649 (Deferred Evaluation Of Annotations Using Descriptors) that will hopefully come to Python 3.13 🎉

@vsoch
Copy link

vsoch commented Aug 19, 2023

I'm not sure if this is related, but I'm hitting:

==================================== ERRORS ====================================
______________________ ERROR collecting tests/test_api.py ______________________
ImportError while importing test module '/__w/flux-restful-api/flux-restful-api/tests/test_api.py'.
Hint: make sure your test modules/packages have valid Python names.
Traceback:
/usr/lib/ Python 3.8/importlib/__init__.py:127: in import_module
return _bootstrap._gcd_import(name[level:], package, level)
tests/test_api.py:6: in <module>
from fastapi.testclient import TestClient
/usr/local/lib/ Python 3.8/dist-packages/fastapi/__init__.py:7: in <module>
from.applications import FastAPI as FastAPI
/usr/local/lib/ Python 3.8/dist-packages/fastapi/applications.py:3: in <module>
from fastapi import routing
/usr/local/lib/ Python 3.8/dist-packages/fastapi/routing.py:20: in <module>
from fastapi import params
/usr/local/lib/ Python 3.8/dist-packages/fastapi/params.py:4: in <module>
from pydantic.fields import FieldInfo, Undefined
E ImportError: cannot import name 'Undefined' from 'pydantic.fields' (/usr/local/lib/ Python 3.8/dist-packages/pydantic/fields.py)

I've installed the lastest fastapi and pydantic, so I suspect this is a new issue! I think probably the only way to fix this now is to fall back to a much older pydantic. Also@tiangoloyour use of emojis in commits is pure 🔥 I love looking at your code! 🙌

@vsoch
Copy link

vsoch commented Aug 19, 2023

I actually can't find a pairing that works! I'm going to look in an older container (where it did work) and cross my fingers I can reproduce that! 🤞

@vsoch
Copy link

vsoch commented Aug 19, 2023

Yeah this is strange - when I go to previously working versions I still get:

from pydantic.fields import FieldInfo, Undefined
ImportError: cannot import name 'Undefined' from 'pydantic.fields' (/env/lib/ Python 3.8/site-packages/pydantic/fields.py)

@johnthagen
Copy link
Contributor

johnthagen commented Aug 28, 2023

When I tried to update from:

  • fastapi (0.101.1 -> 0.103.0)
  • pydantic (1.10.12 -> 2.3.0)

A route that uses a stdlib@dataclassas the return type annotation, started throwing an exception.

pydantic.errors.PydanticUndefinedAnnotation: name 'MyDataclass' is not defined

MyDataclassis defined in another module.

fromother.pathimportMyDataclass

@router.post("/route/")
defroute()->MyDataclass:
...

In my case, it appears that if any of the nested@dataclasses referenced by the top levelMyDataclassare defined in a module withfrom __future__ import annotations,then this error will be thrown by one of them.

The reason we are usingfrom __future__ import annotationsis that many of these models use forward references themselves, so this avoids the (IMO ugiler) manually stringified syntax. We try to avoid forward references as much as possible (usingSelfon@classmethods whenever possible, for example) but there are some instances where it can't be avoided (e.g., a normal method that returns a new instance of itself).

There are also weird things that can happen with manually stringified type annotations:

@AhsanSheraz
Copy link
Contributor

AhsanSheraz commented Sep 14, 2023

You can use create your own data model like below:

from__future__importannotations

importuuid
fromdataclassesimportdataclass,field
fromtypingimportList,Union

fromfastapiimportFastAPI
frompydanticimportBaseModel

classItem(BaseModel):
id:uuid.UUID
name:str
price:float
tags:List[str]=field(default_factory=list)
description:Union[str,None]=None
tax:Union[float,None]=None


app=FastAPI()


@app.get("/items/next",response_model=Item)
asyncdefread_next_item():
return{
"name":"Island In The Moon",
"price":12.99,
"description":"A place to be be playin' and havin' fun",
"tags":["breater"],
}

@anonymoussss
Copy link

Yeah this is strange - when I go to previously working versions I still get:

from pydantic.fields import FieldInfo, Undefined
ImportError: cannot import name 'Undefined' from 'pydantic.fields' (/env/lib/ Python 3.8/site-packages/pydantic/fields.py)

Hi~have you found a solution?

@Kludex
Copy link
Member

Kludex commented Sep 15, 2023

Yeah this is strange - when I go to previously working versions I still get:

from pydantic.fields import FieldInfo, Undefined
ImportError: cannot import name 'Undefined' from 'pydantic.fields' (/env/lib/ Python 3.8/site-packages/pydantic/fields.py)

Hi~have you found a solution?

I think a bump should solve the issue - either FastAPI or Pydantic.

@anonymoussss
Copy link

Yeah this is strange - when I go to previously working versions I still get:

from pydantic.fields import FieldInfo, Undefined
ImportError: cannot import name 'Undefined' from 'pydantic.fields' (/env/lib/ Python 3.8/site-packages/pydantic/fields.py)

Hi~have you found a solution?

I think a bump should solve the issue - either FastAPI or Pydantic.

Right. I have solved this issue by "pip install pydantic==1.9.0"

@Kludex
Copy link
Member

Kludex commented Sep 15, 2023

I said bump, not downgrade. 😅

@dineshbvadhia
Copy link

This might also be related.

Python 3.11x plus latest FastApi and Pydantic V2.

ReplacedBaseModelwithTypedDictas don't want Pydantic models or validation. Usingtyping_extensions.TypedDictas Python < 3.12. Yet, get error in endpoint:

@router.get( "/getthis", response_class=JSONResponse, response_model = Union[Done, Problem])

Traceback (most recent call last):
File "...\Python311\Lib\site-packages\pydantic\type_adapter.py", line 239, in __init__
core_schema = _getattr_no_parents(type, '__pydantic_core_schema__')
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "...\Python311\Lib\site-packages\pydantic\type_adapter.py", line 173, in _getattr_no_parents
raise AttributeError(attribute)
AttributeError: __pydantic_core_schema__

@dunaden001
Copy link

I'm just chiming into this conversation to share an issue I had with this recently and what I did to solve it in case it helps with someone else chasing this down.

I have separated my models, controllers and routers into separate modules - I was trying to create a dependable to extract a provided auth token, pull the appropriate user from my db and then return it as a pydantic User object. This meant that I wanted to reference the dependable in my router module as a method of the controller class held as an instance variable.

So something like this:

class UserRouter:
def __init__(self, db: DynamoDBServiceResource) -> None:
self.__controller = UserController(db)

@property
def router(self) -> APIRouter:
api_router = APIRouter(prefix= "/user", tags=[ "user" ])

@api_router.get( "/my-details" )
async def get_my_details(
requesting_user: Annotated[User, Depends(self.__controller.get_requesting_user)]
) -> User:
logger.info(f "Retrieving user details for user: {requesting_user}" )
return requesting_user

This resulted in an error as below:

Error log
Traceback (most recent call last):
File "/usr/local/lib/ Python 3.12/site-packages/pydantic/type_adapter.py", line 207, in __init__
core_schema = _getattr_no_parents(type, '__pydantic_core_schema__')
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/usr/local/lib/ Python 3.12/site-packages/pydantic/type_adapter.py", line 98, in _getattr_no_parents
raise AttributeError(attribute)
AttributeError: __pydantic_core_schema__

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
File "/usr/local/lib/ Python 3.12/site-packages/pydantic/_internal/_generate_schema.py", line 677, in _resolve_forward_ref
obj = _typing_extra.eval_type_backport(obj, globalns=self._types_namespace)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/usr/local/lib/ Python 3.12/site-packages/pydantic/_internal/_typing_extra.py", line 240, in eval_type_backport
return typing._eval_type( # type: ignore
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/usr/local/lib/ Python 3.12/typing.py", line 400, in _eval_type
return t._evaluate(globalns, localns, recursive_guard)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/usr/local/lib/ Python 3.12/typing.py", line 907, in _evaluate
eval(self.__forward_code__, globalns, localns),
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "<string>", line 1, in <module>
NameError: name 'User' is not defined

The above exception was the direct cause of the following exception:

Traceback (most recent call last):
File "/usr/local/lib/ Python 3.12/multiprocessing/process.py", line 314, in _bootstrap
self.run()
File "/usr/local/lib/ Python 3.12/multiprocessing/process.py", line 108, in run
self._target(*self._args, **self._kwargs)
File "/home/dev_user/.local/lib/ Python 3.12/site-packages/uvicorn/_subprocess.py", line 78, in subprocess_started
target(sockets=sockets)
File "/home/dev_user/.local/lib/ Python 3.12/site-packages/uvicorn/server.py", line 62, in run
return asyncio.run(self.serve(sockets=sockets))
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/usr/local/lib/ Python 3.12/asyncio/runners.py", line 194, in run
return runner.run(main)
^^^^^^^^^^^^^^^^
File "/usr/local/lib/ Python 3.12/asyncio/runners.py", line 118, in run
return self._loop.run_until_complete(task)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/usr/local/lib/ Python 3.12/asyncio/base_events.py", line 685, in run_until_complete
return future.result()
^^^^^^^^^^^^^^^
File "/home/dev_user/.local/lib/ Python 3.12/site-packages/uvicorn/server.py", line 69, in serve
config.load()
File "/home/dev_user/.local/lib/ Python 3.12/site-packages/uvicorn/config.py", line 433, in load
self.loaded_app = import_from_string(self.app)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/home/dev_user/.local/lib/ Python 3.12/site-packages/uvicorn/importer.py", line 19, in import_from_string
module = importlib.import_module(module_str)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/usr/local/lib/ Python 3.12/importlib/__init__.py", line 90, in import_module
return _bootstrap._gcd_import(name[level:], package, level)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "<frozen importlib._bootstrap>", line 1387, in _gcd_import
File "<frozen importlib._bootstrap>", line 1360, in _find_and_load
File "<frozen importlib._bootstrap>", line 1331, in _find_and_load_unlocked
File "<frozen importlib._bootstrap>", line 935, in _load_unlocked
File "<frozen importlib._bootstrap_external>", line 995, in exec_module
File "<frozen importlib._bootstrap>", line 488, in _call_with_frames_removed
File "/workspaces/drip_backend/src/main.py", line 81, in <module>
app.include_router(user_router.router)
^^^^^^^^^^^^^^^^^^
File "/workspaces/drip_backend/src/user/user_router.py", line 69, in router
@api_router.get( "/my-details" )
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/home/dev_user/.local/lib/ Python 3.12/site-packages/fastapi/routing.py", line 944, in decorator
self.add_api_route(
File "/home/dev_user/.local/lib/ Python 3.12/site-packages/fastapi/routing.py", line 883, in add_api_route
route = route_class(
^^^^^^^^^^^^
File "/home/dev_user/.local/lib/ Python 3.12/site-packages/fastapi/routing.py", line 513, in __init__
self.dependant = get_dependant(path=self.path_format, call=self.endpoint)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/home/dev_user/.local/lib/ Python 3.12/site-packages/fastapi/dependencies/utils.py", line 261, in get_dependant
type_annotation, depends, param_field = analyze_param(
^^^^^^^^^^^^^^
File "/home/dev_user/.local/lib/ Python 3.12/site-packages/fastapi/dependencies/utils.py", line 442, in analyze_param
field = create_response_field(
^^^^^^^^^^^^^^^^^^^^^^
File "/home/dev_user/.local/lib/ Python 3.12/site-packages/fastapi/utils.py", line 99, in create_response_field
return ModelField(**kwargs) # type: ignore[arg-type]
^^^^^^^^^^^^^^^^^^^^
File "<string>", line 6, in __init__
File "/home/dev_user/.local/lib/ Python 3.12/site-packages/fastapi/_compat.py", line 107, in __post_init__
self._type_adapter: TypeAdapter[Any] = TypeAdapter(
^^^^^^^^^^^^
File "/usr/local/lib/ Python 3.12/site-packages/pydantic/type_adapter.py", line 209, in __init__
core_schema = _get_schema(type, config_wrapper, parent_depth=_parent_depth + 1)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/usr/local/lib/ Python 3.12/site-packages/pydantic/type_adapter.py", line 81, in _get_schema
schema = gen.generate_schema(type_)
^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/usr/local/lib/ Python 3.12/site-packages/pydantic/_internal/_generate_schema.py", line 499, in generate_schema
schema = self._generate_schema(obj)
^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/usr/local/lib/ Python 3.12/site-packages/pydantic/_internal/_generate_schema.py", line 737, in _generate_schema
schema = self._post_process_generated_schema(self._generate_schema_inner(obj))
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/usr/local/lib/ Python 3.12/site-packages/pydantic/_internal/_generate_schema.py", line 744, in _generate_schema_inner
return self._annotated_schema(obj)
^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/usr/local/lib/ Python 3.12/site-packages/pydantic/_internal/_generate_schema.py", line 1675, in _annotated_schema
source_type, *annotations = self._get_args_resolving_forward_refs(
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/usr/local/lib/ Python 3.12/site-packages/pydantic/_internal/_generate_schema.py", line 701, in _get_args_resolving_forward_refs
args = tuple([self._resolve_forward_ref(a) if isinstance(a, ForwardRef) else a for a in args])
^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/usr/local/lib/ Python 3.12/site-packages/pydantic/_internal/_generate_schema.py", line 679, in _resolve_forward_ref
raise PydanticUndefinedAnnotation.from_name_error(e) from e
pydantic.errors.PydanticUndefinedAnnotation: name 'User' is not defined

So I figured there was an issue with how the type forward refs were being resolved and I quoted the User references. This led to a very similar error but withpydantic.errors.PydanticUndefinedAnnotation: name 'Depends' is not defined.

So, lastly I tried removing theAnnotatedtype and set Depends directly as the default value:

@api_router.get( "/my-details" )
async def get_my_details(
requesting_user: User = Depends(self.__controller.get_requesting_user),
) -> User:
# requesting_user = self.__controller.get_item({ "id": requesting_user_id})
logger.info(f "Retrieving user details for user: {requesting_user}" )
return requesting_user

This now seems to work fine.

I presume the issue is something to do with when Annotated gets resolved as opposed to defining it as a standard default value. Certainly did have me floundering for a while, I would loved to have seen this mentioned somewhere in the otherwise flawless FastAPI docs (please point me to it if it's already there).

@PaleNeutron
Copy link

I think my problem is related to this issue, all code comes from document but I can not resolve it.

#11423

@andreipetre
Copy link

Hello 👋🏻

Had a similar issue which was caused by having

fromfutureimport__annotations__

together with FastAPI dependency injection.

It would result in a weird error

PydanticUndefinedAnnotation: name 'Request' is not defined

where FastAPI would error on all injected dependencies. Removing the import fromfuturefixed the issue.

Thanks.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working
Projects
None yet
Development

No branches or pull requests