mirror of https://github.com/python/cpython
bpo-39904: Move handling of one-argument call of type() from type.__new__() to type.__call__(). (GH-18852)
This commit is contained in:
parent
6012f30bef
commit
413f01352a
|
@ -955,15 +955,9 @@ type_repr(PyTypeObject *type)
|
||||||
static PyObject *
|
static PyObject *
|
||||||
type_call(PyTypeObject *type, PyObject *args, PyObject *kwds)
|
type_call(PyTypeObject *type, PyObject *args, PyObject *kwds)
|
||||||
{
|
{
|
||||||
|
PyObject *obj;
|
||||||
PyThreadState *tstate = _PyThreadState_GET();
|
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
|
#ifdef Py_DEBUG
|
||||||
/* type_call() must not be called with an exception set,
|
/* type_call() must not be called with an exception set,
|
||||||
because it can clear it (directly or indirectly) and so the
|
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));
|
assert(!_PyErr_Occurred(tstate));
|
||||||
#endif
|
#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);
|
obj = _Py_CheckFunctionResult(tstate, (PyObject*)type, obj, NULL);
|
||||||
if (obj == NULL)
|
if (obj == NULL)
|
||||||
return 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,
|
/* If the returned object is not an instance of type,
|
||||||
it won't be initialized. */
|
it won't be initialized. */
|
||||||
if (!PyType_IsSubtype(Py_TYPE(obj), type))
|
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(args != NULL && PyTuple_Check(args));
|
||||||
assert(kwds == NULL || PyDict_Check(kwds));
|
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) */
|
/* Check arguments: (name, bases, dict) */
|
||||||
if (!PyArg_ParseTuple(args, "UO!O!:type.__new__", &name, &PyTuple_Type,
|
if (!PyArg_ParseTuple(args, "UO!O!:type.__new__", &name, &PyTuple_Type,
|
||||||
&bases, &PyDict_Type, &orig_dict))
|
&bases, &PyDict_Type, &orig_dict))
|
||||||
|
|
Loading…
Reference in New Issue