summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGuido van Rossum <guido@python.org>2003-01-07 13:41:37 (GMT)
committerGuido van Rossum <guido@python.org>2003-01-07 13:41:37 (GMT)
commit373c7412f297c375d84c5984f753557b441dd6f4 (patch)
tree4ab1908125675023d61bb0670eaaf6a5acab8f55
parent145a4a0f10009f7ce2644465ccd359938b034ac4 (diff)
downloadcpython-373c7412f297c375d84c5984f753557b441dd6f4.zip
cpython-373c7412f297c375d84c5984f753557b441dd6f4.tar.gz
cpython-373c7412f297c375d84c5984f753557b441dd6f4.tar.bz2
Fix for SF bug #642358: only provide a new with a __dict__ or
__weaklist__ descriptor if we added __dict__ or __weaklist__, respectively. With unit test.
-rw-r--r--Lib/test/test_descr.py14
-rw-r--r--Objects/typeobject.c28
2 files changed, 38 insertions, 4 deletions
diff --git a/Lib/test/test_descr.py b/Lib/test/test_descr.py
index 974fd25..023fcc8 100644
--- a/Lib/test/test_descr.py
+++ b/Lib/test/test_descr.py
@@ -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"
diff --git a/Objects/typeobject.c b/Objects/typeobject.c
index 2de5395..e88f5f5 100644
--- a/Objects/typeobject.c
+++ b/Objects/typeobject.c
@@ -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) {