with self.assertRaises(RecursionError):
add_one_level()
+ def testMetaclassCallOptimization(self):
+ calls = 0
+
+ class TypeMetaclass(type):
+ def __call__(cls, *args, **kwargs):
+ nonlocal calls
+ calls += 1
+ return type.__call__(cls, *args, **kwargs)
+
+ class Type(metaclass=TypeMetaclass):
+ def __init__(self, obj):
+ self._obj = obj
+
+ for i in range(100):
+ Type(i)
+ self.assertEqual(calls, 100)
if __name__ == '__main__':
unittest.main()
--- /dev/null
+No longer specialize calls to classes, if those classes have metaclasses.
+Fixes bug where the ``__call__`` method of the metaclass was not being
+called.
#define SPEC_FAIL_CALL_METHOD_WRAPPER 28
#define SPEC_FAIL_CALL_OPERATOR_WRAPPER 29
#define SPEC_FAIL_CALL_INIT_NOT_SIMPLE 30
+#define SPEC_FAIL_CALL_METACLASS 31
/* COMPARE_OP */
#define SPEC_FAIL_COMPARE_OP_DIFFERENT_TYPES 12
SPEC_FAIL_CALL_STR : SPEC_FAIL_CALL_CLASS_NO_VECTORCALL);
return -1;
}
+ if (Py_TYPE(tp) != &PyType_Type) {
+ SPECIALIZATION_FAIL(CALL, SPEC_FAIL_CALL_METACLASS);
+ return -1;
+ }
if (tp->tp_new == PyBaseObject_Type.tp_new) {
PyFunctionObject *init = get_init_for_simple_managed_python_class(tp);
if (type_get_version(tp, CALL) == 0) {