Skip to content

Commit a7e7f0a

Browse files
committed
Special-case class objects
1 parent a419eb2 commit a7e7f0a

2 files changed

Lines changed: 39 additions & 0 deletions

File tree

Lib/test/test_exceptions.py

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2084,6 +2084,42 @@ def __getattr__(self, name):
20842084
self.assertIs(cm.exception.obj, obj)
20852085
self.assertEqual(cm.exception.name, "missing3")
20862086

2087+
def test_class_getattr_error_message(self):
2088+
def fqn(type):
2089+
return f'{type.__module__}.{type.__qualname__}'
2090+
2091+
class MetaclassRaiseWithName(type):
2092+
def __getattr__(self, name):
2093+
raise AttributeError(name)
2094+
cls = MetaclassRaiseWithName("spam", (), {})
2095+
with self.assertRaises(AttributeError) as cm:
2096+
getattr(cls, "missing1")
2097+
self.assertEqual(str(cm.exception),
2098+
f"type object '{fqn(cls)}' has no attribute 'missing1'")
2099+
self.assertIs(cm.exception.obj, cls)
2100+
self.assertEqual(cm.exception.name, "missing1")
2101+
2102+
class MetaclassBareRaise(type):
2103+
def __getattr__(self, name):
2104+
raise AttributeError
2105+
cls = MetaclassBareRaise("eggs", (), {})
2106+
with self.assertRaises(AttributeError) as cm:
2107+
getattr(cls, "missing2")
2108+
self.assertEqual(str(cm.exception),
2109+
f"type object '{fqn(cls)}' has no attribute 'missing2'")
2110+
self.assertIs(cm.exception.obj, cls)
2111+
self.assertEqual(cm.exception.name, "missing2")
2112+
2113+
class MetaclassRaiseCustom(type):
2114+
def __getattr__(self, name):
2115+
raise AttributeError("custom")
2116+
cls = MetaclassRaiseCustom("ham", (), {})
2117+
with self.assertRaises(AttributeError) as cm:
2118+
getattr(cls, "missing3")
2119+
self.assertEqual(str(cm.exception), "custom")
2120+
self.assertIs(cm.exception.obj, cls)
2121+
self.assertEqual(cm.exception.name, "missing3")
2122+
20872123
def test_module_getattr_error_message(self):
20882124
raisewithname_mod = ModuleType("raisewithname")
20892125
def raise_with_name(name):

Objects/exceptions.c

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2738,6 +2738,9 @@ AttributeError_str(PyObject *op)
27382738
} else {
27392739
result = PyUnicode_FromFormat("module has no attribute '%U'", name);
27402740
}
2741+
} else if (PyType_Check(obj)) {
2742+
result = PyUnicode_FromFormat("type object '%N' has no attribute '%U'",
2743+
_PyType_CAST(obj), name);
27412744
} else {
27422745
result = PyUnicode_FromFormat("'%T' object has no attribute '%U'",
27432746
obj, name);

0 commit comments

Comments
 (0)