μHAL (v2.8.17)
Part of the IPbus software repository
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules Pages
test_buffers.py
Go to the documentation of this file.
1import ctypes
2import io
3import struct
4
5import pytest
6
7import env
8from pybind11_tests import ConstructorStats
9from pybind11_tests import buffers as m
10
11np = pytest.importorskip("numpy")
12
13
14def test_from_python():
15 with pytest.raises(RuntimeError) as excinfo:
16 m.Matrix(np.array([1, 2, 3])) # trying to assign a 1D array
17 assert str(excinfo.value) == "Incompatible buffer format!"
18
19 m3 = np.array([[1, 2, 3], [4, 5, 6]]).astype(np.float32)
20 m4 = m.Matrix(m3)
21
22 for i in range(m4.rows()):
23 for j in range(m4.cols()):
24 assert m3[i, j] == m4[i, j]
25
26 cstats = ConstructorStats.get(m.Matrix)
27 assert cstats.alive() == 1
28 del m3, m4
29 assert cstats.alive() == 0
30 assert cstats.values() == ["2x3 matrix"]
31 assert cstats.copy_constructions == 0
32 # assert cstats.move_constructions >= 0 # Don't invoke any
33 assert cstats.copy_assignments == 0
34 assert cstats.move_assignments == 0
35
36
37# https://foss.heptapod.net/pypy/pypy/-/issues/2444
38# TODO: fix on recent PyPy
39@pytest.mark.xfail(
40 env.PYPY, reason="PyPy 7.3.7 doesn't clear this anymore", strict=False
41)
42def test_to_python():
43 mat = m.Matrix(5, 4)
44 assert memoryview(mat).shape == (5, 4)
45
46 assert mat[2, 3] == 0
47 mat[2, 3] = 4.0
48 mat[3, 2] = 7.0
49 assert mat[2, 3] == 4
50 assert mat[3, 2] == 7
51 assert struct.unpack_from("f", mat, (3 * 4 + 2) * 4) == (7,)
52 assert struct.unpack_from("f", mat, (2 * 4 + 3) * 4) == (4,)
53
54 mat2 = np.array(mat, copy=False)
55 assert mat2.shape == (5, 4)
56 assert abs(mat2).sum() == 11
57 assert mat2[2, 3] == 4 and mat2[3, 2] == 7
58 mat2[2, 3] = 5
59 assert mat2[2, 3] == 5
60
61 cstats = ConstructorStats.get(m.Matrix)
62 assert cstats.alive() == 1
63 del mat
64 pytest.gc_collect()
65 assert cstats.alive() == 1
66 del mat2 # holds a mat reference
67 pytest.gc_collect()
68 assert cstats.alive() == 0
69 assert cstats.values() == ["5x4 matrix"]
70 assert cstats.copy_constructions == 0
71 # assert cstats.move_constructions >= 0 # Don't invoke any
72 assert cstats.copy_assignments == 0
73 assert cstats.move_assignments == 0
74
75
76def test_inherited_protocol():
77 """SquareMatrix is derived from Matrix and inherits the buffer protocol"""
78
79 matrix = m.SquareMatrix(5)
80 assert memoryview(matrix).shape == (5, 5)
81 assert np.asarray(matrix).shape == (5, 5)
82
83
84def test_pointer_to_member_fn():
85 for cls in [m.Buffer, m.ConstBuffer, m.DerivedBuffer]:
86 buf = cls()
87 buf.value = 0x12345678
88 value = struct.unpack("i", bytearray(buf))[0]
89 assert value == 0x12345678
90
91
92def test_readonly_buffer():
93 buf = m.BufferReadOnly(0x64)
94 view = memoryview(buf)
95 assert view[0] == 0x64
96 assert view.readonly
97 with pytest.raises(TypeError):
98 view[0] = 0
99
100
101def test_selective_readonly_buffer():
102 buf = m.BufferReadOnlySelect()
103
104 memoryview(buf)[0] = 0x64
105 assert buf.value == 0x64
106
107 io.BytesIO(b"A").readinto(buf)
108 assert buf.value == ord(b"A")
109
110 buf.readonly = True
111 with pytest.raises(TypeError):
112 memoryview(buf)[0] = 0
113 with pytest.raises(TypeError):
114 io.BytesIO(b"1").readinto(buf)
115
116
117def test_ctypes_array_1d():
118 char1d = (ctypes.c_char * 10)()
119 int1d = (ctypes.c_int * 15)()
120 long1d = (ctypes.c_long * 7)()
121
122 for carray in (char1d, int1d, long1d):
123 info = m.get_buffer_info(carray)
124 assert info.itemsize == ctypes.sizeof(carray._type_)
125 assert info.size == len(carray)
126 assert info.ndim == 1
127 assert info.shape == [info.size]
128 assert info.strides == [info.itemsize]
129 assert not info.readonly
130
131
132def test_ctypes_array_2d():
133 char2d = ((ctypes.c_char * 10) * 4)()
134 int2d = ((ctypes.c_int * 15) * 3)()
135 long2d = ((ctypes.c_long * 7) * 2)()
136
137 for carray in (char2d, int2d, long2d):
138 info = m.get_buffer_info(carray)
139 assert info.itemsize == ctypes.sizeof(carray[0]._type_)
140 assert info.size == len(carray) * len(carray[0])
141 assert info.ndim == 2
142 assert info.shape == [len(carray), len(carray[0])]
143 assert info.strides == [info.itemsize * len(carray[0]), info.itemsize]
144 assert not info.readonly
145
146
147def test_ctypes_from_buffer():
148 test_pystr = b"0123456789"
149 for pyarray in (test_pystr, bytearray(test_pystr)):
150 pyinfo = m.get_buffer_info(pyarray)
151
152 if pyinfo.readonly:
153 cbytes = (ctypes.c_char * len(pyarray)).from_buffer_copy(pyarray)
154 cinfo = m.get_buffer_info(cbytes)
155 else:
156 cbytes = (ctypes.c_char * len(pyarray)).from_buffer(pyarray)
157 cinfo = m.get_buffer_info(cbytes)
158
159 assert cinfo.size == pyinfo.size
160 assert cinfo.ndim == pyinfo.ndim
161 assert cinfo.shape == pyinfo.shape
162 assert cinfo.strides == pyinfo.strides
163 assert not cinfo.readonly
static ConstructorStats & get(std::type_index type)
Definition: pytypes.h:1200
size_t len(handle h)
Get the length of a Python object.
Definition: pytypes.h:2002
std::string abs(const Vector2 &)