0
0
mirror of https://github.com/bec-project/bec_widgets.git synced 2025-07-14 03:31:50 +02:00

WIP change super init for all widgets

This commit is contained in:
2025-04-07 15:43:34 +02:00
parent 4c857d9f54
commit b3beb1375e
44 changed files with 95 additions and 100 deletions

View File

@ -19,9 +19,8 @@ MODULE_PATH = os.path.dirname(bec_widgets.__file__)
class LaunchWindow(BECWidget, QMainWindow):
def __init__(self, gui_id: str = None, *args, **kwargs):
BECWidget.__init__(self, gui_id=gui_id, **kwargs)
QMainWindow.__init__(self, *args, **kwargs)
def __init__(self, parent=None, gui_id: str = None, *args, **kwargs):
super().__init__(parent=parent, gui_id=gui_id, **kwargs)
self.app = QApplication.instance()

View File

@ -88,7 +88,9 @@ class BECConnector:
parent_id: str | None = None,
**kwargs,
):
super().__init__(**kwargs)
# Ensure the parent is always kwargs!
parent = kwargs.pop("parent", None)
super().__init__(parent=parent, **kwargs)
# BEC related connections
self.bec_dispatcher = BECDispatcher(client=client)
self.client = self.bec_dispatcher.client if client is None else client

View File

@ -4,6 +4,7 @@ from typing import TYPE_CHECKING, Any
import darkdetect
from bec_lib.logger import bec_logger
from PySide6.QtCore import QObject
from qtpy.QtCore import Slot
from qtpy.QtWidgets import QApplication, QWidget
@ -64,7 +65,7 @@ class BECWidget(BECConnector):
parent_id=parent_id,
**kwargs,
)
if not isinstance(self, QWidget):
if not isinstance(self, QObject):
raise RuntimeError(f"{repr(self)} is not a subclass of QWidget")
app = QApplication.instance()
if not hasattr(app, "theme"):

View File

