Skip to content

Hitting NameError with Python 3.14 forward reference for TypedDict #536

@jamesbraza

Description

@jamesbraza

Things to check first

  • I have searched the existing issues and didn't find my bug already reported there

  • I have checked that my bug is still present in the latest release

Typeguard version

4.4.4

Python version

3.14.0

What happened?

annotationlib.ForwardRef work fine in Python 3.14 if you have all the relevant variables present:

from typing import Literal, Required

from annotationlib import ForwardRef, get_annotations
from pydantic_core import core_schema as cs

type_forwardref: ForwardRef = get_annotations(cs.JsonOrPythonSchema)["type"]
result = type_forwardref.evaluate(
    globals={"Required": Required, "Literal": Literal}, locals={}, type_params=()
)

However, as of Python 3.14, it seems typeguard isn't handling forward references with TypedDict properly, it his a NameError (see below reproducer's stack).

Coming from pydantic/pydantic#12447, it seems Pydantic (uses pydantic-core) had to do a fix for this too: pydantic/pydantic#12427

How can we reproduce the bug?

Here is a minimal reproducer, it works with Python 3.13.5, but not with Python 3.14.0:

I have pydantic==2.12.3, pydantic-core==2.41.4, and typeguard==4.4.4:

from pydantic_core import core_schema as cs
from typeguard._checkers import check_type_internal
from typeguard._memo import TypeCheckMemo

check_type_internal(
    value={},
    annotation=cs.JsonOrPythonSchema,
    memo=TypeCheckMemo(globals=globals(), locals=locals()),
)

With Python 3.13 there is no error, and here is the stack trace from 3.14.0:

Traceback (most recent call last):
  File "/path/to/a.py", line 5, in <module>
    check_type_internal(
    ~~~~~~~~~~~~~~~~~~~^
        value={},
        ^^^^^^^^^
        annotation=cs.JsonOrPythonSchema,
        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
        memo=TypeCheckMemo(globals=globals(), locals=locals()),
        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    )
    ^
  File "/path/to/repo/.venv/lib/python3.14/site-packages/typeguard/_checkers.py", line 960, in check_type_internal
    checker(value, origin_type, args, memo)
    ~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/path/to/repo/.venv/lib/python3.14/site-packages/typeguard/_checkers.py", line 265, in check_typed_dict
    annotation = evaluate_forwardref(annotation, memo)
  File "/path/to/repo/.venv/lib/python3.14/site-packages/typeguard/_utils.py", line 26, in evaluate_forwardref
    return forwardref.evaluate(
           ~~~~~~~~~~~~~~~~~~~^
        globals=memo.globals, locals=memo.locals, type_params=()
        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    )
    ^
  File "/path/to/.pyenv/versions/3.14.0/lib/python3.14/annotationlib.py", line 186, in evaluate
    return eval(code, globals=globals, locals=locals)
  File "<string>", line 1, in <module>
NameError: name 'Required' is not defined

Metadata

Metadata

Assignees

No one assigned

    Labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions