summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBerker Peksag <berker.peksag@gmail.com>2016-08-19 08:04:07 (GMT)
committerBerker Peksag <berker.peksag@gmail.com>2016-08-19 08:04:07 (GMT)
commit3f015a64b83fd243c165147d225cb37dc7e3e645 (patch)
tree051733732e931ef146f3da1b4509d87382d90cff
parent2a400fd62a292e43df75ca687c4d350e9a98af44 (diff)
downloadcpython-3f015a64b83fd243c165147d225cb37dc7e3e645.zip
cpython-3f015a64b83fd243c165147d225cb37dc7e3e645.tar.gz
cpython-3f015a64b83fd243c165147d225cb37dc7e3e645.tar.bz2
Issue #27157: Make only type() itself accept the one-argument form
Patch by Eryk Sun and Emanuel Barry.
-rw-r--r--Doc/library/functions.rst3
-rw-r--r--Lib/test/test_types.py18
-rw-r--r--Misc/NEWS3
-rw-r--r--Objects/typeobject.c10
4 files changed, 30 insertions, 4 deletions
diff --git a/Doc/library/functions.rst b/Doc/library/functions.rst
index 7216f1d..be6f2ec 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 5e74115..a202196 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 bcc8087..1eadf9f 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 1b4c261..d141bf4 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: */