1# cython: infer_types = True 2 3 4cimport cython 5from cython cimport typeof, infer_types 6 7from cpython cimport bool 8 9################################################## 10# type inference tests in 'full' mode 11 12cdef class MyType: 13 pass 14 15def simple(): 16 """ 17 >>> simple() 18 """ 19 i = 3 20 assert typeof(i) == "long", typeof(i) 21 x = 1.41 22 assert typeof(x) == "double", typeof(x) 23 xptr = &x 24 assert typeof(xptr) == "double *", typeof(xptr) 25 xptrptr = &xptr 26 assert typeof(xptrptr) == "double **", typeof(xptrptr) 27 b = b"abc" 28 assert typeof(b) == "bytes object", typeof(b) 29 s = "abc" 30 assert typeof(s) == "str object", typeof(s) 31 u = u"xyz" 32 assert typeof(u) == "unicode object", typeof(u) 33 L = [1,2,3] 34 assert typeof(L) == "list object", typeof(L) 35 t = (4,5,6,()) 36 assert typeof(t) == "tuple object", typeof(t) 37 t2 = (4, 5.0, 6) 38 assert typeof(t2) == "(long, double, long)", typeof(t) 39 40def builtin_types(): 41 """ 42 >>> builtin_types() 43 """ 44 b = bytes() 45 assert typeof(b) == "bytes object", typeof(b) 46 u = unicode() 47 assert typeof(u) == "unicode object", typeof(u) 48 L = list() 49 assert typeof(L) == "list object", typeof(L) 50 t = tuple() 51 assert typeof(t) == "tuple object", typeof(t) 52 d = dict() 53 assert typeof(d) == "dict object", typeof(d) 54 B = bool() 55 assert typeof(B) == "bool", typeof(B) 56 57def slicing(): 58 """ 59 >>> slicing() 60 """ 61 b = b"abc" 62 assert typeof(b) == "bytes object", typeof(b) 63 b1 = b[1:2] 64 assert typeof(b1) == "bytes object", typeof(b1) 65 b2 = b[1:2:2] 66 assert typeof(b2) == "bytes object", typeof(b2) 67 u = u"xyz" 68 assert typeof(u) == "unicode object", typeof(u) 69 u1 = u[1:2] 70 assert typeof(u1) == "unicode object", typeof(u1) 71 u2 = u[1:2:2] 72 assert typeof(u2) == "unicode object", typeof(u2) 73 s = "xyz" 74 assert typeof(s) == "str object", typeof(s) 75 s1 = s[1:2] 76 assert typeof(s1) == "str object", typeof(s1) 77 s2 = s[1:2:2] 78 assert typeof(s2) == "str object", typeof(s2) 79 L = [1,2,3] 80 assert typeof(L) == "list object", typeof(L) 81 L1 = L[1:2] 82 assert typeof(L1) == "list object", typeof(L1) 83 L2 = L[1:2:2] 84 assert typeof(L2) == "list object", typeof(L2) 85 t = (4,5,6,()) 86 assert typeof(t) == "tuple object", typeof(t) 87 t1 = t[1:2] 88 assert typeof(t1) == "tuple object", typeof(t1) 89 t2 = t[1:2:2] 90 assert typeof(t2) == "tuple object", typeof(t2) 91 92def indexing(): 93 """ 94 >>> indexing() 95 """ 96 b = b"abc" 97 assert typeof(b) == "bytes object", typeof(b) 98 b1 = b[1] 99 assert typeof(b1) == "Python object", typeof(b1) # Py2: bytes, Py3: int 100 u = u"xyz" 101 assert typeof(u) == "unicode object", typeof(u) 102 u1 = u[1] 103 assert typeof(u1) == "Py_UCS4", typeof(u1) 104 s = "xyz" 105 assert typeof(s) == "str object", typeof(s) 106 s1 = s[1] 107 assert typeof(s1) == "str object", typeof(s1) 108 L = [1,2,3] 109 assert typeof(L) == "list object", typeof(L) 110 L1 = L[1] 111 assert typeof(L1) == "Python object", typeof(L1) 112 t = (4,5,()) 113 assert typeof(t) == "tuple object", typeof(t) 114 t1 = t[1] 115 assert typeof(t1) == "long", typeof(t1) 116 t2 = ('abc', 'def', 'ghi') 117 assert typeof(t2) == "tuple object", typeof(t2) 118 t2_1 = t2[1] 119 assert typeof(t2_1) == "str object", typeof(t2_1) 120 t2_2 = t2[t[0]-3] 121 assert typeof(t2_2) == "str object", typeof(t2_2) 122 t5 = (b'abc', 'def', u'ghi') 123 t5_0 = t5[0] 124 assert typeof(t5_0) == "bytes object", typeof(t5_0) 125 t5_1 = t5[1] 126 assert typeof(t5_1) == "str object", typeof(t5_1) 127 t5_2 = t5[2] 128 assert typeof(t5_2) == "unicode object", typeof(t5_2) 129 t5_3 = t5[t[0]-3] 130 assert typeof(t5_3) == "Python object", typeof(t5_3) 131 132 133def multiple_assignments(): 134 """ 135 >>> multiple_assignments() 136 """ 137 a = 3 138 a = 4 139 a = 5 140 assert typeof(a) == "long", typeof(a) 141 b = a 142 b = 3.1 143 b = 3.14159 144 assert typeof(b) == "double", typeof(b) 145 c = a 146 c = b 147 c = [1,2,3] 148 assert typeof(c) == "Python object", typeof(c) 149 d = b'abc' 150 d = bytes() 151 d = bytes(b'xyz') 152 d = None 153 assert typeof(d) == "bytes object", typeof(d) 154 155 156def arithmetic(): 157 """ 158 >>> arithmetic() 159 """ 160 a = 1 + 2 161 assert typeof(a) == "long", typeof(a) 162 b = 1 + 1.5 163 assert typeof(b) == "double", typeof(b) 164 c = 1 + <object>2 165 assert typeof(c) == "Python object", typeof(c) 166 d = 1 * 1.5 ** 2 167 assert typeof(d) == "double", typeof(d) 168 169cdef class some_class: 170 pass 171 172def unary_operators(): 173 """ 174 >>> unary_operators() 175 """ 176 cdef int x = 1 177 assert typeof(~x) == "int", typeof(~x) 178 cdef some_class obj 179 assert typeof(~obj) == "Python object", typeof(~obj) 180 a = int(1) 181 assert typeof(a) == "Python object", typeof(a) 182 b = not int(3) 183 assert typeof(b) == "bint", typeof(b) 184 c = +int(3) 185 assert typeof(c) == "Python object", typeof(c) 186 d = -int(5) 187 assert typeof(d) == "Python object", typeof(d) 188 189 190def builtin_type_operations(): 191 """ 192 >>> builtin_type_operations() 193 """ 194 b1 = b'a' * 10 195 b1 = 10 * b'a' 196 b1 = 10 * b'a' * 10 197 assert typeof(b1) == "bytes object", typeof(b1) 198 b2 = b'a' + b'b' 199 assert typeof(b2) == "bytes object", typeof(b2) 200 u1 = u'a' * 10 201 u1 = 10 * u'a' 202 assert typeof(u1) == "unicode object", typeof(u1) 203 u2 = u'a' + u'b' 204 assert typeof(u2) == "unicode object", typeof(u2) 205 u3 = u'a%s' % u'b' 206 u3 = u'a%s' % 10 207 assert typeof(u3) == "unicode object", typeof(u3) 208 s1 = "abc %s" % "x" 209 s1 = "abc %s" % 10 210 assert typeof(s1) == "str object", typeof(s1) 211 s2 = "abc %s" + "x" 212 assert typeof(s2) == "str object", typeof(s2) 213 s3 = "abc %s" * 10 214 s3 = "abc %s" * 10 * 10 215 s3 = 10 * "abc %s" * 10 216 assert typeof(s3) == "str object", typeof(s3) 217 L1 = [] + [] 218 assert typeof(L1) == "list object", typeof(L1) 219 L2 = [] * 2 220 assert typeof(L2) == "list object", typeof(L2) 221 T1 = () + () 222 assert typeof(T1) == "tuple object", typeof(T1) 223 T2 = () * 2 224 assert typeof(T2) == "tuple object", typeof(T2) 225 226def builtin_type_methods(): 227 """ 228 >>> builtin_type_methods() 229 """ 230 l = [] 231 assert typeof(l) == 'list object', typeof(l) 232 append = l.append 233 assert typeof(append) == 'Python object', typeof(append) 234 append(1) 235 assert l == [1], str(l) 236 237cdef int cfunc(int x): 238 return x+1 239 240def c_functions(): 241 """ 242 >>> c_functions() 243 """ 244 f = cfunc 245 assert typeof(f) == 'int (*)(int)', typeof(f) 246 assert 2 == f(1) 247 248def builtin_functions(): 249 """ 250 >>> _abs, _getattr = builtin_functions() 251 Python object 252 Python object 253 >>> _abs(-1) 254 1 255 >>> class o(object): pass 256 >>> o.x = 1 257 >>> _getattr(o, 'x') 258 1 259 """ 260 _abs = abs 261 print(typeof(_abs)) 262 _getattr = getattr 263 print(typeof(_getattr)) 264 return _abs, _getattr 265 266def cascade(): 267 """ 268 >>> cascade() 269 """ 270 a = 1.0 271 b = a + 2 272 c = b + 3 273 d = c + 4 274 assert typeof(d) == "double" 275 e = a + b + c + d 276 assert typeof(e) == "double" 277 278def cascaded_assignment(): 279 a = b = c = d = 1.0 280 assert typeof(a) == "double" 281 assert typeof(b) == "double" 282 assert typeof(c) == "double" 283 assert typeof(d) == "double" 284 e = a + b + c + d 285 assert typeof(e) == "double" 286 287def increment(): 288 """ 289 >>> increment() 290 """ 291 a = 5 292 a += 1 293 assert typeof(a) == "long" 294 295def loop(): 296 """ 297 >>> loop() 298 """ 299 for a in range(10): 300 pass 301 assert typeof(a) == "long" 302 303 b = 1.0 304 for b in range(5): 305 pass 306 assert typeof(b) == "double" 307 308 for c from 0 <= c < 10 by .5: 309 pass 310 assert typeof(c) == "double" 311 312 for d in range(0, 10L, 2): 313 pass 314 assert typeof(a) == "long" 315 316def loop_over_charptr(): 317 """ 318 >>> print( loop_over_charptr() ) 319 char 320 """ 321 cdef char* char_ptr_string = 'abcdefg' 322 for c in char_ptr_string: 323 pass 324 return typeof(c) 325 326def loop_over_bytes_literal(): 327 """ 328 >>> print( loop_over_bytes_literal() ) 329 Python object 330 """ 331 for c in b'abcdefg': 332 pass 333 return typeof(c) 334 335def loop_over_bytes(): 336 """ 337 >>> print( loop_over_bytes() ) 338 Python object 339 """ 340 cdef bytes bytes_string = b'abcdefg' 341 # bytes in Py2, int in Py3 342 for c in bytes_string: 343 pass 344 return typeof(c) 345 346def loop_over_str(): 347 """ 348 >>> print( loop_over_str() ) 349 str object 350 """ 351 cdef str string = 'abcdefg' 352 # str (bytes) in Py2, str (unicode) in Py3 353 for c in string: 354 pass 355 return typeof(c) 356 357def loop_over_unicode(): 358 """ 359 >>> print( loop_over_unicode() ) 360 Py_UCS4 361 """ 362 cdef unicode ustring = u'abcdefg' 363 # Py_UCS4 can represent any Unicode character 364 for uchar in ustring: 365 pass 366 return typeof(uchar) 367 368def loop_over_unicode_literal(): 369 """ 370 >>> print( loop_over_unicode_literal() ) 371 Py_UCS4 372 """ 373 # Py_UCS4 can represent any Unicode character 374 for uchar in u'abcdefg': 375 pass 376 return typeof(uchar) 377 378def loop_over_int_array(): 379 """ 380 >>> print( loop_over_int_array() ) 381 int 382 """ 383 cdef int[10] int_array 384 for i in int_array: 385 pass 386 return typeof(i) 387 388cdef struct MyStruct: 389 int a 390 391def loop_over_struct_ptr(): 392 """ 393 >>> print( loop_over_struct_ptr() ) 394 MyStruct 395 """ 396 cdef MyStruct[10] a_list 397 cdef MyStruct *a_ptr = a_list 398 for i in a_list[:10]: 399 pass 400 return typeof(i) 401 402cdef unicode retu(): 403 return u"12345" 404 405cdef bytes retb(): 406 return b"12345" 407 408def conditional(x): 409 """ 410 >>> conditional(True) 411 (True, 'Python object') 412 >>> conditional(False) 413 (False, 'Python object') 414 """ 415 if x: 416 a = retu() 417 else: 418 a = retb() 419 return type(a) is unicode, typeof(a) 420 421################################################## 422# type inference tests that work in 'safe' mode 423 424@infer_types(None) 425def double_inference(): 426 """ 427 >>> values, types = double_inference() 428 >>> values == (1.0, 1.0*2, 1.0*2.0+2.0*2.0, 1.0*2.0) 429 True 430 >>> types 431 ('double', 'double', 'double', 'Python object') 432 """ 433 d_a = 1.0 434 d_b = d_a * float(2) 435 d_c = d_a * float(some_float_value()) + d_b * float(some_float_value()) 436 o_d = d_a * some_float_value() 437 return (d_a,d_b,d_c,o_d), (typeof(d_a), typeof(d_b), typeof(d_c), typeof(o_d)) 438 439cdef object some_float_value(): 440 return 2.0 441 442 443@infer_types(None) 444@cython.test_fail_if_path_exists('//DefNode//NameNode[@type.is_pyobject = True]') 445@cython.test_assert_path_exists('//DefNode//NameNode[@type.is_pyobject]', 446 '//DefNode//NameNode[@type.is_pyobject = False]') 447def double_loop(): 448 """ 449 >>> double_loop() == 1.0 * 10 450 True 451 """ 452 cdef int i 453 d = 1.0 454 for i in range(9): 455 d += 1.0 456 return d 457 458@infer_types(None) 459def safe_only(): 460 """ 461 >>> safe_only() 462 """ 463 a = 1.0 464 assert typeof(a) == "double", typeof(c) 465 b = 1; 466 assert typeof(b) == "long", typeof(b) 467 c = MyType() 468 assert typeof(c) == "MyType", typeof(c) 469 for i in range(10): pass 470 assert typeof(i) == "long", typeof(i) 471 d = 1 472 res = ~d 473 assert typeof(d) == "long", typeof(d) 474 475 # we special-case inference to type str, see 476 # trac #553 477 s = "abc" 478 assert typeof(s) == "Python object", typeof(s) 479 cdef str t = "def" 480 assert typeof(t) == "str object", typeof(t) 481 482 # potentially overflowing arithmetic 483 e = 1 484 e += 1 485 assert typeof(e) == "Python object", typeof(e) 486 f = 1 487 res = f * 10 488 assert typeof(f) == "Python object", typeof(f) 489 g = 1 490 res = 10*(~g) 491 assert typeof(g) == "Python object", typeof(g) 492 for j in range(10): 493 res = -j 494 assert typeof(j) == "Python object", typeof(j) 495 h = 1 496 res = abs(h) 497 assert typeof(h) == "Python object", typeof(h) 498 cdef int c_int = 1 499 assert typeof(abs(c_int)) == "int", typeof(abs(c_int)) 500 501@infer_types(None) 502def safe_c_functions(): 503 """ 504 >>> safe_c_functions() 505 """ 506 f = cfunc 507 assert typeof(f) == 'int (*)(int)', typeof(f) 508 assert 2 == f(1) 509 510@infer_types(None) 511def ptr_types(): 512 """ 513 >>> ptr_types() 514 """ 515 cdef int a 516 a_ptr = &a 517 assert typeof(a_ptr) == "int *", typeof(a_ptr) 518 a_ptr_ptr = &a_ptr 519 assert typeof(a_ptr_ptr) == "int **", typeof(a_ptr_ptr) 520 cdef int[1] b 521 b_ref = b 522 assert typeof(b_ref) == "int *", typeof(b_ref) 523 ptr = &a 524 ptr = b 525 assert typeof(ptr) == "int *", typeof(ptr) 526 527def const_types(const double x, double y, double& z): 528 """ 529 >>> const_types(1, 1, 1) 530 """ 531 a = x 532 a = y 533 a = z 534 assert typeof(a) == "double", typeof(a) 535 536@infer_types(None) 537def args_tuple_keywords(*args, **kwargs): 538 """ 539 >>> args_tuple_keywords(1,2,3, a=1, b=2) 540 """ 541 assert typeof(args) == "tuple object", typeof(args) 542 assert typeof(kwargs) == "dict object", typeof(kwargs) 543 544@infer_types(None) 545def args_tuple_keywords_reassign_same(*args, **kwargs): 546 """ 547 >>> args_tuple_keywords_reassign_same(1,2,3, a=1, b=2) 548 """ 549 assert typeof(args) == "tuple object", typeof(args) 550 assert typeof(kwargs) == "dict object", typeof(kwargs) 551 552 args = () 553 kwargs = {} 554 555@infer_types(None) 556def args_tuple_keywords_reassign_pyobjects(*args, **kwargs): 557 """ 558 >>> args_tuple_keywords_reassign_pyobjects(1,2,3, a=1, b=2) 559 """ 560 assert typeof(args) == "Python object", typeof(args) 561 assert typeof(kwargs) == "Python object", typeof(kwargs) 562 563 args = [] 564 kwargs = "test" 565 566# / A -> AA -> AAA 567# Base0 -> Base - 568# \ B -> BB 569# C -> CC 570 571cdef class Base0: pass 572cdef class Base(Base0): pass 573cdef class A(Base): pass 574cdef class AA(A): pass 575cdef class AAA(AA): pass 576cdef class B(Base): pass 577cdef class BB(B): pass 578cdef class C: pass 579cdef class CC(C): pass 580 581@infer_types(None) 582def common_extension_type_base(): 583 """ 584 >>> common_extension_type_base() 585 """ 586 x = A() 587 x = AA() 588 assert typeof(x) == "A", typeof(x) 589 y = A() 590 y = B() 591 assert typeof(y) == "Base", typeof(y) 592 z = AAA() 593 z = BB() 594 assert typeof(z) == "Base", typeof(z) 595 w = A() 596 w = CC() 597 assert typeof(w) == "Python object", typeof(w) 598 599cdef class AcceptsKeywords: 600 def __init__(self, *args, **kwds): 601 pass 602 603@infer_types(None) 604def constructor_call(): 605 """ 606 >>> constructor_call() 607 """ 608 x = AcceptsKeywords(a=1, b=2) 609 assert typeof(x) == "AcceptsKeywords", typeof(x) 610 611 612@infer_types(None) 613def large_literals(): 614 """ 615 >>> large_literals() 616 """ 617 # It's only safe to infer small integer literals. 618 a = 10 619 b = 100000000000000000000000000000000 620 assert typeof(a) == "long", typeof(a) 621 assert typeof(b) == "Python object", typeof(b) 622 c, d = 10, 100000000000000000000000000000000 623 assert typeof(c) == "long", typeof(c) 624 assert typeof(d) == "Python object", typeof(d) 625 626 627class EmptyContextManager(object): 628 def __enter__(self): 629 return None 630 def __exit__(self, *args): 631 return 0 632 633def with_statement(): 634 """ 635 >>> with_statement() 636 Python object 637 Python object 638 """ 639 x = 1.0 640 with EmptyContextManager() as x: 641 print(typeof(x)) 642 print(typeof(x)) 643 return x 644 645@cython.final 646cdef class TypedContextManager(object): 647 cpdef double __enter__(self): 648 return 2.0 649 def __exit__(self, *args): 650 return 0 651 652def with_statement_typed(): 653 """ 654 >>> with_statement_typed() 655 double 656 double 657 2.0 658 """ 659 x = 1.0 660 with TypedContextManager() as x: 661 print(typeof(x)) 662 print(typeof(x)) 663 return x 664 665def with_statement_untyped(): 666 """ 667 >>> with_statement_untyped() 668 Python object 669 Python object 670 2.0 671 """ 672 x = 1.0 673 cdef object t = TypedContextManager() 674 with t as x: 675 print(typeof(x)) 676 print(typeof(x)) 677 return x 678 679def self_lookup(a): 680 b = a 681 b = b.foo(keyword=None) 682 print typeof(b) 683 684# Regression test for trac #638. 685 686def bar(foo): 687 qux = foo 688 quux = foo[qux.baz] 689 690 691cdef enum MyEnum: 692 enum_x = 1 693 enum_y = 2 694 695ctypedef long my_long 696def test_int_typedef_inference(): 697 """ 698 >>> test_int_typedef_inference() 699 """ 700 cdef long x = 1 701 cdef my_long y = 2 702 cdef long long z = 3 703 assert typeof(x + y) == typeof(y + x) == 'my_long', typeof(x + y) 704 assert typeof(y + z) == typeof(z + y) == 'long long', typeof(y + z) 705 706from libc.stdint cimport int32_t, int64_t 707def int64_long_sum(): 708 cdef long x = 1 709 cdef int32_t x32 = 2 710 cdef int64_t x64 = 3 711 cdef unsigned long ux = 4 712 assert typeof(x + x32) == typeof(x32 + x) == 'long', typeof(x + x32) 713 assert typeof(x + x64) == typeof(x64 + x) == 'int64_t', typeof(x + x64) 714 # The correct answer here is either unsigned long or int64_t, depending on 715 # whether sizeof(long) == 64 or not. Incorrect signedness is probably 716 # preferable to incorrect width. 717 assert typeof(ux + x64) == typeof(x64 + ux) == 'int64_t', typeof(ux + x64) 718 719cdef class InferInProperties: 720 """ 721 >>> InferInProperties().x 722 ('double', 'unicode object', 'MyEnum', 'MyEnum') 723 """ 724 cdef MyEnum attr 725 def __cinit__(self): 726 self.attr = enum_x 727 728 property x: 729 def __get__(self): 730 a = 1.0 731 b = u'abc' 732 c = self.attr 733 d = enum_y 734 c = d 735 return typeof(a), typeof(b), typeof(c), typeof(d) 736 737cdef class WithMethods: 738 cdef int offset 739 def __init__(self, offset): 740 self.offset = offset 741 cpdef int one_arg(self, int x): 742 return x + self.offset 743 cpdef int default_arg(self, int x, int y=0): 744 return x + y + self.offset 745 746def test_bound_methods(): 747 """ 748 >>> test_bound_methods() 749 """ 750 o = WithMethods(10) 751 assert typeof(o) == 'WithMethods', typeof(o) 752 753 one_arg = o.one_arg 754 assert one_arg(2) == 12, one_arg(2) 755 756 default_arg = o.default_arg 757 assert default_arg(2) == 12, default_arg(2) 758 assert default_arg(2, 3) == 15, default_arg(2, 2) 759