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