diff --git a/qiskit/circuit/quantumcircuit.py b/qiskit/circuit/quantumcircuit.py index f35864d2d60d..5c9f1e263657 100644 --- a/qiskit/circuit/quantumcircuit.py +++ b/qiskit/circuit/quantumcircuit.py @@ -22,6 +22,7 @@ import multiprocessing as mp import string import re +import warnings import typing from collections import OrderedDict, defaultdict, namedtuple from typing import ( @@ -300,9 +301,7 @@ def __init__( self.duration = None self.unit = "dt" - if not isinstance(metadata, dict) and metadata is not None: - raise TypeError("Only a dictionary or None is accepted for circuit metadata") - self._metadata = metadata + self.metadata = {} if metadata is None else metadata @staticmethod def from_instructions( @@ -469,7 +468,7 @@ def has_calibration_for(self, instr_context: tuple): @property def metadata(self) -> dict: - """The user provided metadata associated with the circuit + """The user provided metadata associated with the circuit. The metadata for the circuit is a user provided ``dict`` of metadata for the circuit. It will not be used to influence the execution or @@ -483,8 +482,16 @@ def metadata(self) -> dict: @metadata.setter def metadata(self, metadata: dict | None): """Update the circuit metadata""" - if not isinstance(metadata, dict) and metadata is not None: - raise TypeError("Only a dictionary or None is accepted for circuit metadata") + if metadata is None: + metadata = {} + warnings.warn( + "Setting metadata to None was deprecated in Terra 0.24.0 and this ability will be " + "removed in a future release. Instead, set metadata to an empty dictionary.", + DeprecationWarning, + stacklevel=2, + ) + elif not isinstance(metadata, dict): + raise TypeError("Only a dictionary is accepted for circuit metadata") self._metadata = metadata def __str__(self) -> str: diff --git a/qiskit/dagcircuit/dagcircuit.py b/qiskit/dagcircuit/dagcircuit.py index ed3dfc1fd618..9b25dc655e4a 100644 --- a/qiskit/dagcircuit/dagcircuit.py +++ b/qiskit/dagcircuit/dagcircuit.py @@ -60,7 +60,7 @@ def __init__(self): self.name = None # Circuit metadata - self.metadata = None + self.metadata = {} # Set of wires (Register,idx) in the dag self._wires = set() diff --git a/qiskit/dagcircuit/dagdependency.py b/qiskit/dagcircuit/dagdependency.py index d1ad623bdc6d..1ed5eb96e113 100644 --- a/qiskit/dagcircuit/dagdependency.py +++ b/qiskit/dagcircuit/dagdependency.py @@ -91,7 +91,7 @@ def __init__(self): self.name = None # Circuit metadata - self.metadata = None + self.metadata = {} # Directed multigraph whose nodes are operations(gates) and edges # represent non-commutativity between two gates. diff --git a/qiskit/test/base.py b/qiskit/test/base.py index e81226cc1b87..ac9da7a02a2d 100644 --- a/qiskit/test/base.py +++ b/qiskit/test/base.py @@ -240,6 +240,13 @@ def setUpClass(cls): ] for msg in allow_DeprecationWarning_message: warnings.filterwarnings("default", category=DeprecationWarning, message=msg) + # This warning should be fixed once Qiskit/qiskit-aer#1761 is in a release version of Aer. + warnings.filterwarnings( + "default", + category=DeprecationWarning, + module="qiskit_aer.*", + message="Setting metadata to None.*", + ) class FullQiskitTestCase(QiskitTestCase): diff --git a/releasenotes/notes/circuit_metadata_always_dict-49015896dfa49d33.yaml b/releasenotes/notes/circuit_metadata_always_dict-49015896dfa49d33.yaml new file mode 100644 index 000000000000..772daee423c1 --- /dev/null +++ b/releasenotes/notes/circuit_metadata_always_dict-49015896dfa49d33.yaml @@ -0,0 +1,15 @@ +upgrade: + - | + The :class:`.QuantumCircuit` :attr:`.QuantumCircuit.metadata` attribute now + always returns a dictionary, and can only be set to a dictionary. Previously, + its default value was ``None``, and could be manually set to ``None`` or a + dictionary. + - | + The default value of ``metadata`` in both :class:`.DAGCircuit` and + :class:`.DAGDependency` has been changed from ``None`` to ``{}`` for compatibility + with a similar attribute of :class:`.QuantumCircuit`. +deprecations: + - | + Setting the :class:`.QuantumCircuit` :attr:`.QuantumCircuit.metadata` attribute + to ``None`` has been deprecated. Instead, users should set it to an empty + dictionary if they want it to contain no data. diff --git a/test/python/circuit/test_circuit_properties.py b/test/python/circuit/test_circuit_properties.py index 12c3ecd9b0a2..67c6cca5518b 100644 --- a/test/python/circuit/test_circuit_properties.py +++ b/test/python/circuit/test_circuit_properties.py @@ -1267,6 +1267,25 @@ def test_metadata_copy_does_not_share_state(self): self.assertEqual(qc1.metadata["a"], 0) + def test_metadata_is_dict(self): + """Verify setting metadata to None in the constructor results in an empty dict.""" + qc = QuantumCircuit(1) + metadata1 = qc.metadata + self.assertEqual(metadata1, {}) + + def test_metadata_raises(self): + """Test that we must set metadata to a dict.""" + qc = QuantumCircuit(1) + with self.assertRaises(TypeError): + qc.metadata = 1 + + def test_metdata_deprectation(self): + """Test that setting metadata to None emits a deprecation warning.""" + qc = QuantumCircuit(1) + with self.assertWarns(DeprecationWarning): + qc.metadata = None + self.assertEqual(qc.metadata, {}) + def test_scheduling(self): """Test cannot return schedule information without scheduling.""" qc = QuantumCircuit(2) diff --git a/test/python/dagcircuit/test_dagcircuit.py b/test/python/dagcircuit/test_dagcircuit.py index ae6e6afe53d4..c934af733f00 100644 --- a/test/python/dagcircuit/test_dagcircuit.py +++ b/test/python/dagcircuit/test_dagcircuit.py @@ -1225,6 +1225,12 @@ def test_circuit_factors(self): """Test number of separable factors in circuit.""" self.assertEqual(self.dag.num_tensor_factors(), 2) + def test_default_metadata_value(self): + """Test that the default DAGCircuit metadata is valid QuantumCircuit metadata.""" + qc = QuantumCircuit(1) + qc.metadata = self.dag.metadata + self.assertEqual(qc.metadata, {}) + class TestCircuitControlFlowProperties(QiskitTestCase): """Properties tests of DAGCircuit with control-flow instructions.""" diff --git a/test/python/dagcircuit/test_dagdependency.py b/test/python/dagcircuit/test_dagdependency.py index 011584dded2b..ca6890bb40a3 100644 --- a/test/python/dagcircuit/test_dagdependency.py +++ b/test/python/dagcircuit/test_dagdependency.py @@ -319,6 +319,12 @@ def test_dag_depth_empty(self): dag = circuit_to_dagdependency(qc) self.assertEqual(dag.depth(), 0) + def test_default_metadata_value(self): + """Test that the default DAGDependency metadata is valid QuantumCircuit metadata.""" + qc = QuantumCircuit(1) + qc.metadata = self.dag.metadata + self.assertEqual(qc.metadata, {}) + if __name__ == "__main__": unittest.main()