test_buffers.py
Go to the documentation of this file.
1 import ctypes
2 import io
3 import struct
4 
5 import pytest
6 
7 import env
8 from pybind11_tests import ConstructorStats
9 from pybind11_tests import buffers as m
10 
11 np = pytest.importorskip("numpy")
12 
13 if m.long_double_and_double_have_same_size:
14  # Determined by the compiler used to build the pybind11 tests
15  # (e.g. MSVC gets here, but MinGW might not).
16  np_float128 = None
17  np_complex256 = None
18 else:
19  # Determined by the compiler used to build numpy (e.g. MinGW).
20  np_float128 = getattr(np, *["float128"] * 2)
21  np_complex256 = getattr(np, *["complex256"] * 2)
22 
23 CPP_NAME_FORMAT_NP_DTYPE_TABLE = [
24  ("PyObject *", "O", object),
25  ("bool", "?", np.bool_),
26  ("std::int8_t", "b", np.int8),
27  ("std::uint8_t", "B", np.uint8),
28  ("std::int16_t", "h", np.int16),
29  ("std::uint16_t", "H", np.uint16),
30  ("std::int32_t", "i", np.int32),
31  ("std::uint32_t", "I", np.uint32),
32  ("std::int64_t", "q", np.int64),
33  ("std::uint64_t", "Q", np.uint64),
34  ("float", "f", np.float32),
35  ("double", "d", np.float64),
36  ("long double", "g", np_float128),
37  ("std::complex<float>", "Zf", np.complex64),
38  ("std::complex<double>", "Zd", np.complex128),
39  ("std::complex<long double>", "Zg", np_complex256),
40 ]
41 CPP_NAME_FORMAT_TABLE = [
42  (cpp_name, format)
43  for cpp_name, format, np_dtype in CPP_NAME_FORMAT_NP_DTYPE_TABLE
44  if np_dtype is not None
45 ]
46 CPP_NAME_NP_DTYPE_TABLE = [
47  (cpp_name, np_dtype) for cpp_name, _, np_dtype in CPP_NAME_FORMAT_NP_DTYPE_TABLE
48 ]
49 
50 
51 @pytest.mark.parametrize(("cpp_name", "np_dtype"), CPP_NAME_NP_DTYPE_TABLE)
53  if np_dtype is None:
54  pytest.skip(
55  f"cpp_name=`{cpp_name}`: `long double` and `double` have same size."
56  )
57  if isinstance(np_dtype, str):
58  pytest.skip(f"np.{np_dtype} does not exist.")
59  np_array = np.array([], dtype=np_dtype)
60  for other_cpp_name, expected_format in CPP_NAME_FORMAT_TABLE:
61  format, np_array_is_matching = m.format_descriptor_format_buffer_info_equiv(
62  other_cpp_name, np_array
63  )
64  assert format == expected_format
65  if other_cpp_name == cpp_name:
66  assert np_array_is_matching
67  else:
68  assert not np_array_is_matching
69 
70 
72  with pytest.raises(RuntimeError) as excinfo:
73  m.Matrix(np.array([1, 2, 3])) # trying to assign a 1D array
74  assert str(excinfo.value) == "Incompatible buffer format!"
75 
76  m3 = np.array([[1, 2, 3], [4, 5, 6]]).astype(np.float32)
77  m4 = m.Matrix(m3)
78 
79  for i in range(m4.rows()):
80  for j in range(m4.cols()):
81  assert m3[i, j] == m4[i, j]
82 
83  cstats = ConstructorStats.get(m.Matrix)
84  assert cstats.alive() == 1
85  del m3, m4
86  assert cstats.alive() == 0
87  assert cstats.values() == ["2x3 matrix"]
88  assert cstats.copy_constructions == 0
89  # assert cstats.move_constructions >= 0 # Don't invoke any
90  assert cstats.copy_assignments == 0
91  assert cstats.move_assignments == 0
92 
93 
94 # https://foss.heptapod.net/pypy/pypy/-/issues/2444
95 # TODO: fix on recent PyPy
96 @pytest.mark.xfail(
97  env.PYPY, reason="PyPy 7.3.7 doesn't clear this anymore", strict=False
98 )
100  mat = m.Matrix(5, 4)
101  assert memoryview(mat).shape == (5, 4)
102 
103  assert mat[2, 3] == 0
104  mat[2, 3] = 4.0
105  mat[3, 2] = 7.0
106  assert mat[2, 3] == 4
107  assert mat[3, 2] == 7
108  assert struct.unpack_from("f", mat, (3 * 4 + 2) * 4) == (7,)
109  assert struct.unpack_from("f", mat, (2 * 4 + 3) * 4) == (4,)
110 
111  mat2 = np.array(mat, copy=False)
112  assert mat2.shape == (5, 4)
113  assert abs(mat2).sum() == 11
114  assert mat2[2, 3] == 4
115  assert mat2[3, 2] == 7
116  mat2[2, 3] = 5
117  assert mat2[2, 3] == 5
118 
119  cstats = ConstructorStats.get(m.Matrix)
120  assert cstats.alive() == 1
121  del mat
122  pytest.gc_collect()
123  assert cstats.alive() == 1
124  del mat2 # holds a mat reference
125  pytest.gc_collect()
126  assert cstats.alive() == 0
127  assert cstats.values() == ["5x4 matrix"]
128  assert cstats.copy_constructions == 0
129  # assert cstats.move_constructions >= 0 # Don't invoke any
130  assert cstats.copy_assignments == 0
131  assert cstats.move_assignments == 0
132 
133 
135  """SquareMatrix is derived from Matrix and inherits the buffer protocol"""
136 
137  matrix = m.SquareMatrix(5)
138  assert memoryview(matrix).shape == (5, 5)
139  assert np.asarray(matrix).shape == (5, 5)
140 
141 
143  for cls in [m.Buffer, m.ConstBuffer, m.DerivedBuffer]:
144  buf = cls()
145  buf.value = 0x12345678
146  value = struct.unpack("i", bytearray(buf))[0]
147  assert value == 0x12345678
148 
149 
151  buf = m.BufferReadOnly(0x64)
152  view = memoryview(buf)
153  assert view[0] == 0x64
154  assert view.readonly
155  with pytest.raises(TypeError):
156  view[0] = 0
157 
158 
160  buf = m.BufferReadOnlySelect()
161 
162  memoryview(buf)[0] = 0x64
163  assert buf.value == 0x64
164 
165  io.BytesIO(b"A").readinto(buf)
166  assert buf.value == ord(b"A")
167 
168  buf.readonly = True
169  with pytest.raises(TypeError):
170  memoryview(buf)[0] = 0
171  with pytest.raises(TypeError):
172  io.BytesIO(b"1").readinto(buf)
173 
174 
176  char1d = (ctypes.c_char * 10)()
177  int1d = (ctypes.c_int * 15)()
178  long1d = (ctypes.c_long * 7)()
179 
180  for carray in (char1d, int1d, long1d):
181  info = m.get_buffer_info(carray)
182  assert info.itemsize == ctypes.sizeof(carray._type_)
183  assert info.size == len(carray)
184  assert info.ndim == 1
185  assert info.shape == [info.size]
186  assert info.strides == [info.itemsize]
187  assert not info.readonly
188 
189 
191  char2d = ((ctypes.c_char * 10) * 4)()
192  int2d = ((ctypes.c_int * 15) * 3)()
193  long2d = ((ctypes.c_long * 7) * 2)()
194 
195  for carray in (char2d, int2d, long2d):
196  info = m.get_buffer_info(carray)
197  assert info.itemsize == ctypes.sizeof(carray[0]._type_)
198  assert info.size == len(carray) * len(carray[0])
199  assert info.ndim == 2
200  assert info.shape == [len(carray), len(carray[0])]
201  assert info.strides == [info.itemsize * len(carray[0]), info.itemsize]
202  assert not info.readonly
203 
204 
206  test_pystr = b"0123456789"
207  for pyarray in (test_pystr, bytearray(test_pystr)):
208  pyinfo = m.get_buffer_info(pyarray)
209 
210  if pyinfo.readonly:
211  cbytes = (ctypes.c_char * len(pyarray)).from_buffer_copy(pyarray)
212  cinfo = m.get_buffer_info(cbytes)
213  else:
214  cbytes = (ctypes.c_char * len(pyarray)).from_buffer(pyarray)
215  cinfo = m.get_buffer_info(cbytes)
216 
217  assert cinfo.size == pyinfo.size
218  assert cinfo.ndim == pyinfo.ndim
219  assert cinfo.shape == pyinfo.shape
220  assert cinfo.strides == pyinfo.strides
221  assert not cinfo.readonly
getattr
object getattr(handle obj, handle name)
Definition: pytypes.h:873
test_buffers.test_ctypes_from_buffer
def test_ctypes_from_buffer()
Definition: test_buffers.py:205
test_buffers.test_pointer_to_member_fn
def test_pointer_to_member_fn()
Definition: test_buffers.py:142
gtsam::range
Double_ range(const Point2_ &p, const Point2_ &q)
Definition: slam/expressions.h:30
isinstance
bool isinstance(handle obj)
Definition: pytypes.h:825
test_buffers.test_ctypes_array_2d
def test_ctypes_array_2d()
Definition: test_buffers.py:190
bytearray
Definition: pytypes.h:1714
memoryview
Definition: pytypes.h:2241
str
Definition: pytypes.h:1524
test_buffers.test_readonly_buffer
def test_readonly_buffer()
Definition: test_buffers.py:150
test_buffers.test_inherited_protocol
def test_inherited_protocol()
Definition: test_buffers.py:134
test_buffers.test_to_python
def test_to_python()
Definition: test_buffers.py:99
test_buffers.test_ctypes_array_1d
def test_ctypes_array_1d()
Definition: test_buffers.py:175
ConstructorStats::get
static ConstructorStats & get(std::type_index type)
Definition: constructor_stats.h:163
test_buffers.test_format_descriptor_format_buffer_info_equiv
def test_format_descriptor_format_buffer_info_equiv(cpp_name, np_dtype)
Definition: test_buffers.py:52
abs
#define abs(x)
Definition: datatypes.h:17
len
size_t len(handle h)
Get the length of a Python object.
Definition: pytypes.h:2399
test_buffers.test_from_python
def test_from_python()
Definition: test_buffers.py:71
test_buffers.test_selective_readonly_buffer
def test_selective_readonly_buffer()
Definition: test_buffers.py:159


gtsam
Author(s):
autogenerated on Tue Jun 25 2024 03:05:28