From 9412a536d3642ee48164d90615a30c7e9b2bf2a1 Mon Sep 17 00:00:00 2001 From: Jake Lishman Date: Mon, 14 Aug 2023 22:14:41 +0100 Subject: [PATCH 1/2] Add exceptions to API documentation (#10522) The big change here is that `QiskitError` is added to the API documentation, which causes 400--500 previously failing Sphinx lookups (stemming from "Raises:" documentation) to now succeed. This commit also corrects several other places where exceptions were not being fully documented (and in several cases makes the imports more convenient as well), and corrects a couple of places with incorrect references to exceptions. (cherry picked from commit 982807e5bc8d7b0b7fa130b4cb2b09064b4224d4) # Conflicts: # docs/apidocs/exceptions.rst # qiskit/dagcircuit/__init__.py # qiskit/passmanager/__init__.py # qiskit/transpiler/__init__.py --- docs/apidocs/exceptions.rst | 6 + docs/apidocs/terra.rst | 1 + qiskit/algorithms/amplitude_estimators/ae.py | 1 - qiskit/circuit/__init__.py | 10 ++ qiskit/circuit/exceptions.py | 2 - qiskit/dagcircuit/__init__.py | 7 +- qiskit/exceptions.py | 34 +++++- qiskit/extensions/__init__.py | 9 ++ .../gradients/circuit_gradients/lin_comb.py | 4 +- qiskit/passmanager/__init__.py | 103 ++++++++++++++++++ qiskit/providers/__init__.py | 1 + qiskit/pulse/__init__.py | 12 +- qiskit/qasm2/__init__.py | 5 + qiskit/qpy/__init__.py | 6 + qiskit/qpy/exceptions.py | 3 +- qiskit/transpiler/__init__.py | 14 ++- .../passes/synthesis/unitary_synthesis.py | 2 +- 17 files changed, 205 insertions(+), 15 deletions(-) create mode 100644 docs/apidocs/exceptions.rst create mode 100644 qiskit/passmanager/__init__.py diff --git a/docs/apidocs/exceptions.rst b/docs/apidocs/exceptions.rst new file mode 100644 index 000000000000..eb3d59fe8388 --- /dev/null +++ b/docs/apidocs/exceptions.rst @@ -0,0 +1,6 @@ +.. _qiskit-exceptions: + +.. automodule:: qiskit.exceptions + :no-members: + :no-inherited-members: + :no-special-members: diff --git a/docs/apidocs/terra.rst b/docs/apidocs/terra.rst index cde921096f18..36af42fee215 100644 --- a/docs/apidocs/terra.rst +++ b/docs/apidocs/terra.rst @@ -45,3 +45,4 @@ Qiskit Terra API Reference utils_mitigation opflow algorithms + exceptions diff --git a/qiskit/algorithms/amplitude_estimators/ae.py b/qiskit/algorithms/amplitude_estimators/ae.py index d9aced5d9fe2..c454cb18793b 100644 --- a/qiskit/algorithms/amplitude_estimators/ae.py +++ b/qiskit/algorithms/amplitude_estimators/ae.py @@ -458,7 +458,6 @@ def compute_confidence_interval( The (1 - alpha) confidence interval of the specified kind. Raises: - AquaError: If 'mle' is not in self._ret.keys() (i.e. `run` was not called yet). NotImplementedError: If the confidence interval method `kind` is not implemented. """ # if statevector simulator the estimate is exact diff --git a/qiskit/circuit/__init__.py b/qiskit/circuit/__init__.py index 079ead121c85..b293fcdd12c2 100644 --- a/qiskit/circuit/__init__.py +++ b/qiskit/circuit/__init__.py @@ -348,7 +348,17 @@ .. currentmodule:: qiskit.circuit.random .. autofunction:: random_circuit .. currentmodule:: qiskit.circuit + +Exceptions +---------- + +Almost all circuit functions and methods will raise a :exc:`CircuitError` when encountering an error +that is particular to usage of Qiskit (as opposed to regular typing or indexing problems, which will +typically raise the corresponding standard Python error). + +.. autoexception:: CircuitError """ +from .exceptions import CircuitError from .quantumcircuit import QuantumCircuit from .classicalregister import ClassicalRegister, Clbit from .quantumregister import QuantumRegister, Qubit, AncillaRegister, AncillaQubit diff --git a/qiskit/circuit/exceptions.py b/qiskit/circuit/exceptions.py index b3a06ede2380..3687b92431fc 100644 --- a/qiskit/circuit/exceptions.py +++ b/qiskit/circuit/exceptions.py @@ -17,5 +17,3 @@ class CircuitError(QiskitError): """Base class for errors raised while processing a circuit.""" - - pass diff --git a/qiskit/dagcircuit/__init__.py b/qiskit/dagcircuit/__init__.py index b7d558e4b973..7ee9b0f4610f 100644 --- a/qiskit/dagcircuit/__init__.py +++ b/qiskit/dagcircuit/__init__.py @@ -34,6 +34,7 @@ Exceptions ========== +<<<<<<< HEAD .. autosummary:: :toctree: ../stubs/ @@ -48,10 +49,14 @@ BlockCollapser BlockCollector BlockSplitter +======= +.. autoexception:: DAGCircuitError +.. autoexception:: DAGDependencyError +>>>>>>> 982807e5b (Add exceptions to API documentation (#10522)) """ from .collect_blocks import BlockCollapser, BlockCollector, BlockSplitter from .dagcircuit import DAGCircuit from .dagnode import DAGNode, DAGOpNode, DAGInNode, DAGOutNode from .dagdepnode import DAGDepNode -from .exceptions import DAGCircuitError +from .exceptions import DAGCircuitError, DAGDependencyError from .dagdependency import DAGDependency diff --git a/qiskit/exceptions.py b/qiskit/exceptions.py index e086226c13da..048f79dfbc62 100644 --- a/qiskit/exceptions.py +++ b/qiskit/exceptions.py @@ -10,7 +10,39 @@ # copyright notice, and modified files need to carry a notice indicating # that they have been altered from the originals. -"""Exceptions for errors raised by Qiskit.""" +""" +=============================================== +Top-level exceptions (:mod:`qiskit.exceptions`) +=============================================== + +All Qiskit-related errors raised by Qiskit are subclasses of the base: + +.. autoexception:: QiskitError + +.. note:: + + Errors that are just general programming errors, such as incorrect typing, may still raise + standard Python errors such as ``TypeError``. :exc:`QiskitError` is generally for errors raised + in usage that is particular to Qiskit. + +Many of the Qiskit subpackages define their own more granular error, to help in catching only the +subset of errors you care about. For example, :mod:`qiskit.circuit` almost exclusively uses +:exc:`.CircuitError`, while both :exc:`.QASM2ExportError` and :exc:`.QASM2ParseError` derive from +:exc:`.QASM2Error` in :mod:`qiskit.qasm2`, which is in turn a type of :exc:`.QiskitError`. + +Qiskit has several optional features that depend on other packages that are not required for a +minimal install. You can read more about those, and ways to check for their presence, in +:mod:`qiskit.utils.optionals`. Trying to use a feature that requires an optional extra will raise a +particular error, which subclasses both :exc:`QiskitError` and the Python built-in ``ImportError``. + +.. autoexception:: MissingOptionalLibraryError + +Two more uncommon errors relate to failures in reading user-configuration files, or specifying a +filename that cannot be used: + +.. autoexception:: QiskitUserConfigError +.. autoexception:: InvalidFileError +""" from typing import Optional diff --git a/qiskit/extensions/__init__.py b/qiskit/extensions/__init__.py index 2595dea27517..dc87d869cd8a 100644 --- a/qiskit/extensions/__init__.py +++ b/qiskit/extensions/__init__.py @@ -53,12 +53,21 @@ UCRXGate UCRYGate UCRZGate + +Exceptions +========== + +The additional gates in this module will tend to raise a custom exception when they encounter +problems. + +.. autoexception:: ExtensionError """ # import all standard gates from qiskit.circuit.library.standard_gates import * from qiskit.circuit.barrier import Barrier +from .exceptions import ExtensionError from .quantum_initializer import ( Initialize, SingleQubitUnitary, diff --git a/qiskit/opflow/gradients/circuit_gradients/lin_comb.py b/qiskit/opflow/gradients/circuit_gradients/lin_comb.py index 361d13112e85..1e06512e763e 100644 --- a/qiskit/opflow/gradients/circuit_gradients/lin_comb.py +++ b/qiskit/opflow/gradients/circuit_gradients/lin_comb.py @@ -712,7 +712,7 @@ def _gradient_states( parameterized gates to compute the product rule. Raises: - AquaError: If one of the circuits could not be constructed. + QiskitError: If one of the circuits could not be constructed. TypeError: If the operators is of unsupported type. ValueError: If the auxiliary operator preparation fails. """ @@ -804,7 +804,7 @@ def _hessian_states( created per parameterized gates to compute the product rule. Raises: - AquaError: If one of the circuits could not be constructed. + QiskitError: If one of the circuits could not be constructed. TypeError: If ``operator`` is of unsupported type. ValueError: If the auxiliary operator preparation fails. """ diff --git a/qiskit/passmanager/__init__.py b/qiskit/passmanager/__init__.py new file mode 100644 index 000000000000..298925f41dd5 --- /dev/null +++ b/qiskit/passmanager/__init__.py @@ -0,0 +1,103 @@ +# This code is part of Qiskit. +# +# (C) Copyright IBM 2023. +# +# This code is licensed under the Apache License, Version 2.0. You may +# obtain a copy of this license in the LICENSE.txt file in the root directory +# of this source tree or at http://www.apache.org/licenses/LICENSE-2.0. +# +# Any modifications or derivative works of this code must retain this +# copyright notice, and modified files need to carry a notice indicating +# that they have been altered from the originals. + +""" +======================================= +Passmanager (:mod:`qiskit.passmanager`) +======================================= + +.. currentmodule:: qiskit.passmanager + +Overview +======== + +Qiskit pass manager is somewhat inspired by the `LLVM compiler `_, +but it is designed to take Qiskit object as an input instead of plain source code. + +The pass manager converts the input object into an intermediate representation (IR), +and it can be optimized and get lowered with a variety of transformations over multiple passes. +This representation must be preserved throughout the transformation. +The passes may consume the hardware constraints that Qiskit backend may provide. +Finally, the IR is converted back to some Qiskit object. +Note that the input type and output type don't need to match. + +Execution of passes is managed by the :class:`.FlowController`, +which is initialized with a set of transform and analysis passes and provides an iterator of them. +This iterator can be conditioned on the :class:`.PropertySet`, which is a namespace +storing the intermediate data necessary for the transformation. +A pass has read and write access to the property set namespace, +and the stored data is shared among scheduled passes. + +The :class:`BasePassManager` provides a user interface to build and execute transform passes. +It internally spawns a :class:`BasePassRunner` instance to apply transforms to +the input object. In this sense, the pass manager itself is unaware of the +underlying IR, but it is indirectly tied to a particular IR through the pass runner class. + +The responsibilities of the pass runner are the following: + +* Defining the input type / pass manager IR / output type. +* Converting an input object to a particular pass manager IR. +* Preparing own property set namespace. +* Running scheduled flow controllers to apply a series of transformations to the IR. +* Converting the IR back to an output object. + +A single pass runner always takes a single input object and returns a single output object. +Parallelism for multiple input objects is supported by the :class:`BasePassManager` by +broadcasting the pass runner via the :mod:`qiskit.tools.parallel_map` function. + +The base class :class:`BasePassRunner` doesn't define any associated type by itself, +and a developer needs to implement a subclass for a particular object type to optimize. +This `veil of ignorance` allows us to choose the most efficient data representation +for a particular optimization task, while we can reuse the pass flow control machinery +for different input and output types. + + +Base classes +------------ + +.. autosummary:: + :toctree: ../stubs/ + + BasePassRunner + BasePassManager + +Flow controllers +---------------- + +.. autosummary:: + :toctree: ../stubs/ + + FlowController + ConditionalController + DoWhileController + +PropertySet +----------- + +.. autosummary:: + :toctree: ../stubs/ + + PropertySet + +Exceptions +---------- + +.. autoexception:: PassManagerError + +""" + +from .passrunner import BasePassRunner +from .passmanager import BasePassManager +from .flow_controllers import FlowController, ConditionalController, DoWhileController +from .base_pass import GenericPass +from .propertyset import PropertySet +from .exceptions import PassManagerError diff --git a/qiskit/providers/__init__.py b/qiskit/providers/__init__.py index 7b1ef8527049..ded070bc340f 100644 --- a/qiskit/providers/__init__.py +++ b/qiskit/providers/__init__.py @@ -129,6 +129,7 @@ .. autoexception:: BackendPropertyError .. autoexception:: JobError .. autoexception:: JobTimeoutError +.. autoexception:: BackendConfigurationError ====================== Writing a New Provider diff --git a/qiskit/pulse/__init__.py b/qiskit/pulse/__init__.py index 90d84d54f821..84f94f8eb4d3 100644 --- a/qiskit/pulse/__init__.py +++ b/qiskit/pulse/__init__.py @@ -57,6 +57,10 @@ ========== .. autoexception:: PulseError +.. autoexception:: BackendNotSet +.. autoexception:: NoActiveBuilder +.. autoexception:: UnassignedDurationError +.. autoexception:: UnassignedReferenceError """ # Builder imports. @@ -124,7 +128,13 @@ LoConfig, LoRange, ) -from qiskit.pulse.exceptions import PulseError +from qiskit.pulse.exceptions import ( + PulseError, + BackendNotSet, + NoActiveBuilder, + UnassignedDurationError, + UnassignedReferenceError, +) from qiskit.pulse.instruction_schedule_map import InstructionScheduleMap from qiskit.pulse.instructions import ( Acquire, diff --git a/qiskit/qasm2/__init__.py b/qiskit/qasm2/__init__.py index 79765f3951bb..061a5dffe284 100644 --- a/qiskit/qasm2/__init__.py +++ b/qiskit/qasm2/__init__.py @@ -98,6 +98,11 @@ .. autoexception:: QASM2ParseError +Similarly, a failure during the export of an OpenQASM 2 program will raise its own subclass of +:exc:`QASM2Error`: + +.. autoexception:: QASM2ExportError + .. _qasm2-examples: Examples diff --git a/qiskit/qpy/__init__.py b/qiskit/qpy/__init__.py index 4482fb0753bd..eccb6c553819 100644 --- a/qiskit/qpy/__init__.py +++ b/qiskit/qpy/__init__.py @@ -74,6 +74,11 @@ .. autofunction:: load .. autofunction:: dump +These functions will raise a custom subclass of :exc:`.QiskitError` if they encounter problems +during serialization or deserialization. + +.. autoexception:: QpyError + QPY Compatibility ================= @@ -1265,6 +1270,7 @@ class if it's defined in Qiskit. Otherwise it falls back to the custom .. [#f3] https://docs.python.org/3/c-api/complex.html#c.Py_complex """ +from .exceptions import QpyError from .interface import dump, load # For backward compatibility. Provide, Runtime, Experiment call these private functions. diff --git a/qiskit/qpy/exceptions.py b/qiskit/qpy/exceptions.py index 527681a266d1..d8e3146dcc29 100644 --- a/qiskit/qpy/exceptions.py +++ b/qiskit/qpy/exceptions.py @@ -10,7 +10,8 @@ # copyright notice, and modified files need to carry a notice indicating # that they have been altered from the originals. -"""Exception for errors raised by the pulse module.""" +"""Exception for errors raised by the QPY module.""" + from qiskit.exceptions import QiskitError diff --git a/qiskit/transpiler/__init__.py b/qiskit/transpiler/__init__.py index 76cd6fc3d6f4..cfc5b21308f7 100644 --- a/qiskit/transpiler/__init__.py +++ b/qiskit/transpiler/__init__.py @@ -1241,19 +1241,23 @@ Exceptions ---------- -.. autosummary:: - :toctree: ../stubs/ - - TranspilerError - TranspilerAccessError +.. autoexception:: TranspilerError +.. autoexception:: TranspilerAccessError +.. autoexception:: CouplingError +.. autoexception:: LayoutError """ from .runningpassmanager import FlowController, ConditionalController, DoWhileController from .passmanager import PassManager from .passmanager_config import PassManagerConfig +<<<<<<< HEAD from .passmanager import StagedPassManager from .propertyset import PropertySet from .exceptions import TranspilerError, TranspilerAccessError +======= +from .propertyset import PropertySet # pylint: disable=no-name-in-module +from .exceptions import TranspilerError, TranspilerAccessError, CouplingError, LayoutError +>>>>>>> 982807e5b (Add exceptions to API documentation (#10522)) from .fencedobjs import FencedDAGCircuit, FencedPropertySet from .basepasses import AnalysisPass, TransformationPass from .coupling import CouplingMap diff --git a/qiskit/transpiler/passes/synthesis/unitary_synthesis.py b/qiskit/transpiler/passes/synthesis/unitary_synthesis.py index 67176ddf374e..3e1c4d0a3331 100644 --- a/qiskit/transpiler/passes/synthesis/unitary_synthesis.py +++ b/qiskit/transpiler/passes/synthesis/unitary_synthesis.py @@ -312,7 +312,7 @@ def __init__( the gate direction with the shorter duration from the backend properties will be used. If set to True, and a natural direction can not be - determined, raises :class:`~TranspileError`. If set to None, no + determined, raises :class:`.TranspilerError`. If set to None, no exception will be raised if a natural direction can not be determined. synth_gates (list[str]): List of gates to synthesize. If None and From e883dca40420f89591997833c3e9eeb6e9521397 Mon Sep 17 00:00:00 2001 From: Matthew Treinish Date: Tue, 15 Aug 2023 07:40:09 -0400 Subject: [PATCH 2/2] Fix merge conflicts This commit fixes several merge conflicts in the backport. They were mostly minor differences between main and the stable branch that needed to be corrected. --- qiskit/dagcircuit/__init__.py | 11 +--- qiskit/passmanager/__init__.py | 103 --------------------------------- qiskit/transpiler/__init__.py | 5 -- 3 files changed, 2 insertions(+), 117 deletions(-) delete mode 100644 qiskit/passmanager/__init__.py diff --git a/qiskit/dagcircuit/__init__.py b/qiskit/dagcircuit/__init__.py index 7ee9b0f4610f..d6da8164dded 100644 --- a/qiskit/dagcircuit/__init__.py +++ b/qiskit/dagcircuit/__init__.py @@ -34,11 +34,8 @@ Exceptions ========== -<<<<<<< HEAD -.. autosummary:: - :toctree: ../stubs/ - - DAGCircuitError +.. autoexception:: DAGCircuitError +.. autoexception:: DAGDependencyError Utilities ========= @@ -49,10 +46,6 @@ BlockCollapser BlockCollector BlockSplitter -======= -.. autoexception:: DAGCircuitError -.. autoexception:: DAGDependencyError ->>>>>>> 982807e5b (Add exceptions to API documentation (#10522)) """ from .collect_blocks import BlockCollapser, BlockCollector, BlockSplitter from .dagcircuit import DAGCircuit diff --git a/qiskit/passmanager/__init__.py b/qiskit/passmanager/__init__.py deleted file mode 100644 index 298925f41dd5..000000000000 --- a/qiskit/passmanager/__init__.py +++ /dev/null @@ -1,103 +0,0 @@ -# This code is part of Qiskit. -# -# (C) Copyright IBM 2023. -# -# This code is licensed under the Apache License, Version 2.0. You may -# obtain a copy of this license in the LICENSE.txt file in the root directory -# of this source tree or at http://www.apache.org/licenses/LICENSE-2.0. -# -# Any modifications or derivative works of this code must retain this -# copyright notice, and modified files need to carry a notice indicating -# that they have been altered from the originals. - -""" -======================================= -Passmanager (:mod:`qiskit.passmanager`) -======================================= - -.. currentmodule:: qiskit.passmanager - -Overview -======== - -Qiskit pass manager is somewhat inspired by the `LLVM compiler `_, -but it is designed to take Qiskit object as an input instead of plain source code. - -The pass manager converts the input object into an intermediate representation (IR), -and it can be optimized and get lowered with a variety of transformations over multiple passes. -This representation must be preserved throughout the transformation. -The passes may consume the hardware constraints that Qiskit backend may provide. -Finally, the IR is converted back to some Qiskit object. -Note that the input type and output type don't need to match. - -Execution of passes is managed by the :class:`.FlowController`, -which is initialized with a set of transform and analysis passes and provides an iterator of them. -This iterator can be conditioned on the :class:`.PropertySet`, which is a namespace -storing the intermediate data necessary for the transformation. -A pass has read and write access to the property set namespace, -and the stored data is shared among scheduled passes. - -The :class:`BasePassManager` provides a user interface to build and execute transform passes. -It internally spawns a :class:`BasePassRunner` instance to apply transforms to -the input object. In this sense, the pass manager itself is unaware of the -underlying IR, but it is indirectly tied to a particular IR through the pass runner class. - -The responsibilities of the pass runner are the following: - -* Defining the input type / pass manager IR / output type. -* Converting an input object to a particular pass manager IR. -* Preparing own property set namespace. -* Running scheduled flow controllers to apply a series of transformations to the IR. -* Converting the IR back to an output object. - -A single pass runner always takes a single input object and returns a single output object. -Parallelism for multiple input objects is supported by the :class:`BasePassManager` by -broadcasting the pass runner via the :mod:`qiskit.tools.parallel_map` function. - -The base class :class:`BasePassRunner` doesn't define any associated type by itself, -and a developer needs to implement a subclass for a particular object type to optimize. -This `veil of ignorance` allows us to choose the most efficient data representation -for a particular optimization task, while we can reuse the pass flow control machinery -for different input and output types. - - -Base classes ------------- - -.. autosummary:: - :toctree: ../stubs/ - - BasePassRunner - BasePassManager - -Flow controllers ----------------- - -.. autosummary:: - :toctree: ../stubs/ - - FlowController - ConditionalController - DoWhileController - -PropertySet ------------ - -.. autosummary:: - :toctree: ../stubs/ - - PropertySet - -Exceptions ----------- - -.. autoexception:: PassManagerError - -""" - -from .passrunner import BasePassRunner -from .passmanager import BasePassManager -from .flow_controllers import FlowController, ConditionalController, DoWhileController -from .base_pass import GenericPass -from .propertyset import PropertySet -from .exceptions import PassManagerError diff --git a/qiskit/transpiler/__init__.py b/qiskit/transpiler/__init__.py index cfc5b21308f7..d421107bb263 100644 --- a/qiskit/transpiler/__init__.py +++ b/qiskit/transpiler/__init__.py @@ -1250,14 +1250,9 @@ from .runningpassmanager import FlowController, ConditionalController, DoWhileController from .passmanager import PassManager from .passmanager_config import PassManagerConfig -<<<<<<< HEAD from .passmanager import StagedPassManager from .propertyset import PropertySet -from .exceptions import TranspilerError, TranspilerAccessError -======= -from .propertyset import PropertySet # pylint: disable=no-name-in-module from .exceptions import TranspilerError, TranspilerAccessError, CouplingError, LayoutError ->>>>>>> 982807e5b (Add exceptions to API documentation (#10522)) from .fencedobjs import FencedDAGCircuit, FencedPropertySet from .basepasses import AnalysisPass, TransformationPass from .coupling import CouplingMap