Ensuring instruction labels are strings when provided to the Instruction constructor. (#7671)

* Fixes #7667 by ensuring that instruction labels are strings when provided to the Instruction constructor.

* Optimizing speed of instruction label type checking.

* Switching to an equality rather than reference check for instruction labels.

* Adding a release note for label type checking on creation.

* Use Sphinx cross-ref in release note

* Fix release note

* Add ctrl_state to non-parameter kwargs

Co-authored-by: Jake Lishman <jake.lishman@ibm.com>
This commit is contained in:
upsideon 2022-04-18 16:59:18 -06:00 committed by GitHub
parent ff4ee1bb72
commit ef997f9ba2
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 22 additions and 2 deletions

View File

@ -69,6 +69,7 @@ class Instruction:
Raises:
CircuitError: when the register is not in the correct format.
TypeError: when the optional label is provided, but it is not a string.
"""
if not isinstance(num_qubits, int) or not isinstance(num_clbits, int):
raise CircuitError("num_qubits and num_clbits must be integer.")
@ -86,6 +87,8 @@ class Instruction:
# already set is a temporary work around that can be removed after
# the next stable qiskit-aer release
if not hasattr(self, "_label"):
if label is not None and not isinstance(label, str):
raise TypeError("label expects a string or None")
self._label = label
# tuple (ClassicalRegister, int), tuple (Clbit, bool) or tuple (Clbit, int)
# when the instruction has a conditional ("if")

View File

@ -0,0 +1,4 @@
---
upgrade:
- |
:class:`~.circuit.Instruction` labels are now type-checked on instruction creation.

View File

@ -1455,7 +1455,7 @@ class TestStandardMethods(QiskitTestCase):
# gate_class is abstract
continue
sig = signature(gate_class)
free_params = len(set(sig.parameters) - {"label"})
free_params = len(set(sig.parameters) - {"label", "ctrl_state"})
try:
if gate_class == PauliGate:
# special case due to PauliGate using string parameters
@ -1508,7 +1508,7 @@ class TestStandardMethods(QiskitTestCase):
# n_qubits argument is no longer supported.
free_params = 2
else:
free_params = len(set(sig.parameters) - {"label"})
free_params = len(set(sig.parameters) - {"label", "ctrl_state"})
try:
if gate_class == PauliGate:
# special case due to PauliGate using string parameters

View File

@ -692,6 +692,19 @@ class TestInstructions(QiskitTestCase):
for instruction in instruction_list:
self.assertIs(instruction.condition[0], sentinel_register)
def test_label_type_enforcement(self):
"""Test instruction label type enforcement."""
with self.subTest("accepts string labels"):
instruction = Instruction("h", 1, 0, [], label="label")
self.assertEqual(instruction.label, "label")
with self.subTest("raises when a non-string label is provided to constructor"):
with self.assertRaisesRegex(TypeError, r"label expects a string or None"):
Instruction("h", 1, 0, [], label=0)
with self.subTest("raises when a non-string label is provided to setter"):
with self.assertRaisesRegex(TypeError, r"label expects a string or None"):
instruction = HGate()
instruction.label = 0
if __name__ == "__main__":
unittest.main()