Feature or enhancement
Proposal:
People very often raise AttributeError(name) (~40 occurrences in CPython repo) or raise AttributeError (bare, this is rarer), but when displaying the traceback this misses either the object targeted or both the object and the attribute name.
That information is already there. AttributeError.obj and AttributeError.name is automatically set via _PyObject_SetAttributeErrorContext and now is only used to calculate attribute suggestions. Let's improve error messages with it too.
Consider a few examples where the user could raise a bare AttributeError or AttributeError("attr"), how we handle it (-), and how we could handle it (+):
import traceback
class Foo1:
def __getattr__(self, name):
raise AttributeError(name)
try:
Foo1().missing1
except AttributeError as a:
print(f"-{traceback.format_exc().splitlines()[-1]}")
print(f"+AttributeError: {a.obj} has no attribute {a.name!r}\n")
class Foo2:
def __getattr__(self, name):
raise AttributeError
try:
Foo2().missing2
except AttributeError as a:
print(f"-{traceback.format_exc().splitlines()[-1]}")
print(f"+AttributeError: {a.obj} has no attribute {a.name!r}\n")
import mod1 # def __getattr__(name): raise AttributeError(name)
try:
mod1.missing3
except AttributeError as a:
print(f"-{traceback.format_exc().splitlines()[-1]}")
print(f"+AttributeError: {a.obj} has no attribute {a.name!r}\n")
import mod2 # def __getattr__(name): raise AttributeError
try:
mod2.missing4
except AttributeError as a:
print(f"-{traceback.format_exc().splitlines()[-1]}")
print(f"+AttributeError: {a.obj} has no attribute {a.name!r}\n")
-AttributeError: missing1
+AttributeError: <__main__.Foo1 object at 0x109f2c8a0> has no attribute 'missing1'
-AttributeError
+AttributeError: <__main__.Foo2 object at 0x109f2c8a0> has no attribute 'missing2'
-AttributeError: missing3
+AttributeError: <module 'mod1' from './Python/cpython/mod1.py'> has no attribute 'missing3'
-AttributeError
+AttributeError: <module 'mod2' from './Python/cpython/mod2.py'> has no attribute 'missing4'
If we generate messages from collected context, we'll also fix some edge cases in the stdlib and snake knows where else. Consider this functools.singledispatchmethod edge case:
from functools import singledispatchmethod
class C:
@singledispatchmethod
def sdm(self, a):
pass
C().sdm.__code__
which currently fails with - but could be +:
-AttributeError: . Did you mean: '__call__'?
+AttributeError: '_singledispatchmethod_get' object has no attribute '__code__'. Did you mean: '__call__'?
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:
People very often
raise AttributeError(name)(~40 occurrences in CPython repo) orraise AttributeError(bare, this is rarer), but when displaying the traceback this misses either the object targeted or both the object and the attribute name.That information is already there.
AttributeError.objandAttributeError.nameis automatically set via_PyObject_SetAttributeErrorContextand now is only used to calculate attribute suggestions. Let's improve error messages with it too.Consider a few examples where the user could raise a bare
AttributeErrororAttributeError("attr"), how we handle it (-), and how we could handle it (+):If we generate messages from collected context, we'll also fix some edge cases in the stdlib and snake knows where else. Consider this
functools.singledispatchmethodedge case:which currently fails with
-but could be+: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
AttributeErrormessages from context #153786