Pyx_tp_new_func_type = PyrexTypes.CFuncType(
PyrexTypes.py_object_type, [
- PyrexTypes.CFuncTypeArg("type", Builtin.type_type, None)
+ PyrexTypes.CFuncTypeArg("type", Builtin.type_type, None),
+ PyrexTypes.CFuncTypeArg("args", Builtin.tuple_type, None),
])
- def _handle_simple_slot__new__(self, node, args, is_unbound_method):
- """Replace 'exttype.__new__(exttype)' by a call to exttype->tp_new()
+ Pyx_tp_new_kwargs_func_type = PyrexTypes.CFuncType(
+ PyrexTypes.py_object_type, [
+ PyrexTypes.CFuncTypeArg("type", Builtin.type_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()
"""
obj = node.function.obj
- if not is_unbound_method or len(args) != 1:
+ if not is_unbound_method or len(args) < 1:
return node
type_arg = args[0]
if not obj.is_name or not type_arg.is_name:
type_arg = type_arg.as_none_safe_node(
"object.__new__(X): X is not a type object (NoneType)")
- return ExprNodes.PythonCapiCallNode(
- node.pos, "__Pyx_tp_new", self.Pyx_tp_new_func_type,
- args=[type_arg],
- utility_code=UtilityCode.load_cached('tp_new', 'ObjectHandling.c'),
- is_temp=node.is_temp
+ 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(
+ node.pos, "__Pyx_tp_new_kwargs", self.Pyx_tp_new_kwargs_func_type,
+ args=[type_arg, args_tuple, kwargs],
+ utility_code=utility_code,
+ is_temp=node.is_temp
+ )
+ else:
+ return ExprNodes.PythonCapiCallNode(
+ node.pos, "__Pyx_tp_new", self.Pyx_tp_new_func_type,
+ args=[type_arg, args_tuple],
+ utility_code=utility_code,
+ is_temp=node.is_temp
)
### methods of builtin types
/////////////// tp_new.proto ///////////////
-//@substitute: naming
-static CYTHON_INLINE PyObject* __Pyx_tp_new(PyObject* type_obj) {
+#define __Pyx_tp_new(type_obj, args) __Pyx_tp_new_kwargs(type_obj, args, NULL)
+static CYTHON_INLINE PyObject* __Pyx_tp_new_kwargs(PyObject* type_obj, PyObject* args, PyObject* kwargs) {
return (PyObject*) (((PyTypeObject*)(type_obj))->tp_new(
- (PyTypeObject*)(type_obj), $empty_tuple, NULL));
+ (PyTypeObject*)(type_obj), args, kwargs));
}
cimport cython
cdef class MyType:
- def __cinit__(self):
+ cdef public args, kwargs
+ def __cinit__(self, *args, **kwargs):
+ self.args, self.kwargs = args, kwargs
print "CINIT"
- def __init__(self):
+ def __init__(self, *args, **kwargs):
print "INIT"
cdef class MySubType(MyType):
- def __cinit__(self):
+ def __cinit__(self, *args, **kwargs):
+ self.args, self.kwargs = args, kwargs
print "CINIT(SUB)"
- def __init__(self):
+ def __init__(self, *args, **kwargs):
print "INIT"
class MyClass(object):
- def __cinit__(self):
+ def __cinit__(self, *args, **kwargs):
+ self.args, self.kwargs = args, kwargs
print "CINIT"
- def __init__(self):
+ def __init__(self, *args, **kwargs):
print "INIT"
class MyTypeSubClass(MyType):
- def __cinit__(self):
+ def __cinit__(self, *args, **kwargs):
# not called: Python class!
print "CINIT(PYSUB)"
- def __init__(self):
+ def __init__(self, *args, **kwargs):
print "INIT"
# only these can be safely optimised:
@cython.test_assert_path_exists('//PythonCapiCallNode')
@cython.test_fail_if_path_exists('//SimpleCallNode/AttributeNode')
+def make_new_with_args():
+ """
+ >>> isinstance(make_new_with_args(), MyType)
+ CINIT
+ (1, 2, 3)
+ {}
+ True
+ """
+ m = MyType.__new__(MyType, 1, 2 ,3)
+ print m.args
+ print m.kwargs
+ return m
+
+@cython.test_assert_path_exists('//PythonCapiCallNode')
+@cython.test_fail_if_path_exists('//SimpleCallNode/AttributeNode')
+def make_new_with_args_kwargs():
+ """
+ >>> isinstance(make_new_with_args_kwargs(), MyType)
+ CINIT
+ (1, 2, 3)
+ {'a': 4}
+ True
+ """
+ m = MyType.__new__(MyType, 1, 2 ,3, a=4)
+ print m.args
+ print m.kwargs
+ return m
+
+@cython.test_assert_path_exists('//PythonCapiCallNode')
+@cython.test_fail_if_path_exists('//SimpleCallNode/AttributeNode')
def make_new_builtin():
"""
>>> isinstance(make_new_builtin(), tuple)