A faster implementation for the `inspect.get_*` methods.

Plugin/backend lookup is now done by inspecting the manifest files
instead of searching all the subpackages.
This commit is contained in:
Fabio Manganiello 2023-05-13 13:44:46 +02:00
parent 72797e73ff
commit 3c83e7f412
Signed by: blacklight
GPG Key ID: D90FBA7F76362774
1 changed files with 29 additions and 55 deletions

View File

@ -1,20 +1,16 @@
import importlib import importlib
import inspect import inspect
import json import json
import pkgutil
import threading import threading
from typing import Optional from typing import Optional
import platypush.backend # lgtm [py/import-and-import-from]
import platypush.plugins # lgtm [py/import-and-import-from]
import platypush.message.event # lgtm [py/import-and-import-from]
import platypush.message.response # lgtm [py/import-and-import-from]
from platypush.backend import Backend from platypush.backend import Backend
from platypush.config import Config from platypush.config import Config
from platypush.plugins import Plugin, action from platypush.plugins import Plugin, action
from platypush.message.event import Event from platypush.message.event import Event
from platypush.message.response import Response from platypush.message.response import Response
from platypush.utils import get_plugin_class_by_name
from platypush.utils.manifest import Manifest, scan_manifests
from ._model import ( from ._model import (
BackendModel, BackendModel,
@ -42,40 +38,36 @@ class InspectPlugin(Plugin):
self._responses_lock = threading.RLock() self._responses_lock = threading.RLock()
self._html_doc = False self._html_doc = False
def _init_plugins(self): def _get_modules(self, parent_class: type):
package = platypush.plugins for mf_file in scan_manifests(parent_class):
prefix = package.__name__ + '.' manifest = Manifest.from_file(mf_file)
for _, modname, _ in pkgutil.walk_packages(
path=package.__path__, prefix=prefix, onerror=lambda _: None
):
try: try:
module = importlib.import_module(modname) yield importlib.import_module(manifest.package)
except Exception as e: except Exception as e:
self.logger.warning('Could not import module %s: %s', modname, e) self.logger.debug(
'Could not import module %s: %s',
manifest.package,
e,
)
continue continue
for _, obj in inspect.getmembers(module): def _init_plugins(self):
if inspect.isclass(obj) and issubclass(obj, Plugin): prefix = Plugin.__module__ + '.'
model = PluginModel(
plugin=obj, prefix=prefix, html_doc=self._html_doc for module in self._get_modules(Plugin):
) plugin_name = '.'.join(module.__name__.split('.')[2:])
if model.name: plugin_class = get_plugin_class_by_name(plugin_name)
self._plugins[model.name] = model model = PluginModel(
plugin=plugin_class, prefix=prefix, html_doc=self._html_doc
)
if model.name:
self._plugins[model.name] = model
def _init_backends(self): def _init_backends(self):
package = platypush.backend prefix = Backend.__module__ + '.'
prefix = package.__name__ + '.'
for _, modname, _ in pkgutil.walk_packages(
path=package.__path__, prefix=prefix, onerror=lambda _: None
):
try:
module = importlib.import_module(modname)
except Exception as e:
self.logger.debug('Could not import module %s: %s', modname, e)
continue
for module in self._get_modules(Backend):
for _, obj in inspect.getmembers(module): for _, obj in inspect.getmembers(module):
if inspect.isclass(obj) and issubclass(obj, Backend): if inspect.isclass(obj) and issubclass(obj, Backend):
model = BackendModel( model = BackendModel(
@ -85,18 +77,9 @@ class InspectPlugin(Plugin):
self._backends[model.name] = model self._backends[model.name] = model
def _init_events(self): def _init_events(self):
package = platypush.message.event prefix = Event.__module__ + '.'
prefix = package.__name__ + '.'
for _, modname, _ in pkgutil.walk_packages(
path=package.__path__, prefix=prefix, onerror=lambda _: None
):
try:
module = importlib.import_module(modname)
except Exception as e:
self.logger.debug('Could not import module %s: %s', modname, e)
continue
for module in self._get_modules(Event):
for _, obj in inspect.getmembers(module): for _, obj in inspect.getmembers(module):
if type(obj) == Event: # pylint: disable=unidiomatic-typecheck if type(obj) == Event: # pylint: disable=unidiomatic-typecheck
continue continue
@ -111,18 +94,9 @@ class InspectPlugin(Plugin):
self._events[event.package][event.name] = event self._events[event.package][event.name] = event
def _init_responses(self): def _init_responses(self):
package = platypush.message.response prefix = Response.__module__ + '.'
prefix = package.__name__ + '.'
for _, modname, _ in pkgutil.walk_packages(
path=package.__path__, prefix=prefix, onerror=lambda _: None
):
try:
module = importlib.import_module(modname)
except Exception as e:
self.logger.debug('Could not import module %s: %s', modname, e)
continue
for module in self._get_modules(Response):
for _, obj in inspect.getmembers(module): for _, obj in inspect.getmembers(module):
if type(obj) == Response: # pylint: disable=unidiomatic-typecheck if type(obj) == Response: # pylint: disable=unidiomatic-typecheck
continue continue