]> granicus.if.org Git - python/commitdiff
Fix SF bug #486144: Uninitialized __slot__ vrbl is None.
authorGuido van Rossum <guido@python.org>
Tue, 4 Dec 2001 16:23:42 +0000 (16:23 +0000)
committerGuido van Rossum <guido@python.org>
Tue, 4 Dec 2001 16:23:42 +0000 (16:23 +0000)
There's now a new structmember code, T_OBJECT_EX, which is used for
all __slot__ variables (except __weakref__, which has special behavior
anyway).  This new code raises AttributeError when the variable is
NULL rather than converting NULL to None.

Include/structmember.h
Lib/test/test_descr.py
Python/structmember.c

index 2c9f41d3dc1a88cd14fa779ff65d0bb540d3f3ef..98eccc056e546978a075b3684b352b0075158fe0 100644 (file)
@@ -68,6 +68,10 @@ typedef struct PyMemberDef {
 #define T_PSTRING_INPLACE      15
 #endif /* macintosh */
 
+#define T_OBJECT_EX    16      /* Like T_OBJECT, but raises AttributeError
+                                  when the value is NULL, instead of
+                                  converting to None. */
+
 /* Flags */
 #define READONLY       1
 #define RO             READONLY                /* Shorthand */
index d76013e753dca73ee527d475825a979d5b00ef09..48d1138a7d033d73b0ef6296b63bae6db7849e91 100644 (file)
@@ -978,19 +978,21 @@ def slots():
         __slots__ = ['a']
     x = C1()
     verify(not hasattr(x, "__dict__"))
-    vereq(x.a, None)
+    verify(not hasattr(x, "a"))
     x.a = 1
     vereq(x.a, 1)
+    x.a = None
+    veris(x.a, None)
     del x.a
-    vereq(x.a, None)
+    verify(not hasattr(x, "a"))
 
     class C3(object):
         __slots__ = ['a', 'b', 'c']
     x = C3()
     verify(not hasattr(x, "__dict__"))
-    verify(x.a is None)
-    verify(x.b is None)
-    verify(x.c is None)
+    verify(not hasattr(x, 'a'))
+    verify(not hasattr(x, 'b'))
+    verify(not hasattr(x, 'c'))
     x.a = 1
     x.b = 2
     x.c = 3
index aa0ea9fe59e405c4717274caed1d245906264dfe..34310b8979d1222de95c9f8e40870ac1e3de01c8 100644 (file)
@@ -129,6 +129,12 @@ PyMember_GetOne(char *addr, PyMemberDef *l)
                        v = Py_None;
                Py_INCREF(v);
                break;
+       case T_OBJECT_EX:
+               v = *(PyObject **)addr;
+               if (v == NULL)
+                       PyErr_SetString(PyExc_AttributeError, l->name);
+               Py_XINCREF(v);
+               break;
        default:
                PyErr_SetString(PyExc_SystemError, "bad memberdescr type");
                v = NULL;
@@ -175,7 +181,7 @@ PyMember_SetOne(char *addr, PyMemberDef *l, PyObject *v)
                PyErr_SetString(PyExc_RuntimeError, "restricted attribute");
                return -1;
        }
-       if (v == NULL && l->type != T_OBJECT) {
+       if (v == NULL && l->type != T_OBJECT_EX && l->type != T_OBJECT) {
                PyErr_SetString(PyExc_TypeError,
                                "can't delete numeric/char attribute");
                return -1;
@@ -246,6 +252,7 @@ PyMember_SetOne(char *addr, PyMemberDef *l, PyObject *v)
                }
                break;
        case T_OBJECT:
+       case T_OBJECT_EX:
                Py_XINCREF(v);
                oldv = *(PyObject **)addr;
                *(PyObject **)addr = v;