1import sys
2IS_PY2 = sys.version_info[0] < 3
3
4import cython
5from cython import sizeof
6
7is_compiled = cython.compiled
8
9NULL = 5
10_NULL = NULL
11
12
13def test_sizeof():
14    """
15    >>> test_sizeof()
16    True
17    True
18    True
19    True
20    True
21    """
22    x = cython.declare(cython.bint)
23    print(cython.sizeof(x) == cython.sizeof(cython.bint))
24    print(sizeof(cython.char) <= sizeof(cython.short) <= sizeof(cython.int) <= sizeof(cython.long) <= sizeof(cython.longlong))
25    print(cython.sizeof(cython.uint) == cython.sizeof(cython.int))
26    print(cython.sizeof(cython.p_int) == cython.sizeof(cython.p_double))
27    if cython.compiled:
28        print(cython.sizeof(cython.char) < cython.sizeof(cython.longlong))
29    else:
30        print(cython.sizeof(cython.char) == 1)
31
32
33def test_declare(n):
34    """
35    >>> test_declare(100)
36    (100, 100)
37    >>> test_declare(100.5)
38    (100, 100)
39    >>> test_declare(None) #doctest: +ELLIPSIS
40    Traceback (most recent call last):
41    ...
42    TypeError: ...
43    """
44    x = cython.declare(cython.int)
45    y = cython.declare(cython.int, n)
46    if cython.compiled:
47        cython.declare(xx=cython.int, yy=cython.long)
48        i = cython.sizeof(xx)
49    ptr = cython.declare(cython.p_int, cython.address(y))
50    return y, ptr[0]
51
52
53@cython.locals(x=cython.double, n=cython.int)
54def test_cast(x):
55    """
56    >>> test_cast(1.5)
57    1
58    """
59    n = cython.cast(cython.int, x)
60    return n
61
62
63@cython.locals(x=cython.int, y=cython.p_int)
64def test_address(x):
65    """
66    >>> test_address(39)
67    39
68    """
69    y = cython.address(x)
70    return y[0]
71
72
73@cython.wraparound(False)
74def test_wraparound(x):
75    """
76    >>> test_wraparound([1, 2, 3])
77    [1, 2, 1]
78    """
79    with cython.wraparound(True):
80        x[-1] = x[0]
81    return x
82
83
84@cython.boundscheck(False)
85def test_boundscheck(x):
86    """
87    >>> test_boundscheck([1, 2, 3])
88    3
89    >>> try: test_boundscheck([1, 2])
90    ... except IndexError: pass
91    """
92    with cython.boundscheck(True):
93        return x[2]
94
95
96## CURRENTLY BROKEN - FIXME!!
97## Is this test make sense? Implicit conversion in pure Python??
98
99## @cython.locals(x=cython.int)
100## @cython.locals(y=cython.bint)
101## def test_locals(x):
102##     """
103##     >>> test_locals(5)
104##     True
105##     """
106##     y = x
107##     return y
108
109
110def test_with_nogil(nogil, should_raise=False):
111    """
112    >>> raised = []
113    >>> class nogil(object):
114    ...     def __enter__(self):
115    ...         pass
116    ...     def __exit__(self, exc_class, exc, tb):
117    ...         raised.append(exc)
118    ...         return exc_class is None
119
120    >>> test_with_nogil(nogil())
121    WORKS
122    True
123    >>> raised
124    [None]
125
126    >>> test_with_nogil(nogil(), should_raise=True)
127    Traceback (most recent call last):
128    ValueError: RAISED!
129
130    >>> raised[1] is None
131    False
132    """
133    result = False
134    should_raise_bool = True if should_raise else False  # help the type inference ...
135    with nogil:
136        print("WORKS")
137        with cython.nogil:
138            result = True
139            if should_raise_bool:
140                raise ValueError("RAISED!")
141    return result
142
143
144MyUnion = cython.union(n=cython.int, x=cython.double)
145MyStruct = cython.struct(is_integral=cython.bint, data=MyUnion)
146MyStruct2 = cython.typedef(MyStruct[2])
147
148def test_struct(n, x):
149    """
150    >>> test_struct(389, 1.64493)
151    (389, 1.64493)
152    """
153    a = cython.declare(MyStruct2)
154    a[0] = MyStruct(is_integral=True, data=MyUnion(n=n))
155    a[1] = MyStruct(is_integral=False, data={'x': x})
156    return a[0].data.n, a[1].data.x
157
158import cython as cy
159from cython import declare, cast, locals, address, typedef, p_void, compiled
160from cython import declare as my_declare, locals as my_locals, p_void as my_void_star, typedef as my_typedef, compiled as my_compiled
161
162@my_locals(a=cython.p_void)
163def test_imports():
164    """
165    >>> test_imports()
166    (True, True)
167    """
168    a = cython.NULL
169    b = declare(p_void, cython.NULL)
170    c = my_declare(my_void_star, cython.NULL)
171    d = cy.declare(cy.p_void, cython.NULL)
172
173    return a == d, compiled == my_compiled
174
175## CURRENTLY BROKEN - FIXME!!
176
177# MyStruct3 = typedef(MyStruct[3])
178# MyStruct4 = my_typedef(MyStruct[4])
179# MyStruct5 = cy.typedef(MyStruct[5])
180
181def test_declare_c_types(n):
182    """
183    >>> test_declare_c_types(0)
184    >>> test_declare_c_types(1)
185    >>> test_declare_c_types(2)
186    """
187    #
188    b00 = cython.declare(cython.bint, 0)
189    b01 = cython.declare(cython.bint, 1)
190    b02 = cython.declare(cython.bint, 2)
191    #
192    i00 = cython.declare(cython.uchar, n)
193    i01 = cython.declare(cython.char, n)
194    i02 = cython.declare(cython.schar, n)
195    i03 = cython.declare(cython.ushort, n)
196    i04 = cython.declare(cython.short, n)
197    i05 = cython.declare(cython.sshort, n)
198    i06 = cython.declare(cython.uint, n)
199    i07 = cython.declare(cython.int, n)
200    i08 = cython.declare(cython.sint, n)
201    i09 = cython.declare(cython.slong, n)
202    i10 = cython.declare(cython.long, n)
203    i11 = cython.declare(cython.ulong, n)
204    i12 = cython.declare(cython.slonglong, n)
205    i13 = cython.declare(cython.longlong, n)
206    i14 = cython.declare(cython.ulonglong, n)
207
208    i20 = cython.declare(cython.Py_ssize_t, n)
209    i21 = cython.declare(cython.size_t, n)
210    #
211    f00 = cython.declare(cython.float, n)
212    f01 = cython.declare(cython.double, n)
213    f02 = cython.declare(cython.longdouble, n)
214    #
215    #z00 = cython.declare(cython.complex, n+1j)
216    #z01 = cython.declare(cython.floatcomplex, n+1j)
217    #z02 = cython.declare(cython.doublecomplex, n+1j)
218    #z03 = cython.declare(cython.longdoublecomplex, n+1j)
219
220
221@cython.ccall
222@cython.returns(cython.double)
223def c_call(x):
224    return x
225
226
227def call_ccall(x):
228    """
229    Test that a declared return type is honoured when compiled.
230
231    >>> result, return_type = call_ccall(1)
232
233    >>> (not is_compiled and 'double') or return_type
234    'double'
235    >>> (is_compiled and 'int') or return_type
236    'int'
237
238    >>> (not is_compiled and 1.0) or result
239    1.0
240    >>> (is_compiled and 1) or result
241    1
242    """
243    ret = c_call(x)
244    return ret, cython.typeof(ret)
245
246
247@cython.cfunc
248@cython.inline
249@cython.returns(cython.double)
250def cdef_inline(x):
251    return x + 1
252
253
254def call_cdef_inline(x):
255    """
256    >>> result, return_type = call_cdef_inline(1)
257    >>> (not is_compiled and 'float') or type(result).__name__
258    'float'
259    >>> (not is_compiled and 'double') or return_type
260    'double'
261    >>> (is_compiled and 'int') or return_type
262    'int'
263    >>> result == 2.0  or  result
264    True
265    """
266    ret = cdef_inline(x)
267    return ret, cython.typeof(ret)
268
269
270@cython.cfunc
271@cython.nogil
272@cython.locals(x=cython.int)
273@cython.returns(cython.int)
274def cdef_nogil(x):
275    return x + 1
276
277
278@cython.cfunc
279@cython.nogil(True)
280@cython.locals(x=cython.int)
281@cython.returns(cython.int)
282def cdef_nogil_true(x):
283    return x + 1
284
285
286@cython.cfunc
287@cython.nogil(False)
288@cython.locals(x=cython.int)
289@cython.returns(cython.int)
290def cdef_nogil_false(x):
291    return x + 1
292
293
294@cython.locals(x=cython.int, result=cython.int)
295def test_cdef_nogil(x):
296    """
297    >>> test_cdef_nogil(5)
298    18
299    """
300    with cython.nogil:
301        result = cdef_nogil(x)
302    with cython.nogil(True):
303        result += cdef_nogil_true(x)
304    result += cdef_nogil_false(x)
305    return result
306
307
308@cython.locals(counts=cython.int[10], digit=cython.int)
309def count_digits_in_carray(digits):
310    """
311    >>> digits = '37692837651902834128342341'
312    >>> ''.join(sorted(digits))
313    '01112222333334445667788899'
314    >>> count_digits_in_carray(map(int, digits))
315    [1, 3, 4, 5, 3, 1, 2, 2, 3, 2]
316    """
317    counts = [0] * 10
318    for digit in digits:
319        assert 0 <= digit <= 9
320        counts[digit] += 1
321    return counts
322
323
324@cython.test_assert_path_exists("//CFuncDeclaratorNode//IntNode[@value = '-1']")
325@cython.ccall
326@cython.returns(cython.long)
327@cython.exceptval(-1)
328def ccall_except(x):
329    """
330    >>> ccall_except(41)
331    42
332    >>> ccall_except(0)
333    Traceback (most recent call last):
334    ValueError
335    """
336    if x == 0:
337        raise ValueError
338    return x+1
339
340
341@cython.test_assert_path_exists("//CFuncDeclaratorNode//IntNode[@value = '-1']")
342@cython.cfunc
343@cython.returns(cython.long)
344@cython.exceptval(-1)
345def cdef_except(x):
346    if x == 0:
347        raise ValueError
348    return x+1
349
350
351def call_cdef_except(x):
352    """
353    >>> call_cdef_except(41)
354    42
355    >>> call_cdef_except(0)
356    Traceback (most recent call last):
357    ValueError
358    """
359    return cdef_except(x)
360
361
362@cython.test_assert_path_exists("//CFuncDeclaratorNode//IntNode[@value = '-1']")
363@cython.ccall
364@cython.returns(cython.long)
365@cython.exceptval(-1, check=True)
366def ccall_except_check(x):
367    """
368    >>> ccall_except_check(41)
369    42
370    >>> ccall_except_check(-2)
371    -1
372    >>> ccall_except_check(0)
373    Traceback (most recent call last):
374    ValueError
375    """
376    if x == 0:
377        raise ValueError
378    return x+1
379
380
381@cython.test_fail_if_path_exists("//CFuncDeclaratorNode//IntNode[@value = '-1']")
382@cython.test_assert_path_exists("//CFuncDeclaratorNode")
383@cython.ccall
384@cython.returns(cython.long)
385@cython.exceptval(check=True)
386def ccall_except_check_always(x):
387    """
388    >>> ccall_except_check_always(41)
389    42
390    >>> ccall_except_check_always(0)
391    Traceback (most recent call last):
392    ValueError
393    """
394    if x == 0:
395        raise ValueError
396    return x+1
397
398
399@cython.final
400@cython.cclass
401class CClass(object):
402    """
403    >>> c = CClass(2)
404    >>> c.get_attr()
405    int
406    2
407    """
408    cython.declare(attr=cython.int)
409
410    def __init__(self, attr):
411        self.attr = attr
412
413    def get_attr(self):
414        print(cython.typeof(self.attr))
415        return self.attr
416
417
418class TestUnboundMethod:
419    """
420    >>> C = TestUnboundMethod
421    >>> IS_PY2 or (C.meth is C.__dict__["meth"])
422    True
423    """
424    def meth(self): pass
425