diff --git a/qiskit/__init__.py b/qiskit/__init__.py index cbf6d565b3df..7196cb5d6b34 100644 --- a/qiskit/__init__.py +++ b/qiskit/__init__.py @@ -12,10 +12,8 @@ # pylint: disable=wrong-import-order,invalid-name,wrong-import-position - """Main Qiskit public functionality.""" -import pkgutil import sys import warnings import os @@ -23,31 +21,57 @@ # First, check for required Python and API version from . import util +# Extend namespace for backwards compat +from qiskit import namespace +new_meta_path = [] +new_meta_path.append(namespace.QiskitElementImport( + 'qiskit_aer', 'qiskit.providers.aer')) +new_meta_path.append(namespace.QiskitElementImport( + 'qiskit_ignis', 'qiskit.ignis')) +new_meta_path.append(namespace.QiskitElementImport( + 'qiskit_aqua', 'qiskit.aqua')) +new_meta_path.append(namespace.QiskitElementImport( + 'qiskit_aqua.ai', 'qiskit.ai')) +new_meta_path.append(namespace.QiskitElementImport( + 'qiskit_aqua.chemistry', 'qiskit.chemistry')) +new_meta_path.append(namespace.QiskitElementImport( + 'qiskit_aqua.finance', 'qiskit.finance')) +new_meta_path.append(namespace.QiskitElementImport( + 'qiskit_aqua.ml', 'qiskit.ml')) +new_meta_path.append(namespace.QiskitElementImport( + 'qiskit_aqua.optimizations', 'qiskit.optimizations')) +new_meta_path.append(namespace.QiskitElementImport( + 'qiskit_ibmq_provider', 'qiskit.providers.ibmq')) +new_meta_path.append(namespace.QiskitElementImport( + 'qiskit_aqt_provider', 'qiskit.providers.aqt')) +new_meta_path.append(namespace.QiskitElementImport( + 'qiskit_honeywell_provider', 'qiskit.providers.honeywell')) +# Add Qiskit importers to meta_path before PathFinder in the default +# sys.meta_path to avoid the miss penalty on trying to import a module +# which does not exist +old_meta_path = sys.meta_path +sys.meta_path = old_meta_path[:-1] + new_meta_path + [old_meta_path[-1]] + # qiskit errors operator -from qiskit.exceptions import QiskitError +from qiskit.exceptions import QiskitError # noqa # The main qiskit operators -from qiskit.circuit import ClassicalRegister -from qiskit.circuit import QuantumRegister -from qiskit.circuit import AncillaRegister -from qiskit.circuit import QuantumCircuit +from qiskit.circuit import ClassicalRegister # noqa +from qiskit.circuit import QuantumRegister # noqa +from qiskit.circuit import AncillaRegister # noqa +from qiskit.circuit import QuantumCircuit # noqa # user config -from qiskit import user_config as _user_config +from qiskit import user_config as _user_config # noqa # The qiskit.extensions.x imports needs to be placed here due to the # mechanism for adding gates dynamically. -import qiskit.extensions -import qiskit.circuit.measure -import qiskit.circuit.reset - -# Allow extending this namespace. Please note that currently this line needs -# to be placed *before* the wrapper imports or any non-import code AND *before* -# importing the package you want to allow extensions for (in this case `backends`). -__path__ = pkgutil.extend_path(__path__, __name__) +import qiskit.extensions # noqa +import qiskit.circuit.measure # noqa +import qiskit.circuit.reset # noqa # Please note these are global instances, not modules. -from qiskit.providers.basicaer import BasicAer +from qiskit.providers.basicaer import BasicAer # noqa _config = _user_config.get_config() @@ -61,6 +85,7 @@ warnings.warn('Could not import the Aer provider from the qiskit-aer ' 'package. Install qiskit-aer or check your installation.', RuntimeWarning) + # Try to import the IBMQ provider if installed. try: from qiskit.providers.ibmq import IBMQ @@ -73,8 +98,6 @@ 'qiskit-ibmq-provider or check your installation.', RuntimeWarning) -# Moved to after IBMQ and Aer imports due to import issues -# with other modules that check for IBMQ (tools) from qiskit.execute import execute # noqa from qiskit.compiler import transpile, assemble, schedule # noqa diff --git a/qiskit/namespace.py b/qiskit/namespace.py new file mode 100644 index 000000000000..33a7fae79b93 --- /dev/null +++ b/qiskit/namespace.py @@ -0,0 +1,60 @@ +# -*- coding: utf-8 -*- + +# This code is part of Qiskit. +# +# (C) Copyright IBM 2020. +# +# 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. + +# pylint: disable=unused-argument + +"""Module for utilities to manually construct qiskit namespace""" + +import sys +from importlib.abc import MetaPathFinder, Loader +import importlib + + +class QiskitLoader(Loader): + """Load qiskit element as a namespace package.""" + def __init__(self, new_package, old_namespace): + super().__init__() + self.new_package = new_package + self.old_namespace = old_namespace + + def module_repr(self, module): + return repr(module) + + def load_module(self, fullname): + old_name = fullname + names = fullname.split(".") + new_namespace_names = self.new_package.split('.') + old_namespace_names = self.old_namespace.split('.') + fullname = ".".join( + new_namespace_names + names[len(old_namespace_names):]) + module = importlib.import_module(fullname) + sys.modules[old_name] = module + return module + + +class QiskitElementImport(MetaPathFinder): + """Meta importer to enable unified qiskit namespace.""" + def __init__(self, new_package, old_namespace): + super().__init__() + self.new_package = new_package + self.old_namespace = old_namespace + + def find_spec(self, fullname, path=None, target=None): + """Return the ModuleSpec for Qiskit element.""" + if fullname.startswith(self.old_namespace): + return importlib.util.spec_from_loader( + fullname, + QiskitLoader(self.new_package, self.old_namespace), + origin='qiskit') + return None diff --git a/qiskit/providers/__init__.py b/qiskit/providers/__init__.py index fd53fbcbe3e3..c944c09c3f69 100644 --- a/qiskit/providers/__init__.py +++ b/qiskit/providers/__init__.py @@ -47,15 +47,9 @@ JobTimeoutError """ -import pkgutil - from .basebackend import BaseBackend from .baseprovider import BaseProvider from .basejob import BaseJob from .exceptions import (JobError, JobTimeoutError, QiskitBackendNotFoundError, BackendPropertyError, BackendConfigurationError) from .jobstatus import JobStatus - - -# Allow extending this namespace. -__path__ = pkgutil.extend_path(__path__, __name__) diff --git a/qiskit/tools/jupyter/job_watcher.py b/qiskit/tools/jupyter/job_watcher.py index dda4591309e7..98cca99c5fc6 100644 --- a/qiskit/tools/jupyter/job_watcher.py +++ b/qiskit/tools/jupyter/job_watcher.py @@ -176,5 +176,6 @@ def qiskit_disable_job_watcher(self, line='', cell=None): _JOB_WATCHER.stop_viewer() -# The Jupyter job watcher instance -_JOB_WATCHER = JobWatcher() +if HAS_IBMQ: + # The Jupyter job watcher instance + _JOB_WATCHER = JobWatcher() diff --git a/qiskit/version.py b/qiskit/version.py index 2c2f2776fcac..fb300f3b3bfa 100644 --- a/qiskit/version.py +++ b/qiskit/version.py @@ -10,7 +10,7 @@ # copyright notice, and modified files need to carry a notice indicating # that they have been altered from the originals. -# pylint: disable=no-name-in-module,broad-except,cyclic-import +# pylint: disable=no-name-in-module,broad-except,cyclic-import,import-error """Contains the terra version.""" @@ -85,22 +85,22 @@ def _get_qiskit_versions(): out_dict = {} out_dict['qiskit-terra'] = __version__ try: - from qiskit.providers import aer + import qiskit_aer as aer out_dict['qiskit-aer'] = aer.__version__ except Exception: out_dict['qiskit-aer'] = None try: - from qiskit import ignis + import qiskit_ignis as ignis out_dict['qiskit-ignis'] = ignis.__version__ except Exception: out_dict['qiskit-ignis'] = None try: - from qiskit.providers import ibmq + import qiskit_ibmq_provider as ibmq out_dict['qiskit-ibmq-provider'] = ibmq.__version__ except Exception: out_dict['qiskit-ibmq-provider'] = None try: - from qiskit import aqua + import qiskit_aqua as aqua out_dict['qiskit-aqua'] = aqua.__version__ except Exception: out_dict['qiskit-aqua'] = None diff --git a/tox.ini b/tox.ini index 343f90cebcba..997d760ec08d 100644 --- a/tox.ini +++ b/tox.ini @@ -11,7 +11,7 @@ setenv = LANGUAGE=en_US LC_ALL=en_US.utf-8 ARGS="-V" - QISKIT_SUPRESS_PACKAGING_WARNINGS=Y + QISKIT_SUPPRESS_PACKAGING_WARNINGS=Y deps = -r{toxinidir}/requirements.txt -r{toxinidir}/requirements-dev.txt commands = @@ -40,6 +40,7 @@ basepython = python3 setenv = {[testenv]setenv} QISKIT_DOCS=TRUE + QISKIT_SUPPRESS_PACKAGING_WARNINGS=Y deps = -r{toxinidir}/requirements-dev.txt qiskit-aer