fix ticket #602: let bytes literals start off as 'bytes' instead of 'char*'
[cython.git] / tests / run / type_inference.pyx
1 # cython: infer_types = True
2
3
4 cimport cython
5 from cython cimport typeof, infer_types
6
7 from cpython cimport bool
8
9 ##################################################
10 # type inference tests in 'full' mode
11
12 cdef class MyType:
13     pass
14
15 def 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
38 def builtin_types():
39     """
40     >>> builtin_types()
41     """
42     b = bytes()
43     assert typeof(b) == "bytes object", typeof(b)
44     u = unicode()
45     assert typeof(u) == "unicode object", typeof(u)
46     L = list()
47     assert typeof(L) == "list object", typeof(L)
48     t = tuple()
49     assert typeof(t) == "tuple object", typeof(t)
50     d = dict()
51     assert typeof(d) == "dict object", typeof(d)
52     B = bool()
53     assert typeof(B) == "bool", typeof(B)
54
55 def slicing():
56     """
57     >>> slicing()
58     """
59     b = b"abc"
60     assert typeof(b) == "bytes object", typeof(b)
61     b1 = b[1:2]
62     assert typeof(b1) == "bytes object", typeof(b1)
63     b2 = b[1:2:2]
64     assert typeof(b2) == "bytes object", typeof(b2)
65     u = u"xyz"
66     assert typeof(u) == "unicode object", typeof(u)
67     u1 = u[1:2]
68     assert typeof(u1) == "unicode object", typeof(u1)
69     u2 = u[1:2:2]
70     assert typeof(u2) == "unicode object", typeof(u2)
71     s = "xyz"
72     assert typeof(s) == "str object", typeof(s)
73     s1 = s[1:2]
74     assert typeof(s1) == "str object", typeof(s1)
75     s2 = s[1:2:2]
76     assert typeof(s2) == "str object", typeof(s2)
77     L = [1,2,3]
78     assert typeof(L) == "list object", typeof(L)
79     L1 = L[1:2]
80     assert typeof(L1) == "list object", typeof(L1)
81     L2 = L[1:2:2]
82     assert typeof(L2) == "list object", typeof(L2)
83     t = (4,5,6)
84     assert typeof(t) == "tuple object", typeof(t)
85     t1 = t[1:2]
86     assert typeof(t1) == "tuple object", typeof(t1)
87     t2 = t[1:2:2]
88     assert typeof(t2) == "tuple object", typeof(t2)
89
90 def indexing():
91     """
92     >>> indexing()
93     """
94     b = b"abc"
95     assert typeof(b) == "bytes object", typeof(b)
96     b1 = b[1]
97     assert typeof(b1) == "Python object", typeof(b1)
98     u = u"xyz"
99     assert typeof(u) == "unicode object", typeof(u)
100     u1 = u[1]
101     assert typeof(u1) == "Py_UNICODE", typeof(u1)
102     s = "xyz"
103     assert typeof(s) == "str object", typeof(s)
104     s1 = s[1]
105     assert typeof(s1) == "Python object", typeof(s1)
106     L = [1,2,3]
107     assert typeof(L) == "list object", typeof(L)
108     L1 = L[1]
109     assert typeof(L1) == "Python object", typeof(L1)
110     t = (4,5,6)
111     assert typeof(t) == "tuple object", typeof(t)
112     t1 = t[1]
113     assert typeof(t1) == "Python object", typeof(t1)
114
115 def multiple_assignments():
116     """
117     >>> multiple_assignments()
118     """
119     a = 3
120     a = 4
121     a = 5
122     assert typeof(a) == "long"
123     b = a
124     b = 3.1
125     b = 3.14159
126     assert typeof(b) == "double"
127     c = a
128     c = b
129     c = [1,2,3]
130     assert typeof(c) == "Python object"
131
132 def arithmetic():
133     """
134     >>> arithmetic()
135     """
136     a = 1 + 2
137     assert typeof(a) == "long", typeof(a)
138     b = 1 + 1.5
139     assert typeof(b) == "double", typeof(b)
140     c = 1 + <object>2
141     assert typeof(c) == "Python object", typeof(c)
142     d = 1 * 1.5 ** 2
143     assert typeof(d) == "double", typeof(d)
144
145 cdef class some_class:
146     pass
147
148 def unary_operators():
149     """
150     >>> unary_operators()
151     """
152     cdef int x = 1
153     assert typeof(~x) == "int", typeof(~x)
154     cdef some_class obj
155     assert typeof(~obj) == "Python object", typeof(~obj)
156     a = int(1)
157     assert typeof(a) == "Python object", typeof(a)
158     b = not int(3)
159     assert typeof(b) == "int", typeof(b)
160     c = +int(3)
161     assert typeof(c) == "Python object", typeof(c)
162     d = -int(5)
163     assert typeof(d) == "Python object", typeof(d)
164
165
166 def builtin_type_operations():
167     """
168     >>> builtin_type_operations()
169     """
170     b1 = b'a' * 10
171     b1 = 10 * b'a'
172     b1 = 10 * b'a' * 10
173     assert typeof(b1) == "bytes object", typeof(b1)
174     b2 = b'a' + b'b'
175     assert typeof(b2) == "bytes object", typeof(b2)
176     u1 = u'a' * 10
177     u1 = 10 * u'a'
178     assert typeof(u1) == "unicode object", typeof(u1)
179     u2 = u'a' + u'b'
180     assert typeof(u2) == "unicode object", typeof(u2)
181     u3 = u'a%s' % u'b'
182     u3 = u'a%s' % 10
183     assert typeof(u3) == "unicode object", typeof(u3)
184     s1 = "abc %s" % "x"
185     s1 = "abc %s" % 10
186     assert typeof(s1) == "str object", typeof(s1)
187     s2 = "abc %s" + "x"
188     assert typeof(s2) == "str object", typeof(s2)
189     s3 = "abc %s" * 10
190     s3 = "abc %s" * 10 * 10
191     s3 = 10 * "abc %s" * 10
192     assert typeof(s3) == "str object", typeof(s3)
193     L1 = [] + []
194     assert typeof(L1) == "list object", typeof(L1)
195     L2 = [] * 2
196     assert typeof(L2) == "list object", typeof(L2)
197     T1 = () + ()
198     assert typeof(T1) == "tuple object", typeof(T1)
199     T2 = () * 2
200     assert typeof(T2) == "tuple object", typeof(T2)
201
202 def cascade():
203     """
204     >>> cascade()
205     """
206     a = 1.0
207     b = a + 2
208     c = b + 3
209     d = c + 4
210     assert typeof(d) == "double"
211     e = a + b + c + d
212     assert typeof(e) == "double"
213
214 def cascaded_assignment():
215     a = b = c = d = 1.0
216     assert typeof(a) == "double"
217     assert typeof(b) == "double"
218     assert typeof(c) == "double"
219     assert typeof(d) == "double"
220     e = a + b + c + d
221     assert typeof(e) == "double"
222
223 def increment():
224     """
225     >>> increment()
226     """
227     a = 5
228     a += 1
229     assert typeof(a) == "long"
230
231 def loop():
232     """
233     >>> loop()
234     """
235     for a in range(10):
236         pass
237     assert typeof(a) == "long"
238
239     b = 1.0
240     for b in range(5):
241         pass
242     assert typeof(b) == "double"
243
244     for c from 0 <= c < 10 by .5:
245         pass
246     assert typeof(c) == "double"
247
248     for d in range(0, 10L, 2):
249         pass
250     assert typeof(a) == "long"
251
252 def loop_over_charptr():
253     """
254     >>> print( loop_over_charptr() )
255     char
256     """
257     cdef char* char_ptr_string = 'abcdefg'
258     for c in char_ptr_string:
259         pass
260     return typeof(c)
261
262 def loop_over_bytes_literal():
263     """
264     >>> print( loop_over_bytes_literal() )
265     Python object
266     """
267     for c in b'abcdefg':
268         pass
269     return typeof(c)
270
271 def loop_over_bytes():
272     """
273     >>> print( loop_over_bytes() )
274     Python object
275     """
276     cdef bytes bytes_string = b'abcdefg'
277     for c in bytes_string:
278         pass
279     return typeof(c)
280
281 def loop_over_str():
282     """
283     >>> print( loop_over_str() )
284     Python object
285     """
286     cdef str string = 'abcdefg'
287     for c in string:
288         pass
289     return typeof(c)
290
291 def loop_over_unicode():
292     """
293     >>> print( loop_over_unicode() )
294     Py_UNICODE
295     """
296     cdef unicode ustring = u'abcdefg'
297     for uchar in ustring:
298         pass
299     return typeof(uchar)
300
301 def loop_over_int_array():
302     """
303     >>> print( loop_over_int_array() )
304     int
305     """
306     cdef int[10] int_array
307     for i in int_array:
308         pass
309     return typeof(i)
310
311 cdef unicode retu():
312     return u"12345"
313
314 cdef bytes retb():
315     return b"12345"
316
317 def conditional(x):
318     """
319     >>> conditional(True)
320     (True, 'Python object')
321     >>> conditional(False)
322     (False, 'Python object')
323     """
324     if x:
325         a = retu()
326     else:
327         a = retb()
328     return type(a) is unicode, typeof(a)
329
330 ##################################################
331 # type inference tests that work in 'safe' mode
332
333 @infer_types(None)
334 def double_inference():
335     """
336     >>> values, types = double_inference()
337     >>> values == (1.0, 1.0*2, 1.0*2.0+2.0*2.0, 1.0*2.0)
338     True
339     >>> types
340     ('double', 'double', 'double', 'Python object')
341     """
342     d_a = 1.0
343     d_b = d_a * float(2)
344     d_c = d_a * float(some_float_value()) + d_b * float(some_float_value())
345     o_d = d_a * some_float_value()
346     return (d_a,d_b,d_c,o_d), (typeof(d_a), typeof(d_b), typeof(d_c), typeof(o_d))
347
348 cdef object some_float_value():
349     return 2.0
350
351
352 @cython.test_fail_if_path_exists('//NameNode[@type.is_pyobject = True]')
353 @cython.test_assert_path_exists('//NameNode[@type.is_pyobject]',
354                                 '//NameNode[@type.is_pyobject = False]')
355 @infer_types(None)
356 def double_loop():
357     """
358     >>> double_loop() == 1.0 * 10
359     True
360     """
361     cdef int i
362     d = 1.0
363     for i in range(9):
364         d += 1.0
365     return d
366
367 @infer_types(None)
368 def safe_only():
369     """
370     >>> safe_only()
371     """
372     a = 1.0
373     assert typeof(a) == "double", typeof(c)
374     b = 1;
375     assert typeof(b) == "long", typeof(b)
376     c = MyType()
377     assert typeof(c) == "MyType", typeof(c)
378     for i in range(10): pass
379     assert typeof(i) == "long", typeof(i)
380     d = 1
381     res = ~d
382     assert typeof(d) == "long", typeof(d)
383
384     # we special-case inference to type str, see
385     # trac #553
386     s = "abc"
387     assert typeof(s) == "Python object", typeof(s)
388     cdef str t = "def"
389     assert typeof(t) == "str object", typeof(t)
390
391     # potentially overflowing arithmetic
392     e = 1
393     e += 1
394     assert typeof(e) == "Python object", typeof(e)
395     f = 1
396     res = f * 10
397     assert typeof(f) == "Python object", typeof(f)
398     g = 1
399     res = 10*(~g)
400     assert typeof(g) == "Python object", typeof(g)
401     for j in range(10):
402         res = -j
403     assert typeof(j) == "Python object", typeof(j)
404
405 @infer_types(None)
406 def args_tuple_keywords(*args, **kwargs):
407     """
408     >>> args_tuple_keywords(1,2,3, a=1, b=2)
409     """
410     assert typeof(args) == "tuple object", typeof(args)
411     assert typeof(kwargs) == "dict object", typeof(kwargs)
412
413 @infer_types(None)
414 def args_tuple_keywords_reassign_same(*args, **kwargs):
415     """
416     >>> args_tuple_keywords_reassign_same(1,2,3, a=1, b=2)
417     """
418     assert typeof(args) == "tuple object", typeof(args)
419     assert typeof(kwargs) == "dict object", typeof(kwargs)
420
421     args = ()
422     kwargs = {}
423
424 @infer_types(None)
425 def args_tuple_keywords_reassign_pyobjects(*args, **kwargs):
426     """
427     >>> args_tuple_keywords_reassign_pyobjects(1,2,3, a=1, b=2)
428     """
429     assert typeof(args) == "Python object", typeof(args)
430     assert typeof(kwargs) == "Python object", typeof(kwargs)
431
432     args = []
433     kwargs = "test"
434
435 #                 / A -> AA -> AAA
436 # Base0 -> Base -
437 #                 \ B -> BB
438 # C -> CC
439
440 cdef class Base0: pass
441 cdef class Base(Base0): pass
442 cdef class A(Base): pass
443 cdef class AA(A): pass
444 cdef class AAA(AA): pass
445 cdef class B(Base): pass
446 cdef class BB(B): pass
447 cdef class C: pass
448 cdef class CC(C): pass
449
450 @infer_types(None)
451 def common_extension_type_base():
452     """
453     >>> common_extension_type_base()
454     """
455     x = A()
456     x = AA()
457     assert typeof(x) == "A", typeof(x)
458     y = A()
459     y = B()
460     assert typeof(y) == "Base", typeof(y)
461     z = AAA()
462     z = BB()
463     assert typeof(z) == "Base", typeof(z)
464     w = A()
465     w = CC()
466     assert typeof(w) == "Python object", typeof(w)
467
468
469 @infer_types(None)
470 def large_literals():
471     """
472     >>> large_literals()
473     """
474     # It's only safe to infer small integer literals.
475     a = 10
476     b = 100000000000000000000000000000000
477     assert typeof(a) == "long", typeof(a)
478     assert typeof(b) == "Python object", typeof(b)
479     c, d = 10, 100000000000000000000000000000000
480     assert typeof(c) == "long", typeof(c)
481     assert typeof(d) == "Python object", typeof(d)