test_stl_binders.py 7.88 KB
Newer Older
1
# -*- coding: utf-8 -*-
2
3
import pytest

4
import env
5
from pybind11_tests import stl_binders as m
6
7


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

13
14
15
16
    # 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])

17
    v_int2 = m.VectorInt([0, 0])
Dean Moldovan's avatar
Dean Moldovan committed
18
19
20
21
22
23
24
25
    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)
26
    v_int2.insert(6, 3)
Dean Moldovan's avatar
Dean Moldovan committed
27
    assert str(v_int2) == "VectorInt[3, 2, 1, 0, 1, 2, 3]"
28
29
    with pytest.raises(IndexError):
        v_int2.insert(8, 4)
Dean Moldovan's avatar
Dean Moldovan committed
30
31
32

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

39
40
41
42
43
44
45
46
    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):
47
        v_int2.extend([8, "a"])
48
49
50
51
52
53
54

    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])

55
56
57
58
59
60
61
62
63
64
    # 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
65

66
67
68
    v_int2.clear()
    assert len(v_int2) == 0

69

70
# Older PyPy's failed here, related to the PyPy's buffer protocol.
71
72
def test_vector_buffer():
    b = bytearray([1, 2, 3, 4])
73
    v = m.VectorUChar(b)
74
75
    assert v[1] == 2
    v[2] = 5
76
    mv = memoryview(v)  # We expose the buffer interface
77
    if not env.PY2:
78
79
        assert mv[2] == 5
        mv[2] = 6
80
    else:
81
82
        assert mv[2] == "\x05"
        mv[2] = "\x06"
83
84
    assert v[2] == 6

85
    if not env.PY2:
86
87
88
89
        mv = memoryview(b)
        v = m.VectorUChar(mv[::2])
        assert v[1] == 3

90
91
92
    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)
93
94
95


def test_vector_buffer_numpy():
96
    np = pytest.importorskip("numpy")
97
98
    a = np.array([1, 2, 3, 4], dtype=np.int32)
    with pytest.raises(TypeError):
99
        m.VectorInt(a)
100
101

    a = np.array([[1, 2, 3, 4], [5, 6, 7, 8], [9, 10, 11, 12]], dtype=np.uintc)
102
    v = m.VectorInt(a[0, :])
103
104
    assert len(v) == 4
    assert v[2] == 3
105
106
    ma = np.asarray(v)
    ma[2] = 5
107
108
    assert v[2] == 5

109
    v = m.VectorInt(a[:, 1])
110
111
112
    assert len(v) == 3
    assert v[2] == 10

113
    v = m.get_vectorstruct()
114
    assert v[0].x == 5
115
    ma = np.asarray(v)
116
    ma[1]["x"] = 99
117
118
    assert v[1].x == 99

119
120
121
122
123
124
125
126
    v = m.VectorStruct(
        np.zeros(
            3,
            dtype=np.dtype(
                [("w", "bool"), ("x", "I"), ("y", "float64"), ("z", "bool")], align=True
            ),
        )
    )
127
128
    assert len(v) == 3

129
130
131
132
    b = np.array([1, 2, 3, 4], dtype=np.uint8)
    v = m.VectorUChar(b[::2])
    assert v[1] == 3

133

Dean Moldovan's avatar
Dean Moldovan committed
134
def test_vector_bool():
135
136
137
    import pybind11_cross_module_tests as cm

    vv_c = cm.VectorBool()
Dean Moldovan's avatar
Dean Moldovan committed
138
139
140
141
142
    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
143

144

145
146
147
148
149
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
150

151
152
153
154
    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
155
156


157
158
def test_map_string_double():
    mm = m.MapStringDouble()
159
160
    mm["a"] = 1
    mm["b"] = 2.5
161

162
    assert list(mm) == ["a", "b"]
163
    assert str(mm) == "MapStringDouble{a: 1, b: 2.5}"
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
    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)]
191
192

    um = m.UnorderedMapStringDouble()
193
194
    um["ua"] = 1.1
    um["ub"] = 2.6
Sergey Lyskov's avatar
Sergey Lyskov committed
195

196
    assert sorted(list(um)) == ["ua", "ub"]
197
    assert list(um.keys()) == list(um)
198
    assert sorted(list(um.items())) == [("ua", 1.1), ("ub", 2.6)]
199
    assert list(zip(um.keys(), um.values())) == list(um.items())
200
    assert "UnorderedMapStringDouble" in str(um)
Sergey Lyskov's avatar
Sergey Lyskov committed
201
202
203


def test_map_string_double_const():
204
    mc = m.MapStringDoubleConst()
205
206
    mc["a"] = 10
    mc["b"] = 20.5
Sergey Lyskov's avatar
Sergey Lyskov committed
207
208
    assert str(mc) == "MapStringDoubleConst{a: 10, b: 20.5}"

209
    umc = m.UnorderedMapStringDoubleConst()
210
211
    umc["a"] = 11
    umc["b"] = 21.5
Sergey Lyskov's avatar
Sergey Lyskov committed
212
213

    str(umc)
214

215

216
217
218
def test_noncopyable_containers():
    # std::vector
    vnc = m.get_vnc(5)
219
    for i in range(0, 5):
220
221
222
223
        assert vnc[i].value == i + 1

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

225
226
    # std::deque
    dnc = m.get_dnc(5)
227
    for i in range(0, 5):
228
        assert dnc[i].value == i + 1
229
230
231

    i = 1
    for j in dnc:
232
        assert j.value == i
233
234
        i += 1

235
236
    # std::map
    mnc = m.get_mnc(5)
237
    for i in range(1, 6):
238
        assert mnc[i].value == 10 * i
239
240
241

    vsum = 0
    for k, v in mnc.items():
242
        assert v.value == 10 * k
243
244
        vsum += v.value

245
246
    assert vsum == 150

247
248
    # std::unordered_map
    mnc = m.get_umnc(5)
249
    for i in range(1, 6):
250
        assert mnc[i].value == 10 * i
251
252
253

    vsum = 0
    for k, v in mnc.items():
254
        assert v.value == 10 * k
255
256
        vsum += v.value

257
    assert vsum == 150
258

259
260
261
262
263
264
    # 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

265
266
    # Note: maps do not have .values()
    for _, v in nvnc.items():
267
268
269
270
271
272
273
274
275
276
        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
277
    for _, v_o in nmnc.items():
278
279
280
281
282
283
284
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

    # 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
291
    for _, v_o in numnc.items():
292
293
294
295
296
297
        for k_i, v_i in v_o.items():
            assert v_i.value == 10 * k_i
            vsum += v_i.value

    assert vsum == 7500

298
299
300

def test_map_delitem():
    mm = m.MapStringDouble()
301
302
    mm["a"] = 1
    mm["b"] = 2.5
303

304
305
306
307
308
    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)]
309
310

    um = m.UnorderedMapStringDouble()
311
312
313
314
315
316
317
318
    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)]