diff --git a/qiskit/primitives/containers/bit_array.py b/qiskit/primitives/containers/bit_array.py index 29ff3240f3bf..b458b3d49232 100644 --- a/qiskit/primitives/containers/bit_array.py +++ b/qiskit/primitives/containers/bit_array.py @@ -130,10 +130,15 @@ def __repr__(self): return f"BitArray({desc})" def __getitem__(self, indices): - if isinstance(indices, tuple) and len(indices) >= self.ndim + 2: - raise ValueError( - "BitArrays cannot be sliced along the bits axis, see slice_bits() instead." - ) + if isinstance(indices, tuple): + if len(indices) == self.ndim + 1: + raise IndexError( + "BitArray cannot be sliced along the shots axis, use slice_shots() instead." + ) + if len(indices) >= self.ndim + 2: + raise IndexError( + "BitArray cannot be sliced along the bits axis, use slice_bits() instead." + ) return BitArray(self._array[indices], self.num_bits) @property @@ -430,13 +435,13 @@ def slice_bits(self, indices: int | Sequence[int]) -> "BitArray": A bit array sliced along the bit axis. Raises: - ValueError: If there are any invalid indices of the bit axis. + IndexError: If there are any invalid indices of the bit axis. """ if isinstance(indices, int): indices = (indices,) for index in indices: if index < 0 or index >= self.num_bits: - raise ValueError( + raise IndexError( f"index {index} is out of bounds for the number of bits {self.num_bits}." ) # This implementation introduces a temporary 8x memory overhead due to bit @@ -457,13 +462,13 @@ def slice_shots(self, indices: int | Sequence[int]) -> "BitArray": A bit array sliced along the shots axis. Raises: - ValueError: If there are any invalid indices of the shots axis. + IndexError: If there are any invalid indices of the shots axis. """ if isinstance(indices, int): indices = (indices,) for index in indices: if index < 0 or index >= self.num_shots: - raise ValueError( + raise IndexError( f"index {index} is out of bounds for the number of shots {self.num_shots}." ) arr = self._array diff --git a/releasenotes/notes/fix-bitarray-slice-bits-shots-c9cb7e5d907722f5.yaml b/releasenotes/notes/fix-bitarray-slice-bits-shots-c9cb7e5d907722f5.yaml new file mode 100644 index 000000000000..56fd81012428 --- /dev/null +++ b/releasenotes/notes/fix-bitarray-slice-bits-shots-c9cb7e5d907722f5.yaml @@ -0,0 +1,11 @@ +--- +upgrade_primitives: + - | + :meth:`.BitArray.slice_bits` and :meth:`.BitArray.slice_shots` + will now raise ``IndexError`` when indices are out of bounds. + They used to raise ``ValueError`` in the case. + - | + :meth:`.BitArray.__getitem__` will now raise ``IndexError`` + when indices are out of bounds or the number of dimensions + of indices does not match that of BitArray. + They used to raise ``ValueError`` in the case. diff --git a/test/python/primitives/containers/test_bit_array.py b/test/python/primitives/containers/test_bit_array.py index bd41d127689d..fb99ab0332e4 100644 --- a/test/python/primitives/containers/test_bit_array.py +++ b/test/python/primitives/containers/test_bit_array.py @@ -537,6 +537,20 @@ def test_getitem(self): for j in range(2): self.assertEqual(ba.get_counts((0, j, 2)), ba2.get_counts(j)) + with self.subTest("errors"): + with self.assertRaisesRegex(IndexError, "index 2 is out of bounds"): + _ = ba[0, 2, 2] + with self.assertRaisesRegex(IndexError, "index -3 is out of bounds"): + _ = ba[0, -3, 2] + with self.assertRaisesRegex( + IndexError, "BitArray cannot be sliced along the shots axis" + ): + _ = ba[0, 1, 2, 3] + with self.assertRaisesRegex( + IndexError, "BitArray cannot be sliced along the bits axis" + ): + _ = ba[0, 1, 2, 3, 4] + def test_slice_bits(self): """Test the slice_bits method.""" # this creates incrementing bitstrings from 0 to 59 @@ -581,9 +595,9 @@ def test_slice_bits(self): self.assertEqual(ba2.get_counts((i, j, k)), expect) with self.subTest("errors"): - with self.assertRaisesRegex(ValueError, "index -1 is out of bounds"): + with self.assertRaisesRegex(IndexError, "index -1 is out of bounds"): _ = ba.slice_bits(-1) - with self.assertRaisesRegex(ValueError, "index 9 is out of bounds"): + with self.assertRaisesRegex(IndexError, "index 9 is out of bounds"): _ = ba.slice_bits(9) def test_slice_shots(self): @@ -631,9 +645,9 @@ def test_slice_shots(self): self.assertEqual(ba2.get_bitstrings((i, j, k)), expected) with self.subTest("errors"): - with self.assertRaisesRegex(ValueError, "index -1 is out of bounds"): + with self.assertRaisesRegex(IndexError, "index -1 is out of bounds"): _ = ba.slice_shots(-1) - with self.assertRaisesRegex(ValueError, "index 10 is out of bounds"): + with self.assertRaisesRegex(IndexError, "index 10 is out of bounds"): _ = ba.slice_shots(10) def test_expectation_values(self):