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.
This commit is contained in:
Guido van Rossum 2003-01-07 13:41:37 +00:00
parent 145a4a0f10
commit 373c7412f2
2 changed files with 38 additions and 4 deletions

View 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"

View 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) {