diff --git a/Lib/test/test_types.py b/Lib/test/test_types.py --- a/Lib/test/test_types.py +++ b/Lib/test/test_types.py @@ -1170,9 +1170,26 @@ self.assertEqual(ns, ns_roundtrip, pname) +class SharedKeyTests(unittest.TestCase): + + def test_subclasses(self): + # Verify that subclasses can share keys (per PEP 412) + class A: + pass + class B(A): + pass + + a, b = A(), B() + self.assertEqual(sys.getsizeof(vars(a)), sys.getsizeof(vars(b))) + a.x, a.y, a.z, a.w = range(4) + self.assertNotEqual(sys.getsizeof(vars(a)), sys.getsizeof(vars(b))) + a2 = A() + self.assertEqual(sys.getsizeof(vars(a)), sys.getsizeof(vars(a2))) + + def test_main(): run_unittest(TypesTests, MappingProxyTests, ClassCreationTests, - SimpleNamespaceTests) + SimpleNamespaceTests, SharedKeyTests) if __name__ == '__main__': test_main() diff --git a/Objects/typeobject.c b/Objects/typeobject.c --- a/Objects/typeobject.c +++ b/Objects/typeobject.c @@ -2440,6 +2440,9 @@ type->tp_dictoffset = slotoffset; slotoffset += sizeof(PyObject *); } + else if (!type->tp_dictoffset) { + type->tp_dictoffset = base->tp_dictoffset; + } if (type->tp_dictoffset) { et->ht_cached_keys = _PyDict_NewKeysForClass(); } @@ -4342,7 +4345,6 @@ COPYVAL(tp_itemsize); COPYVAL(tp_weaklistoffset); - COPYVAL(tp_dictoffset); /* Setup fast subclass flags */ if (PyType_IsSubtype(base, (PyTypeObject*)PyExc_BaseException))