From 5627af93957ace42ef573e26e3ba6bbd84d350c0 Mon Sep 17 00:00:00 2001 From: Sylvain Leclerc Date: Wed, 25 Sep 2024 18:05:13 +0200 Subject: [PATCH 01/29] few fixes Signed-off-by: Sylvain Leclerc --- src/antares_web_installer/gui/__main__.py | 0 src/antares_web_installer/gui/controller.py | 12 +++++++----- src/antares_web_installer/gui/logger.py | 7 +++++-- src/antares_web_installer/gui/mvc.py | 7 +++++++ 4 files changed, 19 insertions(+), 7 deletions(-) mode change 100644 => 100755 src/antares_web_installer/gui/__main__.py diff --git a/src/antares_web_installer/gui/__main__.py b/src/antares_web_installer/gui/__main__.py old mode 100644 new mode 100755 diff --git a/src/antares_web_installer/gui/controller.py b/src/antares_web_installer/gui/controller.py index 8afd4a7..139817c 100644 --- a/src/antares_web_installer/gui/controller.py +++ b/src/antares_web_installer/gui/controller.py @@ -6,6 +6,7 @@ import typing from pathlib import Path from threading import Thread +from typing import Optional from antares_web_installer.gui.mvc import Controller, ControllerError from antares_web_installer.gui.model import WizardModel @@ -39,8 +40,8 @@ class WizardController(Controller): def __init__(self): super().__init__() self.app = None - self.log_dir = None - self.log_file = None + self.log_dir: Optional[Path] = None + self.log_file: Optional[Path] = None # init loggers self.logger = logger @@ -64,17 +65,18 @@ def init_view(self) -> "WizardView": return WizardView(self) def init_file_handler(self): - self.log_dir = self.model.target_dir.joinpath("logs/") + self.log_dir : Path = self.model.target_dir / "logs" tmp_file_name = "wizard.log" if not self.log_dir.exists(): - self.log_dir = self.model.source_dir.joinpath("logs/") # use the source directory as tmp dir for logs + self.log_dir = self.model.source_dir / "logs" # use the source directory as tmp dir for logs self.logger.debug( "No log directory found with path '{}'. Attempt to generate the path.".format(self.log_dir) ) + self.log_dir.mkdir(parents=True, exist_ok=True) self.logger.info("Path '{}' was successfully created.".format(self.log_dir)) - self.log_file = self.log_dir.joinpath(tmp_file_name) + self.log_file = self.log_dir / tmp_file_name # check if file exists if self.log_file not in list(self.log_dir.iterdir()): diff --git a/src/antares_web_installer/gui/logger.py b/src/antares_web_installer/gui/logger.py index e98d72e..3b253cf 100644 --- a/src/antares_web_installer/gui/logger.py +++ b/src/antares_web_installer/gui/logger.py @@ -2,8 +2,11 @@ import typing +MessageConsumer = typing.Callable[[str], None] + + class ConsoleHandler(logging.Handler): - def __init__(self, callback: typing.Callable): + def __init__(self, callback: MessageConsumer): logging.Handler.__init__(self) self.setLevel(logging.INFO) formatter = logging.Formatter("[%(asctime)-15s] %(message)s") @@ -15,7 +18,7 @@ def emit(self, logs: logging.LogRecord): class ProgressHandler(logging.Handler): - def __init__(self, callback: typing.Callable): + def __init__(self, callback: MessageConsumer): """ This logging handler intercept all logs that are progression values @param progress_var: tkinter.StringVar diff --git a/src/antares_web_installer/gui/mvc.py b/src/antares_web_installer/gui/mvc.py index fb9bf7c..f858f04 100644 --- a/src/antares_web_installer/gui/mvc.py +++ b/src/antares_web_installer/gui/mvc.py @@ -6,6 +6,8 @@ from __future__ import annotations import tkinter as tk +import traceback +from tkinter import messagebox class Model: @@ -35,6 +37,11 @@ class View(tk.Tk): def __init__(self, controller: Controller): super().__init__() self.controller = controller + self.report_callback_exception = self.show_error + + def show_error(self, *args): + err = traceback.format_exception(*args) + messagebox.showerror('Exception', "".join(err)) class ControllerError(Exception): From 53a1e3c7b3223feb6ea907e3ef395e75532297df Mon Sep 17 00:00:00 2001 From: Sylvain Leclerc Date: Wed, 25 Sep 2024 19:42:32 +0200 Subject: [PATCH 02/29] fix regression on thread execution Signed-off-by: Sylvain Leclerc --- src/antares_web_installer/gui/controller.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/antares_web_installer/gui/controller.py b/src/antares_web_installer/gui/controller.py index 139817c..4d468e0 100644 --- a/src/antares_web_installer/gui/controller.py +++ b/src/antares_web_installer/gui/controller.py @@ -145,7 +145,7 @@ def install(self, callback: typing.Callable): thread = InstallationThread(target=self.app.run, args=()) try: - thread.run() + thread.start() except InstallError as e: self.view.raise_error(e) From 02dad225355716b072c18de5ce82e8c063afacd8 Mon Sep 17 00:00:00 2001 From: Sylvain Leclerc Date: Wed, 25 Sep 2024 20:54:56 +0200 Subject: [PATCH 03/29] improve error logging Signed-off-by: Sylvain Leclerc --- pytest.ini | 0 src/antares_web_installer/gui/controller.py | 28 ++++++--------------- src/antares_web_installer/gui/view.py | 1 - 3 files changed, 7 insertions(+), 22 deletions(-) create mode 100644 pytest.ini diff --git a/pytest.ini b/pytest.ini new file mode 100644 index 0000000..e69de29 diff --git a/src/antares_web_installer/gui/controller.py b/src/antares_web_installer/gui/controller.py index 4d468e0..10f225b 100644 --- a/src/antares_web_installer/gui/controller.py +++ b/src/antares_web_installer/gui/controller.py @@ -17,17 +17,12 @@ from antares_web_installer.gui.logger import ConsoleHandler, ProgressHandler, LogFileHandler -class InstallationThread(Thread): - def __init__(self, group=None, target=None, name=None, args=(), kwargs=None, *, daemon=None): - super().__init__(group, target, name, args, kwargs, daemon=daemon) +def run_installation(app: App) -> None: + try: + app.run() + except Exception as e: + logger.exception(f"An error occurred during installation: {e}") - def run(self): - try: - super().run() - except OSError as e: - raise e - except InstallError as e: - raise e class WizardController(Controller): @@ -142,22 +137,13 @@ def install(self, callback: typing.Callable): logger.warning("Impossible to create a new shortcut. Skip this step.") logger.debug(e) - thread = InstallationThread(target=self.app.run, args=()) + self.thread = Thread(target=lambda: run_installation(self.app), args=()) try: - thread.start() + self.thread.start() except InstallError as e: self.view.raise_error(e) - def installation_over(self) -> None: - """ - This method makes sure the thread terminated. If not, it waits for it to terminate. - """ - if self.thread: - while self.thread.join(): - if not self.thread.is_alive(): - break - def get_target_dir(self) -> Path: return self.model.target_dir diff --git a/src/antares_web_installer/gui/view.py b/src/antares_web_installer/gui/view.py index e85f1f0..a8f7997 100644 --- a/src/antares_web_installer/gui/view.py +++ b/src/antares_web_installer/gui/view.py @@ -188,5 +188,4 @@ def run_installation(self, callback): self.controller.install(callback) def installation_over(self): - self.controller.installation_over() self.frames["progress_frame"].installation_over() From beab4fb3c84e9650f7b2bcc66901f65c0f452980 Mon Sep 17 00:00:00 2001 From: Sylvain Leclerc Date: Thu, 26 Sep 2024 09:58:57 +0200 Subject: [PATCH 04/29] raise from exception to improve traceability Signed-off-by: Sylvain Leclerc --- src/antares_web_installer/app.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/antares_web_installer/app.py b/src/antares_web_installer/app.py index ac98895..723b85c 100644 --- a/src/antares_web_installer/app.py +++ b/src/antares_web_installer/app.py @@ -54,7 +54,7 @@ class App: def __post_init__(self): # Prepare the path to the executable which is located in the target directory server_name = SERVER_NAMES[os.name] - self.server_path = self.target_dir.joinpath("AntaresWeb", server_name) + self.server_path = self.target_dir / "AntaresWeb" / server_name # Set all progress variables needed to compute current progress of the installation self.nb_steps = 2 # kill, install steps @@ -254,7 +254,7 @@ def create_shortcuts(self): description="Launch Antares Web Server in background", ) except com_error as e: - raise InstallError("Impossible to create a new shortcut: {}\nSkip shortcut creation".format(e)) + raise InstallError(f"Impossible to create a new shortcut: {e}\nSkipping shortcut creation") from e else: assert shortcut_path in list(desktop_path.iterdir()) logger.info(f"Server shortcut {shortcut_path} was successfully created.") From cf7150381a22ee7f2843851744e419f0f3f53130 Mon Sep 17 00:00:00 2001 From: Sylvain Leclerc Date: Thu, 26 Sep 2024 11:07:00 +0200 Subject: [PATCH 05/29] try moving dispatch method in shortcut function Signed-off-by: Sylvain Leclerc --- src/antares_web_installer/shortcuts/_win32_shell.py | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/antares_web_installer/shortcuts/_win32_shell.py b/src/antares_web_installer/shortcuts/_win32_shell.py index 205095a..ca9e289 100644 --- a/src/antares_web_installer/shortcuts/_win32_shell.py +++ b/src/antares_web_installer/shortcuts/_win32_shell.py @@ -15,9 +15,6 @@ import win32com.client from win32com.shell import shell, shellcon -_WSHELL = win32com.client.Dispatch("Wscript.Shell") - - # Windows Special Folders # see: https://docs.microsoft.com/en-us/windows/win32/shell/csidl @@ -56,6 +53,7 @@ def create_shortcut( if isinstance(arguments, str): arguments = [arguments] if arguments else [] + _WSHELL = win32com.client.Dispatch("Wscript.Shell") wscript = _WSHELL.CreateShortCut(str(target)) wscript.TargetPath = str(exe_path) wscript.Arguments = " ".join(arguments) From 5e5623781f0f3b321b547aa10457474150519286 Mon Sep 17 00:00:00 2001 From: Sylvain Leclerc Date: Thu, 26 Sep 2024 13:35:01 +0200 Subject: [PATCH 06/29] initializing COM Signed-off-by: Sylvain Leclerc --- .../shortcuts/_win32_shell.py | 36 +++++++++++++------ 1 file changed, 25 insertions(+), 11 deletions(-) diff --git a/src/antares_web_installer/shortcuts/_win32_shell.py b/src/antares_web_installer/shortcuts/_win32_shell.py index ca9e289..b1c5ec4 100644 --- a/src/antares_web_installer/shortcuts/_win32_shell.py +++ b/src/antares_web_installer/shortcuts/_win32_shell.py @@ -11,7 +11,9 @@ import os import typing as t +from contextlib import contextmanager +import pythoncom import win32com.client from win32com.shell import shell, shellcon @@ -39,6 +41,15 @@ def get_start_menu() -> str: return shell.SHGetFolderPath(0, shellcon.CSIDL_PROGRAMS, None, 0) # type: ignore +@contextmanager +def initialize_com(): + try: + pythoncom.CoInitialize() + yield + finally: + pythoncom.CoUninitialize() + + def create_shortcut( target: t.Union[str, os.PathLike], exe_path: t.Union[str, os.PathLike], @@ -48,19 +59,22 @@ def create_shortcut( icon_path: t.Union[str, os.PathLike] = "", description: str = "", ) -> None: + working_dir = working_dir or get_homedir() if isinstance(arguments, str): arguments = [arguments] if arguments else [] - _WSHELL = win32com.client.Dispatch("Wscript.Shell") - wscript = _WSHELL.CreateShortCut(str(target)) - wscript.TargetPath = str(exe_path) - wscript.Arguments = " ".join(arguments) - wscript.WorkingDirectory = str(working_dir) - wscript.WindowStyle = 0 - if description: - wscript.Description = description - if icon_path: - wscript.IconLocation = str(icon_path) - wscript.save() + with initialize_com(): + _WSHELL = win32com.client.Dispatch("Wscript.Shell") + wscript = _WSHELL.CreateShortCut(str(target)) + wscript.TargetPath = str(exe_path) + wscript.Arguments = " ".join(arguments) + wscript.WorkingDirectory = str(working_dir) + wscript.WindowStyle = 0 + if description: + wscript.Description = description + if icon_path: + wscript.IconLocation = str(icon_path) + wscript.save() + From b6a765f1ab83bf25d7d25fc71dff0a2e683540b0 Mon Sep 17 00:00:00 2001 From: Sylvain Leclerc Date: Fri, 27 Sep 2024 14:32:18 +0200 Subject: [PATCH 07/29] fix: try to kill all running processes at once Signed-off-by: Sylvain Leclerc --- src/antares_web_installer/app.py | 52 ++++++++++++++++++-------------- 1 file changed, 29 insertions(+), 23 deletions(-) diff --git a/src/antares_web_installer/app.py b/src/antares_web_installer/app.py index 723b85c..913845e 100644 --- a/src/antares_web_installer/app.py +++ b/src/antares_web_installer/app.py @@ -7,8 +7,10 @@ import webbrowser from difflib import SequenceMatcher +from multiprocessing import Process from pathlib import Path from shutil import copy2, copytree +from typing import List import httpx @@ -95,35 +97,39 @@ def kill_running_server(self) -> None: Check whether Antares service is up. Kill the process if so. """ - processes_list = list(psutil.process_iter(["pid", "name"])) - processes_list_length = len(processes_list) + server_processes = self._get_server_processes() + if len(server_processes) > 0: + logger.info("Attempt to stop running server processes ...") + for p in server_processes: + p.kill() + gone, alive = psutil.wait_procs(server_processes, timeout=30) + alive_count = len(alive) + if alive_count > 0: + raise InstallError( + f"Failed to kill all server processes, {alive_count}. Please kill them manually before relaunching the installer." + ) + else: + logger.info("Server processes successfully stopped...") + else: + logger.info("No running server found, resuming installation.") + self.update_progress(100) - for index, proc in enumerate(processes_list): - # evaluate matching between query process name and existing process name + def _get_server_processes(self) -> List[psutil.Process]: + res = [] + for process in psutil.process_iter(["pid", "name"]): try: - matching_ratio = SequenceMatcher(None, "antareswebserver", proc.name().lower()).ratio() + # evaluate matching between query process name and existing process name + matching_ratio = SequenceMatcher(None, "antareswebserver", process.name().lower()).ratio() except FileNotFoundError: - logger.warning("The process '{}' does not exist anymore. Skipping its analysis".format(proc.name())) + logger.warning("The process '{}' does not exist anymore. Skipping its analysis".format(process.name())) continue except psutil.NoSuchProcess: - logger.warning("The process '{}' was stopped before being analyzed. Skipping.".format(proc.name())) + logger.warning("The process '{}' was stopped before being analyzed. Skipping.".format(process.name())) continue if matching_ratio > 0.8: - logger.info("Running server found. Attempt to stop it ...") - logger.debug(f"Server process:{proc.name()} - process id: {proc.pid}") - running_app = psutil.Process(pid=proc.pid) - running_app.kill() - - try: - running_app.wait(5) - except psutil.TimeoutExpired as e: - raise InstallError( - "Impossible to kill the server. Please kill it manually before relaunching the installer." - ) from e - else: - logger.info("The application was successfully stopped.") - self.update_progress((index + 1) * 100 / processes_list_length) - logger.info("No other processes found.") + res.append(process) + logger.debug(f"Running server found: {process.name()} - process id: {process.pid}") + return res def install_files(self): """ """ @@ -288,7 +294,7 @@ def start_server(self): raise InstallError(msg) nb_attempts = 0 - max_attempts = 10 + max_attempts = 30 while nb_attempts < max_attempts: logger.info(f"Attempt #{nb_attempts}...") From 65d9bcf9e456b76cf6689cf22c6671a73a4d4a9b Mon Sep 17 00:00:00 2001 From: Sylvain Leclerc Date: Fri, 27 Sep 2024 15:43:50 +0200 Subject: [PATCH 08/29] try alternative approach for killing server Signed-off-by: Sylvain Leclerc --- src/antares_web_installer/app.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/antares_web_installer/app.py b/src/antares_web_installer/app.py index 913845e..4d98eb6 100644 --- a/src/antares_web_installer/app.py +++ b/src/antares_web_installer/app.py @@ -1,6 +1,7 @@ import dataclasses import os import re +import signal import subprocess import textwrap import time @@ -101,12 +102,12 @@ def kill_running_server(self) -> None: if len(server_processes) > 0: logger.info("Attempt to stop running server processes ...") for p in server_processes: - p.kill() + os.kill(p.pid, signal.SIGTERM) gone, alive = psutil.wait_procs(server_processes, timeout=30) alive_count = len(alive) if alive_count > 0: raise InstallError( - f"Failed to kill all server processes, {alive_count}. Please kill them manually before relaunching the installer." + f"Failed to kill all {alive_count} server processes. Please kill them manually before relaunching the installer." ) else: logger.info("Server processes successfully stopped...") From b20daff02800ff014d72944a3d671311a67ec4db Mon Sep 17 00:00:00 2001 From: Sylvain Leclerc Date: Fri, 27 Sep 2024 16:41:53 +0200 Subject: [PATCH 09/29] dirty hack for windows Signed-off-by: Sylvain Leclerc --- src/antares_web_installer/app.py | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/src/antares_web_installer/app.py b/src/antares_web_installer/app.py index 4d98eb6..d951376 100644 --- a/src/antares_web_installer/app.py +++ b/src/antares_web_installer/app.py @@ -1,14 +1,11 @@ import dataclasses import os import re -import signal import subprocess import textwrap import time import webbrowser - from difflib import SequenceMatcher -from multiprocessing import Process from pathlib import Path from shutil import copy2, copytree from typing import List @@ -102,8 +99,13 @@ def kill_running_server(self) -> None: if len(server_processes) > 0: logger.info("Attempt to stop running server processes ...") for p in server_processes: - os.kill(p.pid, signal.SIGTERM) - gone, alive = psutil.wait_procs(server_processes, timeout=30) + p.kill() + gone, alive = psutil.wait_procs(server_processes, timeout=5) + if len(alive) > 0 and os.name == "nt": + # Dirty hack to circumvent permission issues on windows + os.system("taskkill " + " ".join([f"/PID {p.id}" for p in server_processes])) + gone, alive = psutil.wait_procs(server_processes, timeout=5) + alive_count = len(alive) if alive_count > 0: raise InstallError( From 51653030ed201456acc0ab4b3e45a47dc4214fa0 Mon Sep 17 00:00:00 2001 From: Sylvain Leclerc Date: Fri, 27 Sep 2024 17:20:42 +0200 Subject: [PATCH 10/29] log Signed-off-by: Sylvain Leclerc --- src/antares_web_installer/app.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/antares_web_installer/app.py b/src/antares_web_installer/app.py index d951376..27b42d6 100644 --- a/src/antares_web_installer/app.py +++ b/src/antares_web_installer/app.py @@ -103,7 +103,9 @@ def kill_running_server(self) -> None: gone, alive = psutil.wait_procs(server_processes, timeout=5) if len(alive) > 0 and os.name == "nt": # Dirty hack to circumvent permission issues on windows - os.system("taskkill " + " ".join([f"/PID {p.id}" for p in server_processes])) + cmd = "taskkill " + " ".join([f"/PID {p.id}" for p in server_processes]) + logger.debug(f"Executing {cmd}") + os.system(cmd) gone, alive = psutil.wait_procs(server_processes, timeout=5) alive_count = len(alive) From 5a1161b7a1f07de8e4cbdd220233dfaa27d3071e Mon Sep 17 00:00:00 2001 From: Sylvain Leclerc Date: Fri, 27 Sep 2024 17:41:56 +0200 Subject: [PATCH 11/29] fix Signed-off-by: Sylvain Leclerc --- src/antares_web_installer/app.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/antares_web_installer/app.py b/src/antares_web_installer/app.py index 27b42d6..f21c91a 100644 --- a/src/antares_web_installer/app.py +++ b/src/antares_web_installer/app.py @@ -103,7 +103,7 @@ def kill_running_server(self) -> None: gone, alive = psutil.wait_procs(server_processes, timeout=5) if len(alive) > 0 and os.name == "nt": # Dirty hack to circumvent permission issues on windows - cmd = "taskkill " + " ".join([f"/PID {p.id}" for p in server_processes]) + cmd = "taskkill " + " ".join([f"/PID {p.pid}" for p in server_processes]) logger.debug(f"Executing {cmd}") os.system(cmd) gone, alive = psutil.wait_procs(server_processes, timeout=5) From 780e7b4d97537bc0869f9057b161395ed2ca929d Mon Sep 17 00:00:00 2001 From: Sylvain Leclerc Date: Fri, 27 Sep 2024 20:44:50 +0200 Subject: [PATCH 12/29] alternative call to command Signed-off-by: Sylvain Leclerc --- src/antares_web_installer/app.py | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/antares_web_installer/app.py b/src/antares_web_installer/app.py index f21c91a..3982e7f 100644 --- a/src/antares_web_installer/app.py +++ b/src/antares_web_installer/app.py @@ -103,9 +103,10 @@ def kill_running_server(self) -> None: gone, alive = psutil.wait_procs(server_processes, timeout=5) if len(alive) > 0 and os.name == "nt": # Dirty hack to circumvent permission issues on windows - cmd = "taskkill " + " ".join([f"/PID {p.pid}" for p in server_processes]) - logger.debug(f"Executing {cmd}") - os.system(cmd) + cmd = ["taskkill"] + for p in server_processes: + cmd.extend(["/PID", f"{p.pid}"]) + subprocess.run(cmd) gone, alive = psutil.wait_procs(server_processes, timeout=5) alive_count = len(alive) From 8177a0ff06ad1cd354b20601032480b3d661a1dd Mon Sep 17 00:00:00 2001 From: Sylvain Leclerc Date: Mon, 30 Sep 2024 09:35:53 +0200 Subject: [PATCH 13/29] Revert to simple kill Signed-off-by: Sylvain Leclerc --- src/antares_web_installer/app.py | 20 ++++++++------------ 1 file changed, 8 insertions(+), 12 deletions(-) diff --git a/src/antares_web_installer/app.py b/src/antares_web_installer/app.py index 3982e7f..adbbd1b 100644 --- a/src/antares_web_installer/app.py +++ b/src/antares_web_installer/app.py @@ -97,25 +97,21 @@ def kill_running_server(self) -> None: """ server_processes = self._get_server_processes() if len(server_processes) > 0: - logger.info("Attempt to stop running server processes ...") + logger.info("Attempt to stop running Antares server ...") for p in server_processes: - p.kill() + try: + p.kill() + except psutil.NoSuchProcess: + logger.debug(f"The process '{p.pid}' was stopped before being killed.") + continue gone, alive = psutil.wait_procs(server_processes, timeout=5) - if len(alive) > 0 and os.name == "nt": - # Dirty hack to circumvent permission issues on windows - cmd = ["taskkill"] - for p in server_processes: - cmd.extend(["/PID", f"{p.pid}"]) - subprocess.run(cmd) - gone, alive = psutil.wait_procs(server_processes, timeout=5) - alive_count = len(alive) if alive_count > 0: raise InstallError( - f"Failed to kill all {alive_count} server processes. Please kill them manually before relaunching the installer." + "Could not to stop Antares server. Please stop it before launching again the installation." ) else: - logger.info("Server processes successfully stopped...") + logger.info("Antares server successfully stopped...") else: logger.info("No running server found, resuming installation.") self.update_progress(100) From 58dbe0446e326c0876eb7be7fd13cd6e13c18796 Mon Sep 17 00:00:00 2001 From: Sylvain Leclerc Date: Mon, 30 Sep 2024 14:15:23 +0200 Subject: [PATCH 14/29] feature: improve displayed message when waiting for server start Signed-off-by: Sylvain Leclerc --- src/antares_web_installer/app.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/antares_web_installer/app.py b/src/antares_web_installer/app.py index adbbd1b..b180577 100644 --- a/src/antares_web_installer/app.py +++ b/src/antares_web_installer/app.py @@ -299,7 +299,7 @@ def start_server(self): max_attempts = 30 while nb_attempts < max_attempts: - logger.info(f"Attempt #{nb_attempts}...") + logger.info(f"Waiting for server start (attempt #{nb_attempts})...") try: res = httpx.get(SERVER_ADDRESS + "/health", timeout=1) if res.status_code == 200: From 87d995c322040a2961e016755a9648d845f71c6b Mon Sep 17 00:00:00 2001 From: Sylvain Leclerc Date: Tue, 1 Oct 2024 09:59:12 +0200 Subject: [PATCH 15/29] add migration for config v2.18 Signed-off-by: Sylvain Leclerc --- src/antares_web_installer/config/__init__.py | 3 ++ .../config/config_2_18.py | 10 +++++ tests/config/test_config_2_18.py | 12 ++++++ .../test_config_2_18/application-2.17.yaml | 42 +++++++++++++++++++ .../test_config_2_18/application-2.18.yaml | 42 +++++++++++++++++++ 5 files changed, 109 insertions(+) create mode 100644 src/antares_web_installer/config/config_2_18.py create mode 100644 tests/config/test_config_2_18.py create mode 100644 tests/config/test_config_2_18/application-2.17.yaml create mode 100644 tests/config/test_config_2_18/application-2.18.yaml diff --git a/src/antares_web_installer/config/__init__.py b/src/antares_web_installer/config/__init__.py index a16fc7b..5fdaa15 100644 --- a/src/antares_web_installer/config/__init__.py +++ b/src/antares_web_installer/config/__init__.py @@ -29,5 +29,8 @@ def update_config(source_path: Path, target_path: Path, version: str) -> None: with target_path.open("r") as f: config = yaml.safe_load(f) + if version_info < (2, 18): + update_to_2_15(config) + with source_path.open(mode="w") as f: yaml.dump(config, f) diff --git a/src/antares_web_installer/config/config_2_18.py b/src/antares_web_installer/config/config_2_18.py new file mode 100644 index 0000000..538152d --- /dev/null +++ b/src/antares_web_installer/config/config_2_18.py @@ -0,0 +1,10 @@ +import typing as t + + +def update_to_2_18(config: t.MutableMapping[str, t.Any]) -> None: + """ + Update the configuration file to version 2.18 in-place: + we need to ensure root_path is / and api_prefix is /api + """ + del config["root_path"] + config["api_prefix"] = "/api" diff --git a/tests/config/test_config_2_18.py b/tests/config/test_config_2_18.py new file mode 100644 index 0000000..c375103 --- /dev/null +++ b/tests/config/test_config_2_18.py @@ -0,0 +1,12 @@ +from pathlib import Path + +import yaml + +from antares_web_installer.config.config_2_18 import update_to_2_18 + + +def test_update_to_2_18(datadir: Path) -> None: + config = yaml.safe_load(datadir.joinpath(f"application-2.17.yaml").read_text()) + expected = yaml.safe_load(datadir.joinpath(f"application-2.18.yaml").read_text()) + update_to_2_18(config) + assert config == expected diff --git a/tests/config/test_config_2_18/application-2.17.yaml b/tests/config/test_config_2_18/application-2.17.yaml new file mode 100644 index 0000000..7641da3 --- /dev/null +++ b/tests/config/test_config_2_18/application-2.17.yaml @@ -0,0 +1,42 @@ +security: + disabled: false + jwt: + key: super-secret + login: + admin: + pwd: admin + +db: + url: "sqlite:////home/john/antares_data/database.db" + +storage: + tmp_dir: /tmp + matrixstore: /home/john/antares_data/matrices + archive_dir: /home/john/antares_data/archives + allow_deletion: false + workspaces: + default: + path: /home/john/antares_data/internal_studies/ + studies: + path: /home/john/antares_data/studies/ + +launcher: + default: local + local: + binaries: + 850: /home/john/opt/antares-8.5.0-Ubuntu-20.04/antares-solver + 860: /home/john/opt/antares-8.6.0-Ubuntu-20.04/antares-8.6-solver + enable_nb_cores_detection: True + +debug: false + +root_path: "/api" + +server: + worker_threadpool_size: 12 + services: + - watcher + - matrix_gc + +logging: + level: INFO diff --git a/tests/config/test_config_2_18/application-2.18.yaml b/tests/config/test_config_2_18/application-2.18.yaml new file mode 100644 index 0000000..2a6d796 --- /dev/null +++ b/tests/config/test_config_2_18/application-2.18.yaml @@ -0,0 +1,42 @@ +security: + disabled: false + jwt: + key: super-secret + login: + admin: + pwd: admin + +db: + url: "sqlite:////home/john/antares_data/database.db" + +storage: + tmp_dir: /tmp + matrixstore: /home/john/antares_data/matrices + archive_dir: /home/john/antares_data/archives + allow_deletion: false + workspaces: + default: + path: /home/john/antares_data/internal_studies/ + studies: + path: /home/john/antares_data/studies/ + +launcher: + default: local + local: + binaries: + 850: /home/john/opt/antares-8.5.0-Ubuntu-20.04/antares-solver + 860: /home/john/opt/antares-8.6.0-Ubuntu-20.04/antares-8.6-solver + enable_nb_cores_detection: True + +debug: false + +api_prefix: "/api" + +server: + worker_threadpool_size: 12 + services: + - watcher + - matrix_gc + +logging: + level: INFO From ce1b0098b219a78bbda8babd4af54f4e39280be5 Mon Sep 17 00:00:00 2001 From: Sylvain Leclerc Date: Tue, 1 Oct 2024 10:57:13 +0200 Subject: [PATCH 16/29] fix: remove cancel button for final frame Signed-off-by: Sylvain Leclerc --- src/antares_web_installer/gui/widgets/frame.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/antares_web_installer/gui/widgets/frame.py b/src/antares_web_installer/gui/widgets/frame.py index e7234e9..9bd42a9 100644 --- a/src/antares_web_installer/gui/widgets/frame.py +++ b/src/antares_web_installer/gui/widgets/frame.py @@ -280,5 +280,5 @@ def __init__(self, master: tk.Misc, window: "WizardView", *args, **kwargs): style="Description.TLabel", ).pack(side="top", fill="x") - self.control_btn = ControlFrame(parent=self, window=window, finish_btn=True) + self.control_btn = ControlFrame(parent=self, window=window, cancel_btn=False, finish_btn=True) self.control_btn.pack(side="bottom", fill="x") From d9ed7735029640f8ad7237a690b3565c9d5c843e Mon Sep 17 00:00:00 2001 From: Sylvain Leclerc Date: Tue, 1 Oct 2024 13:25:36 +0200 Subject: [PATCH 17/29] format Signed-off-by: Sylvain Leclerc --- src/antares_web_installer/gui/controller.py | 3 +-- src/antares_web_installer/gui/mvc.py | 2 +- src/antares_web_installer/shortcuts/_win32_shell.py | 2 -- tests/config/test_config_2_18.py | 4 ++-- 4 files changed, 4 insertions(+), 7 deletions(-) diff --git a/src/antares_web_installer/gui/controller.py b/src/antares_web_installer/gui/controller.py index 10f225b..41b36ee 100644 --- a/src/antares_web_installer/gui/controller.py +++ b/src/antares_web_installer/gui/controller.py @@ -24,7 +24,6 @@ def run_installation(app: App) -> None: logger.exception(f"An error occurred during installation: {e}") - class WizardController(Controller): """ Must intercept all logic errors. @@ -60,7 +59,7 @@ def init_view(self) -> "WizardView": return WizardView(self) def init_file_handler(self): - self.log_dir : Path = self.model.target_dir / "logs" + self.log_dir: Path = self.model.target_dir / "logs" tmp_file_name = "wizard.log" if not self.log_dir.exists(): diff --git a/src/antares_web_installer/gui/mvc.py b/src/antares_web_installer/gui/mvc.py index f858f04..8d3455a 100644 --- a/src/antares_web_installer/gui/mvc.py +++ b/src/antares_web_installer/gui/mvc.py @@ -41,7 +41,7 @@ def __init__(self, controller: Controller): def show_error(self, *args): err = traceback.format_exception(*args) - messagebox.showerror('Exception', "".join(err)) + messagebox.showerror("Exception", "".join(err)) class ControllerError(Exception): diff --git a/src/antares_web_installer/shortcuts/_win32_shell.py b/src/antares_web_installer/shortcuts/_win32_shell.py index b1c5ec4..e146b6a 100644 --- a/src/antares_web_installer/shortcuts/_win32_shell.py +++ b/src/antares_web_installer/shortcuts/_win32_shell.py @@ -59,7 +59,6 @@ def create_shortcut( icon_path: t.Union[str, os.PathLike] = "", description: str = "", ) -> None: - working_dir = working_dir or get_homedir() if isinstance(arguments, str): @@ -77,4 +76,3 @@ def create_shortcut( if icon_path: wscript.IconLocation = str(icon_path) wscript.save() - diff --git a/tests/config/test_config_2_18.py b/tests/config/test_config_2_18.py index c375103..c6a1201 100644 --- a/tests/config/test_config_2_18.py +++ b/tests/config/test_config_2_18.py @@ -6,7 +6,7 @@ def test_update_to_2_18(datadir: Path) -> None: - config = yaml.safe_load(datadir.joinpath(f"application-2.17.yaml").read_text()) - expected = yaml.safe_load(datadir.joinpath(f"application-2.18.yaml").read_text()) + config = yaml.safe_load(datadir.joinpath("application-2.17.yaml").read_text()) + expected = yaml.safe_load(datadir.joinpath("application-2.18.yaml").read_text()) update_to_2_18(config) assert config == expected From 998079f6f35e094a7a00497415ba940322541060 Mon Sep 17 00:00:00 2001 From: Sylvain Leclerc Date: Wed, 2 Oct 2024 13:35:44 +0200 Subject: [PATCH 18/29] fix: wait also when status code is not 200 Signed-off-by: Sylvain Leclerc --- src/antares_web_installer/app.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/antares_web_installer/app.py b/src/antares_web_installer/app.py index b180577..519c798 100644 --- a/src/antares_web_installer/app.py +++ b/src/antares_web_installer/app.py @@ -5,6 +5,7 @@ import textwrap import time import webbrowser +from contextlib import suppress from difflib import SequenceMatcher from pathlib import Path from shutil import copy2, copytree @@ -300,13 +301,12 @@ def start_server(self): while nb_attempts < max_attempts: logger.info(f"Waiting for server start (attempt #{nb_attempts})...") - try: + with suppress(httpx.RequestError): res = httpx.get(SERVER_ADDRESS + "/health", timeout=1) if res.status_code == 200: logger.info("The server is now running.") break - except httpx.RequestError: - time.sleep(1) + time.sleep(1) nb_attempts += 1 else: stdout, stderr = server_process.communicate() From 0df83b02cebea3aad16f5ed05c525e482ad444d5 Mon Sep 17 00:00:00 2001 From: Sylvain Leclerc Date: Fri, 4 Oct 2024 20:18:18 +0200 Subject: [PATCH 19/29] fix: don't wait for process to terminate on timeout Allow longer start (5 minutes). Signed-off-by: Sylvain Leclerc --- src/antares_web_installer/app.py | 24 +++++------------------- 1 file changed, 5 insertions(+), 19 deletions(-) diff --git a/src/antares_web_installer/app.py b/src/antares_web_installer/app.py index 519c798..7b3789b 100644 --- a/src/antares_web_installer/app.py +++ b/src/antares_web_installer/app.py @@ -5,6 +5,7 @@ import textwrap import time import webbrowser +from abc import abstractclassmethod, ABC, abstractmethod from contextlib import suppress from difflib import SequenceMatcher from pathlib import Path @@ -279,28 +280,17 @@ def start_server(self): args = [self.server_path] server_process = subprocess.Popen( args=args, - stdin=subprocess.PIPE, - stdout=subprocess.PIPE, - stderr=subprocess.STDOUT, cwd=self.target_dir, shell=True, ) self.update_progress(50) - if not server_process.poll(): - logger.info("Server is starting up ...") - else: - stdout, stderr = server_process.communicate() - msg = f"The server unexpectedly stopped running. (code {server_process.returncode})" - logger.info(msg) - logger.info(f"Server unexpectedly stopped.\nstdout: {stdout}\nstderr: {stderr}") - raise InstallError(msg) - nb_attempts = 0 - max_attempts = 30 - + max_attempts = 300 while nb_attempts < max_attempts: logger.info(f"Waiting for server start (attempt #{nb_attempts})...") + if server_process.poll() is not None: + raise InstallError("Server failed to start, please check server logs.") with suppress(httpx.RequestError): res = httpx.get(SERVER_ADDRESS + "/health", timeout=1) if res.status_code == 200: @@ -309,11 +299,7 @@ def start_server(self): time.sleep(1) nb_attempts += 1 else: - stdout, stderr = server_process.communicate() - msg = "The server didn't start in time" - logger.error(msg) - logger.error(f"stdout: {stdout}\nstderr: {stderr}") - raise InstallError(msg) + raise InstallError("Server didn't start in time, please check server logs.") def open_browser(self): """ From faf164de955b4d5aa9fef13a9754938ea46f0c24 Mon Sep 17 00:00:00 2001 From: Sylvain Leclerc Date: Fri, 4 Oct 2024 20:25:18 +0200 Subject: [PATCH 20/29] increase timeout on health polling request Signed-off-by: Sylvain Leclerc --- src/antares_web_installer/app.py | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/src/antares_web_installer/app.py b/src/antares_web_installer/app.py index 7b3789b..0afb75e 100644 --- a/src/antares_web_installer/app.py +++ b/src/antares_web_installer/app.py @@ -285,14 +285,15 @@ def start_server(self): ) self.update_progress(50) - nb_attempts = 0 - max_attempts = 300 - while nb_attempts < max_attempts: + start_time = time.time() + max_wait_time = 300 + nb_attempts = 1 + while time.time() - start_time < max_wait_time: logger.info(f"Waiting for server start (attempt #{nb_attempts})...") if server_process.poll() is not None: raise InstallError("Server failed to start, please check server logs.") with suppress(httpx.RequestError): - res = httpx.get(SERVER_ADDRESS + "/health", timeout=1) + res = httpx.get(SERVER_ADDRESS + "/health") if res.status_code == 200: logger.info("The server is now running.") break From a48b857d68e5f0afa4149c10f996bfd2c55484ec Mon Sep 17 00:00:00 2001 From: Sylvain Leclerc Date: Mon, 7 Oct 2024 09:22:59 +0200 Subject: [PATCH 21/29] remove useless imports Signed-off-by: Sylvain Leclerc --- src/antares_web_installer/app.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/antares_web_installer/app.py b/src/antares_web_installer/app.py index 0afb75e..23e2c6a 100644 --- a/src/antares_web_installer/app.py +++ b/src/antares_web_installer/app.py @@ -5,7 +5,6 @@ import textwrap import time import webbrowser -from abc import abstractclassmethod, ABC, abstractmethod from contextlib import suppress from difflib import SequenceMatcher from pathlib import Path @@ -281,6 +280,8 @@ def start_server(self): server_process = subprocess.Popen( args=args, cwd=self.target_dir, + stdout=subprocess.DEVNULL, + stderr=subprocess.DEVNULL, shell=True, ) self.update_progress(50) From f7c702dac7fd5e4a563c51f5ba4e01a4a2f5b1bc Mon Sep 17 00:00:00 2001 From: Sylvain Leclerc Date: Tue, 8 Oct 2024 14:41:45 +0200 Subject: [PATCH 22/29] fix: update healthcheck URL Signed-off-by: Sylvain Leclerc --- src/antares_web_installer/app.py | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/antares_web_installer/app.py b/src/antares_web_installer/app.py index 23e2c6a..fa0ddaf 100644 --- a/src/antares_web_installer/app.py +++ b/src/antares_web_installer/app.py @@ -32,6 +32,9 @@ SHORTCUT_NAMES = {"posix": "AntaresWebServer.desktop", "nt": "AntaresWebServer.lnk"} SERVER_ADDRESS = "http://127.0.0.1:8080" +HEALTHCHECK_ADDRESS = f"{SERVER_ADDRESS}/api/health" + +MAX_SERVER_START_TIME = 60 class InstallError(Exception): @@ -287,14 +290,13 @@ def start_server(self): self.update_progress(50) start_time = time.time() - max_wait_time = 300 nb_attempts = 1 - while time.time() - start_time < max_wait_time: + while time.time() - start_time < MAX_SERVER_START_TIME: logger.info(f"Waiting for server start (attempt #{nb_attempts})...") if server_process.poll() is not None: raise InstallError("Server failed to start, please check server logs.") with suppress(httpx.RequestError): - res = httpx.get(SERVER_ADDRESS + "/health") + res = httpx.get(HEALTHCHECK_ADDRESS) if res.status_code == 200: logger.info("The server is now running.") break From 348299eb3a340273ab777786e2750ecb7e5f7b16 Mon Sep 17 00:00:00 2001 From: Sylvain Leclerc Date: Tue, 8 Oct 2024 16:41:59 +0200 Subject: [PATCH 23/29] fix: do not throw an error when target dir does not exist Signed-off-by: Sylvain Leclerc --- src/antares_web_installer/gui/controller.py | 6 ++---- src/antares_web_installer/gui/view.py | 6 +----- 2 files changed, 3 insertions(+), 9 deletions(-) diff --git a/src/antares_web_installer/gui/controller.py b/src/antares_web_installer/gui/controller.py index 41b36ee..00ba4ff 100644 --- a/src/antares_web_installer/gui/controller.py +++ b/src/antares_web_installer/gui/controller.py @@ -146,10 +146,8 @@ def install(self, callback: typing.Callable): def get_target_dir(self) -> Path: return self.model.target_dir - def set_target_dir(self, path: Path): - result = self.model.set_target_dir(path) - if not result: - raise ControllerError("Path '{}' is not a directory.".format(path)) + def set_target_dir(self, path: Path) -> None: + self.model.set_target_dir(path) def get_shortcut(self) -> bool: return self.model.shortcut diff --git a/src/antares_web_installer/gui/view.py b/src/antares_web_installer/gui/view.py index a8f7997..2dc140e 100644 --- a/src/antares_web_installer/gui/view.py +++ b/src/antares_web_installer/gui/view.py @@ -154,11 +154,7 @@ def get_target_dir(self) -> Path: return self.controller.get_target_dir() def set_target_dir(self, new_target_dir: str): - try: - self.controller.set_target_dir(Path(new_target_dir)) - except ControllerError as e: - logger.warning("Path is not valid: {}".format(e)) - self.raise_warning("Path selected is not valid") + self.controller.set_target_dir(Path(new_target_dir)) def get_launch(self) -> bool: return self.controller.get_launch() From 7a94b91e7c9235254313aedaec6e35dd244b4ac1 Mon Sep 17 00:00:00 2001 From: Sylvain Leclerc Date: Thu, 10 Oct 2024 16:38:49 +0200 Subject: [PATCH 24/29] fix: add logs Signed-off-by: Sylvain Leclerc --- src/antares_web_installer/app.py | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/antares_web_installer/app.py b/src/antares_web_installer/app.py index fa0ddaf..505f722 100644 --- a/src/antares_web_installer/app.py +++ b/src/antares_web_installer/app.py @@ -295,11 +295,16 @@ def start_server(self): logger.info(f"Waiting for server start (attempt #{nb_attempts})...") if server_process.poll() is not None: raise InstallError("Server failed to start, please check server logs.") - with suppress(httpx.RequestError): + try: res = httpx.get(HEALTHCHECK_ADDRESS) if res.status_code == 200: logger.info("The server is now running.") break + else: + logger.debug(f"Got HTTP status code {res.status_code} while requesting {HEALTHCHECK_ADDRESS}") + logger.debug(f"Content: {res.text}") + except httpx.RequestError as http_err: + logger.debug(f"Error while requesting {HEALTHCHECK_ADDRESS}: {http_err}", exc_info=http_err) time.sleep(1) nb_attempts += 1 else: From 07a630762f775b951b2aee1bedaa31169883a3ff Mon Sep 17 00:00:00 2001 From: Sylvain Leclerc Date: Fri, 11 Oct 2024 09:56:01 +0200 Subject: [PATCH 25/29] fix: revert to requests, httpx has issues with proxy on windows Signed-off-by: Sylvain Leclerc --- pyproject.toml | 5 ++--- src/antares_web_installer/app.py | 9 ++++----- 2 files changed, 6 insertions(+), 8 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index e782ac8..e140bda 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -31,7 +31,7 @@ dependencies = [ 'psutil<5.10', 'pyyaml<6.1', 'pywin32<=306; sys_platform == "win32"', - 'httpx<0.28', + 'requests', 'platformdirs<=4.2.2', 'uvicorn', ] @@ -52,7 +52,6 @@ dependencies = [ "pytest-datadir", "fastapi", "pyinstaller", - "httpx==0.27.0", "requests", "platformdirs==4.2.2", "uvicorn", @@ -79,7 +78,7 @@ dependencies = [ "mypy>=1.0.0", "fastapi", "pyinstaller", - "httpx==0.27.0" + "requests" ] [tool.hatch.envs.types.scripts] check = "mypy --install-types --non-interactive {args:src/antares_web_installer tests}" diff --git a/src/antares_web_installer/app.py b/src/antares_web_installer/app.py index 505f722..8961a46 100644 --- a/src/antares_web_installer/app.py +++ b/src/antares_web_installer/app.py @@ -5,13 +5,12 @@ import textwrap import time import webbrowser -from contextlib import suppress from difflib import SequenceMatcher from pathlib import Path from shutil import copy2, copytree from typing import List -import httpx +import requests if os.name == "nt": from pythoncom import com_error @@ -296,15 +295,15 @@ def start_server(self): if server_process.poll() is not None: raise InstallError("Server failed to start, please check server logs.") try: - res = httpx.get(HEALTHCHECK_ADDRESS) + res = requests.get(HEALTHCHECK_ADDRESS) if res.status_code == 200: logger.info("The server is now running.") break else: logger.debug(f"Got HTTP status code {res.status_code} while requesting {HEALTHCHECK_ADDRESS}") logger.debug(f"Content: {res.text}") - except httpx.RequestError as http_err: - logger.debug(f"Error while requesting {HEALTHCHECK_ADDRESS}: {http_err}", exc_info=http_err) + except requests.RequestException as req_err: + logger.debug(f"Error while requesting {HEALTHCHECK_ADDRESS}: {req_err}", exc_info=req_err) time.sleep(1) nb_attempts += 1 else: From 3457553b3a58552b07bfa4099df97d46cc26ced3 Mon Sep 17 00:00:00 2001 From: Sylvain Leclerc Date: Fri, 11 Oct 2024 16:32:52 +0200 Subject: [PATCH 26/29] fix: tests Signed-off-by: Sylvain Leclerc --- tests/integration/test_run_server.py | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/tests/integration/test_run_server.py b/tests/integration/test_run_server.py index 84063fe..06566ef 100644 --- a/tests/integration/test_run_server.py +++ b/tests/integration/test_run_server.py @@ -1,8 +1,9 @@ -import httpx # type: ignore -import subprocess import socket +import subprocess import time +import requests # type: ignore + SPAWN_TIMEOUT = 10 """Timeout in seconds to wait for the server process to start.""" @@ -67,7 +68,7 @@ def test_server_health(antares_web_server_paths): else: raise RuntimeError("The server did not start in time.") - res = httpx.get("http://localhost:8080/health", timeout=0.25) + res = requests.get("http://localhost:8080/health", timeout=0.25) assert res.status_code == 200, res.json() assert res.json() == {"status": "available"} From aa3c3696883cfaae13719d96a3e7fb98e06b2d38 Mon Sep 17 00:00:00 2001 From: Sylvain Leclerc Date: Fri, 11 Oct 2024 16:56:14 +0200 Subject: [PATCH 27/29] fix mock Signed-off-by: Sylvain Leclerc --- tests/integration/server_mock/web.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/integration/server_mock/web.py b/tests/integration/server_mock/web.py index b484601..f29c0ca 100644 --- a/tests/integration/server_mock/web.py +++ b/tests/integration/server_mock/web.py @@ -30,7 +30,7 @@ async def lifespan(_unused_app: FastAPI) -> t.AsyncGenerator[None, None]: app = FastAPI(lifespan=lifespan) -@app.get("/health") +@app.get("/api/health") async def health(): """ Endpoint to check that the server is ready. From 54c0e775c3158deeb7d198061f6abf18e09a3343 Mon Sep 17 00:00:00 2001 From: Sylvain Leclerc Date: Fri, 11 Oct 2024 17:04:52 +0200 Subject: [PATCH 28/29] fix: fix healthcheck test Signed-off-by: Sylvain Leclerc --- tests/integration/test_run_server.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/integration/test_run_server.py b/tests/integration/test_run_server.py index 06566ef..5b7a1ce 100644 --- a/tests/integration/test_run_server.py +++ b/tests/integration/test_run_server.py @@ -68,7 +68,7 @@ def test_server_health(antares_web_server_paths): else: raise RuntimeError("The server did not start in time.") - res = requests.get("http://localhost:8080/health", timeout=0.25) + res = requests.get("http://localhost:8080/api/health", timeout=0.25) assert res.status_code == 200, res.json() assert res.json() == {"status": "available"} From d84a6ea4b79ee32156087f2cd0ee6f2ac01c8a1d Mon Sep 17 00:00:00 2001 From: Sylvain Leclerc Date: Fri, 11 Oct 2024 17:08:28 +0200 Subject: [PATCH 29/29] fix: format Signed-off-by: Sylvain Leclerc --- src/antares_web_installer/gui/controller.py | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/src/antares_web_installer/gui/controller.py b/src/antares_web_installer/gui/controller.py index 00ba4ff..d05dc4c 100644 --- a/src/antares_web_installer/gui/controller.py +++ b/src/antares_web_installer/gui/controller.py @@ -8,13 +8,12 @@ from threading import Thread from typing import Optional -from antares_web_installer.gui.mvc import Controller, ControllerError -from antares_web_installer.gui.model import WizardModel -from antares_web_installer.gui.view import WizardView - from antares_web_installer import logger from antares_web_installer.app import App, InstallError from antares_web_installer.gui.logger import ConsoleHandler, ProgressHandler, LogFileHandler +from antares_web_installer.gui.model import WizardModel +from antares_web_installer.gui.mvc import Controller +from antares_web_installer.gui.view import WizardView def run_installation(app: App) -> None: