plugins: split load_plugins()
This commit is contained in:
@@ -29,7 +29,7 @@ import time
|
|||||||
import threading
|
import threading
|
||||||
import sys
|
import sys
|
||||||
from typing import (NamedTuple, Any, Union, TYPE_CHECKING, Optional, Tuple,
|
from typing import (NamedTuple, Any, Union, TYPE_CHECKING, Optional, Tuple,
|
||||||
Dict, Iterable, List, Sequence, Callable, TypeVar, Mapping)
|
Dict, Iterable, List, Sequence, Callable, TypeVar, Mapping, Set)
|
||||||
import concurrent
|
import concurrent
|
||||||
from concurrent import futures
|
from concurrent import futures
|
||||||
from functools import wraps, partial
|
from functools import wraps, partial
|
||||||
@@ -56,12 +56,13 @@ hooks = {}
|
|||||||
class Plugins(DaemonThread):
|
class Plugins(DaemonThread):
|
||||||
|
|
||||||
LOGGING_SHORTCUT = 'p'
|
LOGGING_SHORTCUT = 'p'
|
||||||
|
pkgpath = os.path.dirname(plugins.__file__)
|
||||||
|
_all_found_plugins = None # type: Optional[Dict[str, dict]]
|
||||||
|
|
||||||
@profiler
|
@profiler
|
||||||
def __init__(self, config: SimpleConfig, gui_name):
|
def __init__(self, config: SimpleConfig, gui_name):
|
||||||
DaemonThread.__init__(self)
|
DaemonThread.__init__(self)
|
||||||
self.name = 'Plugins' # set name of thread
|
self.name = 'Plugins' # set name of thread
|
||||||
self.pkgpath = os.path.dirname(plugins.__file__)
|
|
||||||
self.config = config
|
self.config = config
|
||||||
self.hw_wallets = {}
|
self.hw_wallets = {}
|
||||||
self.plugins = {} # type: Dict[str, BasePlugin]
|
self.plugins = {} # type: Dict[str, BasePlugin]
|
||||||
@@ -72,21 +73,33 @@ class Plugins(DaemonThread):
|
|||||||
self.add_jobs(self.device_manager.thread_jobs())
|
self.add_jobs(self.device_manager.thread_jobs())
|
||||||
self.start()
|
self.start()
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def find_all_plugins(cls) -> Mapping[str, dict]:
|
||||||
|
"""Return a map of all found plugins: name -> description.
|
||||||
|
Note that plugins not available for the current GUI are also included.
|
||||||
|
"""
|
||||||
|
if cls._all_found_plugins is None:
|
||||||
|
cls._all_found_plugins = dict()
|
||||||
|
for loader, name, ispkg in pkgutil.iter_modules([cls.pkgpath]):
|
||||||
|
full_name = f'electrum.plugins.{name}'
|
||||||
|
spec = importlib.util.find_spec(full_name)
|
||||||
|
if spec is None: # pkgutil found it but importlib can't ?!
|
||||||
|
raise Exception(f"Error pre-loading {full_name}: no spec")
|
||||||
|
try:
|
||||||
|
module = importlib.util.module_from_spec(spec)
|
||||||
|
# sys.modules needs to be modified for relative imports to work
|
||||||
|
# see https://stackoverflow.com/a/50395128
|
||||||
|
sys.modules[spec.name] = module
|
||||||
|
spec.loader.exec_module(module)
|
||||||
|
except Exception as e:
|
||||||
|
raise Exception(f"Error pre-loading {full_name}: {repr(e)}") from e
|
||||||
|
d = module.__dict__
|
||||||
|
assert name not in cls._all_found_plugins
|
||||||
|
cls._all_found_plugins[name] = d
|
||||||
|
return cls._all_found_plugins
|
||||||
|
|
||||||
def load_plugins(self):
|
def load_plugins(self):
|
||||||
for loader, name, ispkg in pkgutil.iter_modules([self.pkgpath]):
|
for name, d in self.find_all_plugins().items():
|
||||||
full_name = f'electrum.plugins.{name}'
|
|
||||||
spec = importlib.util.find_spec(full_name)
|
|
||||||
if spec is None: # pkgutil found it but importlib can't ?!
|
|
||||||
raise Exception(f"Error pre-loading {full_name}: no spec")
|
|
||||||
try:
|
|
||||||
module = importlib.util.module_from_spec(spec)
|
|
||||||
# sys.modules needs to be modified for relative imports to work
|
|
||||||
# see https://stackoverflow.com/a/50395128
|
|
||||||
sys.modules[spec.name] = module
|
|
||||||
spec.loader.exec_module(module)
|
|
||||||
except Exception as e:
|
|
||||||
raise Exception(f"Error pre-loading {full_name}: {repr(e)}") from e
|
|
||||||
d = module.__dict__
|
|
||||||
gui_good = self.gui_name in d.get('available_for', [])
|
gui_good = self.gui_name in d.get('available_for', [])
|
||||||
if not gui_good:
|
if not gui_good:
|
||||||
continue
|
continue
|
||||||
|
|||||||
Reference in New Issue
Block a user