Mercurial > libervia-backend
comparison 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 |
comparison
equal
deleted
inserted
replaced
4192:1d24ff583794 | 4193:730f542e4ad0 |
---|---|
20 import os.path | 20 import os.path |
21 import uuid | 21 import uuid |
22 import hashlib | 22 import hashlib |
23 import copy | 23 import copy |
24 from pathlib import Path | 24 from pathlib import Path |
25 from typing import Optional, List, Tuple, Dict | 25 from typing import Optional, List, Tuple, Dict, cast |
26 | 26 |
27 from wokkel.data_form import Option | 27 from wokkel.data_form import Option |
28 from libervia import backend | 28 from libervia import backend |
29 from libervia.backend.core.i18n import _, D_, language_switch | 29 from libervia.backend.core.i18n import _, D_, language_switch |
30 from libervia.backend.core import patches | 30 from libervia.backend.core import patches |
47 from libervia.backend.tools import utils | 47 from libervia.backend.tools import utils |
48 from libervia.backend.tools import image | 48 from libervia.backend.tools import image |
49 from libervia.backend.tools.common import dynamic_import | 49 from libervia.backend.tools.common import dynamic_import |
50 from libervia.backend.tools.common import regex | 50 from libervia.backend.tools.common import regex |
51 from libervia.backend.tools.common import data_format | 51 from libervia.backend.tools.common import data_format |
52 from libervia.backend.tools.common import async_process | |
52 from libervia.backend.stdui import ui_contact_list, ui_profile_manager | 53 from libervia.backend.stdui import ui_contact_list, ui_profile_manager |
53 import libervia.backend.plugins | 54 import libervia.backend.plugins |
54 | 55 |
55 | 56 |
56 log = getLogger(__name__) | 57 log = getLogger(__name__) |
64 self._cb_map = {} # map from callback_id to callbacks | 65 self._cb_map = {} # map from callback_id to callbacks |
65 # dynamic menus. key: callback_id, value: menu data (dictionnary) | 66 # dynamic menus. key: callback_id, value: menu data (dictionnary) |
66 self._menus = {} | 67 self._menus = {} |
67 self._menus_paths = {} # path to id. key: (menu_type, lower case tuple of path), | 68 self._menus_paths = {} # path to id. key: (menu_type, lower case tuple of path), |
68 # value: menu id | 69 # value: menu id |
70 | |
71 # like initialised, but launched before init script is done, mainly useful for CLI | |
72 # frontend, so it can be used in init script, while other frontends are waiting. | |
73 self.init_pre_script = defer.Deferred() | |
69 self.initialised = defer.Deferred() | 74 self.initialised = defer.Deferred() |
70 self.profiles = {} | 75 self.profiles = {} |
71 self.plugins = {} | 76 self.plugins = {} |
72 # map for short name to whole namespace, | 77 # map for short name to whole namespace, |
73 # extended by plugins with register_namespace | 78 # extended by plugins with register_namespace |
141 log.exception("Could not initialize bridge") | 146 log.exception("Could not initialize bridge") |
142 # because init is not complete at this stage, we use callLater | 147 # because init is not complete at this stage, we use callLater |
143 reactor.callLater(0, self.stop) | 148 reactor.callLater(0, self.stop) |
144 return | 149 return |
145 | 150 |
151 self.bridge.register_method("init_pre_script", lambda: self.init_pre_script) | |
146 self.bridge.register_method("ready_get", lambda: self.initialised) | 152 self.bridge.register_method("ready_get", lambda: self.initialised) |
147 self.bridge.register_method("version_get", lambda: self.full_version) | 153 self.bridge.register_method("version_get", lambda: self.full_version) |
148 self.bridge.register_method("features_get", self.features_get) | 154 self.bridge.register_method("features_get", self.features_get) |
149 self.bridge.register_method("profile_name_get", self.memory.get_profile_name) | 155 self.bridge.register_method("profile_name_get", self.memory.get_profile_name) |
150 self.bridge.register_method("profiles_list_get", self.memory.get_profiles_list) | 156 self.bridge.register_method("profiles_list_get", self.memory.get_profiles_list) |
237 except Exception as e: | 243 except Exception as e: |
238 log.error(f"Could not initialize backend: {e}") | 244 log.error(f"Could not initialize backend: {e}") |
239 sys.exit(1) | 245 sys.exit(1) |
240 self._add_base_menus() | 246 self._add_base_menus() |
241 | 247 |
248 self.init_pre_script.callback(None) | |
249 | |
250 init_script = self.memory.config_get(None, "init_script_path") | |
251 if init_script is not None: | |
252 init_script = cast(str, init_script) | |
253 script_path = Path(init_script) | |
254 if not script_path.exists(): | |
255 log.error(f"Init script doesn't exist: {init_script}") | |
256 sys.exit(C.EXIT_BAD_ARG) | |
257 elif not script_path.is_file(): | |
258 log.error(f"Init script is not a file: {init_script}") | |
259 sys.exit(C.EXIT_BAD_ARG) | |
260 else: | |
261 log.info(f"Running init script {init_script!r}.") | |
262 try: | |
263 await async_process.run( | |
264 str(init_script), | |
265 verbose=True | |
266 ) | |
267 except RuntimeError as e: | |
268 log.error(f"Init script failed: {e}") | |
269 self.stopService() | |
270 sys.exit(C.EXIT_ERROR) | |
271 | |
242 self.initialised.callback(None) | 272 self.initialised.callback(None) |
243 log.info(_("Backend is ready")) | 273 log.info(_("Backend is ready")) |
244 | 274 |
245 # profile autoconnection must be done after self.initialised is called because | 275 # profile autoconnection must be done after self.initialised is called because |
246 # start_session waits for it. | 276 # start_session waits for it. |