Feature or enhancement
Proposal:
The new ForwardRef.evaluate() implementation had a fast path introduced in #124337 to not call eval():
|
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:
|
#define NAME_ERROR_MSG "name '%.200s' is not defined" |
and raised this way:
|
_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
Feature or enhancement
Proposal:
The new
ForwardRef.evaluate()implementation had a fast path introduced in #124337 to not calleval():cpython/Lib/annotationlib.py
Lines 177 to 187 in cb39410
However, when the
NameErroris raised, the format is different from the one raised byeval():The exception message is defined as:
cpython/Python/ceval_macros.h
Line 308 in cb39410
and raised this way:
cpython/Python/ceval.c
Lines 3339 to 3351 in cb39410
To have consistent exceptions raised, would it be possible to change the Python fast path implementation to match the C eval code?
This requires
_NAME_ERROR_MSGto be in sync with the one fromceval_macros.h.Or at least, the
NameErrorshould have itsnameproperty set (especially as type stubs showsNameError.nameasstrcurrently).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
NameErrorexceptions inForwardRef.evaluate()#135663NameErrorexceptions inForwardRef.evaluate()(GH-135663) #135673