Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

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

Merged
merged 12 commits into from
Apr 18, 2022
Merged
3 changes: 3 additions & 0 deletions qiskit/circuit/instruction.py
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,7 @@ def __init__(self, name, num_qubits, num_clbits, params, duration=None, unit="dt

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.")
Expand All @@ -86,6 +87,8 @@ def __init__(self, name, num_qubits, num_clbits, params, duration=None, unit="dt
# 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")
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
---
upgrade:
- |
:class:`~.circuit.Instruction` labels are now type-checked on instruction creation.
4 changes: 2 additions & 2 deletions test/python/circuit/test_extensions_standard.py
Original file line number Diff line number Diff line change
Expand Up @@ -1455,7 +1455,7 @@ def test_to_matrix(self):
# 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
Expand Down Expand Up @@ -1508,7 +1508,7 @@ def test_to_matrix_op(self):
# 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
Expand Down
13 changes: 13 additions & 0 deletions test/python/circuit/test_instructions.py
Original file line number Diff line number Diff line change
Expand Up @@ -692,6 +692,19 @@ def dummy_requester(specifier):
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()