Deprecate passing `None` to `DAGCircuit` appenders (#10752)

This has been against the documented typing of the functions for some
time, but some scheduling methods have mistakenly been passing `None`.
There is no need to support `None` here; the empty tuple `()` is equally
immutable and a CPython singleton, so there are neither mutability nor
memory benefits to supporting both, and removing `None` as an input is a
simple way to remove a(n admittedly cheap) branch from the appender
methods.

Co-authored-by: Luciano Bello <bel@zurich.ibm.com>
This commit is contained in:
Jake Lishman 2023-10-18 16:23:14 +01:00 committed by GitHub
parent d86e708f11
commit b18faa3f89
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 50 additions and 5 deletions

View File

@ -23,6 +23,7 @@ directly from the graph.
from collections import OrderedDict, defaultdict, deque, namedtuple
import copy
import math
import warnings
from typing import Dict, Generator, Any, List
import numpy as np
@ -656,8 +657,16 @@ class DAGCircuit:
DAGCircuitError: if a leaf node is connected to multiple outputs
"""
qargs = tuple(qargs) if qargs is not None else ()
cargs = tuple(cargs) if cargs is not None else ()
if qargs is None:
_warn_none_args()
qargs = ()
else:
qargs = tuple(qargs)
if cargs is None:
_warn_none_args()
cargs = ()
else:
cargs = tuple(cargs)
if self._operation_may_have_bits(op):
# This is the slow path; most of the time, this won't happen.
@ -701,8 +710,16 @@ class DAGCircuit:
Raises:
DAGCircuitError: if initial nodes connected to multiple out edges
"""
qargs = tuple(qargs) if qargs is not None else ()
cargs = tuple(cargs) if cargs is not None else ()
if qargs is None:
_warn_none_args()
qargs = ()
else:
qargs = tuple(qargs)
if cargs is None:
_warn_none_args()
cargs = ()
else:
cargs = tuple(cargs)
if self._operation_may_have_bits(op):
# This is the slow path; most of the time, this won't happen.
@ -2099,3 +2116,12 @@ class DAGCircuit:
from qiskit.visualization.dag_visualization import dag_drawer
return dag_drawer(dag=self, scale=scale, filename=filename, style=style)
def _warn_none_args():
warnings.warn(
"Passing 'None' as the qubits or clbits of an operation to 'DAGCircuit' methods"
" is deprecated since Qiskit 0.45 and will be removed in Qiskit 1.0. Instead, pass '()'.",
DeprecationWarning,
stacklevel=3,
)

View File

@ -198,7 +198,7 @@ class BasePadding(TransformationPass):
t_start: int,
oper: Instruction,
qubits: Qubit | Iterable[Qubit],
clbits: Clbit | Iterable[Clbit] | None = None,
clbits: Clbit | Iterable[Clbit] = (),
):
"""Add new operation to DAG with scheduled information.

View File

@ -0,0 +1,7 @@
---
deprecations:
- |
Passing ``None`` as the ``qargs`` or ``cargs`` arguments to :meth:`.DAGCircuit.apply_operation_back`
or :meth:`~.DAGCircuit.apply_operation_front` is deprecated and will be removed in Qiskit 1.0.
This has been explicitly against the typing documentation for some time, but silently accepted
by Qiskit. Instead, simply pass ``()`` rather than ``None``.

View File

@ -487,6 +487,18 @@ class TestDagApplyOperation(QiskitTestCase):
self.assertEqual(len(list(self.dag.nodes())), 16)
self.assertEqual(len(list(self.dag.edges())), 17)
def test_apply_operation_rejects_none(self):
"""Test that the ``apply_operation_*`` methods warn when given ``None``."""
noop = Instruction("noop", 0, 0, [])
with self.assertWarnsRegex(DeprecationWarning, "Passing 'None'"):
self.dag.apply_operation_back(noop, None, ())
with self.assertWarnsRegex(DeprecationWarning, "Passing 'None'"):
self.dag.apply_operation_back(noop, (), None)
with self.assertWarnsRegex(DeprecationWarning, "Passing 'None'"):
self.dag.apply_operation_front(noop, None, ())
with self.assertWarnsRegex(DeprecationWarning, "Passing 'None'"):
self.dag.apply_operation_front(noop, (), None)
def test_edges(self):
"""Test that DAGCircuit.edges() behaves as expected with ops."""
x_gate = XGate().c_if(*self.condition)