1# mode: run 2 3""" 4Test Python def functions without extern types 5""" 6 7cy = __import__("cython") 8cimport cython 9 10cdef extern from *: 11 int __Pyx_CyFunction_Check(object) 12 13cdef class Base(object): 14 def __repr__(self): 15 return type(self).__name__ 16 17 18cdef class ExtClassA(Base): 19 pass 20 21cdef class ExtClassB(Base): 22 pass 23 24cdef enum MyEnum: 25 entry0 26 entry1 27 entry2 28 entry3 29 entry4 30 31ctypedef fused fused_t: 32 str 33 int 34 long 35 complex 36 ExtClassA 37 ExtClassB 38 MyEnum 39 40 41ctypedef ExtClassA xxxlast 42ctypedef ExtClassB aaafirst 43 44 45ctypedef fused fused_with_object: 46 aaafirst 47 object 48 xxxlast 49 int 50 long 51 52 53f = 5.6 54i = 9 55 56 57def opt_func(fused_t obj, cython.floating myf = 1.2, cython.integral myi = 7): 58 """ 59 Test runtime dispatch, indexing of various kinds and optional arguments 60 61 >>> opt_func("spam", f, i) 62 str object double long 63 spam 5.60 9 5.60 9 64 >>> opt_func("spam", f, myi=i) 65 str object double long 66 spam 5.60 9 5.60 9 67 >>> opt_func("spam", myf=f, myi=i) 68 str object double long 69 spam 5.60 9 5.60 9 70 >>> opt_func[str, float, int]("spam", f, i) 71 str object float int 72 spam 5.60 9 5.60 9 73 >>> opt_func[str, cy.double, cy.long]("spam", f, i) 74 str object double long 75 spam 5.60 9 5.60 9 76 >>> opt_func[str, cy.double, cy.long]("spam", f, myi=i) 77 str object double long 78 spam 5.60 9 5.60 9 79 >>> opt_func[str, float, cy.int]("spam", f, i) 80 str object float int 81 spam 5.60 9 5.60 9 82 83 84 >>> opt_func(ExtClassA(), f, i) 85 ExtClassA double long 86 ExtClassA 5.60 9 5.60 9 87 >>> opt_func[ExtClassA, float, int](ExtClassA(), f, i) 88 ExtClassA float int 89 ExtClassA 5.60 9 5.60 9 90 >>> opt_func[ExtClassA, cy.double, cy.long](ExtClassA(), f, i) 91 ExtClassA double long 92 ExtClassA 5.60 9 5.60 9 93 94 >>> opt_func(ExtClassB(), f, i) 95 ExtClassB double long 96 ExtClassB 5.60 9 5.60 9 97 >>> opt_func[ExtClassB, cy.double, cy.long](ExtClassB(), f, i) 98 ExtClassB double long 99 ExtClassB 5.60 9 5.60 9 100 101 >>> opt_func(10, f) 102 long double long 103 10 5.60 7 5.60 9 104 >>> opt_func[int, float, int](10, f) 105 int float int 106 10 5.60 7 5.60 9 107 108 >>> opt_func(10 + 2j, myf = 2.6) 109 double complex double long 110 (10+2j) 2.60 7 5.60 9 111 >>> opt_func[cy.py_complex, float, int](10 + 2j, myf = 2.6) 112 double complex float int 113 (10+2j) 2.60 7 5.60 9 114 >>> opt_func[cy.doublecomplex, cy.float, cy.int](10 + 2j, myf = 2.6) 115 double complex float int 116 (10+2j) 2.60 7 5.60 9 117 118 >>> opt_func(object(), f) 119 Traceback (most recent call last): 120 TypeError: Function call with ambiguous argument types 121 >>> opt_func() 122 Traceback (most recent call last): 123 TypeError: Expected at least 1 argument, got 0 124 >>> opt_func("abc", f, i, 5) # doctest: +ELLIPSIS 125 Traceback (most recent call last): 126 TypeError: ...at most 3... 127 >>> opt_func[ExtClassA, cy.float, cy.long](object(), f) 128 Traceback (most recent call last): 129 TypeError: Argument 'obj' has incorrect type (expected fused_def.ExtClassA, got object) 130 """ 131 print cython.typeof(obj), cython.typeof(myf), cython.typeof(myi) 132 print obj, "%.2f" % myf, myi, "%.2f" % f, i 133 134def run_cyfunction_check(): 135 """ 136 tp_base of the fused function was being set incorrectly meaning 137 it wasn't being identified as a CyFunction 138 >>> run_cyfunction_check() 139 fused_cython_function 140 1 141 """ 142 print(type(opt_func).__name__) 143 print(__Pyx_CyFunction_Check(opt_func)) # should be True 144 145def test_opt_func(): 146 """ 147 >>> test_opt_func() 148 str object double long 149 ham 5.60 4 5.60 9 150 """ 151 opt_func("ham", f, entry4) 152 153 154def test_opt_func_introspection(): 155 """ 156 >>> opt_func.__defaults__ 157 (1.2, 7) 158 >>> opt_func.__kwdefaults__ 159 >>> opt_func.__annotations__ 160 {} 161 162 >>> opt_func[str, float, int].__defaults__ 163 (1.2, 7) 164 >>> opt_func[str, float, int].__kwdefaults__ 165 >>> opt_func[str, float, int].__annotations__ 166 {} 167 168 >>> opt_func[str, cy.double, cy.long].__defaults__ 169 (1.2, 7) 170 >>> opt_func[str, cy.double, cy.long].__kwdefaults__ 171 >>> opt_func[str, cy.double, cy.long].__annotations__ 172 {} 173 """ 174 175 176def func_with_object(fused_with_object obj, cython.integral myi = 7): 177 """ 178 >>> func_with_object(1) 179 long long 180 1 7 181 >>> func_with_object(1, 3) 182 long long 183 1 3 184 >>> func_with_object['int', 'int'](1, 3) 185 int int 186 1 3 187 >>> func_with_object(1j, 3) 188 Python object long 189 1j 3 190 >>> func_with_object('abc', 3) 191 Python object long 192 abc 3 193 >>> func_with_object(ExtClassA(), 3) 194 xxxlast long 195 ExtClassA 3 196 >>> func_with_object(ExtClassB(), 3) 197 aaafirst long 198 ExtClassB 3 199 >>> func_with_object['object', 'long'](ExtClassA(), 3) 200 Python object long 201 ExtClassA 3 202 >>> func_with_object['object', 'long'](ExtClassB(), 3) 203 Python object long 204 ExtClassB 3 205 """ 206 print cython.typeof(obj), cython.typeof(myi) 207 print obj, myi 208 209 210 211def args_kwargs(fused_t obj, cython.floating myf = 1.2, *args, **kwargs): 212 """ 213 >>> args_kwargs("foo") 214 str object double 215 foo 1.20 5.60 () {} 216 217 >>> args_kwargs("eggs", f, 1, 2, [], d={}) 218 str object double 219 eggs 5.60 5.60 (1, 2, []) {'d': {}} 220 221 >>> args_kwargs[str, float]("eggs", f, 1, 2, [], d={}) 222 str object float 223 eggs 5.60 5.60 (1, 2, []) {'d': {}} 224 225 """ 226 print cython.typeof(obj), cython.typeof(myf) 227 print obj, "%.2f" % myf, "%.2f" % f, args, kwargs 228 229 230class BaseClass(object): 231 """ 232 Test fused class/static/normal methods and super() without args 233 """ 234 235 @staticmethod 236 def mystaticmethod(cython.integral arg1): 237 print cython.typeof(arg1), arg1 238 239 @classmethod 240 def myclassmethod(cls, cython.integral arg1): 241 print cls, cython.typeof(arg1), arg1 242 243 def normalmethod(self, cython.integral arg1): 244 print self, cython.typeof(arg1), arg1 245 246 def __repr__(self): 247 return "<%s.%s object>" % (__name__, type(self).__name__) 248 249class SubClass(BaseClass): 250 251 @staticmethod 252 def mystaticmethod(self, cython.integral arg1): 253 print cython.typeof(arg1), arg1 254 super().mystaticmethod(arg1 + 1) 255 256 @classmethod 257 def myclassmethod(cls, cython.integral arg1): 258 print cls, cython.typeof(arg1), arg1 259 super().myclassmethod(arg1 + 1) 260 261 def normalmethod(self, cython.integral arg1): 262 print self, cython.typeof(arg1), arg1 263 super().normalmethod(arg1 + 1) 264 265class SubSubClass(SubClass): 266 pass 267 268def test_fused_def_super(): 269 """ 270 >>> test_fused_def_super() 271 long 10 272 long 11 273 long 11 274 long 12 275 short 12 276 long 13 277 short 13 278 long 14 279 <class 'fused_def.SubClass'> long 14 280 <class 'fused_def.SubClass'> long 15 281 <class 'fused_def.SubClass'> long 15 282 <class 'fused_def.SubClass'> long 16 283 <class 'fused_def.SubClass'> short 16 284 <class 'fused_def.SubClass'> long 17 285 <class 'fused_def.SubClass'> short 17 286 <class 'fused_def.SubClass'> long 18 287 <fused_def.SubClass object> long 18 288 <fused_def.SubClass object> long 19 289 <fused_def.SubClass object> long 19 290 <fused_def.SubClass object> long 20 291 <fused_def.SubClass object> short 20 292 <fused_def.SubClass object> long 21 293 <fused_def.SubClass object> short 21 294 <fused_def.SubClass object> long 22 295 """ 296 obj = SubClass() 297 cls = SubClass 298 299 obj.mystaticmethod(obj, 10) 300 cls.mystaticmethod(obj, 11) 301 obj.mystaticmethod[cy.short](obj, 12) 302 cls.mystaticmethod[cy.short](obj, 13) 303 304 obj.myclassmethod(14) 305 cls.myclassmethod(15) 306 obj.myclassmethod[cy.short](16) 307 cls.myclassmethod[cy.short](17) 308 309 obj.normalmethod(18) 310 cls.normalmethod(obj, 19) 311 obj.normalmethod[cy.short](20) 312 cls.normalmethod[cy.short](obj, 21) 313 314def test_fused_def_classmethod(): 315 """ 316 >>> test_fused_def_classmethod() 317 <class 'fused_def.SubSubClass'> long 10 318 <class 'fused_def.SubSubClass'> long 11 319 <class 'fused_def.SubSubClass'> long 11 320 <class 'fused_def.SubSubClass'> long 12 321 <class 'fused_def.SubSubClass'> short 12 322 <class 'fused_def.SubSubClass'> long 13 323 <class 'fused_def.SubSubClass'> short 13 324 <class 'fused_def.SubSubClass'> long 14 325 """ 326 SubSubClass().myclassmethod(10) 327 SubSubClass.myclassmethod(11) 328 329 SubSubClass().myclassmethod[cy.short](12) 330 SubSubClass.myclassmethod[cy.short](13) 331 332cdef class CBaseClass(object): 333 """ 334 Test fused def and cpdef methods in cdef classes. 335 336 >>> import cython as cy 337 >>> obj = CBaseClass() 338 >>> cls = CBaseClass 339 340 >>> obj.mystaticmethod(10) 341 long 10 342 >>> obj.mystaticmethod[cy.short](10) 343 short 10 344 >>> cls.mystaticmethod(10) 345 long 10 346 >>> cls.mystaticmethod[cy.short](10) 347 short 10 348 349 >>> obj.myclassmethod(10) 350 CBaseClass long 10 351 >>> obj.myclassmethod[cy.short](10) 352 CBaseClass short 10 353 >>> cls.myclassmethod(10) 354 CBaseClass long 10 355 >>> cls.myclassmethod[cy.short](10) 356 CBaseClass short 10 357 358 >>> obj.normalmethod(10, 11, 12) 359 <fused_def.CBaseClass object> long 10 11 12 360 >>> obj.normalmethod[cy.short](10, 11, 12) 361 <fused_def.CBaseClass object> short 10 11 12 362 >>> cls.normalmethod(obj, 10, 11, 12) 363 <fused_def.CBaseClass object> long 10 11 12 364 >>> cls.normalmethod[cy.short](obj, 10, 11, 12) 365 <fused_def.CBaseClass object> short 10 11 12 366 367 >>> obj.cpdefmethod(10) 368 <fused_def.CBaseClass object> long 10 369 >>> obj.cpdefmethod[cy.short](10) 370 <fused_def.CBaseClass object> short 10 371 >>> cls.cpdefmethod(obj, 10) 372 <fused_def.CBaseClass object> long 10 373 >>> cls.cpdefmethod[cy.short](obj, 10) 374 <fused_def.CBaseClass object> short 10 375 """ 376 377 @staticmethod 378 def mystaticmethod(cython.integral arg1): 379 print cython.typeof(arg1), arg1 380 381 @classmethod 382 def myclassmethod(cls, cython.integral arg1): 383 print cls.__name__, cython.typeof(arg1), arg1 384 385 def normalmethod(self, cython.integral arg1, arg2, arg3): 386 print self, cython.typeof(arg1), arg1, arg2, arg3 387 388 cpdef cpdefmethod(self, cython.integral arg1): 389 print self, cython.typeof(arg1), arg1 390 391 def __repr__(self): 392 return "<%s.%s object>" % (__name__, type(self).__name__) 393 394def getcode(func): 395 return getattr(func, '__code__', None) or func.func_code 396 397def test_code_object(cython.floating dummy = 2.0): 398 """ 399 A test for default arguments is in cyfunction_defaults 400 401 >>> getcode(test_code_object) is getcode(test_code_object[float]) 402 True 403 """ 404 405def create_dec(value): 406 def dec(f): 407 if not hasattr(f, 'order'): 408 f.order = [] 409 f.order.append(value) 410 return f 411 return dec 412 413@create_dec(1) 414@create_dec(2) 415@create_dec(3) 416def test_decorators(cython.floating arg): 417 """ 418 >>> test_decorators.order 419 [3, 2, 1] 420 """ 421 422@cython.binding(True) 423def bind_me(self, cython.floating a=1.): 424 return a 425 426cdef class HasBound: 427 """ 428 Using default arguments of bound specialized fused functions used to cause a segfault 429 https://github.com/cython/cython/issues/3370 430 >>> inst = HasBound() 431 >>> inst.func() 432 1.0 433 >>> inst.func(2) 434 2.0 435 >>> inst.func_fused() 436 1.0 437 >>> inst.func_fused(2.) 438 2.0 439 >>> bind_me.__defaults__ 440 (1.0,) 441 >>> inst.func.__defaults__ 442 (1.0,) 443 >>> inst.func_fused.__defaults__ 444 (1.0,) 445 """ 446 func = bind_me[float] 447 448 func_fused = bind_me 449