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.
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 @@
     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 @@
     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 @@
 	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 @@
 	{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->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) {