diff --git a/src/antares_web_installer/gui/controller.py b/src/antares_web_installer/gui/controller.py index de35d7c..aac5877 100644 --- a/src/antares_web_installer/gui/controller.py +++ b/src/antares_web_installer/gui/controller.py @@ -8,6 +8,9 @@ import typing from pathlib import Path +import psutil +from platformdirs import user_log_dir + from .mvc import Controller, Model, View from .model import WizardModel from .view import WizardView @@ -25,10 +28,35 @@ class WizardController(Controller): launch: typing.Optional[bool] = True server_path: typing.Optional[Path] = None + log_path: typing.Optional[Path] = dataclasses.field(init=False) + log_file: typing.Optional[Path] = dataclasses.field(init=False) app: App = dataclasses.field(init=False) def __post_init__(self): super().__init__() + self.initialize_log_path() + + def initialize_log_path(self): + self.log_path = Path(user_log_dir("AntaresWebInstaller", "RTE")) + if not self.log_path.exists(): + msg = "No log directory found with path '{}'.".format(self.log_path) + logger.warning(msg) + try: + self.log_path.mkdir(parents=True) + except FileExistsError: + logger.warning("Path '{}' already exists.".format(self.log_path)) + else: + logger.info("Path '{}' successfully created.".format(self.log_path)) + tmp_file_name = "web-installer.log" + + self.log_file = self.log_path.joinpath(tmp_file_name) + + # check if file exists + if self.log_file not in list(self.log_path.iterdir()): + # if not, create it first + with open(self.log_file, "w") as f: + pass + f.close() def init_model(self, **kwargs) -> Model: model = WizardModel(self) @@ -51,11 +79,16 @@ def install(self): self.app.run() except InstallError as e: logger.error(e) - self.view.raise_error("The installation encountered an error. The target directory may have be corrupted. " - "Please check its integrity and try again.") + self.view.raise_error("The installation encountered an error. The target directory may have been " + "corrupted. Please check its integrity and try again.") + except psutil.NoSuchProcess as e: + logger.error(e) + self.view.raise_error("The installation encountered an error. The installation encountered an error while " + "scanning processes. Please retry later.") else: logger.debug("Launch installer worker") logger.debug("Installation complete") + self.view.frames[self.view.current_index].event_generate("<>") def save_target_dir(self, path: str): diff --git a/src/antares_web_installer/gui/view.py b/src/antares_web_installer/gui/view.py index 1752ca7..9d83b98 100644 --- a/src/antares_web_installer/gui/view.py +++ b/src/antares_web_installer/gui/view.py @@ -56,6 +56,12 @@ def current_index(self, new_index: int): self._current_index = new_index self.change_frame() + def get_log_file(self): + try: + return self.controller.log_file + except AttributeError as e: + self.raise_error("The installer encountered an error while initializing the logger. Please retry later.") + def set_geometry(self, width, height): """ @param width: diff --git a/src/antares_web_installer/gui/widgets/frame.py b/src/antares_web_installer/gui/widgets/frame.py index a69d3ba..9335cc8 100644 --- a/src/antares_web_installer/gui/widgets/frame.py +++ b/src/antares_web_installer/gui/widgets/frame.py @@ -23,7 +23,7 @@ class LogManager(logging.Handler): def __init__(self, progress_frame: "ProgressFrame"): logging.Handler.__init__(self) self.setLevel(logging.INFO) - formatter = logging.Formatter(FORMAT) + formatter = logging.Formatter("[%(asctime)-15s] %(message)s") self.setFormatter(formatter) self.progress_frame = progress_frame @@ -258,6 +258,31 @@ def __init__(self, master: tk.Misc, window: "WizardView", index: int, *args, **k def progress_update(self, value: float): self.progress_bar["value"] = value + def initialize_user_log_manager(self, logger): + # One log after another is displayed in the main window + log_manager = LogManager(self) + logger.addHandler(log_manager) + + def initialize_file_log_manager(self, logger): + from antares_web_installer.gui.controller import WizardController + + if isinstance(self.window.controller, WizardController): + # create new tmp directory if it does not exist yet + tmp_dir_path = self.window.controller.log_path + tmp_file_name = "web-installer.log" + + tmp_file = tmp_dir_path.joinpath(tmp_file_name) + + # check if file exists + if tmp_file not in list(tmp_dir_path.iterdir()): + logger.info("No temporary file was found. Create a new one.") + # if not, create it first + + if tmp_file.exists(): + logger.info("Creation successful") + else: + self.window.raise_error("No temporary file was created or found.") + def on_active_frame(self, event): # Lazy import for typing and testing purposes from antares_web_installer.gui.controller import WizardController @@ -265,39 +290,35 @@ def on_active_frame(self, event): # retrieve app logger main_logger = logging.getLogger("antares_web_installer.app") - if isinstance(self.window.controller, WizardController): - # create new tmp directory if it does not exist yet - tmp_dir_path = self.window.controller.target_dir.joinpath("tmp/") - - try: - os.mkdir(tmp_dir_path) - except FileExistsError: - main_logger.warning("Directory already exists. Skip directory creation step.") - except FileNotFoundError as e: - msg = "An error occured while saving logs." - main_logger.error(f"'tmp' directory was not found in {tmp_dir_path}: {e}") - main_logger.info(msg) - self.window.raise_error(msg) + # Initialize log manager + log_manager = LogManager(self) + main_logger.addHandler(log_manager) + if isinstance(self.window.controller, WizardController): # redirect logs in the target `tmp` directory - file_logger = logging.FileHandler(tmp_dir_path.joinpath("web-installer.log")) - file_logger.setFormatter(logging.Formatter(FORMAT)) - file_logger.setLevel(logging.ERROR) + file_logger = logging.FileHandler(self.window.get_log_file()) + file_logger.setFormatter(logging.Formatter("%(asctime)s - %(levelname)s: %(message)s")) + file_logger.setLevel(logging.INFO) main_logger.addHandler(file_logger) - # One log after another is displayed in the main window - log_manager = LogManager(self) - main_logger.addHandler(log_manager) - # Launching installation in concurrency with the current process self.thread = Thread(target=self.window.controller.install, args=()) self.thread.start() else: - msg = "The installer encounters an issue while instantiating controller (code 'NotImplementedError')." + msg = "The installer encounters an issue while instantiating controller ('NotImplementedError')." main_logger.error(f"Not implemented {type(self.window.controller)}.") self.window.raise_error(msg) def on_installation_complete(self, event): + # Lazy import for typing and testing purposes + from antares_web_installer.gui.controller import WizardController + + if isinstance(self.window.controller, WizardController): + # move log file in application log directory + file_name = self.window.controller.log_file.name + log_directory = self.window.controller.target_dir.joinpath('logs') + self.window.get_log_file().rename(self.window.controller.target_dir.joinpath(log_directory, file_name)) + self.control_btn.btns["next"].toggle_btn(True)