diff options
author | Serhiy Storchaka <storchaka@gmail.com> | 2020-03-09 17:59:03 (GMT) |
---|---|---|
committer | GitHub <noreply@github.com> | 2020-03-09 17:59:03 (GMT) |
commit | 413f01352a8268fb62bb47bde965462d7b82a06a (patch) | |
tree | e0f1c6d1fe8141df73e950cce303b515d6e6b11c /Objects | |
parent | 6012f30beff7fa8396718dfb198ccafc333c565b (diff) | |
download | cpython-413f01352a8268fb62bb47bde965462d7b82a06a.zip cpython-413f01352a8268fb62bb47bde965462d7b82a06a.tar.gz cpython-413f01352a8268fb62bb47bde965462d7b82a06a.tar.bz2 |
bpo-39904: Move handling of one-argument call of type() from type.__new__() to type.__call__(). (GH-18852)
Diffstat (limited to 'Objects')
-rw-r--r-- | Objects/typeobject.c | 71 |
1 files changed, 32 insertions, 39 deletions
diff --git a/Objects/typeobject.c b/Objects/typeobject.c index ec8dc19..e27c4b2 100644 --- a/Objects/typeobject.c +++ b/Objects/typeobject.c @@ -955,15 +955,9 @@ type_repr(PyTypeObject *type) static PyObject * type_call(PyTypeObject *type, PyObject *args, PyObject *kwds) { + PyObject *obj; PyThreadState *tstate = _PyThreadState_GET(); - if (type->tp_new == NULL) { - _PyErr_Format(tstate, PyExc_TypeError, - "cannot create '%.100s' instances", - type->tp_name); - return NULL; - } - #ifdef Py_DEBUG /* type_call() must not be called with an exception set, because it can clear it (directly or indirectly) and so the @@ -971,19 +965,41 @@ type_call(PyTypeObject *type, PyObject *args, PyObject *kwds) assert(!_PyErr_Occurred(tstate)); #endif - PyObject *obj = type->tp_new(type, args, kwds); + /* Special case: type(x) should return Py_TYPE(x) */ + /* We only want type itself to accept the one-argument form (#27157) */ + if (type == &PyType_Type) { + assert(args != NULL && PyTuple_Check(args)); + assert(kwds == NULL || PyDict_Check(kwds)); + Py_ssize_t nargs = PyTuple_GET_SIZE(args); + + if (nargs == 1 && (kwds == NULL || !PyDict_GET_SIZE(kwds))) { + obj = (PyObject *) Py_TYPE(PyTuple_GET_ITEM(args, 0)); + Py_INCREF(obj); + return obj; + } + + /* SF bug 475327 -- if that didn't trigger, we need 3 + arguments. But PyArg_ParseTuple in type_new may give + a msg saying type() needs exactly 3. */ + if (nargs != 3) { + PyErr_SetString(PyExc_TypeError, + "type() takes 1 or 3 arguments"); + return NULL; + } + } + + if (type->tp_new == NULL) { + _PyErr_Format(tstate, PyExc_TypeError, + "cannot create '%.100s' instances", + type->tp_name); + return NULL; + } + + obj = type->tp_new(type, args, kwds); obj = _Py_CheckFunctionResult(tstate, (PyObject*)type, obj, NULL); if (obj == NULL) return NULL; - /* Ugly exception: when the call was type(something), - don't call tp_init on the result. */ - if (type == &PyType_Type && - PyTuple_Check(args) && PyTuple_GET_SIZE(args) == 1 && - (kwds == NULL || - (PyDict_Check(kwds) && PyDict_GET_SIZE(kwds) == 0))) - return obj; - /* If the returned object is not an instance of type, it won't be initialized. */ if (!PyType_IsSubtype(Py_TYPE(obj), type)) @@ -2345,29 +2361,6 @@ type_new(PyTypeObject *metatype, PyObject *args, PyObject *kwds) assert(args != NULL && PyTuple_Check(args)); assert(kwds == NULL || PyDict_Check(kwds)); - /* Special case: type(x) should return Py_TYPE(x) */ - /* 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_GET_SIZE(kwds); - - if (nargs == 1 && nkwds == 0) { - PyObject *x = PyTuple_GET_ITEM(args, 0); - Py_INCREF(Py_TYPE(x)); - return (PyObject *) Py_TYPE(x); - } - - /* SF bug 475327 -- if that didn't trigger, we need 3 - arguments. but PyArg_ParseTuple below may give - a msg saying type() needs exactly 3. */ - if (nargs != 3) { - PyErr_SetString(PyExc_TypeError, - "type() takes 1 or 3 arguments"); - return NULL; - } - } - /* Check arguments: (name, bases, dict) */ if (!PyArg_ParseTuple(args, "UO!O!:type.__new__", &name, &PyTuple_Type, &bases, &PyDict_Type, &orig_dict)) |