Source code for uniqc.task.optional_deps

"""Optional dependency management with clear error messages.

This module provides utilities for handling optional dependencies across
different quantum cloud platforms. When a dependency is not installed,
users receive clear instructions on how to install it.

Usage::

    # Check if dependency is available
    from uniqc.task.optional_deps import QUAFU_AVAILABLE
    if QUAFU_AVAILABLE:
        from uniqc.task.adapters.quafu_adapter import QuafuAdapter

    # Require dependency with error message
    from uniqc.task.optional_deps import require
    quafu = require("quafu", "quafu")  # Raises MissingDependencyError if not installed
"""

from __future__ import annotations

__all__ = [
    "MissingDependencyError",
    "require",
    "check_quafu",
    "check_qiskit",
    "check_pyqpanda3",
    "check_uniqc_cpp",
    "check_qutip",
    "check_simulation",
    "QUAFU_AVAILABLE",
    "QISKIT_AVAILABLE",
    "PYQPANDA3_AVAILABLE",
    "UNIQC_CPP_AVAILABLE",
    "QUTIP_AVAILABLE",
    "SIMULATION_AVAILABLE",
]


[docs] class MissingDependencyError(ImportError): """Raised when an optional dependency is not installed. Provides a clear error message indicating which package is missing and, when available, how to install or rebuild the required support. Attributes: package: The name of the missing package. extra: The pip extras name to install the package, if applicable. install_hint: An explicit install or recovery hint, if applicable. """ def __init__(self, package: str, extra: str | None = None, install_hint: str | None = None) -> None: self.package = package self.extra = extra self.install_hint = install_hint if install_hint is not None: msg = f"Package '{package}' is required for this feature. {install_hint}" elif extra is not None: msg = ( f"Package '{package}' is required for this feature. " f"Install it with: pip install unified-quantum[{extra}]" ) else: msg = f"Package '{package}' is required for this feature." super().__init__(msg)
[docs] def require(name: str, extra: str): """Import an optional module with a clear error message if missing. Args: name: The module name to import (e.g., 'quafu', 'qiskit'). extra: The pip extras name for installation (e.g., 'quafu', 'qiskit'). Returns: The imported module. Raises: MissingDependencyError: If the module cannot be imported. Example: >>> quafu = require("quafu", "quafu") >>> # If quafu is not installed: >>> # MissingDependencyError: Package 'quafu' is required... """ try: return __import__(name) except ImportError as e: raise MissingDependencyError(name, extra) from e
[docs] def check_quafu() -> bool: """Check if the quafu package is available. Returns: True if quafu can be imported, False otherwise. """ try: import quafu # noqa: F401 return True except ImportError: return False
[docs] def check_qiskit() -> bool: """Check if the qiskit and qiskit_ibm_provider packages are available. Returns: True if both packages can be imported, False otherwise. """ try: import qiskit # noqa: F401 import qiskit_ibm_provider # noqa: F401 return True except ImportError: return False
[docs] def check_pyqpanda3() -> bool: """Check if the pyqpanda3 package is available. Returns: True if pyqpanda3 can be imported, False otherwise. """ try: import pyqpanda3 # noqa: F401 return True except ImportError: return False
[docs] def check_uniqc_cpp() -> bool: """Check if the uniqc_cpp C++ simulator extension is available. Returns: True if uniqc_cpp can be imported, False otherwise. """ try: import uniqc_cpp # noqa: F401 return True except ImportError: return False
[docs] def check_qutip() -> bool: """Check if the QuTiP-based simulation stack is available. Returns: True if qutip and qutip_qip can be imported, False otherwise. """ try: import qutip # noqa: F401 import qutip_qip # noqa: F401 return True except ImportError: return False
[docs] def check_simulation(target: str = "cpp") -> bool: """Check simulation support for a specific backend family. Args: target: Which simulation capability to check. - ``"cpp"``: built-in C++ simulator extension (default) - ``"qutip"``: QuTiP-based simulation stack - ``"all"``: both C++ simulator and QuTiP stack Returns: True if the requested simulation target is available, False otherwise. Raises: ValueError: If ``target`` is not one of ``"cpp"``, ``"qutip"``, or ``"all"``. """ if target == "cpp": return check_uniqc_cpp() if target == "qutip": return check_qutip() if target == "all": return check_uniqc_cpp() and check_qutip() raise ValueError(f"Unsupported simulation target: {target}")
# Pre-computed availability flags (evaluated at module load time) QUAFU_AVAILABLE = check_quafu() QISKIT_AVAILABLE = check_qiskit() PYQPANDA3_AVAILABLE = check_pyqpanda3() UNIQC_CPP_AVAILABLE = check_uniqc_cpp() QUTIP_AVAILABLE = check_qutip() SIMULATION_AVAILABLE = UNIQC_CPP_AVAILABLE