@ -22,10 +22,10 @@ class PaletteViewer(BECWidget, QWidget):
"""
ICON_NAME = "palette"
RPC = False
def __init__(self, *args, parent=None, **kwargs):
super().__init__(*args, theme_update=True, **kwargs)
QWidget.__init__(self, parent=parent)
super().__init__(parent=parent, **kwargs)
self.setFixedSize(400, 600)
layout = QVBoxLayout(self)
dark_mode_button = DarkModeButton(self)

View File

@ -148,11 +148,10 @@ class BECDock(BECWidget, Dock):
if isinstance(config, dict):
config = DockConfig(**config)
self.config = config
super().__init__(
client=client, config=config, gui_id=gui_id, name=name, parent_id=parent_id
) # Name was checked and created in BEC Widget
label = CustomDockLabel(text=name, closable=closable)
Dock.__init__(self, name=name, label=label, parent=self, **kwargs)
super().__init__(
parent=parent, client=client, gui_id=gui_id, config=config, label=label, **kwargs
)
# Dock.__init__(self, name=name, **kwargs)
self.parent_dock_area = parent_dock_area

View File

@ -82,8 +82,7 @@ class BECDockArea(BECWidget, QWidget):
if isinstance(config, dict):
config = DockAreaConfig(**config)
self.config = config
super().__init__(client=client, config=config, gui_id=gui_id, name=name, **kwargs)
QWidget.__init__(self, parent=parent)
super().__init__(parent=parent, client=client, gui_id=gui_id, config=config, **kwargs)
self._parent = parent
self.layout = QVBoxLayout(self)
self.layout.setSpacing(5)

View File

@ -20,9 +20,8 @@ logger = bec_logger.logger
class BECMainWindow(BECWidget, QMainWindow):
def __init__(self, gui_id: str = None, *args, **kwargs):
BECWidget.__init__(self, gui_id=gui_id, **kwargs)
QMainWindow.__init__(self, *args, **kwargs)
def __init__(self, parent=None, gui_id: str = None, *args, **kwargs):
super().__init__(parent=parent, gui_id=gui_id, **kwargs)
self.app = QApplication.instance()

View File

@ -11,6 +11,7 @@ class AbortButton(BECWidget, QWidget):
PLUGIN = True
ICON_NAME = "cancel"
RPC = False
def __init__(
self,
@ -22,9 +23,7 @@ class AbortButton(BECWidget, QWidget):
scan_id=None,
**kwargs,
):
super().__init__(client=client, config=config, gui_id=gui_id, **kwargs)
QWidget.__init__(self, parent=parent)
super().__init__(parent=parent, client=client, gui_id=gui_id, config=config, **kwargs)
self.get_bec_shortcuts()
self.layout = QHBoxLayout(self)

View File

@ -11,11 +11,10 @@ class ResetButton(BECWidget, QWidget):
PLUGIN = True
ICON_NAME = "restart_alt"
RPC = False
def __init__(self, parent=None, client=None, config=None, gui_id=None, toolbar=False, **kwargs):
super().__init__(client=client, config=config, gui_id=gui_id, **kwargs)
QWidget.__init__(self, parent=parent)
super().__init__(parent=parent, client=client, gui_id=gui_id, config=config, **kwargs)
self.get_bec_shortcuts()
self.layout = QHBoxLayout(self)

View File

@ -11,10 +11,10 @@ class ResumeButton(BECWidget, QWidget):
PLUGIN = True
ICON_NAME = "resume"
RPC = False
def __init__(self, parent=None, client=None, config=None, gui_id=None, toolbar=False, **kwargs):
super().__init__(client=client, config=config, gui_id=gui_id, **kwargs)
QWidget.__init__(self, parent=parent)
super().__init__(parent=parent, client=client, gui_id=gui_id, config=config, **kwargs)
self.get_bec_shortcuts()

View File

@ -11,10 +11,10 @@ class StopButton(BECWidget, QWidget):
PLUGIN = True
ICON_NAME = "dangerous"
RPC = False
def __init__(self, parent=None, client=None, config=None, gui_id=None, toolbar=False, **kwargs):
super().__init__(client=client, config=config, gui_id=gui_id, **kwargs)
QWidget.__init__(self, parent=parent)
super().__init__(parent=parent, client=client, gui_id=gui_id, config=config, **kwargs)
self.get_bec_shortcuts()

View File

@ -13,8 +13,8 @@ class PositionIndicator(BECWidget, QWidget):
ICON_NAME = "horizontal_distribute"
def __init__(self, parent=None, client=None, config=None, gui_id=None, **kwargs):
super().__init__(client=client, config=config, gui_id=gui_id, **kwargs)
QWidget.__init__(self, parent=parent)
super().__init__(parent=parent, client=client, gui_id=gui_id, config=config, **kwargs)
self.position = 50
self.min_value = 0
self.max_value = 100

View File

@ -47,6 +47,7 @@ class PositionerBoxBase(BECWidget, CompactPopupWidget):
current_path = ""
ICON_NAME = "switch_right"
RPC = False
def __init__(self, parent=None, **kwargs):
"""Initialize the PositionerBox widget.
@ -55,8 +56,7 @@ class PositionerBoxBase(BECWidget, CompactPopupWidget):
parent: The parent widget.
device (Positioner): The device to control.
"""
super().__init__(**kwargs)
CompactPopupWidget.__init__(self, parent=parent, layout=QVBoxLayout)
super().__init__(parent=parent, layout=QVBoxLayout, **kwargs)
self._dialog = None
self.get_bec_shortcuts()

View File

@ -69,8 +69,7 @@ class PositionerGroup(BECWidget, QWidget):
Args:
parent: The parent widget.
"""
super().__init__(**kwargs)
QWidget.__init__(self, parent)
super().__init__(parent=parent, **kwargs)
self.get_bec_shortcuts()

View File

