forked from Qiskit/qiskit
-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Remove namespace packaging and hardcode elements (attempt 2)
Namespace packages are constant source of problems for users. The python packaging ecosystem around splitting packages across namespaces is fragile at the best of times and can often leave a you with an environment that isn't recoverable (especially when mixing install methods). There is also a performance hit whenever there is a piece of the namespace we allow external packages to extend since it requires doing a full python path search which can be slow depending on the backing I/O and the number of paths in sys.path for an environment. This commit starts the process of addressing this by removing the arbitrary namespace hook points and hard coding the element namespace maps via a custom import loader at the root of the namespace. This has 2 advantages it removes the use of namespace packages so the fragility and performance impact are fixed since every element will be renamed to use 'qiskit_' instead of 'qiskit.', but it also makes it explicit where we extend the namespace. The previous method allowed any package to extend qiskit.* and qiskit.providers.* with whatever they wanted. We'll need to coordinate updating the elements with this merging, because it is a breaking change for each element (although not for end users). A potential follow on is to add a plugin interface for 3rd party providers like what was proposed in Qiskit#1465 so that we can make external providers externally discoverable without needing to add manual hook points moving forward (this was done for backwards compat with the aqt and honeywell provider). This is a second attempt at removing namespace packaging. The first attempt in PR Qiskit#4767 was merged and had to be reverted because there were some circular import error issues that needed to be resolved. Since having this in terra blocks CI for all the qiskit elements a revert was necessary to unblock developement for the entire project while those were resolved.
- Loading branch information
Showing
5 changed files
with
120 additions
and
43 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters