diff libervia/backend/plugins/plugin_misc_app_manager/__init__.py @ 4270:0d7bb4df2343

Reformatted code base using black.
author Goffi <goffi@goffi.org>
date Wed, 19 Jun 2024 18:44:57 +0200
parents 4aa62767f501
children
line wrap: on
line diff
--- a/libervia/backend/plugins/plugin_misc_app_manager/__init__.py	Tue Jun 18 12:06:45 2024 +0200
+++ b/libervia/backend/plugins/plugin_misc_app_manager/__init__.py	Wed Jun 19 18:44:57 2024 +0200
@@ -45,7 +45,7 @@
     import yaml
 except ImportError:
     raise exceptions.MissingModule(
-        'Missing module PyYAML, please download/install it. You can use '
+        "Missing module PyYAML, please download/install it. You can use "
         '"pip install pyyaml"'
     )
 
@@ -59,8 +59,6 @@
     from yaml import Loader, Dumper
 
 
-
-
 PLUGIN_INFO = {
     C.PI_NAME: "Applications Manager",
     C.PI_IMPORT_NAME: "APP_MANAGER",
@@ -73,7 +71,8 @@
 
 Manage external applications using packagers, OS virtualization/containers or other
 software management tools.
-"""),
+"""
+    ),
 }
 
 APP_FILE_PREFIX = "libervia_app_"
@@ -92,7 +91,6 @@
         # instance id to app data map
         self._instances = {}
 
-
         self.persistent_data = persistent.LazyPersistentBinaryDict("app_manager")
 
         host.bridge.add_method(
@@ -128,30 +126,28 @@
         )
         # application has been started succeesfully,
         # args: name, instance_id, extra
-        host.bridge.add_signal(
-            "application_started", ".plugin", signature="sss"
-        )
+        host.bridge.add_signal("application_started", ".plugin", signature="sss")
         # application went wrong with the application
         # args: name, instance_id, extra
-        host.bridge.add_signal(
-            "application_error", ".plugin", signature="sss"
+        host.bridge.add_signal("application_error", ".plugin", signature="sss")
+        yaml.add_constructor("!libervia_conf", self._libervia_conf_constr, Loader=Loader)
+        yaml.add_constructor(
+            "!libervia_generate_pwd", self._libervia_generate_pwd_constr, Loader=Loader
         )
         yaml.add_constructor(
-            "!libervia_conf", self._libervia_conf_constr, Loader=Loader)
-        yaml.add_constructor(
-            "!libervia_generate_pwd", self._libervia_generate_pwd_constr, Loader=Loader)
-        yaml.add_constructor(
-            "!libervia_param", self._libervia_param_constr, Loader=Loader)
+            "!libervia_param", self._libervia_param_constr, Loader=Loader
+        )
 
     def unload(self):
         log.debug("unloading applications manager")
         for instances in self._started.values():
             for instance in instances:
