Fix for SF bug #642358: only provide a new with a __dict__ or
authorGuido van Rossum <guido@python.org>
Tue, 7 Jan 2003 13:41:37 +0000 (13:41 +0000)
committerGuido van Rossum <guido@python.org>
Tue, 7 Jan 2003 13:41:37 +0000 (13:41 +0000)
__weaklist__ descriptor if we added __dict__ or __weaklist__,
respectively.  With unit test.

Lib/test/test_descr.py
Objects/typeobject.c

index 974fd25cd70158a42c57168907dec469e2e6de17..023fcc82f53e993603e19055ad9408a8354e03ed 100644 (file)
@@ -3686,6 +3686,19 @@ def subclass_right_op():
     vereq(E(1) / C(1), "C.__div__")
     vereq(C(1) / E(1), "C.__div__") # This one would fail
 
+def dict_type_with_metaclass():
+    if verbose:
+        print "Testing type of __dict__ when __metaclass__ set..."
+
+    class B(object):
+        pass
+    class M(type):
+        pass
+    class C:
+        # In 2.3a1, C.__dict__ was a real dict rather than a dict proxy
+        __metaclass__ = M
+    veris(type(C.__dict__), type(B.__dict__))
+
 
 def test_main():
     do_this_first()
@@ -3771,6 +3784,7 @@ def test_main():
     test_mutable_bases_catch_mro_conflict()
     mutable_names()
     subclass_right_op()
+    dict_type_with_metaclass()
 
     if verbose: print "All OK"
 
index 2de539515c1a419ac7915b2cc780aada7dd5c9c0..e88f5f59248002182cd5d4151ec180c7789ce782 100644 (file)
@@ -1353,9 +1353,9 @@ subtype_getweakref(PyObject *obj, void *context)
        return result;
 }
 
-static PyGetSetDef subtype_getsets[] = {
-       /* Not all objects have these attributes!
-          The descriptor's __get__ method may raise AttributeError. */
+/* Three variants on the subtype_getsets list. */
+
+static PyGetSetDef subtype_getsets_full[] = {
        {"__dict__", subtype_dict, subtype_setdict,
         PyDoc_STR("dictionary for instance variables (if defined)")},
        {"__weakref__", subtype_getweakref, NULL,
@@ -1363,6 +1363,18 @@ static PyGetSetDef subtype_getsets[] = {
        {0}
 };
 
+static PyGetSetDef subtype_getsets_dict_only[] = {
+       {"__dict__", subtype_dict, subtype_setdict,
+        PyDoc_STR("dictionary for instance variables (if defined)")},
+       {0}
+};
+
+static PyGetSetDef subtype_getsets_weakref_only[] = {
+       {"__weakref__", subtype_getweakref, NULL,
+        PyDoc_STR("list of weak references to the object (if defined)")},
+       {0}
+};
+
 /* bozo: __getstate__ that raises TypeError */
 
 static PyObject *
@@ -1810,7 +1822,15 @@ type_new(PyTypeObject *metatype, PyObject *args, PyObject *kwds)
        type->tp_basicsize = slotoffset;
        type->tp_itemsize = base->tp_itemsize;
        type->tp_members = et->members;
-       type->tp_getset = subtype_getsets;
+
+       if (type->tp_weaklistoffset && type->tp_dictoffset)
+               type->tp_getset = subtype_getsets_full;
+       else if (type->tp_weaklistoffset && !type->tp_dictoffset)
+               type->tp_getset = subtype_getsets_weakref_only;
+       else if (!type->tp_weaklistoffset && type->tp_dictoffset)
+               type->tp_getset = subtype_getsets_dict_only;
+       else
+               type->tp_getset = NULL;
 
        /* Special case some slots */
        if (type->tp_dictoffset != 0 || nslots > 0) {