0
0
mirror of https://github.com/bec-project/bec_widgets.git synced 2025-07-13 19:21:50 +02:00

fix(plugins): fixes and tests for auto-gen plugins

This commit is contained in:
2024-06-28 13:49:12 +02:00
parent db62f9e998
commit c42511dd44
2 changed files with 170 additions and 14 deletions

View File

@ -47,13 +47,12 @@ class DesignerPluginGenerator:
def __init__(self, widget: type):
self._excluded = False
self.widget = widget
self.info = DesignerPluginInfo(widget)
if widget.__name__ in EXCLUDED_PLUGINS:
self._excluded = True
return
self.info = DesignerPluginInfo(widget)
self.templates = {}
self.template_path = os.path.join(
os.path.dirname(os.path.abspath(__file__)), "plugin_templates"
@ -75,7 +74,7 @@ class DesignerPluginGenerator:
# Check if the widget class has parent as the first argument. This is a strict requirement of Qt!
signature = list(inspect.signature(self.widget.__init__).parameters.values())
if signature[1].name != "parent":
if len(signature) == 1 or signature[1].name != "parent":
raise ValueError(
f"Widget class {self.widget.__name__} must have parent as the first argument."
)
@ -89,20 +88,22 @@ class DesignerPluginGenerator:
# Check if the widget class calls the super constructor with parent argument
init_source = inspect.getsource(self.widget.__init__)
cls_init_found = (
bool(init_source.find(f"{base_cls[0].__name__}.__init__(self, parent=parent"))
or bool(init_source.find(f"{base_cls[0].__name__}.__init__(self, parent)"))
or bool(init_source.find(f"{base_cls[0].__name__}.__init__(self, parent,"))
bool(init_source.find(f"{base_cls[0].__name__}.__init__(self, parent=parent") > 0)
or bool(init_source.find(f"{base_cls[0].__name__}.__init__(self, parent)") > 0)
or bool(init_source.find(f"{base_cls[0].__name__}.__init__(self, parent,") > 0)
)
super_init_found = (
bool(init_source.find(f"super({self.widget.__name__}, self).__init__(parent=parent"))
or bool(init_source.find(f"super({self.widget.__name__}, self).__init__(parent,"))
or bool(init_source.find(f"super({self.widget.__name__}, self).__init__(parent)"))
bool(
init_source.find(f"super({base_cls[0].__name__}, self).__init__(parent=parent") > 0
)
or bool(init_source.find(f"super({base_cls[0].__name__}, self).__init__(parent,") > 0)
or bool(init_source.find(f"super({base_cls[0].__name__}, self).__init__(parent)") > 0)
)
if issubclass(self.widget.__bases__[0], QObject) and super_init_found == -1:
if issubclass(self.widget.__bases__[0], QObject) and not super_init_found:
super_init_found = (
bool(init_source.find("super().__init__(parent=parent"))
or bool(init_source.find("super().__init__(parent,"))
or bool(init_source.find("super().__init__(parent)"))
bool(init_source.find("super().__init__(parent=parent") > 0)
or bool(init_source.find("super().__init__(parent,") > 0)
or bool(init_source.find("super().__init__(parent)") > 0)
)
if not cls_init_found and not super_init_found:
@ -139,7 +140,7 @@ class DesignerPluginGenerator:
self.templates[file.split(".")[0]] = f.read()
if __name__ == "__main__":
if __name__ == "__main__": # pragma: no cover
# from bec_widgets.widgets.bec_queue.bec_queue import BECQueue
from bec_widgets.widgets.dock import BECDockArea

View File

@ -0,0 +1,155 @@
import importlib
import inspect
import os
import sys
import pytest
from bec_widgets.utils.generate_designer_plugin import DesignerPluginGenerator
def load_plugin(dir_path, content, plugin_name="MyWidget"):
plugin_path = dir_path.mkdir("plugin").join("plugin.py")
plugin_path.write(content)
sys.path.append(str(dir_path))
plugin = importlib.import_module("plugin.plugin")
importlib.reload(plugin)
yield getattr(plugin, plugin_name)
sys.path.pop()
@pytest.fixture(
params=[
"""
from qtpy.QtWidgets import QWidget
class MyWidget(QWidget):
def __init__(self, parent=None):
QWidget.__init__(self, parent)
""",
"""
from qtpy.QtWidgets import QWidget
class MyWidget(QWidget):
def __init__(self, parent=None):
QWidget.__init__(self, parent=parent)
""",
"""
from qtpy.QtWidgets import QWidget
class MyWidget(QWidget):
def __init__(self, parent=None):
super().__init__(parent)
""",
"""
from qtpy.QtWidgets import QWidget
class MyWidget(QWidget):
def __init__(self, parent=None):
super().__init__(parent=parent)
""",
"""
from qtpy.QtWidgets import QWidget
class MyWidget(QWidget):
def __init__(self, parent=None):
super(QWidget, self).__init__(parent)"""
"""
from qtpy.QtWidgets import QWidget
class MyWidget(QWidget):
def __init__(self, parent=None):
super(QWidget, self).__init__(parent=parent)
""",
]
)
def plugin_with_correct_parent(tmpdir, request):
yield from load_plugin(tmpdir, request.param)
@pytest.fixture(
params=[
"""
from qtpy.QtWidgets import QWidget
class MyWidget(QWidget):
def __init__(self, parent=None):
QWidget.__init__(self)
""",
"""
from qtpy.QtWidgets import QWidget
class MyWidget(QWidget):
def __init__(self, parent=None):
super().__init__()
""",
"""
from qtpy.QtWidgets import QWidget
class MyWidget(QWidget):
def __init__(self, parent=None):
super(QWidget, self).__init__()
""",
]
)
def plugin_with_missing_parent(tmpdir, request):
yield from load_plugin(tmpdir, request.param)
def test_generate_plugin(plugin_with_correct_parent):
generator = DesignerPluginGenerator(plugin_with_correct_parent)
generator.run()
assert os.path.exists(f"{generator.info.base_path}/register_my_widget.py")
assert os.path.exists(f"{generator.info.base_path}/my_widget_plugin.py")
assert os.path.exists(f"{generator.info.base_path}/my_widget.pyproject")
def test_generate_plugin_with_missing_parent(plugin_with_missing_parent):
with pytest.raises(ValueError) as excinfo:
generator = DesignerPluginGenerator(plugin_with_missing_parent)
generator.run()
assert "Widget class MyWidget must call the super constructor with parent." in str(
excinfo.value
)
@pytest.fixture()
def plugin_with_excluded_widget(tmpdir):
content = """
from qtpy.QtWidgets import QWidget
class BECDock(QWidget):
def __init__(self, parent=None):
QWidget.__init__(self, parent)
"""
yield from load_plugin(tmpdir, content, plugin_name="BECDock")
def test_generate_plugin_with_excluded_widget(plugin_with_excluded_widget, capsys):
generator = DesignerPluginGenerator(plugin_with_excluded_widget)
generator.run()
captured = capsys.readouterr()
assert "Plugin BECDock is excluded from generation." in captured.out
assert not os.path.exists(f"{generator.info.base_path}/register_bec_dock.py")
assert not os.path.exists(f"{generator.info.base_path}/bec_dock_plugin.py")
assert not os.path.exists(f"{generator.info.base_path}/bec_dock.pyproject")
@pytest.fixture(
params=[
"""
from qtpy.QtWidgets import QWidget
class MyWidget(QWidget):
def __init__(self):
QWidget.__init__(self)
""",
"""
from qtpy.QtWidgets import QWidget
class MyWidget(QWidget):
def __init__(self, config, parent=None):
super().__init__()
""",
]
)
def plugin_with_no_parent_as_first_arg(tmpdir, request):
yield from load_plugin(tmpdir, request.param)
def test_generate_plugin_raises_exception_when_first_argument_is_not_parent(
plugin_with_no_parent_as_first_arg,
):
with pytest.raises(ValueError) as excinfo:
generator = DesignerPluginGenerator(plugin_with_no_parent_as_first_arg)
generator.run()
assert "Widget class MyWidget must have parent as the first argument." in str(excinfo.value)