test_stl_binders.py 8.96 KB
Newer Older
1
2
import pytest

3
from pybind11_tests import stl_binders as m
4
5


Dean Moldovan's avatar
Dean Moldovan committed
6
def test_vector_int():
7
    v_int = m.VectorInt([0, 0])
Dean Moldovan's avatar
Dean Moldovan committed
8
9
10
    assert len(v_int) == 2
    assert bool(v_int) is True

11
12
13
14
    # test construction from a generator
    v_int1 = m.VectorInt(x for x in range(5))
    assert v_int1 == m.VectorInt([0, 1, 2, 3, 4])

15
    v_int2 = m.VectorInt([0, 0])
Dean Moldovan's avatar
Dean Moldovan committed
16
17
18
19
20
21
22
23
    assert v_int == v_int2
    v_int2[1] = 1
    assert v_int != v_int2

    v_int2.append(2)
    v_int2.insert(0, 1)
    v_int2.insert(0, 2)
    v_int2.insert(0, 3)
24
    v_int2.insert(6, 3)
Dean Moldovan's avatar
Dean Moldovan committed
25
    assert str(v_int2) == "VectorInt[3, 2, 1, 0, 1, 2, 3]"
26
27
    with pytest.raises(IndexError):
        v_int2.insert(8, 4)
Dean Moldovan's avatar
Dean Moldovan committed
28
29
30

    v_int.append(99)
    v_int2[2:-2] = v_int
31
    assert v_int2 == m.VectorInt([3, 2, 0, 0, 99, 2, 3])
Dean Moldovan's avatar
Dean Moldovan committed
32
    del v_int2[1:3]
33
    assert v_int2 == m.VectorInt([3, 0, 99, 2, 3])
Dean Moldovan's avatar
Dean Moldovan committed
34
    del v_int2[0]
35
    assert v_int2 == m.VectorInt([0, 99, 2, 3])
Dean Moldovan's avatar
Dean Moldovan committed
36

37
38
39
40
41
42
43
44
    v_int2.extend(m.VectorInt([4, 5]))
    assert v_int2 == m.VectorInt([0, 99, 2, 3, 4, 5])

    v_int2.extend([6, 7])
    assert v_int2 == m.VectorInt([0, 99, 2, 3, 4, 5, 6, 7])

    # test error handling, and that the vector is unchanged
    with pytest.raises(RuntimeError):
45
        v_int2.extend([8, "a"])
46
47
48
49
50
51
52

    assert v_int2 == m.VectorInt([0, 99, 2, 3, 4, 5, 6, 7])

    # test extending from a generator
    v_int2.extend(x for x in range(5))
    assert v_int2 == m.VectorInt([0, 99, 2, 3, 4, 5, 6, 7, 0, 1, 2, 3, 4])

53
54
55
56
57
58
59
60
61
62
    # test negative indexing
    assert v_int2[-1] == 4

    # insert with negative index
    v_int2.insert(-1, 88)
    assert v_int2 == m.VectorInt([0, 99, 2, 3, 4, 5, 6, 7, 0, 1, 2, 3, 88, 4])

    # delete negative index
    del v_int2[-1]
    assert v_int2 == m.VectorInt([0, 99, 2, 3, 4, 5, 6, 7, 0, 1, 2, 3, 88])
Dean Moldovan's avatar
Dean Moldovan committed
63

64
65
66
    v_int2.clear()
    assert len(v_int2) == 0

67

68
# Older PyPy's failed here, related to the PyPy's buffer protocol.
69
70
def test_vector_buffer():
    b = bytearray([1, 2, 3, 4])
71
    v = m.VectorUChar(b)
72
73
    assert v[1] == 2
    v[2] = 5
74
    mv = memoryview(v)  # We expose the buffer interface
75
76
    assert mv[2] == 5
    mv[2] = 6
77
78
    assert v[2] == 6

79
80
81
    mv = memoryview(b)
    v = m.VectorUChar(mv[::2])
    assert v[1] == 3
82

83
84
85
    with pytest.raises(RuntimeError) as excinfo:
        m.create_undeclstruct()  # Undeclared struct contents, no buffer interface
    assert "NumPy type info missing for " in str(excinfo.value)
86
87
88


def test_vector_buffer_numpy():
89
    np = pytest.importorskip("numpy")
90
91
    a = np.array([1, 2, 3, 4], dtype=np.int32)
    with pytest.raises(TypeError):
92
        m.VectorInt(a)
93
94

    a = np.array([[1, 2, 3, 4], [5, 6, 7, 8], [9, 10, 11, 12]], dtype=np.uintc)
95
    v = m.VectorInt(a[0, :])
96
97
    assert len(v) == 4
    assert v[2] == 3
98
99
    ma = np.asarray(v)
    ma[2] = 5
100
101
    assert v[2] == 5

102
    v = m.VectorInt(a[:, 1])
103
104
105
    assert len(v) == 3
    assert v[2] == 10

106
    v = m.get_vectorstruct()
107
    assert v[0].x == 5
108
    ma = np.asarray(v)
109
    ma[1]["x"] = 99
110
111
    assert v[1].x == 99

112
113
114
115
116
117
118
119
    v = m.VectorStruct(
        np.zeros(
            3,
            dtype=np.dtype(
                [("w", "bool"), ("x", "I"), ("y", "float64"), ("z", "bool")], align=True
            ),
        )
    )
120
121
    assert len(v) == 3

122
123
124
125
    b = np.array([1, 2, 3, 4], dtype=np.uint8)
    v = m.VectorUChar(b[::2])
    assert v[1] == 3

126

Dean Moldovan's avatar
Dean Moldovan committed
127
def test_vector_bool():
128
129
130
    import pybind11_cross_module_tests as cm

    vv_c = cm.VectorBool()
Dean Moldovan's avatar
Dean Moldovan committed
131
132
133
134
135
    for i in range(10):
        vv_c.append(i % 2 == 0)
    for i in range(10):
        assert vv_c[i] == (i % 2 == 0)
    assert str(vv_c) == "VectorBool[1, 0, 1, 0, 1, 0, 1, 0, 1, 0]"
Sergey Lyskov's avatar
Sergey Lyskov committed
136

137

138
139
140
141
142
def test_vector_custom():
    v_a = m.VectorEl()
    v_a.append(m.El(1))
    v_a.append(m.El(2))
    assert str(v_a) == "VectorEl[El{1}, El{2}]"
Sergey Lyskov's avatar
Sergey Lyskov committed
143

144
145
146
147
    vv_a = m.VectorVectorEl()
    vv_a.append(v_a)
    vv_b = vv_a[0]
    assert str(vv_b) == "VectorEl[El{1}, El{2}]"
Sergey Lyskov's avatar
Sergey Lyskov committed
148
149


150
151
def test_map_string_double():
    mm = m.MapStringDouble()
152
153
    mm["a"] = 1
    mm["b"] = 2.5
154

155
    assert list(mm) == ["a", "b"]
156
    assert str(mm) == "MapStringDouble{a: 1, b: 2.5}"
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
    assert "b" in mm
    assert "c" not in mm
    assert 123 not in mm

    # Check that keys, values, items are views, not merely iterable
    keys = mm.keys()
    values = mm.values()
    items = mm.items()
    assert list(keys) == ["a", "b"]
    assert len(keys) == 2
    assert "a" in keys
    assert "c" not in keys
    assert 123 not in keys
    assert list(items) == [("a", 1), ("b", 2.5)]
    assert len(items) == 2
    assert ("b", 2.5) in items
    assert "hello" not in items
    assert ("b", 2.5, None) not in items
    assert list(values) == [1, 2.5]
    assert len(values) == 2
    assert 1 in values
    assert 2 not in values
    # Check that views update when the map is updated
    mm["c"] = -1
    assert list(keys) == ["a", "b", "c"]
    assert list(values) == [1, 2.5, -1]
    assert list(items) == [("a", 1), ("b", 2.5), ("c", -1)]
184
185

    um = m.UnorderedMapStringDouble()
186
187
    um["ua"] = 1.1
    um["ub"] = 2.6
Sergey Lyskov's avatar
Sergey Lyskov committed
188

189
    assert sorted(list(um)) == ["ua", "ub"]
190
    assert list(um.keys()) == list(um)
191
    assert sorted(list(um.items())) == [("ua", 1.1), ("ub", 2.6)]
192
    assert list(zip(um.keys(), um.values())) == list(um.items())
193
    assert "UnorderedMapStringDouble" in str(um)
Sergey Lyskov's avatar
Sergey Lyskov committed
194
195
196


def test_map_string_double_const():
197
    mc = m.MapStringDoubleConst()
198
199
    mc["a"] = 10
    mc["b"] = 20.5
Sergey Lyskov's avatar
Sergey Lyskov committed
200
201
    assert str(mc) == "MapStringDoubleConst{a: 10, b: 20.5}"

202
    umc = m.UnorderedMapStringDoubleConst()
203
204
    umc["a"] = 11
    umc["b"] = 21.5
Sergey Lyskov's avatar
Sergey Lyskov committed
205
206

    str(umc)
