1# mode: run
2# tag: pep484, warnings
3
4cimport cython
5from cython cimport typeof
6
7
8def old_dict_syntax(a: list, b: "int" = 2, c: {'ctype': 'long int'} = 3, d: {'type': 'float'} = 4) -> list:
9    """
10    >>> old_dict_syntax([1])
11    ('list object', 'int', 'long', 'float')
12    [1, 2, 3, 4.0]
13    >>> old_dict_syntax([1], 3)
14    ('list object', 'int', 'long', 'float')
15    [1, 3, 3, 4.0]
16    >>> old_dict_syntax(123)
17    Traceback (most recent call last):
18    TypeError: Argument 'a' has incorrect type (expected list, got int)
19    """
20    print(typeof(a), typeof(b), typeof(c), typeof(d))
21    a.append(b)
22    a.append(c)
23    a.append(d)
24    return a
25
26
27def pytypes_def(a: list, b: int = 2, c: long = 3, d: float = 4) -> list:
28    """
29    >>> pytypes_def([1])
30    ('list object', 'Python object', 'Python object', 'double')
31    [1, 2, 3, 4.0]
32    >>> pytypes_def([1], 3)
33    ('list object', 'Python object', 'Python object', 'double')
34    [1, 3, 3, 4.0]
35    >>> pytypes_def(123)
36    Traceback (most recent call last):
37    TypeError: Argument 'a' has incorrect type (expected list, got int)
38    """
39    print(typeof(a), typeof(b), typeof(c), typeof(d))
40    a.append(b)
41    a.append(c)
42    a.append(d)
43    return a
44
45
46cpdef pytypes_cpdef(a: list, b: int = 2, c: long = 3, d: float = 4):
47    """
48    >>> pytypes_cpdef([1])
49    ('list object', 'Python object', 'Python object', 'double')
50    [1, 2, 3, 4.0]
51    >>> pytypes_cpdef([1], 3)
52    ('list object', 'Python object', 'Python object', 'double')
53    [1, 3, 3, 4.0]
54    >>> pytypes_cpdef(123)
55    Traceback (most recent call last):
56    TypeError: Argument 'a' has incorrect type (expected list, got int)
57    """
58    print(typeof(a), typeof(b), typeof(c), typeof(d))
59    a.append(b)
60    a.append(c)
61    a.append(d)
62    return a
63
64
65cdef c_pytypes_cdef(a: list, b: int = 2, c: long = 3, d: float = 4):
66    print(typeof(a), typeof(b), typeof(c), typeof(d))
67    a.append(b)
68    a.append(c)
69    a.append(d)
70    return a
71
72
73def pytypes_cdef(a, b=2, c=3, d=4):
74    """
75    >>> pytypes_cdef([1])
76    ('list object', 'Python object', 'Python object', 'double')
77    [1, 2, 3, 4.0]
78    >>> pytypes_cdef([1], 3)
79    ('list object', 'Python object', 'Python object', 'double')
80    [1, 3, 3, 4.0]
81    >>> pytypes_cdef(123)   # doctest: +ELLIPSIS
82    Traceback (most recent call last):
83    TypeError: ...
84    """
85    return c_pytypes_cdef(a, b, c, d)
86
87
88def ctypes_def(a: list, b: cython.int = 2, c: cython.long = 3, d: cython.float = 4) -> list:
89    """
90    >>> ctypes_def([1])
91    ('list object', 'int', 'long', 'float')
92    [1, 2, 3, 4.0]
93    >>> ctypes_def([1], 3)
94    ('list object', 'int', 'long', 'float')
95    [1, 3, 3, 4.0]
96    >>> ctypes_def(123)
97    Traceback (most recent call last):
98    TypeError: Argument 'a' has incorrect type (expected list, got int)
99    """
100    print(typeof(a), typeof(b), typeof(c), typeof(d))
101    a.append(b)
102    a.append(c)
103    a.append(d)
104    return a
105
106
107def return_tuple_for_carray() -> tuple:
108    """
109    >>> return_tuple_for_carray()
110    (1, 2, 3)
111    """
112    cdef int[3] x
113    x = [1, 2, 3]
114    return x
115
116
117MyStruct = cython.struct(x=cython.int, y=cython.int, data=cython.double)
118
119
120@cython.ccall
121def struct_io(s : MyStruct) -> MyStruct:
122    """
123    >>> d = struct_io(dict(x=1, y=2, data=3))
124    >>> sorted(d.items())
125    [('data', 3.0), ('x', 2), ('y', 1)]
126    """
127    t = s
128    t.x, t.y = s.y, s.x
129    return t
130
131
132@cython.test_fail_if_path_exists(
133    "//CoerceFromPyTypeNode",
134    "//SimpleCallNode//CoerceToPyTypeNode",
135)
136@cython.test_assert_path_exists(
137    "//CoerceToPyTypeNode",
138    "//CoerceToPyTypeNode//SimpleCallNode",
139)
140def call_struct_io(s : MyStruct) -> MyStruct:
141    """
142    >>> d = call_struct_io(dict(x=1, y=2, data=3))
143    >>> sorted(d.items())
144    [('data', 3.0), ('x', 2), ('y', 1)]
145    """
146    return struct_io(s)
147
148
149@cython.test_assert_path_exists(
150    "//CFuncDefNode",
151    "//CFuncDefNode//DefNode",
152    "//CFuncDefNode[@return_type]",
153    "//CFuncDefNode[@return_type.is_struct_or_union = True]",
154)
155@cython.ccall
156def struct_convert(d) -> MyStruct:
157    """
158    >>> d = struct_convert(dict(x=1, y=2, data=3))
159    >>> sorted(d.items())
160    [('data', 3.0), ('x', 1), ('y', 2)]
161    >>> struct_convert({})  # make sure we can raise exceptions through struct return values
162    Traceback (most recent call last):
163    ValueError: No value specified for struct attribute 'x'
164    """
165    return d
166
167
168@cython.test_assert_path_exists(
169    "//CFuncDefNode",
170    "//CFuncDefNode//DefNode",
171    "//CFuncDefNode[@return_type]",
172    "//CFuncDefNode[@return_type.is_int = True]",
173)
174@cython.ccall
175def exception_default(raise_exc : cython.bint = False) -> cython.int:
176    """
177    >>> exception_default(raise_exc=False)
178    10
179    >>> exception_default(raise_exc=True)
180    Traceback (most recent call last):
181    ValueError: huhu!
182    """
183    if raise_exc:
184        raise ValueError("huhu!")
185    return 10
186
187
188def call_exception_default(raise_exc=False):
189    """
190    >>> call_exception_default(raise_exc=False)
191    10
192    >>> call_exception_default(raise_exc=True)
193    Traceback (most recent call last):
194    ValueError: huhu!
195    """
196    return exception_default(raise_exc)
197
198
199class EarlyClass(object):
200    """
201    >>> a = EarlyClass(1)
202    >>> a.string_forward_declaration()  # should probably raise an error at some point
203    1
204    >>> x = LateClass()
205    >>> a = EarlyClass(x)
206    >>> x2 = a.string_forward_declaration()
207    >>> assert x is x2, x2
208    """
209    def __init__(self, x):
210        self.x = x
211    def string_forward_declaration(self) -> 'LateClass':
212        return self.x
213
214class LateClass(object):
215    pass
216
217
218def py_float_default(price : float=None, ndigits=4):
219    """
220    Python default arguments should prevent C type inference.
221
222    >>> py_float_default()
223    (None, 4)
224    >>> py_float_default(2)
225    (2, 4)
226    >>> py_float_default(2.0)
227    (2.0, 4)
228    >>> py_float_default(2, 3)
229    (2, 3)
230    """
231    return price, ndigits
232
233
234_WARNINGS = """
2358:32: Strings should no longer be used for type declarations. Use 'cython.int' etc. directly.
2368:47: Dicts should no longer be used as type annotations. Use 'cython.int' etc. directly.
2378:56: Strings should no longer be used for type declarations. Use 'cython.int' etc. directly.
2388:77: Dicts should no longer be used as type annotations. Use 'cython.int' etc. directly.
2398:85: Python type declaration in signature annotation does not refer to a Python type
2408:85: Strings should no longer be used for type declarations. Use 'cython.int' etc. directly.
241211:44: Unknown type declaration in annotation, ignoring
242218:29: Ambiguous types in annotation, ignoring
243# BUG:
24446:6: 'pytypes_cpdef' redeclared
245121:0: 'struct_io' redeclared
246156:0: 'struct_convert' redeclared
247175:0: 'exception_default' redeclared
248"""
249