Skip to content

Pydantic v2, dataclasses, UUID, and __annotations__ #10007

@tiangolo

Description

@tiangolo

Privileged issue

  • I'm @tiangolo or 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 @raddevon with the minimal example by @fantix:

from __future__ import annotations

import uuid
from dataclasses import dataclass, field
from typing import List, Union

from fastapi import FastAPI


@dataclass
class Item:
    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)
async def read_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/python3.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/python3.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/python3.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/python3.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/python3.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/python3.10/site-packages/click/core.py", line 1130, in __call__
    return self.main(*args, **kwargs)
  File "/Users/user/code/fastapi/env3.10/lib/python3.10/site-packages/click/core.py", line 1055, in main
    rv = self.invoke(ctx)
  File "/Users/user/code/fastapi/env3.10/lib/python3.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/python3.10/site-packages/click/core.py", line 760, in invoke
    return __callback(*args, **kwargs)
  File "/Users/user/code/fastapi/env3.10/lib/python3.10/site-packages/uvicorn/main.py", line 410, in main
    run(
  File "/Users/user/code/fastapi/env3.10/lib/python3.10/site-packages/uvicorn/main.py", line 578, in run
    server.run()
  File "/Users/user/code/fastapi/env3.10/lib/python3.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/python3.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/python3.10/site-packages/uvicorn/server.py", line 68, in serve
    config.load()
  File "/Users/user/code/fastapi/env3.10/lib/python3.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/python3.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/python3.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/python3.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/python3.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/python3.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/python3.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/python3.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/python3.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/python3.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/python3.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/python3.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/python3.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/python3.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/python3.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/python3.10/site-packages/pydantic/_internal/_generate_schema.py", line 1317, in _dataclass_schema
    args = sorted(
  File "/Users/user/code/fastapi/env3.10/lib/python3.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/python3.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/python3.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/python3.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/python3.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/python3.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/python3.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/python3.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.

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions