summaryrefslogtreecommitdiff
path: root/tests/memoryview/memslice.pyx
diff options
context:
space:
mode:
Diffstat (limited to 'tests/memoryview/memslice.pyx')
-rw-r--r--tests/memoryview/memslice.pyx147
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)