add plugin registry
This commit is contained in:
0
raven/__init__.py
Normal file
0
raven/__init__.py
Normal file
3
raven/pluginbase.py
Normal file
3
raven/pluginbase.py
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
class PluginBase():
|
||||||
|
def __init__(self):
|
||||||
|
pass
|
||||||
55
raven/pluginregistry.py
Normal file
55
raven/pluginregistry.py
Normal file
@@ -0,0 +1,55 @@
|
|||||||
|
from types import ModuleType
|
||||||
|
from typing import Dict
|
||||||
|
from inspect import isclass
|
||||||
|
from pkgutil import iter_modules
|
||||||
|
from pathlib import Path
|
||||||
|
from os.path import dirname
|
||||||
|
from importlib import import_module
|
||||||
|
from raven.pluginbase import PluginBase
|
||||||
|
|
||||||
|
|
||||||
|
class PluginRegistry():
|
||||||
|
plugins: Dict[str, PluginBase] = {}
|
||||||
|
|
||||||
|
modules: [ModuleType] = []
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def register_plugin(name: str, plugin: PluginBase):
|
||||||
|
PluginRegistry.plugins[name] = plugin
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def get_plugins_by_function(function_name: str) -> [PluginBase]:
|
||||||
|
result = []
|
||||||
|
for plugin in PluginRegistry.plugins.values():
|
||||||
|
fun = getattr(plugin, function_name, None)
|
||||||
|
if callable(fun):
|
||||||
|
result.append(plugin)
|
||||||
|
return result
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def load_module(module_name: str) -> ModuleType:
|
||||||
|
module_name = f"plugins.{module_name}"
|
||||||
|
# import the module and iterate through its attributes
|
||||||
|
module = import_module(module_name)
|
||||||
|
PluginRegistry.modules.append(module)
|
||||||
|
return module
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def load_plugin(plugin_name: str):
|
||||||
|
module_name = f"plugins.{plugin_name.lower()}"
|
||||||
|
module = import_module(module_name)
|
||||||
|
if plugin_name in dir(module):
|
||||||
|
plugin_class = getattr(module, plugin_name)
|
||||||
|
|
||||||
|
if isclass(plugin_class) and issubclass(plugin_class, PluginBase):
|
||||||
|
PluginRegistry.register_plugin(plugin_name, plugin_class)
|
||||||
|
print("%s -> %s :: %s in %s" % (plugin_name, plugin_class, module_name, module))
|
||||||
|
return plugin_class
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def get_modules() -> [ModuleType]:
|
||||||
|
return PluginRegistry.modules.copy()
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def get_plugins() -> [ModuleType]:
|
||||||
|
return PluginRegistry.modules.copy()
|
||||||
25
raven/plugins/__init__.py
Normal file
25
raven/plugins/__init__.py
Normal file
@@ -0,0 +1,25 @@
|
|||||||
|
from inspect import isclass
|
||||||
|
from pkgutil import iter_modules
|
||||||
|
from pathlib import Path
|
||||||
|
from importlib import import_module
|
||||||
|
from raven.pluginbase import PluginBase
|
||||||
|
|
||||||
|
# iterate through the modules in the current package
|
||||||
|
from raven.pluginregistry import PluginRegistry
|
||||||
|
|
||||||
|
if False:
|
||||||
|
package_dir = Path(__file__).resolve().parent
|
||||||
|
for (_, module_name, _) in iter_modules([str(package_dir)]):
|
||||||
|
# import the module and iterate through its attributes
|
||||||
|
module = import_module(f"{__name__}.{module_name}")
|
||||||
|
print("module: %s" % module)
|
||||||
|
|
||||||
|
for attribute_name in dir(module):
|
||||||
|
if attribute_name == "PluginBase":
|
||||||
|
continue
|
||||||
|
attribute = getattr(module, attribute_name)
|
||||||
|
|
||||||
|
if isclass(attribute) and issubclass(attribute, PluginBase):
|
||||||
|
globals()[attribute_name] = attribute
|
||||||
|
PluginRegistry.register_plugin(attribute_name, attribute)
|
||||||
|
print("%s -> %s :: %s in %s" % (attribute_name, attribute, module_name, module))
|
||||||
11
raven/plugins/filterplugin.py
Normal file
11
raven/plugins/filterplugin.py
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
from raven.pluginbase import PluginBase
|
||||||
|
|
||||||
|
|
||||||
|
class FilterPlugin(PluginBase):
|
||||||
|
def __init__(self):
|
||||||
|
super(FilterPlugin, self).__init__()
|
||||||
|
print("init FilterPlugin")
|
||||||
|
|
||||||
|
|
||||||
|
def init():
|
||||||
|
print("initializing filter plugin")
|
||||||
7
raven/plugins/logfileviewerplugin.py
Normal file
7
raven/plugins/logfileviewerplugin.py
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
from raven.pluginbase import PluginBase
|
||||||
|
|
||||||
|
|
||||||
|
class LogFileViewerPlugin(PluginBase):
|
||||||
|
def __init__(self):
|
||||||
|
super(LogFileViewerPlugin, self).__init__()
|
||||||
|
print("init LogFileViewerPlugin")
|
||||||
80
raven/ravenlog.py
Normal file
80
raven/ravenlog.py
Normal file
@@ -0,0 +1,80 @@
|
|||||||
|
import ctypes
|
||||||
|
import logging
|
||||||
|
import signal
|
||||||
|
import sys
|
||||||
|
from inspect import isclass
|
||||||
|
from importlib import import_module
|
||||||
|
from pathlib import Path
|
||||||
|
from pkgutil import iter_modules
|
||||||
|
|
||||||
|
from plugins import *
|
||||||
|
|
||||||
|
from PyQt6 import QtCore
|
||||||
|
from PyQt6.QtCore import QTimer
|
||||||
|
from PyQt6.QtGui import QIcon
|
||||||
|
from PyQt6.QtWidgets import QApplication
|
||||||
|
|
||||||
|
import constants
|
||||||
|
from raven.ravenwindow import RavenWindow
|
||||||
|
from ravenui import RavenUI
|
||||||
|
|
||||||
|
logging.basicConfig(level=logging.INFO)
|
||||||
|
log = logging.getLogger("main")
|
||||||
|
|
||||||
|
|
||||||
|
def stop_signal(signum, _stackframe):
|
||||||
|
""" Handle terminate signal """
|
||||||
|
try:
|
||||||
|
log.info("Terminate signal received. %s", signum)
|
||||||
|
QtCore.QCoreApplication.quit()
|
||||||
|
except Exception:
|
||||||
|
log.exception("Exception occurred while terminating")
|
||||||
|
sys.exit(1)
|
||||||
|
sys.exit(0)
|
||||||
|
|
||||||
|
|
||||||
|
def init_signal_handler():
|
||||||
|
# workaround to make signals work in QT apps.
|
||||||
|
# They do not work out of the box, because the main thread
|
||||||
|
# is running in C++ code once app.exec() is executed
|
||||||
|
# Forcing an empty lambda to be executed periodically gives
|
||||||
|
# control back to python and allows python to react to signals
|
||||||
|
timer = QTimer()
|
||||||
|
timer.timeout.connect(lambda: None)
|
||||||
|
timer.start(100)
|
||||||
|
signal.signal(signal.SIGINT, stop_signal)
|
||||||
|
signal.signal(signal.SIGTERM, stop_signal)
|
||||||
|
|
||||||
|
|
||||||
|
def init_translator(app: QApplication):
|
||||||
|
# translator = QTranslator()
|
||||||
|
# if translator.load(QLocale("de"), "messages_de.ts"):
|
||||||
|
# app.installTranslator(translator)
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
def set_window_icon(app: QApplication):
|
||||||
|
app.setWindowIcon(QIcon("../" + constants.raven_icon))
|
||||||
|
|
||||||
|
# see https://stackoverflow.com/questions/1551605/how-to-set-applications-taskbar-icon-in-windows-7/1552105#1552105
|
||||||
|
if sys.platform == 'win32' or sys.platform == 'cygwin':
|
||||||
|
ctypes.windll.shell32.SetCurrentProcessExplicitAppUserModelID('opentext.ravenlog')
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
filterplugin = PluginRegistry.load_plugin("FilterPlugin")
|
||||||
|
filterplugin()
|
||||||
|
|
||||||
|
logfileviewerplugin = PluginRegistry.load_plugin("LogFileViewerPlugin")
|
||||||
|
logfileviewerplugin()
|
||||||
|
|
||||||
|
app = QApplication(sys.argv)
|
||||||
|
set_window_icon(app)
|
||||||
|
init_translator(app)
|
||||||
|
init_signal_handler()
|
||||||
|
|
||||||
|
window = RavenWindow()
|
||||||
|
RavenUI.window = window
|
||||||
|
window.show()
|
||||||
|
|
||||||
|
app.exec()
|
||||||
34
raven/ravenwindow.py
Normal file
34
raven/ravenwindow.py
Normal file
@@ -0,0 +1,34 @@
|
|||||||
|
from PyQt6.QtWidgets import QMainWindow, QMenu, QStatusBar
|
||||||
|
|
||||||
|
from cutesettings import CuteSettings
|
||||||
|
from settingsstore import SettingsStore
|
||||||
|
|
||||||
|
|
||||||
|
class RavenWindow(QMainWindow):
|
||||||
|
def __init__(self, *args, **kwargs):
|
||||||
|
super(RavenWindow, self).__init__(*args, **kwargs)
|
||||||
|
|
||||||
|
self.settings = SettingsStore.load()
|
||||||
|
self.setWindowTitle(self.tr("RavenLog"))
|
||||||
|
self._restore_window()
|
||||||
|
|
||||||
|
self.setDockNestingEnabled(True)
|
||||||
|
self.setAcceptDrops(True)
|
||||||
|
|
||||||
|
# self.tabs = Tabs(self.settings)
|
||||||
|
|
||||||
|
# self._menu_recent_files = QMenu(self.tr("Open &Recent"), self)
|
||||||
|
|
||||||
|
# self.setCentralWidget(self.tabs)
|
||||||
|
# self.status_bar = QStatusBar(self)
|
||||||
|
# self.setStatusBar(self.status_bar)
|
||||||
|
# self.setMenuBar(self.create_menu_bar())
|
||||||
|
|
||||||
|
def _restore_window(self):
|
||||||
|
qsettings = CuteSettings()
|
||||||
|
geometry_restored = False
|
||||||
|
geometry = qsettings.value("mainWindow/geometry")
|
||||||
|
if geometry:
|
||||||
|
geometry_restored = self.restoreGeometry(geometry)
|
||||||
|
if not geometry_restored:
|
||||||
|
self.setGeometry(0, 0, 800, 600)
|
||||||
Reference in New Issue
Block a user