blob: d6adaf1f5eee00f93e2b0ba7e3838c1107297080 [file] [log] [blame]
Henry Schreinerd8c7ee02020-07-20 13:35:21 -04001# -*- coding: utf-8 -*-
Sebastian Koslowskidc65d662019-11-24 08:33:05 +01002import io
Bruce Merryfe0cf8b2017-05-17 10:52:33 +02003import struct
Sebastian Koslowskidc65d662019-11-24 08:33:05 +01004
Dean Moldovana0c1ccf2016-08-12 13:50:00 +02005import pytest
Sebastian Koslowskidc65d662019-11-24 08:33:05 +01006
Henry Schreiner4d9024e2020-08-16 16:02:12 -04007import env # noqa: F401
8
Jason Rhinelander391c7542017-07-25 16:47:36 -04009from pybind11_tests import buffers as m
10from pybind11_tests import ConstructorStats
Dean Moldovana0c1ccf2016-08-12 13:50:00 +020011
Henry Schreiner4d9024e2020-08-16 16:02:12 -040012np = pytest.importorskip("numpy")
Dean Moldovana0c1ccf2016-08-12 13:50:00 +020013
14
Dean Moldovana0c1ccf2016-08-12 13:50:00 +020015def test_from_python():
16 with pytest.raises(RuntimeError) as excinfo:
Jason Rhinelander391c7542017-07-25 16:47:36 -040017 m.Matrix(np.array([1, 2, 3])) # trying to assign a 1D array
Dean Moldovana0c1ccf2016-08-12 13:50:00 +020018 assert str(excinfo.value) == "Incompatible buffer format!"
19
20 m3 = np.array([[1, 2, 3], [4, 5, 6]]).astype(np.float32)
Jason Rhinelander391c7542017-07-25 16:47:36 -040021 m4 = m.Matrix(m3)
Dean Moldovana0c1ccf2016-08-12 13:50:00 +020022
23 for i in range(m4.rows()):
24 for j in range(m4.cols()):
25 assert m3[i, j] == m4[i, j]
26
Jason Rhinelander391c7542017-07-25 16:47:36 -040027 cstats = ConstructorStats.get(m.Matrix)
Dean Moldovana0c1ccf2016-08-12 13:50:00 +020028 assert cstats.alive() == 1
29 del m3, m4
30 assert cstats.alive() == 0
31 assert cstats.values() == ["2x3 matrix"]
32 assert cstats.copy_constructions == 0
33 # assert cstats.move_constructions >= 0 # Don't invoke any
34 assert cstats.copy_assignments == 0
35 assert cstats.move_assignments == 0
Wenzel Jakob1d1f81b2016-12-16 15:00:46 +010036
37
Henry Schreiner4d9024e2020-08-16 16:02:12 -040038# https://foss.heptapod.net/pypy/pypy/-/issues/2444
Wenzel Jakob1d1f81b2016-12-16 15:00:46 +010039def test_to_python():
Ansgar Burchardta22dd2d2017-09-21 23:07:48 +020040 mat = m.Matrix(5, 4)
41 assert memoryview(mat).shape == (5, 4)
Wenzel Jakob1d1f81b2016-12-16 15:00:46 +010042
Jason Rhinelander391c7542017-07-25 16:47:36 -040043 assert mat[2, 3] == 0
Ansgar Burchardta22dd2d2017-09-21 23:07:48 +020044 mat[2, 3] = 4.0
45 mat[3, 2] = 7.0
Jason Rhinelander391c7542017-07-25 16:47:36 -040046 assert mat[2, 3] == 4
Ansgar Burchardta22dd2d2017-09-21 23:07:48 +020047 assert mat[3, 2] == 7
48 assert struct.unpack_from('f', mat, (3 * 4 + 2) * 4) == (7, )
49 assert struct.unpack_from('f', mat, (2 * 4 + 3) * 4) == (4, )
Wenzel Jakob1d1f81b2016-12-16 15:00:46 +010050
Jason Rhinelander391c7542017-07-25 16:47:36 -040051 mat2 = np.array(mat, copy=False)
Ansgar Burchardta22dd2d2017-09-21 23:07:48 +020052 assert mat2.shape == (5, 4)
53 assert abs(mat2).sum() == 11
54 assert mat2[2, 3] == 4 and mat2[3, 2] == 7
Jason Rhinelander391c7542017-07-25 16:47:36 -040055 mat2[2, 3] = 5
56 assert mat2[2, 3] == 5
Wenzel Jakob1d1f81b2016-12-16 15:00:46 +010057
Jason Rhinelander391c7542017-07-25 16:47:36 -040058 cstats = ConstructorStats.get(m.Matrix)
Wenzel Jakob1d1f81b2016-12-16 15:00:46 +010059 assert cstats.alive() == 1
Jason Rhinelander391c7542017-07-25 16:47:36 -040060 del mat
Wenzel Jakob1d1f81b2016-12-16 15:00:46 +010061 pytest.gc_collect()
62 assert cstats.alive() == 1
Jason Rhinelander391c7542017-07-25 16:47:36 -040063 del mat2 # holds a mat reference
Wenzel Jakob1d1f81b2016-12-16 15:00:46 +010064 pytest.gc_collect()
65 assert cstats.alive() == 0
Ansgar Burchardta22dd2d2017-09-21 23:07:48 +020066 assert cstats.values() == ["5x4 matrix"]
Wenzel Jakob1d1f81b2016-12-16 15:00:46 +010067 assert cstats.copy_constructions == 0
68 # assert cstats.move_constructions >= 0 # Don't invoke any
69 assert cstats.copy_assignments == 0
70 assert cstats.move_assignments == 0
Bruce Merryfe0cf8b2017-05-17 10:52:33 +020071
72
Dean Moldovan427e4af2017-05-28 16:35:02 +020073def test_inherited_protocol():
74 """SquareMatrix is derived from Matrix and inherits the buffer protocol"""
Dean Moldovan427e4af2017-05-28 16:35:02 +020075
Jason Rhinelander391c7542017-07-25 16:47:36 -040076 matrix = m.SquareMatrix(5)
Dean Moldovan427e4af2017-05-28 16:35:02 +020077 assert memoryview(matrix).shape == (5, 5)
78 assert np.asarray(matrix).shape == (5, 5)
79
80
Jason Rhinelander391c7542017-07-25 16:47:36 -040081def test_pointer_to_member_fn():
82 for cls in [m.Buffer, m.ConstBuffer, m.DerivedBuffer]:
Bruce Merryfe0cf8b2017-05-17 10:52:33 +020083 buf = cls()
84 buf.value = 0x12345678
85 value = struct.unpack('i', bytearray(buf))[0]
86 assert value == 0x12345678
Sebastian Koslowskidc65d662019-11-24 08:33:05 +010087
88
Sebastian Koslowskidc65d662019-11-24 08:33:05 +010089def test_readonly_buffer():
90 buf = m.BufferReadOnly(0x64)
91 view = memoryview(buf)
Henry Schreiner4d9024e2020-08-16 16:02:12 -040092 assert view[0] == b'd' if env.PY2 else 0x64
Sebastian Koslowskidc65d662019-11-24 08:33:05 +010093 assert view.readonly
94
95
Sebastian Koslowskidc65d662019-11-24 08:33:05 +010096def test_selective_readonly_buffer():
97 buf = m.BufferReadOnlySelect()
98
Henry Schreiner4d9024e2020-08-16 16:02:12 -040099 memoryview(buf)[0] = b'd' if env.PY2 else 0x64
Sebastian Koslowskidc65d662019-11-24 08:33:05 +0100100 assert buf.value == 0x64
101
102 io.BytesIO(b'A').readinto(buf)
103 assert buf.value == ord(b'A')
104
105 buf.readonly = True
106 with pytest.raises(TypeError):
Henry Schreiner4d9024e2020-08-16 16:02:12 -0400107 memoryview(buf)[0] = b'\0' if env.PY2 else 0
Sebastian Koslowskidc65d662019-11-24 08:33:05 +0100108 with pytest.raises(TypeError):
109 io.BytesIO(b'1').readinto(buf)