-                data = instance['data']
-                if not data['single_instance']:
+                data = instance["data"]
+                if not data["single_instance"]:
                     log.debug(
-                        f"cleaning temporary directory at {data['_instance_dir_path']}")
-                    data['_instance_dir_obj'].cleanup()
+                        f"cleaning temporary directory at {data['_instance_dir_path']}"
+                    )
+                    data["_instance_dir_obj"].cleanup()
 
     def _libervia_conf_constr(self, loader, node) -> str:
         """Get a value from Libervia configuration
@@ -183,22 +179,27 @@
 
         value = self.host.memory.config_get(section, name, default)
         # FIXME: "public_url" is used only here and doesn't take multi-sites into account
-        if name == "public_url" and (not value or value.startswith('http')):
+        if name == "public_url" and (not value or value.startswith("http")):
             if not value:
-                log.warning(_(
-                    'No value found for "public_url", using "example.org" for '
-                    'now, please set the proper value in libervia.conf'))
+                log.warning(
+                    _(
+                        'No value found for "public_url", using "example.org" for '
+                        "now, please set the proper value in libervia.conf"
+                    )
+                )
             else:
-                log.warning(_(
-                    'invalid value for "public_url" ({value}), it musts not start with '
-                    'schema ("http"), ignoring it and using "example.org" '
-                    'instead')
-                        .format(value=value))
+                log.warning(
+                    _(
+                        'invalid value for "public_url" ({value}), it musts not start with '
+                        'schema ("http"), ignoring it and using "example.org" '
+                        "instead"
+                    ).format(value=value)
+                )
             value = "example.org"
 
         if filter_ is None:
             pass
-        elif filter_ == 'first':
+        elif filter_ == "first":
             value = value[0]
         elif filter_ == "not":
             value = C.bool(value)
@@ -232,7 +233,7 @@
         except KeyError:
             alphabet = string.ascii_letters + string.digits
             key_size = int(kwargs.get("size", 30))
-            key = ''.join(secrets.choice(alphabet) for __ in range(key_size))
+            key = "".join(secrets.choice(alphabet) for __ in range(key_size))
             self._app_persistent_data[pwd_data_key] = key
         else:
             log.debug(f"Re-using existing key for {name!r} password.")
@@ -255,7 +256,8 @@
         name = manager.name
         if name in self._managers:
             raise exceptions.ConflictError(
-                f"There is already a manager with the name {name}")
+                f"There is already a manager with the name {name}"
+            )
         self._managers[manager.name] = manager
         if manager.discover_path is not None:
             self.discover(manager.discover_path, manager)
@@ -269,25 +271,18 @@
         try:
             app_type = app_data["type"]
         except KeyError:
-            raise exceptions.DataError(
-                "app file doesn't have the mandatory \"type\" key"
-            )
+            raise exceptions.DataError('app file doesn\'t have the mandatory "type" key')
         if not isinstance(app_type, str):
-            raise exceptions.DataError(
-                f"invalid app data type: {app_type!r}"
-            )
+            raise exceptions.DataError(f"invalid app data type: {app_type!r}")
         app_type = app_type.strip()
         try:
             return self._managers[app_type]
         except KeyError:
             raise exceptions.NotFound(
-                f"No manager found to manage app of type {app_type!r}")
+                f"No manager found to manage app of type {app_type!r}"
+            )
 
-    def get_app_data(
-        self,
-        id_type: Optional[str],
-        identifier: str
-    ) -> dict:
+    def get_app_data(self, id_type: Optional[str], identifier: str) -> dict:
         """Retrieve instance's app_data from identifier
 
         @param id_type: type of the identifier, can be:
@@ -300,8 +295,8 @@
         @raise ValueError: id_type is invalid
         """
         if not id_type:
-            id_type = 'name'
-        if id_type == 'name':
+            id_type = "name"
+        if id_type == "name":
             identifier = identifier.lower().strip()
             try:
                 return next(iter(self._started[identifier]))
@@ -309,7 +304,7 @@
                 raise exceptions.NotFound(
                     f"No instance of {identifier!r} is currently running"
                 )
-        elif id_type == 'instance':
+        elif id_type == "instance":
             instance_id = identifier
             try:
                 return self._instances[instance_id]
@@ -320,11 +315,7 @@
         else:
             raise ValueError(f"invalid id_type: {id_type!r}")
 
-    def discover(
-        self,
-        dir_path: Path,
-        manager: AppManagerBackend|None = None
-    ) -> None:
+    def discover(self, dir_path: Path, manager: AppManagerBackend | None = None) -> None:
         """Search for app configuration file.
 
         App configuration files must start with [APP_FILE_PREFIX] and have a ``.yaml``
@@ -336,19 +327,16 @@
                     app_data = self.parse(file_path)
                     manager = self.get_manager(app_data)
                 except (exceptions.DataError, exceptions.NotFound) as e:
-                    log.warning(
-                        f"Can't parse {file_path}, skipping: {e}")
+                    log.warning(f"Can't parse {file_path}, skipping: {e}")
                     continue
-            app_name = file_path.stem[len(APP_FILE_PREFIX):].strip().lower()
+            app_name = file_path.stem[len(APP_FILE_PREFIX) :].strip().lower()
             if not app_name:
                 log.warning(f"invalid app file name at {file_path}")
                 continue
             app_dict = self._apps.setdefault(app_name, {})
             manager_set = app_dict.setdefault(manager, set())
             manager_set.add(file_path)