207

208

209
210
211
def test_noncopyable_containers():
    # std::vector
    vnc = m.get_vnc(5)
212
    for i in range(0, 5):
213
214
215
216
        assert vnc[i].value == i + 1

    for i, j in enumerate(vnc, start=1):
        assert j.value == i
217

218
219
    # std::deque
    dnc = m.get_dnc(5)
220
    for i in range(0, 5):
221
        assert dnc[i].value == i + 1
222
223
224

    i = 1
    for j in dnc:
225
        assert j.value == i
226
227
        i += 1

228
229
    # std::map
    mnc = m.get_mnc(5)
230
    for i in range(1, 6):
231
        assert mnc[i].value == 10 * i
232
233
234

    vsum = 0
    for k, v in mnc.items():
235
        assert v.value == 10 * k
236
237
        vsum += v.value

238
239
    assert vsum == 150

240
241
    # std::unordered_map
    mnc = m.get_umnc(5)
242
    for i in range(1, 6):
243
        assert mnc[i].value == 10 * i
244
245
246

    vsum = 0
    for k, v in mnc.items():
247
        assert v.value == 10 * k
248
249
        vsum += v.value

250
    assert vsum == 150
251

252
253
254
255
256
257
    # nested std::map<std::vector>
    nvnc = m.get_nvnc(5)
    for i in range(1, 6):
        for j in range(0, 5):
            assert nvnc[i][j].value == j + 1

258
259
    # Note: maps do not have .values()
    for _, v in nvnc.items():
260
261
262
263
264
265
266
267
268
269
        for i, j in enumerate(v, start=1):
            assert j.value == i

    # nested std::map<std::map>
    nmnc = m.get_nmnc(5)
    for i in range(1, 6):
        for j in range(10, 60, 10):
            assert nmnc[i][j].value == 10 * j

    vsum = 0
270
    for _, v_o in nmnc.items():
271
272
273
274
275
276
277
278
279
280
281
282
283
        for k_i, v_i in v_o.items():
            assert v_i.value == 10 * k_i
            vsum += v_i.value

    assert vsum == 7500

    # nested std::unordered_map<std::unordered_map>
    numnc = m.get_numnc(5)
    for i in range(1, 6):
        for j in range(10, 60, 10):
            assert numnc[i][j].value == 10 * j

    vsum = 0
284
    for _, v_o in numnc.items():
285
286
287
288
289
290
        for k_i, v_i in v_o.items():
            assert v_i.value == 10 * k_i
            vsum += v_i.value

    assert vsum == 7500

291
292
293

def test_map_delitem():
    mm = m.MapStringDouble()
294
295
    mm["a"] = 1
    mm["b"] = 2.5
296

297
298
299
300
301
    assert list(mm) == ["a", "b"]
    assert list(mm.items()) == [("a", 1), ("b", 2.5)]
    del mm["a"]
    assert list(mm) == ["b"]
    assert list(mm.items()) == [("b", 2.5)]
302
303

    um = m.UnorderedMapStringDouble()
304
305
306
307
308
309
310
311
    um["ua"] = 1.1
    um["ub"] = 2.6

    assert sorted(list(um)) == ["ua", "ub"]
    assert sorted(list(um.items())) == [("ua", 1.1), ("ub", 2.6)]
    del um["ua"]
    assert sorted(list(um)) == ["ub"]
    assert sorted(list(um.items())) == [("ub", 2.6)]
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337


def test_map_view_types():
    map_string_double = m.MapStringDouble()
    unordered_map_string_double = m.UnorderedMapStringDouble()
    map_string_double_const = m.MapStringDoubleConst()
    unordered_map_string_double_const = m.UnorderedMapStringDoubleConst()

    assert map_string_double.keys().__class__.__name__ == "KeysView[str]"
    assert map_string_double.values().__class__.__name__ == "ValuesView[float]"
    assert map_string_double.items().__class__.__name__ == "ItemsView[str, float]"

    keys_type = type(map_string_double.keys())
    assert type(unordered_map_string_double.keys()) is keys_type
    assert type(map_string_double_const.keys()) is keys_type
    assert type(unordered_map_string_double_const.keys()) is keys_type

    values_type = type(map_string_double.values())
    assert type(unordered_map_string_double.values()) is values_type
    assert type(map_string_double_const.values()) is values_type
    assert type(unordered_map_string_double_const.values()) is values_type

    items_type = type(map_string_double.items())
    assert type(unordered_map_string_double.items()) is items_type
    assert type(map_string_double_const.items()) is items_type
    assert type(unordered_map_string_double_const.items()) is items_type