]> granicus.if.org Git - python/commitdiff
Issue #27157: Make only type() itself accept the one-argument form
authorBerker Peksag <berker.peksag@gmail.com>
Fri, 19 Aug 2016 08:04:07 +0000 (11:04 +0300)
committerBerker Peksag <berker.peksag@gmail.com>
Fri, 19 Aug 2016 08:04:07 +0000 (11:04 +0300)
Patch by Eryk Sun and Emanuel Barry.

Doc/library/functions.rst
Lib/test/test_types.py
Misc/NEWS
Objects/typeobject.c

index 7216f1d340c04aa3741b4741f9c72f443a43e31b..be6f2ec305fb22f8f9aad5e45c75dc831dedd455 100644 (file)
@@ -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])
 
index 5e741153f42d6c14e6b7e50720a6b611dd9c1fd1..a202196bd2fcfa8c7f05f3739045bc3c25adcdcd 100644 (file)
@@ -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):
 
index bcc808713d4ea8feb210bf79311305c4c0c4c513..1eadf9f0eb40c822eb5216742107a467fbbfb492 100644 (file)
--- 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.
index 1b4c2613b598b3887eb20538a3e6efe7a5a55d81..d141bf4b400a830ed6de253c0a928944c2144312 100644 (file)
@@ -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: */