Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-12-16 10:37:01

0001 import ctypes
0002 import io
0003 import struct
0004 
0005 import pytest
0006 
0007 import env
0008 from pybind11_tests import ConstructorStats
0009 from pybind11_tests import buffers as m
0010 
0011 np = pytest.importorskip("numpy")
0012 
0013 
0014 def test_from_python():
0015     with pytest.raises(RuntimeError) as excinfo:
0016         m.Matrix(np.array([1, 2, 3]))  # trying to assign a 1D array
0017     assert str(excinfo.value) == "Incompatible buffer format!"
0018 
0019     m3 = np.array([[1, 2, 3], [4, 5, 6]]).astype(np.float32)
0020     m4 = m.Matrix(m3)
0021 
0022     for i in range(m4.rows()):
0023         for j in range(m4.cols()):
0024             assert m3[i, j] == m4[i, j]
0025 
0026     cstats = ConstructorStats.get(m.Matrix)
0027     assert cstats.alive() == 1
0028     del m3, m4
0029     assert cstats.alive() == 0
0030     assert cstats.values() == ["2x3 matrix"]
0031     assert cstats.copy_constructions == 0
0032     # assert cstats.move_constructions >= 0  # Don't invoke any
0033     assert cstats.copy_assignments == 0
0034     assert cstats.move_assignments == 0
0035 
0036 
0037 # https://foss.heptapod.net/pypy/pypy/-/issues/2444
0038 # TODO: fix on recent PyPy
0039 @pytest.mark.xfail(
0040     env.PYPY, reason="PyPy 7.3.7 doesn't clear this anymore", strict=False
0041 )
0042 def test_to_python():
0043     mat = m.Matrix(5, 4)
0044     assert memoryview(mat).shape == (5, 4)
0045 
0046     assert mat[2, 3] == 0
0047     mat[2, 3] = 4.0
0048     mat[3, 2] = 7.0
0049     assert mat[2, 3] == 4
0050     assert mat[3, 2] == 7
0051     assert struct.unpack_from("f", mat, (3 * 4 + 2) * 4) == (7,)
0052     assert struct.unpack_from("f", mat, (2 * 4 + 3) * 4) == (4,)
0053 
0054     mat2 = np.array(mat, copy=False)
0055     assert mat2.shape == (5, 4)
0056     assert abs(mat2).sum() == 11
0057     assert mat2[2, 3] == 4 and mat2[3, 2] == 7
0058     mat2[2, 3] = 5
0059     assert mat2[2, 3] == 5
0060 
0061     cstats = ConstructorStats.get(m.Matrix)
0062     assert cstats.alive() == 1
0063     del mat
0064     pytest.gc_collect()
0065     assert cstats.alive() == 1
0066     del mat2  # holds a mat reference
0067     pytest.gc_collect()
0068     assert cstats.alive() == 0
0069     assert cstats.values() == ["5x4 matrix"]
0070     assert cstats.copy_constructions == 0
0071     # assert cstats.move_constructions >= 0  # Don't invoke any
0072     assert cstats.copy_assignments == 0
0073     assert cstats.move_assignments == 0
0074 
0075 
0076 def test_inherited_protocol():
0077     """SquareMatrix is derived from Matrix and inherits the buffer protocol"""
0078 
0079     matrix = m.SquareMatrix(5)
0080     assert memoryview(matrix).shape == (5, 5)
0081     assert np.asarray(matrix).shape == (5, 5)
0082 
0083 
0084 def test_pointer_to_member_fn():
0085     for cls in [m.Buffer, m.ConstBuffer, m.DerivedBuffer]:
0086         buf = cls()
0087         buf.value = 0x12345678
0088         value = struct.unpack("i", bytearray(buf))[0]
0089         assert value == 0x12345678
0090 
0091 
0092 def test_readonly_buffer():
0093     buf = m.BufferReadOnly(0x64)
0094     view = memoryview(buf)
0095     assert view[0] == 0x64
0096     assert view.readonly
0097     with pytest.raises(TypeError):
0098         view[0] = 0
0099 
0100 
0101 def test_selective_readonly_buffer():
0102     buf = m.BufferReadOnlySelect()
0103 
0104     memoryview(buf)[0] = 0x64
0105     assert buf.value == 0x64
0106 
0107     io.BytesIO(b"A").readinto(buf)
0108     assert buf.value == ord(b"A")
0109 
0110     buf.readonly = True
0111     with pytest.raises(TypeError):
0112         memoryview(buf)[0] = 0
0113     with pytest.raises(TypeError):
0114         io.BytesIO(b"1").readinto(buf)
0115 
0116 
0117 def test_ctypes_array_1d():
0118     char1d = (ctypes.c_char * 10)()
0119     int1d = (ctypes.c_int * 15)()
0120     long1d = (ctypes.c_long * 7)()
0121 
0122     for carray in (char1d, int1d, long1d):
0123         info = m.get_buffer_info(carray)
0124         assert info.itemsize == ctypes.sizeof(carray._type_)
0125         assert info.size == len(carray)
0126         assert info.ndim == 1
0127         assert info.shape == [info.size]
0128         assert info.strides == [info.itemsize]
0129         assert not info.readonly
0130 
0131 
0132 def test_ctypes_array_2d():
0133     char2d = ((ctypes.c_char * 10) * 4)()
0134     int2d = ((ctypes.c_int * 15) * 3)()
0135     long2d = ((ctypes.c_long * 7) * 2)()
0136 
0137     for carray in (char2d, int2d, long2d):
0138         info = m.get_buffer_info(carray)
0139         assert info.itemsize == ctypes.sizeof(carray[0]._type_)
0140         assert info.size == len(carray) * len(carray[0])
0141         assert info.ndim == 2
0142         assert info.shape == [len(carray), len(carray[0])]
0143         assert info.strides == [info.itemsize * len(carray[0]), info.itemsize]
0144         assert not info.readonly
0145 
0146 
0147 def test_ctypes_from_buffer():
0148     test_pystr = b"0123456789"
0149     for pyarray in (test_pystr, bytearray(test_pystr)):
0150         pyinfo = m.get_buffer_info(pyarray)
0151 
0152         if pyinfo.readonly:
0153             cbytes = (ctypes.c_char * len(pyarray)).from_buffer_copy(pyarray)
0154             cinfo = m.get_buffer_info(cbytes)
0155         else:
0156             cbytes = (ctypes.c_char * len(pyarray)).from_buffer(pyarray)
0157             cinfo = m.get_buffer_info(cbytes)
0158 
0159         assert cinfo.size == pyinfo.size
0160         assert cinfo.ndim == pyinfo.ndim
0161         assert cinfo.shape == pyinfo.shape
0162         assert cinfo.strides == pyinfo.strides
0163         assert not cinfo.readonly