GV

GeezerVison

The World Wide Web, restored to 800 pixels of glory.

Home|About|Gaming cabinet|Archives|How it works|Starter sites

On this site

  • Sign in
  • ActionsCI/CD and automation
  • CodespacesCloud development environments
  • All Features
  • Documentation
  • Training
  • Certifications
  • Build with Copilot
  • Customize Copilot
  • Integrations
  • Trending repos
  • GitHub Sponsors
  • Developer articles
  • Enterprises

This view

  • Original page
  • New address

GeezerVison is showing github.com — Raise consistent `NameError` in `ForwardRef.evaluate()` · Issue #135646 · python/cpython

Raise consistent NameError in ForwardRef.evaluate() #135646

New issue
Copy link
New issue
Copy link
Closed
Closed
Raise consistent NameError in ForwardRef.evaluate()#135646
Copy link
Labels
type-featureA feature request or enhancementA feature request or enhancement

Description

@Viicos
Viicos
opened on Jun 17, 2025
Issue body actions

Feature or enhancement

Proposal:

The new ForwardRef.evaluate() implementation had a fast path introduced in #124337 to not call eval():

cpython/Lib/annotationlib.py

Lines 177 to 187 in cb39410

if arg.isidentifier() and not keyword.iskeyword(arg):
if arg in locals:
return locals[arg]
elif arg in globals:
return globals[arg]
elif hasattr(builtins, arg):
return getattr(builtins, arg)
elif is_forwardref_format:
return self
else:
raise NameError(arg)

However, when the NameError is raised, the format is different from the one raised by eval():

The exception message is defined as:

cpython/Python/ceval_macros.h

Line 308 in cb39410

#define NAME_ERROR_MSG "name '%.200s' is not defined"

and raised this way:

cpython/Python/ceval.c

Lines 3339 to 3351 in cb39410

_PyErr_Format(tstate, exc, format_str, obj_str);
if (exc == PyExc_NameError) {
// Include the name in the NameError exceptions to offer suggestions later.
PyObject *exc = PyErr_GetRaisedException();
if (PyErr_GivenExceptionMatches(exc, PyExc_NameError)) {
if (((PyNameErrorObject*)exc)->name == NULL) {
// We do not care if this fails because we are going to restore the
// NameError anyway.
(void)PyObject_SetAttr(exc, &_Py_ID(name), obj);
}
}
PyErr_SetRaisedException(exc);

To have consistent exceptions raised, would it be possible to change the Python fast path implementation to match the C eval code?

diff --git a/Lib/annotationlib.py b/Lib/annotationlib.py
index 731817a9973..c83a1573ccd 100644
--- a/Lib/annotationlib.py
+++ b/Lib/annotationlib.py
@@ -27,6 +27,9 @@ class Format(enum.IntEnum):
 
 
 _sentinel = object()
+# Following `NAME_ERROR_MSG` in `ceval_macros.h`:
+_NAME_ERROR_MSG = "name '{name:.200}' is not defined"
+
 
 # Slots shared by ForwardRef and _Stringifier. The __forward__ names must be
 # preserved for compatibility with the old typing.ForwardRef class. The remaining
@@ -184,7 +187,7 @@ def evaluate(
             elif is_forwardref_format:
                 return self
             else:
-                raise NameError(arg)
+                raise NameError(_NAME_ERROR_MSG.format(name=arg), name=arg)
         else:
             code = self.__forward_code__
             try:

This requires _NAME_ERROR_MSG to be in sync with the one from ceval_macros.h.

Or at least, the NameError should have its name property set (especially as type stubs shows NameError.name as str currently).

cc @JelleZijlstra.

Has this already been discussed elsewhere?

This is a minor feature, which does not need previous discussion elsewhere

Links to previous discussion of this feature:

No response

Linked PRs

  • gh-135646: Raise consistent NameError exceptions in ForwardRef.evaluate() #135663
  • [3.14] gh-135646: Raise consistent NameError exceptions in ForwardRef.evaluate() (GH-135663) #135673

Activity

  1. Viicos
    added
    type-featureA feature request or enhancementA feature request or enhancement
    on Jun 17, 2025
  2. JelleZijlstra commented on Jun 18, 2025

    @JelleZijlstra
    JelleZijlstra
    on Jun 18, 2025
    Member
    More actions

    Yes, let's change this. Feel free to send a PR!

  3. Viicos
    added 2 commits that reference this issue on Jun 18, 2025

    pythongh-135646: Raise consistent `NameError` exceptions in `ForwardR…

    b4843e2

    pythongh-135646: Raise consistent `NameError` exceptions in `ForwardR…

    d28e0a9
  4. JelleZijlstra
    added a commit that references this issue on Jun 18, 2025

    gh-135646: Raise consistent `NameError` exceptions in `ForwardRef.eva…

    343719d
  5. miss-islington
    added a commit that references this issue on Jun 18, 2025

    pythongh-135646: Raise consistent `NameError` exceptions in `ForwardR…

    846c240
  6. JelleZijlstra
    added a commit that references this issue on Jun 18, 2025

    [3.14] gh-135646: Raise consistent `NameError` exceptions in `Forward…

    d4daf4d
  7. JelleZijlstra
    closed this as completedon Jun 18, 2025
  8. lkollar
    added a commit that references this issue on Jun 19, 2025

    pythongh-135646: Raise consistent `NameError` exceptions in `ForwardR…

    ec1acad
  9. Pranjal095
    added a commit that references this issue on Jul 12, 2025

    pythongh-135646: Raise consistent `NameError` exceptions in `ForwardR…

    564d9b5
  10. taegyunkim
    added a commit that references this issue on Aug 4, 2025

    pythongh-135646: Raise consistent `NameError` exceptions in `ForwardR…

    f4d7ae3
  11. Agent-Hellboy
    added a commit that references this issue on Aug 19, 2025

    pythongh-135646: Raise consistent `NameError` exceptions in `ForwardR…

    9c729d1
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    type-featureA feature request or enhancementA feature request or enhancement

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions

      You are visitor 01402503 — GeezerVison does not store the pages you look up.
      Best viewed with Netscape Navigator 4.7 or Internet Explorer 6 at 800×600. No cookies required.