-            log.debug(
-                f"{app_name!r} {manager.name} application found"
-            )
+            log.debug(f"{app_name!r} {manager.name} application found")
 
     def parse(self, file_path: Path, params: Optional[dict] = None) -> dict:
         """Parse Libervia application file
@@ -367,7 +355,7 @@
         if "name" not in app_data:
             # note that we don't use lower() here as we want human readable name and
             # uppercase may be set on purpose
-            app_data['name'] = file_path.stem[len(APP_FILE_PREFIX):].strip()
+            app_data["name"] = file_path.stem[len(APP_FILE_PREFIX) :].strip()
         single_instance = app_data.setdefault("single_instance", True)
         if not isinstance(single_instance, bool):
             raise ValueError(
@@ -429,9 +417,7 @@
         try:
             app_file_path = next(iter(next(iter(self._apps[app_name].values()))))
         except KeyError:
-            raise exceptions.NotFound(
-                f"No application found with the name {app_name!r}"
-            )
+            raise exceptions.NotFound(f"No application found with the name {app_name!r}")
         log.info(f"starting {app_name!r}")
         self._app_persistent_data = await self.persistent_data.get(app_name) or {}
         self._app_persistent_data["last_started"] = time.time()
@@ -439,13 +425,10 @@
         app_data = self.parse(app_file_path, extra)
         await self.persistent_data.aset(app_name, self._app_persistent_data)
         app_data["_started"] = False
-        app_data['_file_path'] = app_file_path
-        app_data['_name_canonical'] = app_name
-        single_instance = app_data['single_instance']
-        ret_data = {
-            "name": app_name,
-            "started": False
-        }
+        app_data["_file_path"] = app_file_path
+        app_data["_name_canonical"] = app_name
+        single_instance = app_data["single_instance"]
+        ret_data = {"name": app_name, "started": False}
         if single_instance:
             if started_data:
                 instance_data = started_data[0]
@@ -462,14 +445,14 @@
                     PLUGIN_INFO[C.PI_IMPORT_NAME], app_name
                 )
                 cache_path.mkdir(0o700, parents=True, exist_ok=True)
-                app_data['_instance_dir_path'] = cache_path
+                app_data["_instance_dir_path"] = cache_path
         else:
             dest_dir_obj = tempfile.TemporaryDirectory(prefix="libervia_app_")
-            app_data['_instance_dir_obj'] = dest_dir_obj
-            app_data['_instance_dir_path'] = Path(dest_dir_obj.name)
-        instance_id = ret_data["instance"] = app_data['_instance_id'] = shortuuid.uuid()
+            app_data["_instance_dir_obj"] = dest_dir_obj
+            app_data["_instance_dir_path"] = Path(dest_dir_obj.name)
+        instance_id = ret_data["instance"] = app_data["_instance_id"] = shortuuid.uuid()
         manager = self.get_manager(app_data)
-        app_data['_manager'] = manager
+        app_data["_manager"] = manager
         started_data.append(app_data)
         self._instances[instance_id] = app_data
         # we retrieve exposed data such as url_prefix which can be useful computed exposed
@@ -482,7 +465,7 @@
             start = manager.start
         except AttributeError:
             raise exceptions.InternalError(
-                f"{manager.name} doesn't have the mandatory \"start\" method"
+                f'{manager.name} doesn\'t have the mandatory "start" method'
             )
         else:
             defer.ensureDeferred(self.start_app(start, app_data))
@@ -498,12 +481,8 @@
             self.host.bridge.application_error(
                 app_name,
                 instance_id,
-                data_format.serialise(
-                    {
-                        "class": str(type(e)),
-                        "msg": str(e)
-                    }
-                ))
+                data_format.serialise({"class": str(type(e)), "msg": str(e)}),
+            )
         else:
             app_data["_started"] = True
             self.host.bridge.application_started(app_name, instance_id, "")
@@ -512,7 +491,8 @@
     def _stop(self, identifier, id_type, extra):
         extra = data_format.deserialise(extra)
         return defer.ensureDeferred(
-            self.stop(str(identifier), str(id_type) or None, extra))
+            self.stop(str(identifier), str(id_type) or None, extra)
+        )
 
     async def stop(
         self,
@@ -527,15 +507,15 @@
 
         log.info(f"stopping {app_data['name']!r}")
 
-        app_name = app_data['_name_canonical']
-        instance_id = app_data['_instance_id']
-        manager = app_data['_manager']
+        app_name = app_data["_name_canonical"]
+        instance_id = app_data["_instance_id"]
+        manager = app_data["_manager"]
 
         try:
             stop = manager.stop
         except AttributeError:
             raise exceptions.InternalError(
-                f"{manager.name} doesn't have the mandatory \"stop\" method"
+                f'{manager.name} doesn\'t have the mandatory "stop" method'
             )
         else:
             try:
@@ -551,7 +531,8 @@
             del self._instances[instance_id]
         except KeyError:
             log.error(
-                f"INTERNAL ERROR: {instance_id!r} is not present in self._instances")
+                f"INTERNAL ERROR: {instance_id!r} is not present in self._instances"
+            )
 
         try:
             self._started[app_name].remove(app_data)
@@ -590,13 +571,13 @@
         to handle manager specific conventions.
         """
         app_data = self.get_app_data(id_type, identifier)
