with self.assertRaises(AttributeError):
del X().a
+ # Inherit from object on purpose to check some backwards compatibility paths
+ class X(object):
+ __slots__ = "a"
+ with self.assertRaisesRegex(AttributeError, "'X' object has no attribute 'a'"):
+ X().a
+
def test_slots_special(self):
# Testing __dict__ and __weakref__ in __slots__...
class D(object):
#include "structmember.h" // PyMemberDef
PyObject *
-PyMember_GetOne(const char *addr, PyMemberDef *l)
+PyMember_GetOne(const char *obj_addr, PyMemberDef *l)
{
PyObject *v;
- addr += l->offset;
+ const char* addr = obj_addr + l->offset;
switch (l->type) {
case T_BOOL:
v = PyBool_FromLong(*(char*)addr);
break;
case T_OBJECT_EX:
v = *(PyObject **)addr;
- if (v == NULL)
- PyErr_SetString(PyExc_AttributeError, l->name);
+ if (v == NULL) {
+ PyObject *obj = (PyObject *)obj_addr;
+ PyTypeObject *tp = Py_TYPE(obj);
+ PyErr_Format(PyExc_AttributeError,
+ "'%.200s' object has no attribute '%s'",
+ tp->tp_name, l->name);
+ }
Py_XINCREF(v);
break;
case T_LONGLONG: