1# mode: run 2# tag: cyfunction,call,python 3# cython: binding=True 4 5####### 6# Test that Cython and Python functions can call each other in various signature combinations. 7####### 8 9py_call_noargs = eval("lambda: 'noargs'") 10py_call_onearg = eval("lambda arg: arg") 11py_call_twoargs = eval("lambda arg, arg2: (arg, arg2)") 12py_call_starargs = eval("lambda *args: args") 13py_call_pos_and_starargs = eval("lambda arg, *args: (arg, args)") 14py_call_starstarargs = eval("lambda **kw: sorted(kw.items())") 15py_call_args_and_starstarargs = eval("lambda *args, **kw: (args, sorted(kw.items()))") 16 17 18def cy_call_noargs(): 19 """ 20 >>> cy_call_noargs() 21 'noargs' 22 """ 23 return py_call_noargs() 24 25 26def cy_call_onearg(f): 27 """ 28 >>> cy_call_onearg(py_call_onearg) 29 'onearg' 30 >>> try: cy_call_onearg(py_call_noargs) 31 ... except TypeError: pass 32 ... else: print("FAILED!") 33 >>> try: cy_call_onearg(py_call_twoargs) 34 ... except TypeError: pass 35 ... else: print("FAILED!") 36 37 >>> class Class(object): 38 ... def method(self, arg): return arg 39 40 >>> cy_call_onearg(Class().method) 41 'onearg' 42 """ 43 return f('onearg') 44 45 46def cy_call_twoargs(f, arg): 47 """ 48 >>> cy_call_twoargs(py_call_twoargs, 132) 49 (132, 'twoargs') 50 51 >>> class Class2(object): 52 ... def method(self, arg, arg2): return arg, arg2 53 >>> cy_call_twoargs(Class2().method, 123) 54 (123, 'twoargs') 55 56 >>> class Class1(object): 57 ... def method(self, arg): return arg 58 >>> cy_call_twoargs(Class1.method, Class1()) 59 'twoargs' 60 """ 61 return f(arg, 'twoargs') 62 63 64def cy_call_two_kwargs(f, arg): 65 """ 66 >>> cy_call_two_kwargs(py_call_twoargs, arg=132) 67 (132, 'two-kwargs') 68 >>> cy_call_two_kwargs(f=py_call_twoargs, arg=132) 69 (132, 'two-kwargs') 70 >>> cy_call_two_kwargs(arg=132, f=py_call_twoargs) 71 (132, 'two-kwargs') 72 73 >>> class Class(object): 74 ... def method(self, arg, arg2): return arg, arg2 75 76 >>> cy_call_two_kwargs(Class().method, 123) 77 (123, 'two-kwargs') 78 """ 79 return f(arg2='two-kwargs', arg=arg) 80 81 82def cy_call_starargs(*args): 83 """ 84 >>> cy_call_starargs() 85 () 86 >>> cy_call_starargs(1) 87 (1,) 88 >>> cy_call_starargs(1, 2) 89 (1, 2) 90 >>> cy_call_starargs(1, 2, 3) 91 (1, 2, 3) 92 """ 93 return py_call_starargs(*args) 94 95 96def cy_call_pos_and_starargs(f, *args): 97 """ 98 >>> cy_call_pos_and_starargs(py_call_onearg) 99 'no-arg' 100 >>> cy_call_pos_and_starargs(py_call_onearg, 123) 101 123 102 >>> cy_call_pos_and_starargs(py_call_twoargs, 123, 321) 103 (123, 321) 104 >>> cy_call_pos_and_starargs(py_call_starargs) 105 ('no-arg',) 106 >>> cy_call_pos_and_starargs(py_call_starargs, 123) 107 (123,) 108 >>> cy_call_pos_and_starargs(py_call_starargs, 123, 321) 109 (123, 321) 110 >>> cy_call_pos_and_starargs(py_call_pos_and_starargs) 111 ('no-arg', ()) 112 >>> cy_call_pos_and_starargs(py_call_pos_and_starargs, 123) 113 (123, ()) 114 >>> cy_call_pos_and_starargs(py_call_pos_and_starargs, 123, 321) 115 (123, (321,)) 116 >>> cy_call_pos_and_starargs(py_call_pos_and_starargs, 123, 321, 234) 117 (123, (321, 234)) 118 119 >>> class Class(object): 120 ... def method(self, arg, arg2): return arg, arg2 121 122 >>> cy_call_pos_and_starargs(Class().method, 123, 321) 123 (123, 321) 124 >>> cy_call_pos_and_starargs(Class.method, Class(), 123, 321) 125 (123, 321) 126 """ 127 return f(args[0] if args else 'no-arg', *args[1:]) 128 129 130def cy_call_starstarargs(**kw): 131 """ 132 >>> kw = {} 133 >>> cy_call_starstarargs(**kw) 134 [] 135 >>> kw = {'a': 123} 136 >>> cy_call_starstarargs(**kw) 137 [('a', 123)] 138 >>> kw = {'a': 123, 'b': 321} 139 >>> cy_call_starstarargs(**kw) 140 [('a', 123), ('b', 321)] 141 """ 142 return py_call_starstarargs(**kw) 143 144 145def cy_call_kw_and_starstarargs(f=None, arg1=None, **kw): 146 """ 147 >>> kw = {} 148 >>> cy_call_kw_and_starstarargs(**kw) 149 [('arg', None)] 150 >>> try: cy_call_kw_and_starstarargs(py_call_noargs, **kw) 151 ... except TypeError: pass 152 >>> try: cy_call_kw_and_starstarargs(py_call_twoargs, **kw) 153 ... except TypeError: pass 154 ... else: print("FAILED!") 155 >>> cy_call_kw_and_starstarargs(py_call_onearg, **kw) 156 >>> cy_call_kw_and_starstarargs(f=py_call_onearg, **kw) 157 >>> cy_call_kw_and_starstarargs(py_call_pos_and_starargs, **kw) 158 (None, ()) 159 160 >>> kw = {'arg1': 123} 161 >>> cy_call_kw_and_starstarargs(**kw) 162 [('arg', 123)] 163 >>> cy_call_kw_and_starstarargs(py_call_onearg, **kw) 164 123 165 >>> cy_call_kw_and_starstarargs(f=py_call_onearg, **kw) 166 123 167 >>> cy_call_kw_and_starstarargs(py_call_twoargs, arg2=321, **kw) 168 (123, 321) 169 >>> cy_call_kw_and_starstarargs(f=py_call_twoargs, arg2=321, **kw) 170 (123, 321) 171 >>> try: cy_call_kw_and_starstarargs(py_call_twoargs, **kw) 172 ... except TypeError: pass 173 ... else: print("FAILED!") 174 >>> try: cy_call_kw_and_starstarargs(py_call_twoargs, arg2=321, other=234, **kw) 175 ... except TypeError: pass 176 ... else: print("FAILED!") 177 >>> cy_call_kw_and_starstarargs(py_call_pos_and_starargs, **kw) 178 (123, ()) 179 180 >>> try: cy_call_kw_and_starstarargs(arg=321, **kw) # duplicate kw in Python call 181 ... except TypeError: pass 182 ... else: print("FAILED!") 183 184 >>> kw = {'a': 123} 185 >>> cy_call_kw_and_starstarargs(**kw) 186 [('a', 123), ('arg', None)] 187 >>> cy_call_kw_and_starstarargs(arg1=321, **kw) 188 [('a', 123), ('arg', 321)] 189 190 >>> kw = {'a': 123, 'b': 321} 191 >>> cy_call_kw_and_starstarargs(**kw) 192 [('a', 123), ('arg', None), ('b', 321)] 193 >>> cy_call_kw_and_starstarargs(arg1=234, **kw) 194 [('a', 123), ('arg', 234), ('b', 321)] 195 196 >>> class Class2(object): 197 ... def method(self, arg, arg2): return arg, arg2 198 199 >>> cy_call_kw_and_starstarargs(Class2().method, arg1=123, arg2=321) 200 (123, 321) 201 """ 202 return (f or py_call_starstarargs)(arg=arg1, **kw) 203 204 205def cy_call_pos_and_starstarargs(f=None, arg1=None, **kw): 206 """ 207 >>> cy_call_pos_and_starstarargs(arg=123) 208 ((None,), [('arg', 123)]) 209 >>> cy_call_pos_and_starstarargs(arg1=123) 210 ((123,), []) 211 >>> cy_call_pos_and_starstarargs(arg=123, arg2=321) 212 ((None,), [('arg', 123), ('arg2', 321)]) 213 >>> cy_call_pos_and_starstarargs(arg1=123, arg2=321) 214 ((123,), [('arg2', 321)]) 215 216 >>> class Class2(object): 217 ... def method(self, arg, arg2=None): return arg, arg2 218 219 >>> cy_call_pos_and_starstarargs(Class2().method, 123) 220 (123, None) 221 >>> cy_call_pos_and_starstarargs(Class2().method, 123, arg2=321) 222 (123, 321) 223 >>> cy_call_pos_and_starstarargs(Class2().method, arg1=123, arg2=321) 224 (123, 321) 225 >>> cy_call_pos_and_starstarargs(Class2.method, Class2(), arg=123) 226 (123, None) 227 >>> cy_call_pos_and_starstarargs(Class2.method, Class2(), arg=123, arg2=321) 228 (123, 321) 229 >>> cy_call_pos_and_starstarargs(Class2.method, arg1=Class2(), arg=123, arg2=321) 230 (123, 321) 231 """ 232 return (f or py_call_args_and_starstarargs)(arg1, **kw) 233