diff libervia/backend/core/main.py @ 4193:730f542e4ad0

core: add new `init_script_path` option: `init_script_path` option can be used in `[DEFAULTS]` to run a script at the end of backend initialisation. A new `init_pre_script` method is used to wait for backend to reach this stage (designed to be used mostly by CLI frontend), then the usual `ready_get` method is finished once the script is finished.
author Goffi <goffi@goffi.org>
date Wed, 13 Dec 2023 22:00:22 +0100
parents 3b95704ab777
children e11b13418ba6
line wrap: on
line diff
--- a/libervia/backend/core/main.py	Tue Dec 12 12:17:15 2023 +0100
+++ b/libervia/backend/core/main.py	Wed Dec 13 22:00:22 2023 +0100
@@ -22,7 +22,7 @@
 import hashlib
 import copy
 from pathlib import Path
-from typing import Optional, List, Tuple, Dict
+from typing import Optional, List, Tuple, Dict, cast
 
 from wokkel.data_form import Option
 from libervia import backend
@@ -49,6 +49,7 @@
 from libervia.backend.tools.common import dynamic_import
 from libervia.backend.tools.common import regex
 from libervia.backend.tools.common import data_format
+from libervia.backend.tools.common import async_process
 from libervia.backend.stdui import ui_contact_list, ui_profile_manager
 import libervia.backend.plugins
 
@@ -66,6 +67,10 @@
         self._menus = {}
         self._menus_paths = {}  # path to id. key: (menu_type, lower case tuple of path),
                                 # value: menu id
+
+        # like initialised, but launched before init script is done, mainly useful for CLI
+        # frontend, so it can be used in init script, while other frontends are waiting.
+        self.init_pre_script = defer.Deferred()
         self.initialised = defer.Deferred()
         self.profiles = {}
         self.plugins = {}
@@ -143,6 +148,7 @@
                 reactor.callLater(0, self.stop)
                 return
 
+        self.bridge.register_method("init_pre_script", lambda: self.init_pre_script)
         self.bridge.register_method("ready_get", lambda: self.initialised)
         self.bridge.register_method("version_get", lambda: self.full_version)
         self.bridge.register_method("features_get", self.features_get)
@@ -239,6 +245,30 @@
             sys.exit(1)
         self._add_base_menus()
 
+        self.init_pre_script.callback(None)
+
+        init_script = self.memory.config_get(None, "init_script_path")
+        if init_script is not None:
+            init_script = cast(str, init_script)
+            script_path = Path(init_script)
+            if not script_path.exists():
+                log.error(f"Init script doesn't exist: {init_script}")
+                sys.exit(C.EXIT_BAD_ARG)
+            elif not script_path.is_file():
+                log.error(f"Init script is not a file: {init_script}")
+                sys.exit(C.EXIT_BAD_ARG)
+            else:
+                log.info(f"Running init script {init_script!r}.")
+                try:
+                    await async_process.run(
+                        str(init_script),
+                        verbose=True
+                    )
+                except RuntimeError as e:
+                    log.error(f"Init script failed: {e}")
+                    self.stopService()
+                    sys.exit(C.EXIT_ERROR)
+
         self.initialised.callback(None)
         log.info(_("Backend is ready"))