1# cython: optimize.inline_defnode_calls=True
2# mode: run
3cimport cython
4
5@cython.test_fail_if_path_exists('//SimpleCallNode')
6@cython.test_assert_path_exists('//InlinedDefNodeCallNode')
7def simple_noargs():
8    """
9    >>> simple_noargs()
10    123
11    """
12    def inner():
13        return 123
14    return inner()
15
16
17@cython.test_fail_if_path_exists('//SimpleCallNode')
18@cython.test_assert_path_exists('//InlinedDefNodeCallNode')
19def test_coerce(a, int b):
20    """
21    >>> test_coerce(2, 2)
22    4
23    """
24    def inner(int a, b):
25        return a * b
26    return inner(a, b)
27
28
29cdef class Foo(object):
30    def __repr__(self):
31        return '<Foo>'
32
33
34@cython.test_fail_if_path_exists('//SimpleCallNode')
35@cython.test_assert_path_exists('//InlinedDefNodeCallNode')
36def test_func_signature(a):
37    """
38    >>> test_func_signature(Foo())
39    <Foo>
40    >>> test_func_signature(123)
41    Traceback (most recent call last):
42    TypeError: Cannot convert int to closure_inlining.Foo
43    """
44
45    def inner(Foo a):
46        return a
47    return inner(a)
48
49@cython.test_fail_if_path_exists('//SimpleCallNode')
50@cython.test_assert_path_exists('//InlinedDefNodeCallNode')
51def test_func_signature2(a, b):
52    """
53    >>> test_func_signature2(Foo(), 123)
54    (<Foo>, 123)
55    >>> test_func_signature2(321, 123)
56    Traceback (most recent call last):
57    TypeError: Cannot convert int to closure_inlining.Foo
58    """
59
60    def inner(Foo a, b):
61        return a, b
62    return inner(a, b)
63
64# Starred args and default values are not yet supported for inlining
65@cython.test_assert_path_exists('//SimpleCallNode')
66def test_defaults(a, b):
67    """
68    >>> test_defaults(1, 2)
69    (1, 2, 123)
70    """
71    def inner(a, b=b, c=123):
72        return a, b, c
73    return inner(a)
74
75@cython.test_assert_path_exists('//SimpleCallNode')
76def test_kwonly_args(a, b):
77    """
78    >>> test_kwonly_args(1, 2)
79    (1, 2, 123)
80    """
81    def inner(a, b=b, *, c=123):
82        return a, b, c
83    return inner(a)
84
85@cython.test_assert_path_exists('//SimpleCallNode')
86def test_kwonly_args_missing(a, b):
87    """
88    >>> test_kwonly_args_missing(1, 2)
89    Traceback (most recent call last):
90    TypeError: inner() needs keyword-only argument c
91    """
92    def inner(a, b=b, *, c):
93        return a, b, c
94    return inner(a)
95
96@cython.test_assert_path_exists('//SimpleCallNode')
97def test_starred(a):
98    """
99    >>> test_starred(123)
100    (123, (), {})
101    """
102    def inner(a, *args, **kwargs):
103        return a, args, kwargs
104    return inner(a)
105
106
107def test_global_calls_still_work():
108    """
109    >>> global_call_result
110    123
111    """
112    return 123
113
114global_call_result = test_global_calls_still_work()
115
116
117@cython.test_fail_if_path_exists(
118    '//InlinedDefNodeCallNode//SimpleCallNode')
119@cython.test_assert_path_exists(
120    '//InlinedDefNodeCallNode',
121    '//InlinedDefNodeCallNode[@function_name.name = "call"]',
122    '//InlinedDefNodeCallNode//InlinedDefNodeCallNode')
123def test_sideeffect_call_order():
124    """
125    >>> test_sideeffect_call_order()
126    [2, 4, 5]
127    """
128    L = []
129    def sideeffect(x):
130        L.append(x)
131        return x
132    def call(x1, x2, x3, x4, x5):
133        pass
134    call(1, sideeffect(2), 3, sideeffect(4), sideeffect(5))
135    return L
136
137
138def test_redef(redefine):
139    """
140    >>> test_redef(False)
141    1
142    >>> test_redef(True)
143    2
144    """
145    def inner():
146        return 1
147    def inner2():
148        return 2
149    def redef():
150        nonlocal inner
151        inner = inner2
152    if redefine:
153        redef()
154        assert inner == inner2
155    else:
156        assert inner != inner2
157    return inner()
158
159
160def test_with_statement():
161    """
162    >>> test_with_statement()
163    enter
164    running
165    exit
166    """
167    def make_context_manager():
168        class CM(object):
169            def __enter__(self):
170                print "enter"
171            def __exit__(self, *args):
172                print "exit"
173        return CM()
174
175    with make_context_manager():
176        print "running"
177