@ -29,6 +29,7 @@ class DeviceSignalInputBase(BECWidget):
signal object based on the current text of the widget.
"""
RPC = False
_filter_handler = {
Kind.hinted: "include_hinted_signals",
Kind.normal: "include_normal_signals",

View File

@ -47,8 +47,7 @@ class DeviceComboBox(DeviceInputBase, QComboBox):
arg_name: str | None = None,
**kwargs,
):
super().__init__(client=client, config=config, gui_id=gui_id, **kwargs)
QComboBox.__init__(self, parent=parent)
super().__init__(parent=parent, client=client, gui_id=gui_id, config=config, **kwargs)
if arg_name is not None:
self.config.arg_name = arg_name
self.arg_name = arg_name

View File

@ -53,8 +53,7 @@ class DeviceLineEdit(DeviceInputBase, QLineEdit):
self._callback_id = None
self._is_valid_input = False
self._accent_colors = get_accent_colors()
super().__init__(client=client, config=config, gui_id=gui_id, **kwargs)
QLineEdit.__init__(self, parent=parent)
super().__init__(parent=parent, client=client, gui_id=gui_id, config=config, **kwargs)
self.completer = QCompleter(self)
self.setCompleter(self.completer)

View File

@ -40,8 +40,7 @@ class SignalComboBox(DeviceSignalInputBase, QComboBox):
arg_name: str | None = None,
**kwargs,
):
super().__init__(client=client, config=config, gui_id=gui_id, **kwargs)
QComboBox.__init__(self, parent=parent)
super().__init__(parent=parent, client=client, gui_id=gui_id, config=config, **kwargs)
if arg_name is not None:
self.config.arg_name = arg_name
self.arg_name = arg_name

View File

@ -42,8 +42,7 @@ class SignalLineEdit(DeviceSignalInputBase, QLineEdit):
**kwargs,
):
self._is_valid_input = False
super().__init__(client=client, config=config, gui_id=gui_id, **kwargs)
QLineEdit.__init__(self, parent=parent)
super().__init__(parent=parent, client=client, gui_id=gui_id, config=config, **kwargs)
self._accent_colors = get_accent_colors()
self.completer = QCompleter(self)
self.setCompleter(self.completer)

View File

@ -65,8 +65,7 @@ class ScanControl(BECWidget, QWidget):
config = ScanControlConfig(
widget_class=self.__class__.__name__, allowed_scans=allowed_scans
)
super().__init__(client=client, gui_id=gui_id, config=config, **kwargs)
QWidget.__init__(self, parent=parent)
super().__init__(parent=parent, client=client, gui_id=gui_id, config=config, **kwargs)
self._hide_add_remove_buttons = False

View File

@ -44,8 +44,7 @@ class DapComboBox(BECWidget, QWidget):
default_fit: str | None = None,
**kwargs,
):
super().__init__(client=client, gui_id=gui_id, **kwargs)
QWidget.__init__(self, parent=parent)
super().__init__(parent=parent, client=client, gui_id=gui_id, **kwargs)
self.layout = QVBoxLayout(self)
self.fit_model_combobox = QComboBox(self)
self.layout.addWidget(self.fit_model_combobox)

View File

@ -17,6 +17,7 @@ class LMFitDialog(BECWidget, QWidget):
PLUGIN = True
ICON_NAME = "monitoring"
RPC = False
# Signal to emit the currently selected fit curve_id
selected_fit = Signal(str)
# Signal to emit a move action in form of a tuple (param_name, value)
@ -43,8 +44,7 @@ class LMFitDialog(BECWidget, QWidget):
gui_id (str): GUI ID.
ui_file (str): The UI file to be loaded.
"""
super().__init__(client=client, config=config, gui_id=gui_id, **kwargs)
QWidget.__init__(self, parent=parent)
super().__init__(parent=parent, client=client, gui_id=gui_id, config=config, **kwargs)
self.setProperty("skip_settings", True)
self.setObjectName("LMFitDialog")
self._ui_file = ui_file

View File

@ -42,6 +42,7 @@ class ScanMetadata(BECWidget, QWidget):
metadata_updated = Signal(dict)
metadata_cleared = Signal(NoneType)
RPC = False
def __init__(
self,
@ -51,8 +52,7 @@ class ScanMetadata(BECWidget, QWidget):
initial_extras: list[list[str]] | None = None,
**kwargs,
):
super().__init__(client=client, **kwargs)
QWidget.__init__(self, parent=parent)
super().__init__(parent=parent, client=client, **kwargs)
self.set_schema(scan_name)

View File

@ -49,8 +49,7 @@ class TextBox(BECWidget, QWidget):
if isinstance(config, dict):
config = TextBoxConfig(**config)
self.config = config
super().__init__(client=client, config=config, gui_id=gui_id, **kwargs)
QWidget.__init__(self, parent)
super().__init__(parent=parent, client=client, gui_id=gui_id, config=config, **kwargs)
self.layout = QVBoxLayout(self)
self.text_box_text_edit = QTextEdit(parent=self)
self.layout.addWidget(self.text_box_text_edit)

View File

