diff options
Diffstat (limited to 'tests/memoryview/memoryview.pyx')
-rw-r--r-- | tests/memoryview/memoryview.pyx | 179 |
1 files changed, 152 insertions, 27 deletions
diff --git a/tests/memoryview/memoryview.pyx b/tests/memoryview/memoryview.pyx index 15c71d481..344d11840 100644 --- a/tests/memoryview/memoryview.pyx +++ b/tests/memoryview/memoryview.pyx @@ -1,5 +1,7 @@ # mode: run +# Test declarations, behaviour and coercions of the memoryview type itself. + u''' >>> f() >>> g() @@ -155,6 +157,7 @@ def assignmvs(): cdef int[:] mv3 mv1 = array((10,), itemsize=sizeof(int), format='i') mv2 = mv1 + mv1 = mv1 mv1 = mv2 mv3 = mv2 @@ -247,7 +250,7 @@ def basic_struct(MyStruct[:] mslice): >>> basic_struct(MyStructMockBuffer(None, [(1, 2, 3, 4, 5)], format="ccqii")) [('a', 1), ('b', 2), ('c', 3), ('d', 4), ('e', 5)] """ - buf = mslice + cdef object buf = mslice print sorted([(k, int(v)) for k, v in buf[0].items()]) def nested_struct(NestedStruct[:] mslice): @@ -259,7 +262,7 @@ def nested_struct(NestedStruct[:] mslice): >>> nested_struct(NestedStructMockBuffer(None, [(1, 2, 3, 4, 5)], format="T{ii}T{2i}i")) 1 2 3 4 5 """ - buf = mslice + cdef object buf = mslice d = buf[0] print d['x']['a'], d['x']['b'], d['y']['a'], d['y']['b'], d['z'] @@ -275,7 +278,7 @@ def packed_struct(PackedStruct[:] mslice): 1 2 """ - buf = mslice + cdef object buf = mslice print buf[0]['a'], buf[0]['b'] def nested_packed_struct(NestedPackedStruct[:] mslice): @@ -289,7 +292,7 @@ def nested_packed_struct(NestedPackedStruct[:] mslice): >>> nested_packed_struct(NestedPackedStructMockBuffer(None, [(1, 2, 3, 4, 5)], format="^c@i^ci@i")) 1 2 3 4 5 """ - buf = mslice + cdef object buf = mslice d = buf[0] print d['a'], d['b'], d['sub']['a'], d['sub']['b'], d['c'] @@ -299,7 +302,7 @@ def complex_dtype(long double complex[:] mslice): >>> complex_dtype(LongComplexMockBuffer(None, [(0, -1)])) -1j """ - buf = mslice + cdef object buf = mslice print buf[0] def complex_inplace(long double complex[:] mslice): @@ -307,7 +310,7 @@ def complex_inplace(long double complex[:] mslice): >>> complex_inplace(LongComplexMockBuffer(None, [(0, -1)])) (1+1j) """ - buf = mslice + cdef object buf = mslice buf[0] = buf[0] + 1 + 2j print buf[0] @@ -318,7 +321,7 @@ def complex_struct_dtype(LongComplex[:] mslice): >>> complex_struct_dtype(LongComplexMockBuffer(None, [(0, -1)])) 0.0 -1.0 """ - buf = mslice + cdef object buf = mslice print buf[0]['real'], buf[0]['imag'] # @@ -356,7 +359,7 @@ def get_int_2d(int[:, :] mslice, int i, int j): ... IndexError: Out of bounds on buffer access (axis 1) """ - buf = mslice + cdef object buf = mslice return buf[i, j] def set_int_2d(int[:, :] mslice, int i, int j, int value): @@ -409,11 +412,50 @@ def set_int_2d(int[:, :] mslice, int i, int j, int value): IndexError: Out of bounds on buffer access (axis 1) """ - buf = mslice + cdef object buf = mslice buf[i, j] = value # +# auto type inference +# (note that for most numeric types "might_overflow" stops the type inference from working well) +# +def type_infer(double[:, :] arg): + """ + >>> type_infer(DoubleMockBuffer(None, range(6), (2,3))) + double + double[:] + double[:] + double[:, :] + """ + a = arg[0,0] + print(cython.typeof(a)) + b = arg[0] + print(cython.typeof(b)) + c = arg[0,:] + print(cython.typeof(c)) + d = arg[:,:] + print(cython.typeof(d)) + +# +# Loop optimization +# +@cython.test_fail_if_path_exists("//CoerceToPyTypeNode") +def memview_iter(double[:, :] arg): + """ + >>> memview_iter(DoubleMockBuffer("C", range(6), (2,3))) + acquired C + released C + True + """ + cdef double total = 0 + for mview1d in arg: + for val in mview1d: + total += val + if total == 15: + return True + +# # Test all kinds of indexing and flags # @@ -426,7 +468,7 @@ def writable(unsigned short int[:, :, :] mslice): >>> [str(x) for x in R.received_flags] # Py2/3 ['FORMAT', 'ND', 'STRIDES', 'WRITABLE'] """ - buf = mslice + cdef object buf = mslice buf[2, 2, 1] = 23 def strided(int[:] mslice): @@ -441,7 +483,7 @@ def strided(int[:] mslice): >>> A.release_ok True """ - buf = mslice + cdef object buf = mslice return buf[2] def c_contig(int[::1] mslice): @@ -450,7 +492,7 @@ def c_contig(int[::1] mslice): >>> c_contig(A) 2 """ - buf = mslice + cdef object buf = mslice return buf[2] def c_contig_2d(int[:, ::1] mslice): @@ -461,7 +503,7 @@ def c_contig_2d(int[:, ::1] mslice): >>> c_contig_2d(A) 7 """ - buf = mslice + cdef object buf = mslice return buf[1, 3] def f_contig(int[::1, :] mslice): @@ -470,7 +512,7 @@ def f_contig(int[::1, :] mslice): >>> f_contig(A) 2 """ - buf = mslice + cdef object buf = mslice return buf[0, 1] def f_contig_2d(int[::1, :] mslice): @@ -481,7 +523,7 @@ def f_contig_2d(int[::1, :] mslice): >>> f_contig_2d(A) 7 """ - buf = mslice + cdef object buf = mslice return buf[3, 1] def generic(int[::view.generic, ::view.generic] mslice1, @@ -552,7 +594,7 @@ def printbuf_td_cy_int(td_cy_int[:] mslice, shape): ... ValueError: Buffer dtype mismatch, expected 'td_cy_int' but got 'short' """ - buf = mslice + cdef object buf = mslice cdef int i for i in range(shape[0]): print buf[i], @@ -567,7 +609,7 @@ def printbuf_td_h_short(td_h_short[:] mslice, shape): ... ValueError: Buffer dtype mismatch, expected 'td_h_short' but got 'int' """ - buf = mslice + cdef object buf = mslice cdef int i for i in range(shape[0]): print buf[i], @@ -582,7 +624,7 @@ def printbuf_td_h_cy_short(td_h_cy_short[:] mslice, shape): ... ValueError: Buffer dtype mismatch, expected 'td_h_cy_short' but got 'int' """ - buf = mslice + cdef object buf = mslice cdef int i for i in range(shape[0]): print buf[i], @@ -597,7 +639,7 @@ def printbuf_td_h_ushort(td_h_ushort[:] mslice, shape): ... ValueError: Buffer dtype mismatch, expected 'td_h_ushort' but got 'short' """ - buf = mslice + cdef object buf = mslice cdef int i for i in range(shape[0]): print buf[i], @@ -612,7 +654,7 @@ def printbuf_td_h_double(td_h_double[:] mslice, shape): ... ValueError: Buffer dtype mismatch, expected 'td_h_double' but got 'float' """ - buf = mslice + cdef object buf = mslice cdef int i for i in range(shape[0]): print buf[i], @@ -626,6 +668,8 @@ def addref(*args): def decref(*args): for item in args: Py_DECREF(item) +@cython.binding(False) +@cython.always_allow_keywords(False) def get_refcount(x): return (<PyObject*>x).ob_refcnt @@ -647,7 +691,7 @@ def printbuf_object(object[:] mslice, shape): {4: 23} 2 [34, 3] 2 """ - buf = mslice + cdef object buf = mslice cdef int i for i in range(shape[0]): print repr(buf[i]), (<PyObject*>buf[i]).ob_refcnt @@ -668,7 +712,7 @@ def assign_to_object(object[:] mslice, int idx, obj): (2, 3) >>> decref(b) """ - buf = mslice + cdef object buf = mslice buf[idx] = obj def assign_temporary_to_object(object[:] mslice): @@ -695,7 +739,7 @@ def assign_temporary_to_object(object[:] mslice): >>> assign_to_object(A, 1, a) >>> decref(a) """ - buf = mslice + cdef object buf = mslice buf[1] = {3-2: 2+(2*4)-2} @@ -743,7 +787,7 @@ def test_generic_slicing(arg, indirect=False): """ cdef int[::view.generic, ::view.generic, :] _a = arg - a = _a + cdef object a = _a b = a[2:8:2, -4:1:-1, 1:3] print b.shape @@ -826,7 +870,7 @@ def test_direct_slicing(arg): released A """ cdef int[:, :, :] _a = arg - a = _a + cdef object a = _a b = a[2:8:2, -4:1:-1, 1:3] print b.shape @@ -854,7 +898,7 @@ def test_slicing_and_indexing(arg): released A """ cdef int[:, :, :] _a = arg - a = _a + cdef object a = _a b = a[-5:, 1, 1::2] c = b[4:1:-1, ::-1] d = c[2, 1:2] @@ -1099,7 +1143,7 @@ def optimised_index_of_slice(int[:,:,:] arr, int x, int y, int z): def test_assign_from_byteslike(byteslike): - # Once http://python3statement.org is accepted, should be just + # Once https://python3statement.org/ is accepted, should be just # >>> test_assign_from_byteslike(bytes(b'hello')) # b'hello' # ... @@ -1130,3 +1174,84 @@ def test_assign_from_byteslike(byteslike): return (<unsigned char*>buf)[:5] finally: free(buf) + +def multiple_memoryview_def(double[:] a, double[:] b): + return a[0] + b[0] + +cpdef multiple_memoryview_cpdef(double[:] a, double[:] b): + return a[0] + b[0] + +cdef multiple_memoryview_cdef(double[:] a, double[:] b): + return a[0] + b[0] + +multiple_memoryview_cdef_wrapper = multiple_memoryview_cdef + +def test_conversion_failures(): + """ + What we're concerned with here is that we don't lose references if one + of several memoryview arguments fails to convert. + + >>> test_conversion_failures() + """ + imb = IntMockBuffer("", range(1), shape=(1,)) + dmb = DoubleMockBuffer("", range(1), shape=(1,)) + for first, second in [(imb, dmb), (dmb, imb)]: + for func in [multiple_memoryview_def, multiple_memoryview_cpdef, multiple_memoryview_cdef_wrapper]: + # note - using python call of "multiple_memoryview_cpdef" deliberately + imb_before = get_refcount(imb) + dmb_before = get_refcount(dmb) + try: + func(first, second) + except: + assert get_refcount(imb) == imb_before, "before %s after %s" % (imb_before, get_refcount(imb)) + assert get_refcount(dmb) == dmb_before, "before %s after %s" % (dmb_before, get_refcount(dmb)) + else: + assert False, "Conversion should fail!" + +def test_is_Sequence(double[:] a): + """ + >>> test_is_Sequence(DoubleMockBuffer(None, range(6), shape=(6,))) + 1 + 1 + True + """ + if sys.version_info < (3, 3): + from collections import Sequence + else: + from collections.abc import Sequence + + for i in range(a.shape[0]): + a[i] = i + print(a.count(1.0)) # test for presence of added collection method + print(a.index(1.0)) # test for presence of added collection method + + if sys.version_info >= (3, 10): + # test structural pattern match in Python + # (because Cython hasn't implemented it yet, and because the details + # of what Python considers a sequence are important) + globs = {'arr': a} + exec(""" +match arr: + case [*_]: + res = True + case _: + res = False +""", globs) + assert globs['res'] + + return isinstance(<object>a, Sequence) + + +ctypedef int aliasT +def test_assignment_typedef(): + """ + >>> test_assignment_typedef() + 1 + 2 + """ + cdef int[2] x + cdef aliasT[:] y + x[:] = [1, 2] + y = x + for v in y: + print(v) |