From: Berker Peksag Date: Fri, 19 Aug 2016 08:04:07 +0000 (+0300) Subject: Issue #27157: Make only type() itself accept the one-argument form X-Git-Tag: v3.6.0b1~669 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=3f015a64b83fd243c165147d225cb37dc7e3e645;p=python Issue #27157: Make only type() itself accept the one-argument form Patch by Eryk Sun and Emanuel Barry. --- diff --git a/Doc/library/functions.rst b/Doc/library/functions.rst index 7216f1d340..be6f2ec305 100644 --- a/Doc/library/functions.rst +++ b/Doc/library/functions.rst @@ -1463,6 +1463,9 @@ are always available. They are listed here in alphabetical order. See also :ref:`bltin-type-objects`. + .. versionchanged:: 3.6 + Subclasses of :class:`type` which don't override ``type.__new__`` may no + longer use the one-argument form to get the type of an object. .. function:: vars([object]) diff --git a/Lib/test/test_types.py b/Lib/test/test_types.py index 5e741153f4..a202196bd2 100644 --- a/Lib/test/test_types.py +++ b/Lib/test/test_types.py @@ -1000,6 +1000,24 @@ class ClassCreationTests(unittest.TestCase): with self.assertRaises(TypeError): X = types.new_class("X", (int(), C)) + def test_one_argument_type(self): + expected_message = 'type.__new__() takes exactly 3 arguments (1 given)' + + # Only type itself can use the one-argument form (#27157) + self.assertIs(type(5), int) + + class M(type): + pass + with self.assertRaises(TypeError) as cm: + M(5) + self.assertEqual(str(cm.exception), expected_message) + + class N(type, metaclass=M): + pass + with self.assertRaises(TypeError) as cm: + N(5) + self.assertEqual(str(cm.exception), expected_message) + class SimpleNamespaceTests(unittest.TestCase): diff --git a/Misc/NEWS b/Misc/NEWS index bcc808713d..1eadf9f0eb 100644 --- a/Misc/NEWS +++ b/Misc/NEWS @@ -10,6 +10,9 @@ What's New in Python 3.6.0 beta 1 Core and Builtins ----------------- +- Issue #27157: Make only type() itself accept the one-argument form. + Patch by Eryk Sun and Emanuel Barry. + - Issue #27558: Fix a SystemError in the implementation of "raise" statement. In a brand new thread, raise a RuntimeError since there is no active exception to reraise. Patch written by Xiang Zhang. diff --git a/Objects/typeobject.c b/Objects/typeobject.c index 1b4c2613b5..d141bf4b40 100644 --- a/Objects/typeobject.c +++ b/Objects/typeobject.c @@ -2287,11 +2287,13 @@ type_new(PyTypeObject *metatype, PyObject *args, PyObject *kwds) assert(kwds == NULL || PyDict_Check(kwds)); /* Special case: type(x) should return x->ob_type */ - { + /* We only want type itself to accept the one-argument form (#27157) + Note: We don't call PyType_CheckExact as that also allows subclasses */ + if (metatype == &PyType_Type) { const Py_ssize_t nargs = PyTuple_GET_SIZE(args); const Py_ssize_t nkwds = kwds == NULL ? 0 : PyDict_Size(kwds); - if (PyType_CheckExact(metatype) && nargs == 1 && nkwds == 0) { + if (nargs == 1 && nkwds == 0) { PyObject *x = PyTuple_GET_ITEM(args, 0); Py_INCREF(Py_TYPE(x)); return (PyObject *) Py_TYPE(x); @@ -2308,8 +2310,8 @@ type_new(PyTypeObject *metatype, PyObject *args, PyObject *kwds) } /* Check arguments: (name, bases, dict) */ - if (!PyArg_ParseTuple(args, "UO!O!:type", &name, &PyTuple_Type, &bases, - &PyDict_Type, &orig_dict)) + if (!PyArg_ParseTuple(args, "UO!O!:type.__new__", &name, &PyTuple_Type, + &bases, &PyDict_Type, &orig_dict)) return NULL; /* Determine the proper metatype to deal with this: */