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


gtsam
Author(s):
autogenerated on Thu Jul 4 2024 03:06:00