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