]> git.ipfire.org Git - thirdparty/Python/cpython.git/commitdiff
bpo-44655: Include the name of the type in unset __slots__ attribute errors (GH-27199)
authorPablo Galindo Salgado <Pablogsal@gmail.com>
Fri, 16 Jul 2021 23:34:46 +0000 (00:34 +0100)
committerGitHub <noreply@github.com>
Fri, 16 Jul 2021 23:34:46 +0000 (00:34 +0100)
Lib/test/test_descr.py
Misc/NEWS.d/next/Core and Builtins/2021-07-16-21-35-14.bpo-44655.95I7M6.rst [new file with mode: 0644]
Python/structmember.c

index 0ff4d022586e18eaa8d9b114a60e8115fa153778..71b6954b6fca35f831f4128d60c089bc65c6d98b 100644 (file)
@@ -1303,6 +1303,12 @@ order (MRO) for bases """
         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):
diff --git a/Misc/NEWS.d/next/Core and Builtins/2021-07-16-21-35-14.bpo-44655.95I7M6.rst b/Misc/NEWS.d/next/Core and Builtins/2021-07-16-21-35-14.bpo-44655.95I7M6.rst
new file mode 100644 (file)
index 0000000..17733b3
--- /dev/null
@@ -0,0 +1,2 @@
+Include the name of the type in unset __slots__ attribute errors. Patch by
+Pablo Galindo
index ba88e15f9386911d31eee3b76e02db9148e0b352..c7e318811d82b8895d40e5fffa01535055ef4f08 100644 (file)
@@ -5,11 +5,11 @@
 #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);
@@ -69,8 +69,13 @@ PyMember_GetOne(const char *addr, PyMemberDef *l)
         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: