-
-
Notifications
You must be signed in to change notification settings - Fork 32.4k
Description
Feature or enhancement
Proposal:
The new ForwardRef.evaluate()
implementation had a fast path introduced in #124337 to not call eval()
:
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:
Line 308 in cb39410
#define NAME_ERROR_MSG "name '%.200s' is not defined" |
and raised this way:
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