1# cython: binding=True 2# mode: run 3# tag: cyfunction, closures 4 5cimport cython 6import sys 7 8def get_defaults(func): 9 if sys.version_info >= (2, 6, 0): 10 return func.__defaults__ 11 return func.func_defaults 12 13def test_defaults_none(): 14 """ 15 >>> get_defaults(test_defaults_none) 16 """ 17 18def test_defaults_literal(a=1, b=(1,2,3)): 19 """ 20 >>> get_defaults(test_defaults_literal) is get_defaults(test_defaults_literal) 21 True 22 >>> get_defaults(test_defaults_literal) 23 (1, (1, 2, 3)) 24 >>> a, b = get_defaults(test_defaults_literal) 25 >>> c, d = test_defaults_literal() 26 >>> a is c 27 True 28 >>> b is d 29 True 30 """ 31 return a, b 32 33def test_defaults_nonliteral(): 34 """ 35 >>> f0, f1 = test_defaults_nonliteral() 36 >>> get_defaults(f0) is get_defaults(f0) # cached 37 True 38 >>> get_defaults(f0) 39 (0, {}, (1, 2, 3)) 40 >>> a, b = get_defaults(f0)[1:] 41 >>> c, d = f0(0) 42 >>> a is c 43 True 44 >>> b is d 45 True 46 >>> get_defaults(f1) is get_defaults(f1) # cached 47 True 48 >>> get_defaults(f1) 49 (0, [], (1, 2, 3)) 50 >>> a, b = get_defaults(f1)[1:] 51 >>> c, d = f1(0) 52 >>> a is c 53 True 54 >>> b is d 55 True 56 """ 57 ret = [] 58 for i in {}, []: 59 def foo(a, b=0, c=i, d=(1,2,3)): 60 return c, d 61 ret.append(foo) 62 return ret 63 64_counter = 0 65def counter(): 66 global _counter 67 _counter += 1 68 return _counter 69 70def test_defaults_nonliteral_func_call(f): 71 """ 72 >>> f = test_defaults_nonliteral_func_call(counter) 73 >>> f() 74 1 75 >>> get_defaults(f) 76 (1,) 77 >>> f = test_defaults_nonliteral_func_call(lambda: list()) 78 >>> f() 79 [] 80 >>> get_defaults(f) 81 ([],) 82 >>> get_defaults(f)[0] is f() 83 True 84 """ 85 def func(a=f()): 86 return a 87 return func 88 89 90def cy_kwonly_default_args(a, x=1, *, b=2): 91 l = m = 1 92 93def test_kwdefaults(value): 94 """ 95 >>> cy_kwonly_default_args.__defaults__ 96 (1,) 97 >>> cy_kwonly_default_args.func_defaults 98 (1,) 99 100 >>> cy_kwonly_default_args.__kwdefaults__ 101 {'b': 2} 102 103 >>> test_kwdefaults.__defaults__ 104 >>> test_kwdefaults.__kwdefaults__ 105 106 >>> f = test_kwdefaults(5) 107 >>> f.__defaults__ 108 (1,) 109 >>> f.__kwdefaults__ 110 {'b': 5} 111 >>> f.__kwdefaults__ = () 112 Traceback (most recent call last): 113 TypeError: __kwdefaults__ must be set to a dict object 114 >>> f.__kwdefaults__ = None 115 >>> f.__kwdefaults__ 116 >>> f.__kwdefaults__ = {} 117 >>> f.__kwdefaults__ 118 {} 119 >>> f.__kwdefaults__ = {'a': 2} 120 >>> f.__kwdefaults__ 121 {'a': 2} 122 """ 123 def kwonly_default_args(a, x=1, *, b=value): 124 return a, x, b 125 return kwonly_default_args 126 127 128_counter2 = 1.0 129def counter2(): 130 global _counter2 131 _counter2 += 1.0 132 return _counter2 133 134def test_defaults_fused(cython.floating arg1, cython.floating arg2 = counter2()): 135 """ 136 >>> test_defaults_fused(1.0) 137 1.0 2.0 138 >>> test_defaults_fused(1.0, 3.0) 139 1.0 3.0 140 >>> _counter2 141 2.0 142 143 >>> get_defaults(test_defaults_fused) 144 (2.0,) 145 >>> get_defaults(test_defaults_fused[float]) 146 (2.0,) 147 """ 148 print arg1, arg2 149 150funcs = [] 151for i in range(10): 152 def defaults_fused(cython.floating a, cython.floating b = i): 153 return a, b 154 funcs.append(defaults_fused) 155 156def test_dynamic_defaults_fused(): 157 """ 158 >>> test_dynamic_defaults_fused() 159 i 0 func result (1.0, 0.0) defaults (0,) 160 i 1 func result (1.0, 1.0) defaults (1,) 161 i 2 func result (1.0, 2.0) defaults (2,) 162 i 3 func result (1.0, 3.0) defaults (3,) 163 i 4 func result (1.0, 4.0) defaults (4,) 164 i 5 func result (1.0, 5.0) defaults (5,) 165 i 6 func result (1.0, 6.0) defaults (6,) 166 i 7 func result (1.0, 7.0) defaults (7,) 167 i 8 func result (1.0, 8.0) defaults (8,) 168 i 9 func result (1.0, 9.0) defaults (9,) 169 """ 170 for i, f in enumerate(funcs): 171 print "i", i, "func result", f(1.0), "defaults", get_defaults(f) 172 173 174def test_memoryview_none(const unsigned char[:] b=None): 175 """ 176 >>> test_memoryview_none() 177 >>> test_memoryview_none(None) 178 >>> test_memoryview_none(b'abc') 179 97 180 """ 181 if b is None: 182 return None 183 return b[0] 184 185 186def test_memoryview_bytes(const unsigned char[:] b=b'xyz'): 187 """ 188 >>> test_memoryview_bytes() 189 120 190 >>> test_memoryview_bytes(None) 191 >>> test_memoryview_bytes(b'abc') 192 97 193 """ 194 if b is None: 195 return None 196 return b[0] 197 198 199@cython.test_fail_if_path_exists( 200 '//NameNode[@entry.in_closure = True]', 201 '//NameNode[@entry.from_closure = True]') 202def test_func_default_inlined(): 203 """ 204 Make sure we don't accidentally generate a closure. 205 206 >>> func = test_func_default_inlined() 207 >>> func() 208 1 209 >>> func(2) 210 2 211 """ 212 def default(): 213 return 1 214 def func(arg=default()): 215 return arg 216 return func 217 218 219@cython.test_fail_if_path_exists( 220 '//NameNode[@entry.in_closure = True]', 221 '//NameNode[@entry.from_closure = True]') 222def test_func_default_scope(): 223 """ 224 Test that the default value expression is evaluated in the outer scope. 225 226 >>> func = test_func_default_scope() 227 3 228 >>> func() 229 [0, 1, 2, 3] 230 >>> func(2) 231 2 232 """ 233 i = -1 234 def func(arg=[ i for i in range(4) ]): 235 return arg 236 print i # list comps leak in Py2 mode => i == 3 237 return func 238 239 240def test_func_default_scope_local(): 241 """ 242 >>> func = test_func_default_scope_local() 243 -1 244 >>> func() 245 [0, 1, 2, 3] 246 >>> func(2) 247 2 248 """ 249 i = -1 250 def func(arg=list(i for i in range(4))): 251 return arg 252 print i # genexprs don't leak 253 return func 254 255cdef class C: 256 def f1(self, a, b=1, c=[]): 257 pass 258 def f2(self, a, b=1,/, c=[1]): 259 pass 260 def f3(self, a, /, b=1, *, c=[1]): 261 pass 262 cpdef f4(self, a, char*c=NULL): 263 pass 264 cpdef f5(self, a, str s = "123"): 265 pass 266 cpdef f6(self, a, int s = 4): 267 pass 268 cpdef f7(self, a, dict s = {'a':22}): 269 pass 270 cpdef f8(self, a, list s = [15]): 271 pass 272 273 274def check_defaults_on_methods_for_introspection(): 275 """ 276 >>> C.f1.__defaults__ 277 (1, []) 278 >>> C.f1.__kwdefaults__ 279 >>> C.f2.__defaults__ 280 (1, [1]) 281 >>> C.f2.__kwdefaults__ 282 >>> C.f3.__defaults__ 283 (1,) 284 >>> C.f3.__kwdefaults__ 285 {'c': [1]} 286 >>> C.f4.__defaults__ 287 >>> C.f4.__kwdefaults__ 288 >>> C.f5.__defaults__ 289 ('123',) 290 >>> C.f5.__kwdefaults__ 291 >>> C.f6.__defaults__ 292 (4,) 293 >>> C.f6.__kwdefaults__ 294 >>> C.f7.__defaults__ 295 ({'a': 22},) 296 >>> C.f7.__kwdefaults__ 297 >>> C.f8.__defaults__ 298 ([15],) 299 >>> C.f8.__kwdefaults__ 300 """ 301 pass 302