diff options
Diffstat (limited to 'tests/memoryview/memslice.pyx')
-rw-r--r-- | tests/memoryview/memslice.pyx | 147 |
1 files changed, 142 insertions, 5 deletions
diff --git a/tests/memoryview/memslice.pyx b/tests/memoryview/memslice.pyx index 4e06c4f41..0de47d9b6 100644 --- a/tests/memoryview/memslice.pyx +++ b/tests/memoryview/memslice.pyx @@ -7,7 +7,7 @@ from __future__ import unicode_literals from cpython.object cimport PyObject -from cpython.ref cimport Py_INCREF, Py_DECREF +from cpython.ref cimport Py_INCREF, Py_DECREF, Py_CLEAR cimport cython from cython cimport view @@ -23,6 +23,12 @@ if sys.version_info[0] < 3: else: import builtins +try: + from Cython.Tests.this_module_does_not_exist import * +except ImportError: + # Fails, but the existence of "import *" interacted badly with some utility code + pass + def testcase(func): @wraps(func) @@ -1134,6 +1140,49 @@ def assign_temporary_to_object(object[:] buf): """ buf[1] = {3-2: 2+(2*4)-2} +@testcase +def check_object_nulled_1d(object[:] buf, int idx, obj): + """ + See comments on printbuf_object above. + + >>> a = object() + >>> rc1 = get_refcount(a) + >>> A = ObjectMockBuffer(None, [a, a]) + >>> check_object_nulled_1d(A, 0, a) + >>> check_object_nulled_1d(A, 1, a) + >>> A = ObjectMockBuffer(None, [a, a, a, a], strides=(2,)) + >>> check_object_nulled_1d(A, 0, a) # only 0 due to stride + >>> get_refcount(a) == rc1 + True + """ + cdef ObjectMockBuffer omb = buf.base + cdef PyObject **data = <PyObject**>(omb.buffer) + Py_CLEAR(data[idx]) + res = buf[idx] # takes None + buf[idx] = obj + return res + +@testcase +def check_object_nulled_2d(object[:, ::1] buf, int idx1, int idx2, obj): + """ + See comments on printbuf_object above. + + >>> a = object() + >>> rc1 = get_refcount(a) + >>> A = ObjectMockBuffer(None, [a, a, a, a], shape=(2, 2)) + >>> check_object_nulled_2d(A, 0, 0, a) + >>> check_object_nulled_2d(A, 1, 1, a) + >>> get_refcount(a) == rc1 + True + """ + cdef ObjectMockBuffer omb = buf.base + cdef PyObject **data = <PyObject**>(omb.buffer) + Py_CLEAR(data[idx1 + 2*idx2]) + res = buf[idx1, idx2] # takes None + buf[idx1, idx2] = obj + return res + + # # Test __cythonbufferdefaults__ # @@ -1679,7 +1728,7 @@ def test_oob(): print a[:, 20] -cdef int nogil_oob(int[:, :] a) nogil except 0: +cdef int nogil_oob(int[:, :] a) except 0 nogil: a[100, 9:] return 1 @@ -1723,7 +1772,7 @@ def test_nogil_oob2(): a[100, 9:] @cython.boundscheck(False) -cdef int cdef_nogil(int[:, :] a) nogil except 0: +cdef int cdef_nogil(int[:, :] a) except 0 nogil: cdef int i, j cdef int[:, :] b = a[::-1, 3:10:2] for i in range(b.shape[0]): @@ -2517,6 +2566,7 @@ def test_const_buffer(const int[:] a): print(a[0]) print(c[-1]) + @testcase def test_loop(int[:] a, throw_exception): """ @@ -2539,6 +2589,7 @@ def test_loop(int[:] a, throw_exception): raise ValueError() print(sum) + @testcase def test_loop_reassign(int[:] a): """ @@ -2551,13 +2602,99 @@ def test_loop_reassign(int[:] a): 3 4 5 - released A 15 + released A """ cdef int sum = 0 for ai in a: sum += ai print(ai) a = None # this should not mess up the loop though! - # release happens here, when the loop temp is released print(sum) + # release happens in the wrapper function + + +@testcase +def test_arg_in_closure(int [:] a): + """ + >>> A = IntMockBuffer("A", range(6), shape=(6,)) + >>> inner = test_arg_in_closure(A) + acquired A + >>> inner() + (0, 1) + + The assignment below is just to avoid printing what was collected + >>> del inner; ignore_me = gc.collect() + released A + """ + def inner(): + return (a[0], a[1]) + return inner + + +cdef arg_in_closure_cdef(int [:] a): + def inner(): + return (a[0], a[1]) + return inner + +def test_arg_in_closure_cdef(a): + """ + >>> A = IntMockBuffer("A", range(6), shape=(6,)) + >>> inner = test_arg_in_closure_cdef(A) + acquired A + >>> inner() + (0, 1) + + The assignment below is just to avoid printing what was collected + >>> del inner; ignore_me = gc.collect() + released A + """ + return arg_in_closure_cdef(a) + + +@testcase +def test_local_in_closure(a): + """ + >>> A = IntMockBuffer("A", range(6), shape=(6,)) + >>> inner = test_local_in_closure(A) + acquired A + >>> inner() + (0, 1) + + The assignment below is just to avoid printing what was collected + >>> del inner; ignore_me = gc.collect() + released A + """ + cdef int[:] a_view = a + def inner(): + return (a_view[0], a_view[1]) + return inner + +@testcase +def test_local_in_generator_expression(a, initialize, execute_now): + """ + >>> A1 = IntMockBuffer("A1", range(6), shape=(6,)) + >>> A2 = IntMockBuffer("A2", range(6), shape=(6,)) + >>> test_local_in_generator_expression(A1, initialize=False, execute_now=False) # doctest: +ELLIPSIS + Traceback (most recent call last): + ... + UnboundLocalError... + + >>> test_local_in_generator_expression(A1, initialize=True, execute_now=True) + acquired A1 + released A1 + True + + >>> genexp = test_local_in_generator_expression(A2, initialize=True, execute_now=False) + acquired A2 + >>> sum(genexp) + released A2 + 2 + """ + cdef int[:] a_view + if initialize: + a_view = a + if execute_now: + return any(ai > 3 for ai in a_view) + else: + return (ai > 3 for ai in a_view) |