@ -26,8 +26,7 @@ class WebsiteWidget(BECWidget, QWidget):
def __init__(
self, parent=None, url: str = None, config=None, client=None, gui_id=None, **kwargs
):
super().__init__(client=client, config=config, gui_id=gui_id, **kwargs)
QWidget.__init__(self, parent=parent)
super().__init__(parent=parent, client=client, gui_id=gui_id, config=config, **kwargs)
layout = QVBoxLayout()
layout.setContentsMargins(0, 0, 0, 0)
self.website = QWebEngineView()

View File

@ -144,10 +144,10 @@ class Minesweeper(BECWidget, QWidget):
PLUGIN = True
ICON_NAME = "videogame_asset"
USER_ACCESS = []
RPC = False
def __init__(self, parent=None, *args, **kwargs):
super().__init__(*args, **kwargs)
QWidget.__init__(self, parent=parent)
super().__init__(parent=parent, *args, **kwargs)
self._ui_initialised = False
self._timer_start_num_seconds = 0

View File

@ -82,11 +82,11 @@ class ImageItem(BECConnector, pg.ImageItem):
self.config = config
else:
self.config = config
self.parent_image = parent_image
self.parent_id = self.parent_image.gui_id
super().__init__(config=config, gui_id=gui_id)
pg.ImageItem.__init__(self)
self.parent_image = parent_image
self.raw_data = None
self.buffer = []
self.max_len = 0
@ -94,6 +94,9 @@ class ImageItem(BECConnector, pg.ImageItem):
# Image processor will handle any setting of data
self._image_processor = ImageProcessor(config=self.config.processing)
def parent(self):
return self.parent_image
def set_data(self, data: np.ndarray):
self.raw_data = data
self._process_image()

View File

@ -74,11 +74,9 @@ class PlotBase(BECWidget, QWidget):
) -> None:
if config is None:
config = ConnectionConfig(widget_class=self.__class__.__name__)
super().__init__(client=client, gui_id=gui_id, config=config, **kwargs)
QWidget.__init__(self, parent=parent)
super().__init__(parent=parent, client=client, gui_id=gui_id, config=config, **kwargs)
# For PropertyManager identification
self.setObjectName("PlotBase")
self.get_bec_shortcuts()
# Layout Management
@ -1018,7 +1016,7 @@ if __name__ == "__main__": # pragma: no cover:
from qtpy.QtWidgets import QApplication
app = QApplication(sys.argv)
window = DemoPlotBase()
window = PlotBase()
window.show()
sys.exit(app.exec_())

View File

