summaryrefslogtreecommitdiffstats
path: root/Objects
diff options
context:
space:
mode:
authorSerhiy Storchaka <storchaka@gmail.com>2020-03-09 17:59:03 (GMT)
committerGitHub <noreply@github.com>2020-03-09 17:59:03 (GMT)
commit413f01352a8268fb62bb47bde965462d7b82a06a (patch)
treee0f1c6d1fe8141df73e950cce303b515d6e6b11c /Objects
parent6012f30beff7fa8396718dfb198ccafc333c565b (diff)
downloadcpython-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.c71
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))