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 *
|
||||
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))
|
||||
|
|
Loading…
Reference in New Issue