@ -77,13 +77,16 @@ class ScatterCurve(BECConnector, pg.PlotDataItem):
else:
self.config = config
name = config.label
super().__init__(config=config, gui_id=gui_id)
pg.PlotDataItem.__init__(self, name=name)
self.parent_item = parent_item
self.parent_id = self.parent_item.gui_id
super().__init__(name=name, config=config, gui_id=gui_id, **kwargs)
self.data_z = None # color scaling needs to be cashed for changing colormap
self.apply_config()
def parent(self):
return self.parent_item
def apply_config(self, config: dict | ScatterCurveConfig | None = None, **kwargs) -> None:
"""
Apply the configuration to the curve.

View File

@ -92,8 +92,7 @@ class Curve(BECConnector, pg.PlotDataItem):
self.config = config
self.parent_item = parent_item
self.parent_id = self.parent_item.gui_id
super().__init__(config=config, gui_id=gui_id)
pg.PlotDataItem.__init__(self, name=name)
super().__init__(name=name, config=config, gui_id=gui_id, **kwargs)
self.apply_config()
self.dap_params = None

View File

@ -334,11 +334,11 @@ class CurveTree(BECWidget, QWidget):
client=None,
gui_id: str | None = None,
waveform: Waveform | None = None,
**kwargs,
) -> None:
if config is None:
config = ConnectionConfig(widget_class=self.__class__.__name__)
super().__init__(client=client, gui_id=gui_id, config=config)
QWidget.__init__(self, parent=parent)
super().__init__(parent=parent, client=client, gui_id=gui_id, config=config, **kwargs)
self.waveform = waveform
if self.waveform and hasattr(self.waveform, "color_palette"):

View File

@ -26,7 +26,7 @@ from bec_widgets.utils.colors import Colors, set_theme
from bec_widgets.utils.error_popups import SafeProperty, SafeSlot
from bec_widgets.utils.settings_dialog import SettingsDialog
from bec_widgets.utils.toolbar import MaterialIconAction
from bec_widgets.widgets.containers.main_window.main_window import BECMainWindow
from bec_widgets.utils.widget_io import WidgetHierarchy
from bec_widgets.widgets.dap.lmfit_dialog.lmfit_dialog import LMFitDialog
from bec_widgets.widgets.plots.plot_base import PlotBase
from bec_widgets.widgets.plots.waveform.curve import Curve, CurveConfig, DeviceSignal
@ -1597,12 +1597,12 @@ class Waveform(PlotBase):
super().cleanup()
class DemoApp(BECMainWindow): # pragma: no cover
class DemoApp(QMainWindow): # pragma: no cover
def __init__(self):
super().__init__()
self.setWindowTitle("Waveform Demo")
self.resize(800, 600)
self.main_widget = QWidget()
self.main_widget = QWidget(self)
self.layout = QHBoxLayout(self.main_widget)
self.setCentralWidget(self.main_widget)
@ -1613,16 +1613,27 @@ class DemoApp(BECMainWindow): # pragma: no cover
self.waveform_side.plot(y_name="bpm4i", y_entry="bpm4i", dap="GaussianModel")
self.waveform_side.plot(y_name="bpm3a", y_entry="bpm3a")
self.hierarchy_button = QPushButton()
self.hierarchy_button.setText("Hierarchy")
self.hierarchy_button.clicked.connect(self.hierarchy)
self.layout.addWidget(self.waveform_side)
self.layout.addWidget(self.waveform_popup)
self.layout.addWidget(self.hierarchy_button)
def hierarchy(self):
print("getting app")
WidgetHierarchy.print_becconnector_hierarchy_from_app() # , only_bec_widgets=True)
print("Waveform popup")
print(self.waveform_popup.objectName())
print("Waveform side")
print(self.waveform_side.objectName())
if __name__ == "__main__": # pragma: no cover
import sys
from bec_widgets.utils.bec_qapp import BECApplication
app = BECApplication(sys.argv)
app = QApplication(sys.argv)
set_theme("dark")
widget = DemoApp()
widget.show()

View File

@ -25,8 +25,7 @@ class BECProgressBar(BECWidget, QWidget):
ICON_NAME = "page_control"
def __init__(self, parent=None, client=None, config=None, gui_id=None, **kwargs):
super().__init__(client=client, config=config, gui_id=gui_id, **kwargs)
QWidget.__init__(self, parent=parent)
super().__init__(parent=parent, client=client, gui_id=gui_id, config=config, **kwargs)
accent_colors = get_accent_colors()

View File

@ -6,6 +6,7 @@ from bec_lib.endpoints import EndpointInfo, MessageEndpoints
from pydantic import BaseModel, Field, field_validator
from pydantic_core import PydanticCustomError
from qtpy import QtGui
from qtpy.QtCore import QObject
from bec_widgets.utils import BECConnector, ConnectionConfig
@ -77,7 +78,7 @@ class RingConfig(ProgressbarConfig):
)
class Ring(BECConnector):
class Ring(BECConnector, QObject):
USER_ACCESS = [
"_get_all_rpc",
"_rpc_id",
@ -108,7 +109,7 @@ class Ring(BECConnector):
if isinstance(config, dict):
config = RingConfig(**config)
self.config = config
super().__init__(client=client, config=config, gui_id=gui_id, **kwargs)
super().__init__(parent=parent, client=client, config=config, gui_id=gui_id, **kwargs)
self.parent_progress_widget = parent_progress_widget
self.color = None

View File

@ -110,8 +110,7 @@ class RingProgressBar(BECWidget, QWidget):
if isinstance(config, dict):
config = RingProgressBarConfig(**config, widget_class=self.__class__.__name__)
self.config = config
super().__init__(client=client, config=config, gui_id=gui_id, **kwargs)
QWidget.__init__(self, parent=parent)
super().__init__(parent=parent, client=client, gui_id=gui_id, config=config, **kwargs)
self.get_bec_shortcuts()
self.entry_validator = EntryValidator(self.dev)

View File

@ -44,8 +44,9 @@ class BECQueue(BECWidget, CompactPopupWidget):
refresh_upon_start: bool = True,
**kwargs,
):
super().__init__(client=client, config=config, gui_id=gui_id, **kwargs)
CompactPopupWidget.__init__(self, parent=parent, layout=QVBoxLayout)
super().__init__(
parent=parent, layout=QVBoxLayout, client=client, gui_id=gui_id, config=config, **kwargs
)
self.layout.setSpacing(0)
self.layout.setContentsMargins(0, 0, 0, 0)

View File

@ -89,8 +89,7 @@ class BECStatusBox(BECWidget, CompactPopupWidget):
gui_id: str = None,
**kwargs,
):
super().__init__(client=client, gui_id=gui_id, **kwargs)
CompactPopupWidget.__init__(self, parent=parent, layout=QHBoxLayout)
super().__init__(parent=parent, layout=QHBoxLayout, client=client, gui_id=gui_id, **kwargs)
self.box_name = box_name
self.status_container = defaultdict(lambda: {"info": None, "item": None, "widget": None})

View File

@ -25,8 +25,7 @@ class DeviceBrowser(BECWidget, QWidget):
gui_id: Optional[str] = None,
**kwargs,
) -> None:
super().__init__(client=client, config=config, gui_id=gui_id, **kwargs)
QWidget.__init__(self, parent)
super().__init__(parent=parent, client=client, gui_id=gui_id, config=config, **kwargs)
self.get_bec_shortcuts()
self.ui = None

View File

@ -30,8 +30,7 @@ class BECSpinBox(BECWidget, QDoubleSpinBox):
) -> None:
if config is None:
config = ConnectionConfig(widget_class=self.__class__.__name__)
super().__init__(client=client, gui_id=gui_id, config=config, **kwargs)
QDoubleSpinBox.__init__(self, parent=parent)
super().__init__(parent=parent, client=client, gui_id=gui_id, config=config, **kwargs)
self.setObjectName("BECSpinBox")
# Make the widget as compact as possible horizontally.

View File

@ -9,13 +9,11 @@ from bec_widgets.utils.bec_widget import BECWidget
class BECColorMapWidget(BECWidget, QWidget):
colormap_changed_signal = Signal(str)
ICON_NAME = "palette"
USER_ACCESS = ["colormap"]
PLUGIN = True
RPC = False
def __init__(self, parent=None, cmap: str = "magma", **kwargs):
super().__init__(**kwargs)
QWidget.__init__(self, parent=parent)
super().__init__(parent=parent, **kwargs)
# Create the ColorMapButton
self.button = ColorMapButton()

View File

@ -22,8 +22,7 @@ class DarkModeButton(BECWidget, QWidget):
toolbar: bool = False,
**kwargs,
) -> None:
super().__init__(client=client, gui_id=gui_id, theme_update=True, **kwargs)
QWidget.__init__(self, parent)
super().__init__(parent=parent, client=client, gui_id=gui_id, theme_update=True, **kwargs)
self._dark_mode_enabled = False
self.layout = QHBoxLayout(self)

View File

@ -130,11 +130,11 @@ class ExamplePlotWidget(BECWidget, QWidget):
config: ConnectionConfig | None = None,
client=None,
gui_id: str | None = None,
**kwargs,
) -> None:
if config is None:
config = ConnectionConfig(widget_class=self.__class__.__name__)
super().__init__(client=client, gui_id=gui_id, config=config)
QWidget.__init__(self, parent=parent)
super().__init__(parent=parent, client=client, gui_id=gui_id, config=config, **kwargs)
self.layout = QVBoxLayout(self)
self.glw = pg.GraphicsLayoutWidget()

View File

@ -17,9 +17,8 @@ from .conftest import create_widget
class DeviceInputWidget(DeviceInputBase, QWidget):
"""Thin wrapper around DeviceInputBase to make it a QWidget"""
def __init__(self, parent=None, client=None, config=None, gui_id=None):
super().__init__(client=client, config=config, gui_id=gui_id)
QWidget.__init__(self, parent=parent)
def __init__(self, parent=None, client=None, config=None, gui_id=None, **kwargs):
super().__init__(parent=parent, client=client, gui_id=gui_id, config=config, **kwargs)
@pytest.fixture

View File

@ -22,8 +22,7 @@ class DeviceInputWidget(DeviceSignalInputBase, QWidget):
"""Thin wrapper around DeviceInputBase to make it a QWidget"""
def __init__(self, parent=None, client=None, config=None, gui_id=None):
super().__init__(client=client, config=config, gui_id=gui_id)
QWidget.__init__(self, parent=parent)
super().__init__(parent=parent, client=client, gui_id=gui_id, config=config, **kwargs)
@pytest.fixture