diff sat_frontends/jp/cmd_info.py @ 3040:fee60f17ebac

jp: jp asyncio port: /!\ this commit is huge. Jp is temporarily not working with `dbus` bridge /!\ This patch implements the port of jp to asyncio, so it is now correctly using the bridge asynchronously, and it can be used with bridges like `pb`. This also simplify the code, notably for things which were previously implemented with many callbacks (like pagination with RSM). During the process, some behaviours have been modified/fixed, in jp and backends, check diff for details.
author Goffi <goffi@goffi.org>
date Wed, 25 Sep 2019 08:56:41 +0200
parents ab2696e34d29
children 9d0df638c8b4
line wrap: on
line diff
--- a/sat_frontends/jp/cmd_info.py	Wed Sep 25 08:53:38 2019 +0200
+++ b/sat_frontends/jp/cmd_info.py	Wed Sep 25 08:56:41 2019 +0200
@@ -31,53 +31,19 @@
 
     def __init__(self, host):
         extra_outputs = {'default': self.default_output}
-        super(Disco, self).__init__(host, 'disco', use_output='complex', extra_outputs=extra_outputs, help=_('service discovery'))
-        self.need_loop=True
+        super(Disco, self).__init__(
+            host, 'disco', use_output='complex', extra_outputs=extra_outputs,
+            help=_('service discovery'))
 
     def add_parser_options(self):
         self.parser.add_argument("jid", help=_("entity to discover"))
-        self.parser.add_argument("-t", "--type", type=str, choices=('infos', 'items', 'both'), default='both', help=_("type of data to discover"))
+        self.parser.add_argument(
+            "-t", "--type", type=str, choices=('infos', 'items', 'both'), default='both',
+            help=_("type of data to discover"))
         self.parser.add_argument("-n", "--node", default='', help=_("node to use"))
-        self.parser.add_argument("-C", "--no-cache", dest='use_cache', action="store_false", help=_("ignore cache"))
-
-    def start(self):
-        self.get_infos = self.args.type in ('infos', 'both')
-        self.get_items = self.args.type in ('items', 'both')
-        jids = self.host.check_jids([self.args.jid])
-        jid = jids[0]
-        if not self.get_infos:
-            self.gotInfos(None, jid)
-        else:
-            self.host.bridge.discoInfos(jid, node=self.args.node, use_cache=self.args.use_cache, profile_key=self.host.profile, callback=lambda infos: self.gotInfos(infos, jid), errback=self.error)
-
-    def error(self, failure):
-        print((_("Error while doing discovery [%s]") % failure))
-        self.host.quit(1)
-
-    def gotInfos(self, infos, jid):
-        if not self.get_items:
-            self.gotItems(infos, None)
-        else:
-            self.host.bridge.discoItems(jid, node=self.args.node, use_cache=self.args.use_cache, profile_key=self.host.profile, callback=lambda items: self.gotItems(infos, items), errback=self.error)
-
-    def gotItems(self, infos, items):
-        data = {}
-
-        if self.get_infos:
-            features, identities, extensions = infos
-            features.sort()
-            identities.sort(key=lambda identity: identity[2])
-            data.update({
-                'features': features,
-                'identities': identities,
-                'extensions': extensions})
-
-        if self.get_items:
-            items.sort(key=lambda item: item[2])
-            data['items'] = items
-
-        self.output(data)
-        self.host.quit()
+        self.parser.add_argument(
+            "-C", "--no-cache", dest='use_cache', action="store_false",
+            help=_("ignore cache"))
 
     def default_output(self, data):
         features = data.get('features', [])
@@ -115,15 +81,18 @@
                     for value in values:
                         field_lines.append(A.color('\t  - ', A.BOLD, value))
                 fields.append('\n'.join(field_lines))
-            extensions_tpl.append('{type_}\n{fields}'.format(type_=type_,
-                                                              fields='\n\n'.join(fields)))
+            extensions_tpl.append('{type_}\n{fields}'.format(
+                type_=type_,
+                fields='\n\n'.join(fields)))
 
-        items_table = common.Table(self.host,
-                                   items,
-                                   headers=(_('entity'),
-                                            _('node'),
-                                            _('name')),
-                                   use_buffer=True)
+        items_table = common.Table(
+            self.host,
+            items,
+            headers=(
+                _('entity'),
+                _('node'),
+                _('name')),
+            use_buffer=True)
 
         template = []
         if features:
@@ -135,76 +104,131 @@
         if items:
             template.append(A.color(C.A_HEADER, _("Items")) + "\n\n{items}")
 
-        print("\n\n".join(template).format(features = '\n'.join(features),
-                                            identities = identities_table.display().string,
-                                            extensions = '\n'.join(extensions_tpl),
-                                            items = items_table.display().string,
-                                           ))
+        print("\n\n".join(template).format(
+            features = '\n'.join(features),
+            identities = identities_table.display().string,
+            extensions = '\n'.join(extensions_tpl),
+            items = items_table.display().string,
+            ))
+
+    async def start(self):
+        infos_requested = self.args.type in ('infos', 'both')
+        items_requested = self.args.type in ('items', 'both')
+        jids = await self.host.check_jids([self.args.jid])
+        jid = jids[0]
+
+        # infos
+        if not infos_requested:
+            infos = None
+        else:
+            try:
+                infos = await self.host.bridge.discoInfos(
+                    jid,
+                    node=self.args.node,
+                    use_cache=self.args.use_cache,
+                    profile_key=self.host.profile
+                )
+            except Exception as e:
+                self.disp(_(f"error while doing discovery: {e}"), error=True)
+                self.host.quit(C.EXIT_BRIDGE_ERRBACK)
 
