From 9966ea3f97dbcf92d7536d22ff46fc39f3cddbb1 Mon Sep 17 00:00:00 2001 From: "Ganyushin, Dmitry" Date: Mon, 6 May 2024 12:02:00 -0400 Subject: [PATCH] Added src files --- src/bm3dornl/__init__.py | 15 ++++ src/bm3dornl/bm3dornl.py | 66 +++++++++++++++ src/bm3dornl/configuration.py | 107 ++++++++++++++++++++++++ src/bm3dornl/configuration_template.ini | 2 + src/bm3dornl/version.py | 8 ++ 5 files changed, 198 insertions(+) create mode 100644 src/bm3dornl/__init__.py create mode 100644 src/bm3dornl/bm3dornl.py create mode 100644 src/bm3dornl/configuration.py create mode 100644 src/bm3dornl/configuration_template.ini create mode 100644 src/bm3dornl/version.py diff --git a/src/bm3dornl/__init__.py b/src/bm3dornl/__init__.py new file mode 100644 index 0000000..3ab36bc --- /dev/null +++ b/src/bm3dornl/__init__.py @@ -0,0 +1,15 @@ +""" +Contains the entry point for the application +""" + +try: + from ._version import __version__ # noqa: F401 +except ImportError: + __version__ = "0.0.1" + + +def PackageName(): # pylint: disable=invalid-name + """This is needed for backward compatibility because mantid workbench does "from shiver import Shiver" """ + from .packagenamepy import PackageName as packagename # pylint: disable=import-outside-toplevel + + return packagename() diff --git a/src/bm3dornl/bm3dornl.py b/src/bm3dornl/bm3dornl.py new file mode 100644 index 0000000..d30dde6 --- /dev/null +++ b/src/bm3dornl/bm3dornl.py @@ -0,0 +1,66 @@ +""" +Main Qt application +""" + +import sys +from qtpy.QtWidgets import QApplication, QMainWindow + +from mantid.kernel import Logger +from mantidqt.gui_helper import set_matplotlib_backend + +# make sure matplotlib is correctly set before we import shiver +set_matplotlib_backend() + +# make sure the algorithms have been loaded so they are available to the AlgorithmManager +import mantid.simpleapi # noqa: F401, E402 pylint: disable=unused-import, wrong-import-position + +from packagenamepy.configuration import Configuration # noqa: E402 pylint: disable=wrong-import-position +from packagenamepy.version import __version__ # noqa: E402 pylint: disable=wrong-import-position +from packagenamepy.mainwindow import MainWindow # noqa: E402 pylint: disable=wrong-import-position + +logger = Logger("PACKAGENAME") + + +class PackageName(QMainWindow): + """Main Package window""" + + __instance = None + + def __new__(cls): + if PackageName.__instance is None: + PackageName.__instance = QMainWindow.__new__(cls) # pylint: disable=no-value-for-parameter + return PackageName.__instance + + def __init__(self, parent=None): + super().__init__(parent) + logger.information(f"PackageName version: {__version__}") + config = Configuration() + + if not config.is_valid(): + msg = ( + "Error with configuration settings!", + f"Check and update your file: {config.config_file_path}", + "with the latest settings found here:", + f"{config.template_file_path} and start the application again.", + ) + + print(" ".join(msg)) + sys.exit(-1) + self.setWindowTitle(f"PACKAGENAME - {__version__}") + self.main_window = MainWindow(self) + self.setCentralWidget(self.main_window) + + +def gui(): + """ + Main entry point for Qt application + """ + input_flags = sys.argv[1::] + if "--v" in input_flags or "--version" in input_flags: + print(__version__) + sys.exit() + else: + app = QApplication(sys.argv) + window = PackageName() + window.show() + sys.exit(app.exec_()) diff --git a/src/bm3dornl/configuration.py b/src/bm3dornl/configuration.py new file mode 100644 index 0000000..86c68ba --- /dev/null +++ b/src/bm3dornl/configuration.py @@ -0,0 +1,107 @@ +"""Module to load the the settings from SHOME/.packagename/configuration.ini file + +Will fall back to a default""" + +import os +import shutil + +from configparser import ConfigParser +from pathlib import Path +from mantid.kernel import Logger + +logger = Logger("PACKAGENAME") + +# configuration settings file path +CONFIG_PATH_FILE = os.path.join(Path.home(), ".packagename", "configuration.ini") + + +class Configuration: + """Load and validate Configuration Data""" + + def __init__(self): + """initialization of configuration mechanism""" + # capture the current state + self.valid = False + + # locate the template configuration file + project_directory = Path(__file__).resolve().parent + self.template_file_path = os.path.join( + project_directory, "configuration_template.ini" + ) + + # retrieve the file path of the file + self.config_file_path = CONFIG_PATH_FILE + logger.information(f"{self.config_file_path} will be used") + + # if template conf file path exists + if os.path.exists(self.template_file_path): + # file does not exist create it from template + if not os.path.exists(self.config_file_path): + # if directory structure does not exist create it + if not os.path.exists(os.path.dirname(self.config_file_path)): + os.makedirs(os.path.dirname(self.config_file_path)) + shutil.copy2(self.template_file_path, self.config_file_path) + + self.config = ConfigParser(allow_no_value=True, comment_prefixes="/") + # parse the file + try: + self.config.read(self.config_file_path) + # validate the file has the all the latest variables + self.validate() + except ValueError as err: + logger.error(str(err)) + logger.error(f"Problem with the file: {self.config_file_path}") + else: + logger.error( + f"Template configuration file: {self.template_file_path} is missing!" + ) + + def validate(self): + """validates that the fields exist at the config_file_path and writes any missing fields/data + using the template configuration file: configuration_template.ini as a guide""" + template_config = ConfigParser(allow_no_value=True, comment_prefixes="/") + template_config.read(self.template_file_path) + for section in template_config.sections(): + # if section is missing + if section not in self.config.sections(): + # copy the whole section + self.config.add_section(section) + + for item in template_config.items(section): + field, _ = item + if field not in self.config[section]: + # copy the field + self.config[section][field] = template_config[section][field] + with open(self.config_file_path, "w", encoding="utf8") as config_file: + self.config.write(config_file) + self.valid = True + + def is_valid(self): + """returns the configuration state""" + return self.valid + + +def get_data(section, name=None): + """retrieves the configuration data for a variable with name""" + # default file path location + config_file_path = CONFIG_PATH_FILE + if os.path.exists(config_file_path): + config = ConfigParser() + # parse the file + config.read(config_file_path) + try: + if name: + value = config[section][name] + # in case of boolean string value cast it to bool + if value in ("True", "False"): + return value == "True" + # in case of None + if value == "None": + return None + return value + return config[section] + except KeyError as err: + # requested section/field do not exist + logger.error(str(err)) + return None + return None diff --git a/src/bm3dornl/configuration_template.ini b/src/bm3dornl/configuration_template.ini new file mode 100644 index 0000000..c8ea100 --- /dev/null +++ b/src/bm3dornl/configuration_template.ini @@ -0,0 +1,2 @@ +[global.other] +help_url = https://github.com/neutrons/python_project_template/blob/main/README.md diff --git a/src/bm3dornl/version.py b/src/bm3dornl/version.py new file mode 100644 index 0000000..6f674ca --- /dev/null +++ b/src/bm3dornl/version.py @@ -0,0 +1,8 @@ +"""Module to load the version created by versioningit + +Will fall back to a default packagename is not installed""" + +try: + from ._version import __version__ +except ModuleNotFoundError: + __version__ = "0.0.1"