Skip to content

Commit 725b8cb

Browse files
committed
[test] stl vector __iadd__ with array.array
1 parent faa5689 commit 725b8cb

File tree

1 file changed

+85
-0
lines changed

1 file changed

+85
-0
lines changed

bindings/pyroot/pythonizations/test/stl_vector.py

Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,19 @@
44

55
import ROOT
66

7+
# Helper function to assert that the elements of an array object and a std::vector proxy are equal
8+
def assertVec(vec, arr):
9+
# cppyy automatically casts random integers to unicode characters,
10+
# so do the same in python so the validation doesn't fail
11+
if isinstance(arr, array.array) and arr.typecode in ("b", "B"):
12+
arr = [chr(b) for b in arr]
13+
14+
tc = unittest.TestCase()
15+
# first check lengths match
16+
tc.assertEqual(len(vec), len(arr), f"Length mismatch: std::vector is {len(vec)}, array is {len(arr)}")
17+
18+
tc.assertSequenceEqual(vec, arr, msg="std::vector and array differ, iadd failed")
19+
720

821
class STL_vector(unittest.TestCase):
922
"""
@@ -45,6 +58,78 @@ def test_stl_vector_boolean(self):
4558
self.assertFalse(vector.empty())
4659
self.assertTrue(bool(vector))
4760

61+
def test_stl_vector_iadd(self):
62+
import array
63+
import random
64+
65+
"""
66+
Test that the __iadd__ pythonization of std::vector works as expected.
67+
This call dispatches to std::insert
68+
https://github.com/root-project/root/issues/18768
69+
"""
70+
71+
# we go over all possible numeric PODs
72+
# https://docs.python.org/3/library/array.html
73+
entry_type = [
74+
"char",
75+
"unsigned char",
76+
"short",
77+
"unsigned short",
78+
"int",
79+
"unsigned int",
80+
"long",
81+
"unsigned long",
82+
"long long",
83+
"float",
84+
"double",
85+
]
86+
array_type = ["b", "B", "h", "H", "i", "I", "l", "L", "q", "Q", "f", "d"]
87+
88+
typemap = zip(entry_type, array_type)
89+
n = 5
90+
for dtype in typemap:
91+
vec = ROOT.std.vector[dtype[0]]()
92+
self.assertTrue(vec.empty())
93+
li = [random.randint(1, 100) for _ in range(n)]
94+
arr = array.array(dtype[1], li)
95+
vec += arr
96+
self.assertFalse(vec.empty())
97+
assertVec(vec, arr)
98+
vec.pop_back()
99+
arr = arr[:-1]
100+
assertVec(vec, arr)
101+
102+
def test_stl_vector_iadd_2D(self):
103+
"""
104+
Test that the __iadd__ pythonization of std::vector works as expected in 2D
105+
"""
106+
initial = [
107+
[1, 2, 3],
108+
[4, 5, 6],
109+
[7, 8, 9],
110+
]
111+
112+
vec2d = ROOT.std.vector[ROOT.std.vector[int]](initial)
113+
self.assertEqual(
114+
len(vec2d), len(initial), f"Initial 2D vector row count wrong ({len(vec2d)} vs {len(initial)})"
115+
)
116+
117+
# verify rows before iadd
118+
for idx, (subvec, sublist) in enumerate(zip(vec2d, initial)):
119+
with self.subTest(row=idx, phase="before"):
120+
assertVec(subvec, sublist)
121+
122+
vec2d += initial
123+
expected = initial + initial
124+
125+
self.assertEqual(
126+
len(vec2d), len(expected), f"2D vector row count after iadd wrong ({len(vec2d)} vs {len(expected)})"
127+
)
128+
129+
for idx, (subvec, sublist) in enumerate(zip(vec2d, expected)):
130+
with self.subTest(row=idx, phase="after"):
131+
assertVec(subvec, sublist)
132+
48133
def test_tree_with_containers(self):
49134
"""
50135
Test that the boolean conversion of a std::vector works as expected inside a TTree.

0 commit comments

Comments
 (0)