1# mode: run
2# tag: annotation_typing, pure3.0, mypy
3
4import cython
5
6is_compiled = cython.compiled
7
8MyUnion = cython.union(n=cython.int, x=cython.double)
9MyStruct = cython.struct(is_integral=cython.bint, data=MyUnion)
10MyStruct2 = cython.typedef(MyStruct[2])  # type: cython.StructType
11
12
13@cython.ccall  # cpdef => C return type
14def test_return_type(n: cython.int) -> cython.double:
15    """
16    >>> test_return_type(389)
17    389.0
18    """
19    assert cython.typeof(n) == 'int', cython.typeof(n)
20    return n if is_compiled else float(n)
21
22
23def test_struct(n: cython.int, x: cython.double) -> MyStruct2:
24    """
25    >>> test_struct(389, 1.64493)
26    (389, 1.64493)
27    >>> d = test_struct.__annotations__
28    >>> sorted(d)
29    ['n', 'return', 'x']
30    """
31    assert cython.typeof(n) == 'int', cython.typeof(n)
32    if is_compiled:
33        assert cython.typeof(x) == 'double', cython.typeof(x)  # C double
34    else:
35        assert cython.typeof(x) == 'float', cython.typeof(x)   # Python float
36
37    a = cython.declare(MyStruct2)
38    a[0] = MyStruct(is_integral=True, data=MyUnion(n=n))
39    a[1] = MyStruct(is_integral=False, data={'x': x})
40    return a[0].data.n, a[1].data.x
41
42
43@cython.ccall
44def c_call(x) -> cython.double:
45    return x
46
47
48def call_ccall(x):
49    """
50    Test that a declared return type is honoured when compiled.
51
52    >>> result, return_type = call_ccall(1)
53
54    >>> (not is_compiled and 'double') or return_type
55    'double'
56    >>> (is_compiled and 'int') or return_type
57    'int'
58
59    >>> (not is_compiled and 1.0) or result
60    1.0
61    >>> (is_compiled and 1) or result
62    1
63    """
64    ret = c_call(x)
65    return ret, cython.typeof(ret)
66
67
68@cython.cfunc
69@cython.inline
70def cdef_inline(x) -> cython.double:
71    return x + 1
72
73
74def call_cdef_inline(x):
75    """
76    >>> result, return_type = call_cdef_inline(1)
77    >>> (not is_compiled and 'float') or type(result).__name__
78    'float'
79    >>> (not is_compiled and 'double') or return_type
80    'double'
81    >>> (is_compiled and 'int') or return_type
82    'int'
83    >>> result == 2.0  or  result
84    True
85    """
86    ret = cdef_inline(x)
87    return ret, cython.typeof(ret)
88