diff -r a1235865dd54 Lib/test/test_abc.py --- a/Lib/test/test_abc.py Sat Apr 09 13:00:17 2011 -0700 +++ b/Lib/test/test_abc.py Sat Apr 09 22:27:18 2011 -0400 @@ -263,6 +263,37 @@ C() self.assertEqual(B.counter, 1) + def test_builtin_classes(self): + class DirectDict(dict, metaclass=abc.ABCMeta): + @abc.abstractmethod + def foo(): + pass + class DirectTuple(tuple, metaclass=abc.ABCMeta): + @abc.abstractmethod + def foo(): + pass + + class Base(metaclass=abc.ABCMeta): + @abc.abstractmethod + def foo(): + pass + class Dict(dict, Base): + pass + class Tuple(tuple, Base): + pass + class List(list, Base): + pass + class Str(str, Base): + pass + + self.assertRaises(TypeError, DirectDict) + self.assertRaises(TypeError, DirectTuple) + self.assertRaises(TypeError, Base) + self.assertRaises(TypeError, Dict) + self.assertRaises(TypeError, Tuple) + self.assertRaises(TypeError, List) + self.assertRaises(TypeError, Str) + def test_main(): support.run_unittest(TestABC) diff -r a1235865dd54 Objects/typeobject.c --- a/Objects/typeobject.c Sat Apr 09 13:00:17 2011 -0700 +++ b/Objects/typeobject.c Sat Apr 09 22:27:18 2011 -0400 @@ -700,9 +700,56 @@ PyType_GenericAlloc(PyTypeObject *type, Py_ssize_t nitems) { PyObject *obj; - const size_t size = _PyObject_VAR_SIZE(type, nitems+1); + size_t size; /* note that we need to add one, for the sentinel */ + if (type->tp_flags & Py_TPFLAGS_IS_ABSTRACT) { + static PyObject *comma = NULL; + PyObject *abstract_methods = NULL; + PyObject *builtins; + PyObject *sorted; + PyObject *sorted_methods = NULL; + PyObject *joined = NULL; + + /* Compute ", ".join(sorted(type.__abstractmethods__)) + into joined. */ + abstract_methods = type_abstractmethods(type, NULL); + if (abstract_methods == NULL) + goto error; + builtins = PyEval_GetBuiltins(); + if (builtins == NULL) + goto error; + sorted = PyDict_GetItemString(builtins, "sorted"); + if (sorted == NULL) + goto error; + sorted_methods = PyObject_CallFunctionObjArgs(sorted, + abstract_methods, + NULL); + if (sorted_methods == NULL) + goto error; + if (comma == NULL) { + comma = PyUnicode_InternFromString(", "); + if (comma == NULL) + goto error; + } + joined = PyObject_CallMethod(comma, "join", + "O", sorted_methods); + if (joined == NULL) + goto error; + + PyErr_Format(PyExc_TypeError, + "Can't instantiate abstract class %s " + "with abstract methods %U", + type->tp_name, + joined); + error: + Py_XDECREF(joined); + Py_XDECREF(sorted_methods); + Py_XDECREF(abstract_methods); + return NULL; + } + + size = _PyObject_VAR_SIZE(type, nitems+1); if (PyType_IS_GC(type)) obj = _PyObject_GC_Malloc(size); else @@ -2801,51 +2848,6 @@ if (err < 0) return NULL; - if (type->tp_flags & Py_TPFLAGS_IS_ABSTRACT) { - static PyObject *comma = NULL; - PyObject *abstract_methods = NULL; - PyObject *builtins; - PyObject *sorted; - PyObject *sorted_methods = NULL; - PyObject *joined = NULL; - - /* Compute ", ".join(sorted(type.__abstractmethods__)) - into joined. */ - abstract_methods = type_abstractmethods(type, NULL); - if (abstract_methods == NULL) - goto error; - builtins = PyEval_GetBuiltins(); - if (builtins == NULL) - goto error; - sorted = PyDict_GetItemString(builtins, "sorted"); - if (sorted == NULL) - goto error; - sorted_methods = PyObject_CallFunctionObjArgs(sorted, - abstract_methods, - NULL); - if (sorted_methods == NULL) - goto error; - if (comma == NULL) { - comma = PyUnicode_InternFromString(", "); - if (comma == NULL) - goto error; - } - joined = PyObject_CallMethod(comma, "join", - "O", sorted_methods); - if (joined == NULL) - goto error; - - PyErr_Format(PyExc_TypeError, - "Can't instantiate abstract class %s " - "with abstract methods %U", - type->tp_name, - joined); - error: - Py_XDECREF(joined); - Py_XDECREF(sorted_methods); - Py_XDECREF(abstract_methods); - return NULL; - } return type->tp_alloc(type, 0); }