-        if app_data.get('_exposed_computed', False):
-            return app_data['expose']
+        if app_data.get("_exposed_computed", False):
+            return app_data["expose"]
         if extra is None:
             extra = {}
         expose = app_data.setdefault("expose", {})
         if "passwords" in expose:
-            passwords = expose['passwords']
+            passwords = expose["passwords"]
             for name, value in list(passwords.items()):
                 if isinstance(value, list):
                     # if we have a list, is the sequence of keys leading to the value
@@ -605,7 +586,8 @@
                         passwords[name] = self.get_app_data_value(value, app_data)
                     except KeyError:
                         log.warning(
-                            f"Can't retrieve exposed value for password {name!r}: {e}")
+                            f"Can't retrieve exposed value for password {name!r}: {e}"
+                        )
                         del passwords[name]
 
         for key in ("url_prefix", "front_url"):
@@ -614,9 +596,7 @@
                 try:
                     expose[key] = self.get_app_data_value(value, app_data)
                 except KeyError:
-                    log.warning(
-                        f"Can't retrieve exposed value for {key!r} at {value}"
-                    )
+                    log.warning(f"Can't retrieve exposed value for {key!r} at {value}")
                     del expose[key]
 
         front_url = expose.get("front_url")
@@ -628,35 +608,35 @@
                     path_elt = parsed_url.path.split("/", 1)
                     parsed_url = parsed_url._replace(
                         netloc=path_elt[0],
-                        path=f"/{path_elt[1]}" if len(path_elt) > 1 else ""
+                        path=f"/{path_elt[1]}" if len(path_elt) > 1 else "",
                     )
-                parsed_url = parsed_url._replace(scheme='https')
+                parsed_url = parsed_url._replace(scheme="https")
                 expose["front_url"] = urlunparse(parsed_url)
 
         if extra.get("skip_compute", False):
             return expose
 
         try:
-            compute_expose = app_data['_manager'].compute_expose
+            compute_expose = app_data["_manager"].compute_expose
         except AttributeError:
             pass
         else:
             await compute_expose(app_data)
 
-        app_data['_exposed_computed'] = True
+        app_data["_exposed_computed"] = True
         return expose
 
     async def _do_prepare(
         self,
         app_data: dict,
     ) -> None:
-        name = app_data['name']
-        dest_path = app_data['_instance_dir_path']
+        name = app_data["name"]
+        dest_path = app_data["_instance_dir_path"]
         if next(dest_path.iterdir(), None) != None:
             log.debug(f"There is already a prepared dir at {dest_path}, nothing to do")
             return
         try:
-            prepare = app_data['prepare'].copy()
+            prepare = app_data["prepare"].copy()
         except KeyError:
             prepare = {}
 
@@ -668,7 +648,7 @@
             log.debug(f"[{name}] [prepare] running {action!r} action")
             if action == "git":
                 try:
-                    git_path = which('git')[0]
+                    git_path = which("git")[0]
                 except IndexError:
                     raise exceptions.NotFound(
                         "Can't find \"git\" executable, {name} can't be started without it"
@@ -688,8 +668,8 @@
         self,
         app_data: dict,
     ) -> None:
-        dest_path = app_data['_instance_dir_path']
-        files = app_data.get('files')
+        dest_path = app_data["_instance_dir_path"]
+        files = app_data.get("files")
         if not files:
             return
         if not isinstance(files, dict):