forked from root-project/root
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathstl_vector.py
More file actions
175 lines (138 loc) · 5.59 KB
/
stl_vector.py
File metadata and controls
175 lines (138 loc) · 5.59 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
import array
import random
import unittest
import ROOT
# Helper function to assert that the elements of an array object and a std::vector proxy are equal
def assertVec(vec, arr):
# cppyy automatically casts random integers to unicode characters,
# so do the same in python so the validation doesn't fail
if isinstance(arr, array.array) and arr.typecode in ("b", "B"):
arr = [chr(b) for b in arr]
tc = unittest.TestCase()
# first check lengths match
tc.assertEqual(len(vec), len(arr), f"Length mismatch: std::vector is {len(vec)}, array is {len(arr)}")
tc.assertSequenceEqual(vec, arr, msg="std::vector and array differ, iadd failed")
class STL_vector(unittest.TestCase):
"""
Tests for the pythonizations of std::vector.
"""
def test_vec_char_data(self):
"""
Test that calling std::vector<char>::data() returns a Python string
that contains the characters of the vector and no exception is raised.
Check also that the iteration over the vector runs normally (#9632).
"""
elems = ['a', 'b', 'c']
v = ROOT.std.vector['char'](elems)
self.assertEqual(v.data(), ''.join(elems))
for elem in v:
self.assertEqual(elem, elems.pop(0))
def test_vec_const_char_p(self):
"""
Test that creating a std::vector<const char*> does not raise any
exception (#11581).
"""
ROOT.std.vector['const char*']()
def test_stl_vector_boolean(self):
"""
Test that the boolean conversion of a std::vector works as expected.
https://github.com/root-project/root/issues/14573
"""
for entry_type in ['int', 'float', 'double']:
vector = ROOT.std.vector[entry_type]()
self.assertTrue(vector.empty())
self.assertFalse(bool(vector))
vector.push_back(1)
self.assertFalse(vector.empty())
self.assertTrue(bool(vector))
def test_stl_vector_iadd(self):
import array
import random
"""
Test that the __iadd__ pythonization of std::vector works as expected.
This call dispatches to std::insert
https://github.com/root-project/root/issues/18768
"""
# we go over all possible numeric PODs
# https://docs.python.org/3/library/array.html
entry_type = [
"char",
"unsigned char",
"short",
"unsigned short",
"int",
"unsigned int",
"long",
"unsigned long",
"long long",
"float",
"double",
]
array_type = ["b", "B", "h", "H", "i", "I", "l", "L", "q", "Q", "f", "d"]
typemap = zip(entry_type, array_type)
n = 5
for dtype in typemap:
vec = ROOT.std.vector[dtype[0]]()
self.assertTrue(vec.empty())
li = [random.randint(1, 100) for _ in range(n)]
arr = array.array(dtype[1], li)
vec += arr
self.assertFalse(vec.empty())
assertVec(vec, arr)
vec.pop_back()
arr = arr[:-1]
assertVec(vec, arr)
def test_stl_vector_iadd_2D(self):
"""
Test that the __iadd__ pythonization of std::vector works as expected in 2D
"""
initial = [
[1, 2, 3],
[4, 5, 6],
[7, 8, 9],
]
vec2d = ROOT.std.vector[ROOT.std.vector[int]](initial)
self.assertEqual(
len(vec2d), len(initial), f"Initial 2D vector row count wrong ({len(vec2d)} vs {len(initial)})"
)
# verify rows before iadd
for idx, (subvec, sublist) in enumerate(zip(vec2d, initial)):
with self.subTest(row=idx, phase="before"):
assertVec(subvec, sublist)
vec2d += initial
expected = initial + initial
self.assertEqual(
len(vec2d), len(expected), f"2D vector row count after iadd wrong ({len(vec2d)} vs {len(expected)})"
)
for idx, (subvec, sublist) in enumerate(zip(vec2d, expected)):
with self.subTest(row=idx, phase="after"):
assertVec(subvec, sublist)
def test_tree_with_containers(self):
"""
Test that the boolean conversion of a std::vector works as expected inside a TTree.
Also checks that the contents are correctly filled and read back.
https://github.com/root-project/root/issues/14573
"""
# Create a TTree
tree = ROOT.TTree("tree", "Tree with std::vector")
# list of random arrays with lengths between 0 and 5 (0 is always included)
entries_to_fill = [array.array("f", [random.uniform(10, 20) for _ in range(n % 5)]) for n in range(100)]
# Create variables to store std::vector elements
entry_root = ROOT.std.vector(float)()
# Create branches in the TTree
tree.Branch("vector", entry_root)
# Fill the TTree with 100 entries
for entry in entries_to_fill:
entry_root.clear()
for element in entry:
entry_root.push_back(element)
tree.Fill()
for i in range(tree.GetEntries()):
tree.GetEntry(i)
entry_array = entries_to_fill[i]
self.assertEqual(len(entry_array), len(entry_root))
self.assertEqual(bool(list(entry_root)), bool(entry_root)) # numpy arrays cannot be converted to bool
for entry_array_i, entry_root_i in zip(entry_array, entry_root):
self.assertEqual(entry_array_i, entry_root_i)
if __name__ == '__main__':
unittest.main()