+        # items
+        if not items_requested:
+            items = None
+        else:
+            try:
+                items = await self.host.bridge.discoItems(
+                    jid,
+                    node=self.args.node,
+                    use_cache=self.args.use_cache,
+                    profile_key=self.host.profile
+                )
+            except Exception as e:
+                self.disp(_(f"error while doing discovery: {e}"), error=True)
+                self.host.quit(C.EXIT_BRIDGE_ERRBACK)
+
+        # output
+        data = {}
+
+        if infos_requested:
+            features, identities, extensions = infos
+            features.sort()
+            identities.sort(key=lambda identity: identity[2])
+            data.update({
+                'features': features,
+                'identities': identities,
+                'extensions': extensions})
+
+        if items_requested:
+            items.sort(key=lambda item: item[2])
+            data['items'] = items
+
+        await self.output(data)
+        self.host.quit()
 
 class Version(base.CommandBase):
 
     def __init__(self, host):
         super(Version, self).__init__(host, 'version', help=_('software version'))
-        self.need_loop=True
 
     def add_parser_options(self):
         self.parser.add_argument("jid", type=str, help=_("Entity to request"))
 
-    def start(self):
-        jids = self.host.check_jids([self.args.jid])
+    async def start(self):
+        jids = await self.host.check_jids([self.args.jid])
         jid = jids[0]
-        self.host.bridge.getSoftwareVersion(jid, self.host.profile, callback=self.gotVersion, errback=self.error)
-
-    def error(self, failure):
-        print((_("Error while trying to get version [%s]") % failure))
-        self.host.quit(1)
+        try:
+            data = await self.host.bridge.getSoftwareVersion(jid, self.host.profile)
+        except Exception as e:
+            self.disp(_(f"error while trying to get version: {e}"), error=True)
+            self.host.quit(C.EXIT_BRIDGE_ERRBACK)
+        else:
+            infos = []
+            name, version, os = data
+            if name:
+                infos.append(_(f"Software name: {name}"))
+            if version:
+                infos.append(_(f"Software version: {version}"))
+            if os:
+                infos.append(_(f"Operating System: {os}"))
 
-    def gotVersion(self, data):
-        infos = []
-        name, version, os = data
-        if name:
-            infos.append(_("Software name: %s") %  name)
-        if version:
-            infos.append(_("Software version: %s") %  version)
-        if os:
-            infos.append(_("Operating System: %s") %  os)
-
-        print("\n".join(infos))
-        self.host.quit()
+            print("\n".join(infos))
+            self.host.quit()
 
 
 class Session(base.CommandBase):
 
     def __init__(self, host):
         extra_outputs = {'default': self.default_output}
-        super(Session, self).__init__(host, 'session', use_output='dict', extra_outputs=extra_outputs, help=_('running session'))
-        self.need_loop=True
+        super(Session, self).__init__(
+            host, 'session', use_output='dict', extra_outputs=extra_outputs,
+            help=_('running session'))
 
-    def default_output(self, data):
+    def add_parser_options(self):
+        pass
+
+    async def default_output(self, data):
         started = data['started']
         data['started'] = '{short} (UTC, {relative})'.format(
             short=date_utils.date_fmt(started),
             relative=date_utils.date_fmt(started, 'relative'))
-        self.host.output(C.OUTPUT_DICT, 'simple', {}, data)
-
-    def add_parser_options(self):
-        pass
-
-    def start(self):
-        self.host.bridge.sessionInfosGet(self.host.profile, callback=self._sessionInfoGetCb, errback=self._sessionInfoGetEb)
+        await self.host.output(C.OUTPUT_DICT, 'simple', {}, data)
 
-    def _sessionInfoGetCb(self, data):
-        self.output(data)
-        self.host.quit()
-
-    def _sessionInfoGetEb(self, error_data):
-        self.disp(_('Error getting session infos: {}').format(error_data), error=True)
-        self.host.quit(C.EXIT_BRIDGE_ERRBACK)
+    async def start(self):
+        try:
+            data = await self.host.bridge.sessionInfosGet(self.host.profile)
+        except Exception as e:
+            self.disp(_(f'Error getting session infos: {e}'), error=True)
+            self.host.quit(C.EXIT_BRIDGE_ERRBACK)
+        else:
+            await self.output(data)
+            self.host.quit()
 
 
 class Info(base.CommandBase):
     subcommands = (Disco, Version, Session)
 
     def __init__(self, host):
-        super(Info, self).__init__(host, 'info', use_profile=False, help=_('Get various pieces of information on entities'))
+        super(Info, self).__init__(
+            host, 'info', use_profile=False,
+            help=_('Get various pieces of information on entities'))