diff --git a/examples/ApplicationConfig.py b/examples/ApplicationConfig.py index a867f4bf0463ddd6bdf545ba70994fbd4c07ecd1..0ce64ed6bdd34f0fbd1741ec1bc432f10b1f5e62 100644 --- a/examples/ApplicationConfig.py +++ b/examples/ApplicationConfig.py @@ -8,8 +8,8 @@ from LaserConfig import LaserConfig class ApplicationConfig(cfg.ConfigNode): - def __init__(self, path="./configs") -> None: - super().__init__(path=path) + def __init__(self, enable_log=True) -> None: + super().__init__(enable_log=enable_log) self.output_directory: cfg.Field[Path] = cfg.Field(Path("C:\\{wafer_nr}"), friendly_name="Output Directory", @@ -39,7 +39,7 @@ class ApplicationConfig(cfg.ConfigNode): friendly_name="wafer_list", description="The version of the wafer") - self.laser_config: LaserConfig = LaserConfig(path='configs') + self.laser_config: LaserConfig = LaserConfig() self.register() diff --git a/examples/LaserConfig.py b/examples/LaserConfig.py index 3d04c6bec5070f2756eabe4b142fde892a75724e..ce3b5c757fe9ff4442bd5ab63545d1eedfffbc37 100644 --- a/examples/LaserConfig.py +++ b/examples/LaserConfig.py @@ -3,8 +3,8 @@ import confighandler as cfg class LaserConfig(cfg.ConfigNode): - def __init__(self, path=None) -> None: - super().__init__(path=path) + def __init__(self, enable_log=False) -> None: + super().__init__(enable_log=enable_log) self.wavelength_range = cfg.Field(850) self.velocity = cfg.Field(2.0) self.acceleration = cfg.Field(1.0) diff --git a/examples/main.py b/examples/main.py index 14e3ec547386a115475696a47a385ec56ae67e27..4eac1a358b386338c2375241928729dd2c6ea680 100644 --- a/examples/main.py +++ b/examples/main.py @@ -18,8 +18,9 @@ if __name__ == "__main__": ] ) - config = ApplicationConfig() - #print(config.load('config.yaml')) + config = ApplicationConfig(enable_log=True) + print(config.load('./configs/ApplicationConfig.yaml')) + config.autosave(enable=True, path='./configs_autosave') #print(config.wafer_version) #config.wafer_version.get() @@ -41,13 +42,13 @@ if __name__ == "__main__": tree.addTopLevelItem(config.view.ui_tree_widget_item(tree)) grd.addWidget(tree, 2, 0) - btn = QtWidgets.QPushButton("Test") - btn.clicked.connect(lambda: config.wafer_nr.set("1234")) - grd.addWidget(btn, 3, 0) + btn_set = QtWidgets.QPushButton("Set Wafer Number to 123") + btn_set.clicked.connect(lambda: config.wafer_nr.set("123")) + grd.addWidget(btn_set, 3, 0) - btn = QtWidgets.QPushButton("Test2") - btn.clicked.connect(lambda: print(config.output_directory.get())) - grd.addWidget(btn, 4, 0) + btn_save = QtWidgets.QPushButton("Save Config") + btn_save.clicked.connect(lambda: config.save('./configs/ApplicationConfig.yaml')) + grd.addWidget(btn_save, 4, 0) window.setCentralWidget(wdg) #print(config.save('config.yaml')) diff --git a/src/confighandler/controller/ConfigNode.py b/src/confighandler/controller/ConfigNode.py index c2c7723ac01920702b3946542ac838c12d0a6d24..9f0d70b277ac9cc990c2045540cee02a03bb8372 100644 --- a/src/confighandler/controller/ConfigNode.py +++ b/src/confighandler/controller/ConfigNode.py @@ -10,6 +10,7 @@ import datetime import logging import yaml +from PySide6.QtWidgets import QMessageBox from .CSignal import CSignal from .Field import Field @@ -23,9 +24,10 @@ class ConfigNode(object): cur_time = datetime.datetime.now() - def __init__(self, path: str = None, enable_log: bool = False): + def __init__(self, enable_log: bool = False): super().__init__() + self._autosave = False self.enable_log = enable_log self.name = self.__class__.__name__ self.logger = logging.getLogger(self.name) @@ -43,14 +45,6 @@ class ConfigNode(object): "date_time": self.cur_time.strftime("%Y%m%d_%H%M") } - if path is None: - self._path = pathlib.Path(".") - else: - self._path = pathlib.Path(path) - # Check if the path exists otherwise create it - if not self._path.exists(): - self._path.mkdir(parents=True, exist_ok=True) - self.field_changed.connect(self._on_field_changed) self.config_logger(enable=self.enable_log) @@ -106,7 +100,7 @@ class ConfigNode(object): def deserialize(self, content): """Deserializes the content of the config based on the yaml file""" - print(f"Deserializing {content}") + self.logger.info(f"Deserializing {content}") for attr, val in content.items(): # Check if the attribute is not of type GenericConfig # therefore get the attribute type of this class @@ -115,19 +109,21 @@ class ConfigNode(object): print(f"Found own config") self.deserialize(val) elif attr in self.__dict__: - field = getattr(self, attr) - if not isinstance(field, ConfigNode): - print(f"Deserializing field {attr} with content: {val}") - field.set(val) + if not isinstance(getattr(self, attr), ConfigNode): + self.logger.info(f"Deserializing field {attr} with content: {val}") + val = getattr(self, attr)._field_parser(val) + getattr(self, attr).set(val) else: - print(f"Deserializing config {attr} with content: {val}") + self.logger.info(f"Deserializing config {attr} with content: {val}") getattr(self, attr).deserialize(val) + + + # ================================================================================================================== # Registering the fields and configs # ================================================================================================================== def register(self): - # print("register") self._register_field() self._register_config() @@ -153,7 +149,9 @@ class ConfigNode(object): # ================================================================================================================== # I/O Operations # ================================================================================================================== - def save(self, file: str, background_save=True): + def save(self, file: str=None, background_save=True): + if file is None: + file = f"{self._path}/{self.__class__.__name__}.yaml" # write the string to a file with open(file, 'w+') as stream: stream.write(self.serialize()) @@ -166,6 +164,17 @@ class ConfigNode(object): # stream.write( # print(self._dump(cfg)) + def autosave(self, enable: bool = False, path: str = None): + self._autosave = enable + if self._autosave: + if path is None: + self._path = pathlib.Path(".") + else: + self._path = pathlib.Path(path) + # Check if the path exists otherwise create it + if not self._path.exists(): + self._path.mkdir(parents=True, exist_ok=True) + def load(self, file: str): # load the yaml file with open(file, 'r') as stream: @@ -182,10 +191,10 @@ class ConfigNode(object): val: Field val._on_keyword_changed() - if self._level == 0: - # print(f"Saving config {self.name}") - file = f"{self._path}/{self.__class__.__name__}.yaml" - self.save(file=file, background_save=True) + if self._level == 0 and self._autosave: + file = f"{self._path}/{self.__class__.__name__}.yaml" + # Saves on every field change + self.save(file=file, background_save=True) # ================================================================================================================== # Miscs diff --git a/src/confighandler/controller/Field.py b/src/confighandler/controller/Field.py index 224b8209b00c62894cd5896db7b8084ec4fda368..c57f07f86ae6df075e2e024407af9506b67aa5b7 100644 --- a/src/confighandler/controller/Field.py +++ b/src/confighandler/controller/Field.py @@ -124,6 +124,10 @@ class Field(Generic[T]): else: return fr + def _field_parser(self, val): + # Dummy function, which can be overwritten, if the field should get parsed beforehand (e.g. when using pathes) + return val + # ================================================================================================================== # Getter and Setter for value retrival # ================================================================================================================== diff --git a/src/confighandler/controller/fields/FieldPath.py b/src/confighandler/controller/fields/FieldPath.py index 05b0542d5ec97b50a267913d201fffbe3a7848af..51ef60c13524233eb4d9b43466faa1f9ab352c1b 100644 --- a/src/confighandler/controller/fields/FieldPath.py +++ b/src/confighandler/controller/fields/FieldPath.py @@ -7,6 +7,7 @@ Description: """ import pathlib +import re from pathlib import Path from confighandler.controller.Field import Field @@ -31,3 +32,15 @@ class FieldPath(Field): def _yaml_repr(self): return str('"@Path:<' + str(Path(self.value).as_posix()) + '>"') + + def _field_parser(self, val): + # Overwritten function, to replace the @Path keyword + match = re.findall(r'@Path:<([^>]*)>', val) + if len(match) > 0: + self.logger.info(f"Found @Path: {val}. Check syntax, multiple @Path: are not allowed in one field.") + return Path(match[0]) + elif len(match) == 0: + self.logger.debug(f"No @Path: found in {val}. Please check field.") + return Path('./') + def __str__(self): + return str(Path(self.value).as_posix()) \ No newline at end of file diff --git a/src/confighandler/view/FieldView.py b/src/confighandler/view/FieldView.py index 7af56fc152f9353354ed24517f69dba628dc37ed..2ea4337cd898d6fb8f4a9bbca022d37b7d22806b 100644 --- a/src/confighandler/view/FieldView.py +++ b/src/confighandler/view/FieldView.py @@ -6,18 +6,20 @@ Package Version: 0.0.1 Description: """ -from typing import T + from PySide6.QtCore import Signal from PySide6.QtWidgets import QWidget, QTreeWidgetItem, QMessageBox +import confighandler.controller.Field as Field + class FieldView(QWidget): - value_changed = Signal(T) + value_changed = Signal(Field.T) - def __init__(self, parent_field: 'Field'): + def __init__(self, parent_field: Field): super().__init__() - self.parent_field = parent_field + self.parent_field: Field.Field = parent_field self.label = None self.ui_edit_fields = [] @@ -26,7 +28,7 @@ class FieldView(QWidget): self.value_changed.connect(self._on_value_changed) #self.setToolTip(parent_field._description) - if isinstance(T, str): + if isinstance(Field.T, str): print(">>> String") def _on_value_changed(self, value): diff --git a/src/confighandler/view/fields/FieldViewBool.py b/src/confighandler/view/fields/FieldViewBool.py index 89ecb48601712c73badee07650f03600b7bc3580..d0dc2d979e72906e5c70af0ce3f2e995d8a1a77c 100644 --- a/src/confighandler/view/fields/FieldViewBool.py +++ b/src/confighandler/view/fields/FieldViewBool.py @@ -28,7 +28,7 @@ class FieldViewBool(FieldView): dsp = QCheckBox() else: dsp: QCheckBox = view - dsp.setToolTip(self.parent_field._description) + dsp.setToolTip(f"({self.parent_field.name}) {self.parent_field._description}") dsp.setChecked(self.parent_field.value) self.ui_edit_fields.append(dsp) self.ui_edit_fields[-1].stateChanged.connect(self._on_state_changed) diff --git a/src/confighandler/view/fields/FieldViewFloat.py b/src/confighandler/view/fields/FieldViewFloat.py index 67fd4da7277323c750c506775d778c31a997d78b..9ff44c4fb6007d990c28a99e0f0aa4d43eb2352f 100644 --- a/src/confighandler/view/fields/FieldViewFloat.py +++ b/src/confighandler/view/fields/FieldViewFloat.py @@ -31,7 +31,7 @@ class FieldViewFloat(FieldView): dsp.setRange(-100000, 100000) dsp.setValue(self.parent_field.value) dsp.setDecimals(3) - dsp.setToolTip(self.parent_field._description) + dsp.setToolTip(f"({self.parent_field.name}) {self.parent_field._description}") self.ui_edit_fields.append(dsp) self.ui_edit_fields[-1].valueChanged.connect(self._on_value_edited) diff --git a/src/confighandler/view/fields/FieldViewInt.py b/src/confighandler/view/fields/FieldViewInt.py index 5de6913eb57efa4317e13947091be97327b233c8..345b548ff635e6a02eba8080b1d4277e217d04da 100644 --- a/src/confighandler/view/fields/FieldViewInt.py +++ b/src/confighandler/view/fields/FieldViewInt.py @@ -28,7 +28,7 @@ class FieldViewInt(FieldView): dsp = QtWidgets.QSpinBox() else: dsp: QSpinBox = view - dsp.setToolTip(self.parent_field._description) + dsp.setToolTip(f"({self.parent_field.name}) {self.parent_field._description}") dsp.setRange(-100000, 100000) dsp.setValue(self.parent_field.value) self.ui_edit_fields.append(dsp) diff --git a/src/confighandler/view/fields/FieldViewList.py b/src/confighandler/view/fields/FieldViewList.py index 65f2dfe7ffd2533feda8e7f33e003efa16c3cd9f..097991ccb223af239f07ca839d3da23bd4d1456b 100644 --- a/src/confighandler/view/fields/FieldViewList.py +++ b/src/confighandler/view/fields/FieldViewList.py @@ -28,7 +28,7 @@ class FieldViewList(FieldView): le = QLineEdit(str(self.parent_field.value)) else: le: QLineEdit = view - le.setToolTip(self.parent_field._description) + le.setToolTip(f"({self.parent_field.name}) {self.parent_field._description}") self.ui_edit_fields.append(le) self.ui_edit_fields[-1].textEdited.connect(self._on_text_edited) # self.ui_edit_fields[-1] : QtWidgets.QLineEdit diff --git a/src/confighandler/view/fields/FieldViewPath.py b/src/confighandler/view/fields/FieldViewPath.py index ae1277dc51b89c6b79c9d263738ee751fa997f15..cc0af7010609e3d783b875627973e7427921a414 100644 --- a/src/confighandler/view/fields/FieldViewPath.py +++ b/src/confighandler/view/fields/FieldViewPath.py @@ -37,7 +37,7 @@ class FieldViewPath(FieldView): le = QLineEdit(str(self.parent_field.value), parent=self) else: le: QLineEdit = view - le.setToolTip(self.parent_field._description) + le.setToolTip(f"({self.parent_field.name}) {self.parent_field._description}") self.ui_edit_fields_lbl.append(QtWidgets.QLabel(str(self.parent_field.get()), parent=self)) self.ui_edit_fields.append(le) diff --git a/src/confighandler/view/fields/FieldViewString.py b/src/confighandler/view/fields/FieldViewString.py index ea6063bbd46129c168efb601e0c1800a8aa6fff9..50b6af7fb1a2a830931f1a974b8e5221196fc8e0 100644 --- a/src/confighandler/view/fields/FieldViewString.py +++ b/src/confighandler/view/fields/FieldViewString.py @@ -29,7 +29,7 @@ class FieldViewString(FieldView): le = QtWidgets.QLineEdit(str(self.parent_field.value)) else: le: QLineEdit = view - le.setToolTip(self.parent_field._description) + le.setToolTip(f"({self.parent_field.name}) {self.parent_field._description}") self.ui_edit_fields.append(le) self.parent_field.logger.debug(f"Registering LineEdit {le}") self.ui_edit_fields[-1].textEdited.connect(lambda d: self._on_text_edited(le, d)) diff --git a/src/confighandler/view/fields/FieldViewTuple.py b/src/confighandler/view/fields/FieldViewTuple.py index 198f83c437267afbc26d704b06505ef0a17fcd31..32fb81472da9e545349725ac5d8b7d18d43a2c0b 100644 --- a/src/confighandler/view/fields/FieldViewTuple.py +++ b/src/confighandler/view/fields/FieldViewTuple.py @@ -27,7 +27,7 @@ class FieldViewTuple(FieldView): le = QtWidgets.QLineEdit(str(self.parent_field.value)) else: le: QLineEdit = view - le.setToolTip(self.parent_field._description) + le.setToolTip(f"({self.parent_field.name}) {self.parent_field._description}") self.ui_edit_fields.append(le) self.ui_edit_fields[-1].textEdited.connect(self._on_text_edited) # self.ui_edit_fields[-1] : QtWidgets.QLineEdit