Pyx_tp_new_func_type = PyrexTypes.CFuncType(
PyrexTypes.py_object_type, [
- PyrexTypes.CFuncTypeArg("type", Builtin.type_type, None),
+ PyrexTypes.CFuncTypeArg("type", PyrexTypes.py_object_type, None),
PyrexTypes.CFuncTypeArg("args", Builtin.tuple_type, None),
])
Pyx_tp_new_kwargs_func_type = PyrexTypes.CFuncType(
PyrexTypes.py_object_type, [
- PyrexTypes.CFuncTypeArg("type", Builtin.type_type, None),
+ PyrexTypes.CFuncTypeArg("type", PyrexTypes.py_object_type, None),
PyrexTypes.CFuncTypeArg("args", Builtin.tuple_type, None),
PyrexTypes.CFuncTypeArg("kwargs", Builtin.dict_type, None),
])
+ Pyx_call_tp_new_func_type = PyrexTypes.CFuncType(
+ PyrexTypes.py_object_type, [
+ PyrexTypes.CFuncTypeArg("tpnew_func", PyrexTypes.c_void_ptr_type, None),
+ PyrexTypes.CFuncTypeArg("type", PyrexTypes.py_object_type, None),
+ PyrexTypes.CFuncTypeArg("args", Builtin.tuple_type, None),
+ ])
+
+ Pyx_call_tp_new_kwargs_func_type = PyrexTypes.CFuncType(
+ PyrexTypes.py_object_type, [
+ PyrexTypes.CFuncTypeArg("tpnew_func", PyrexTypes.c_void_ptr_type, None),
+ PyrexTypes.CFuncTypeArg("type", PyrexTypes.py_object_type, None),
+ PyrexTypes.CFuncTypeArg("args", Builtin.tuple_type, None),
+ PyrexTypes.CFuncTypeArg("kwargs", Builtin.dict_type, None),
+ ])
+
def _handle_any_slot__new__(self, node, args, is_unbound_method, kwargs=None):
"""Replace 'exttype.__new__(exttype, ...)' by a call to exttype->tp_new()
"""
# different types - may or may not lead to an error at runtime
return node
- # FIXME: we could potentially look up the actual tp_new C
- # method of the extension type and call that instead of the
- # generic slot. That would also allow us to pass parameters
- # efficiently.
+ args_tuple = ExprNodes.TupleNode(node.pos, args=args[1:])
+ args_tuple = args_tuple.analyse_types(
+ self.current_env(), skip_children=True)
- if not type_arg.type_entry:
+ if type_arg.type_entry:
+ ext_type = type_arg.type_entry.type
+ if ext_type.is_extension_type and not ext_type.is_external:
+ utility_code = UtilityCode.load_cached(
+ 'call_tp_new', 'ObjectHandling.c')
+ slot_func_cname = ext_type.scope.mangle_internal("tp_new")
+ slot_func = ExprNodes.RawCNameExprNode(
+ node.pos, cname=slot_func_cname,
+ type=PyrexTypes.c_void_ptr_type)
+
+ if kwargs:
+ return ExprNodes.PythonCapiCallNode(
+ node.pos, "__Pyx_call_tp_new_kwargs",
+ self.Pyx_call_tp_new_kwargs_func_type,
+ args=[slot_func, type_arg, args_tuple, kwargs],
+ utility_code=utility_code,
+ is_temp=node.is_temp
+ )
+ else:
+ return ExprNodes.PythonCapiCallNode(
+ node.pos, "__Pyx_call_tp_new",
+ self.Pyx_call_tp_new_func_type,
+ args=[slot_func, type_arg, args_tuple],
+ utility_code=utility_code,
+ is_temp=node.is_temp
+ )
+ else:
# arbitrary variable, needs a None check for safety
type_arg = type_arg.as_none_safe_node(
"object.__new__(X): X is not a type object (NoneType)")
- args_tuple = ExprNodes.TupleNode(node.pos, args=args[1:])
- args_tuple = args_tuple.analyse_types(
- self.current_env(), skip_children=True)
-
utility_code = UtilityCode.load_cached('tp_new', 'ObjectHandling.c')
if kwargs:
return ExprNodes.PythonCapiCallNode(