diff sat_frontends/jp/cmd_profile.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 4486d72658b9
line wrap: on
line diff
--- a/sat_frontends/jp/cmd_profile.py	Wed Sep 25 08:53:38 2019 +0200
+++ b/sat_frontends/jp/cmd_profile.py	Wed Sep 25 08:56:41 2019 +0200
@@ -25,7 +25,6 @@
 log = getLogger(__name__)
 from sat.core.i18n import _
 from sat_frontends.jp import base
-from functools import partial
 
 __commands__ = ["Profile"]
 
@@ -43,18 +42,73 @@
     def add_parser_options(self):
         pass
 
+    async def start(self):
+        # connection is already managed by profile common commands
+        # so we just need to check arguments and quit
+        if not self.args.connect and not self.args.start_session:
+            self.parser.error(_("You need to use either --connect or --start-session"))
+        self.host.quit()
 
 class ProfileDisconnect(base.CommandBase):
 
     def __init__(self, host):
         super(ProfileDisconnect, self).__init__(host, 'disconnect', need_connect=False, help=('disconnect a profile'))
-        self.need_loop = True
 
     def add_parser_options(self):
         pass
 
-    def start(self):
-        self.host.bridge.disconnect(self.args.profile, callback=self.host.quit)
+    async def start(self):
+        try:
+            await self.host.bridge.disconnect(self.args.profile)
+        except Exception as e:
+            self.disp(f"can't disconnect profile: {e}", error=True)
+            self.host.quit(C.EXIT_BRIDGE_ERRBACK)
+        else:
+            self.host.quit()
+
+
+class ProfileCreate(base.CommandBase):
+    def __init__(self, host):
+        super(ProfileCreate, self).__init__(host, 'create', use_profile=False, help=('create a new profile'))
+
+    def add_parser_options(self):
+        self.parser.add_argument('profile', type=str, help=_('the name of the profile'))
+        self.parser.add_argument('-p', '--password', type=str, default='', help=_('the password of the profile'))
+        self.parser.add_argument('-j', '--jid', type=str, help=_('the jid of the profile'))
+        self.parser.add_argument('-x', '--xmpp-password', type=str, help=_('the password of the XMPP account (use profile password if not specified)'),
+                                 metavar='PASSWORD')
+        self.parser.add_argument('-C', '--component', default='',
+                                 help=_('set to component import name (entry point) if this is a component'))
+
+    async def start(self):
+        """Create a new profile"""
+        if self.args.profile in await self.host.bridge.profilesListGet():
+            self.disp(f"Profile {self.args.profile} already exists.", error=True)
+            self.host.quit(C.EXIT_BRIDGE_ERROR)
+        try:
+            await self.host.bridge.profileCreate(
+                self.args.profile, self.args.password, self.args.component)
+        except Exception as e:
+            self.disp(f"can't create profile: {e}", error=True)
+            self.host.quit(C.EXIT_BRIDGE_ERRBACK)
+
+        try:
+            await self.host.bridge.profileStartSession(
+                self.args.password, self.args.profile)
+        except Exception as e:
+            self.disp(f"can't start profile session: {e}", error=True)
+            self.host.quit(C.EXIT_BRIDGE_ERRBACK)
+
+        if self.args.jid:
+            await self.host.bridge.setParam(
+                "JabberID", self.args.jid, "Connection", profile_key=self.args.profile)
+        xmpp_pwd = self.args.password or self.args.xmpp_password
+        if xmpp_pwd:
+            await self.host.bridge.setParam(
+                "Password", xmpp_pwd, "Connection", profile_key=self.args.profile)
+
+        self.disp(f'profile {self.args.profile} created successfully', 1)
+        self.host.quit()
 
 
 class ProfileDefault(base.CommandBase):
@@ -64,8 +118,9 @@
     def add_parser_options(self):
         pass
 
-    def start(self):
-        print(self.host.bridge.profileNameGet('@DEFAULT@'))
+    async def start(self):
+        print(await self.host.bridge.profileNameGet('@DEFAULT@'))
+        self.host.quit()
 
 
 class ProfileDelete(base.CommandBase):
@@ -76,47 +131,51 @@
         self.parser.add_argument('profile', type=str, help=PROFILE_HELP)
         self.parser.add_argument('-f', '--force', action='store_true', help=_('delete profile without confirmation'))
 
-    def start(self):
-        if self.args.profile not in self.host.bridge.profilesListGet():
-            log.error("Profile %s doesn't exist." % self.args.profile)
-            self.host.quit(1)
+    async def start(self):
+        if self.args.profile not in await self.host.bridge.profilesListGet():
+            log.error(f"Profile {self.args.profile} doesn't exist.")
+            self.host.quit(C.EXIT_NOT_FOUND)
         if not self.args.force:
-            message = "Are you sure to delete profile [{}] ?".format(self.args.profile)
-            res = input("{} (y/N)? ".format(message))
-            if res not in ("y", "Y"):
-                self.disp(_("Profile deletion cancelled"))
-                self.host.quit(2)
+            message = f"Are you sure to delete profile [{self.args.profile}] ?"
+            cancel_message = "Profile deletion cancelled"
+            await self.host.confirmOrQuit(message, cancel_message)
 
-        self.host.bridge.asyncDeleteProfile(self.args.profile, callback=lambda __: None)
+        await self.host.bridge.asyncDeleteProfile(self.args.profile)
+        self.host.quit()
 
 
 class ProfileInfo(base.CommandBase):
     def __init__(self, host):
         super(ProfileInfo, self).__init__(host, 'info', need_connect=False, help=_('get information about a profile'))
-        self.need_loop = True
         self.to_show = [(_("jid"), "Connection", "JabberID"),]
         self.largest = max([len(item[0]) for item in self.to_show])
 
-
     def add_parser_options(self):
         self.parser.add_argument('--show-password', action='store_true', help=_('show the XMPP password IN CLEAR TEXT'))
 
-    def showNextValue(self, label=None, category=None, value=None):
+    async def showNextValue(self, label=None, category=None, value=None):
         """Show next value from self.to_show and quit on last one"""
         if label is not None:
-            print((("{label:<"+str(self.largest+2)+"}{value}").format(label=label+": ", value=value)))
+            print((("{label:<"+str(self.largest+2)+"}{value}").format(
+                label=label+": ", value=value)))
         try:
             label, category, name = self.to_show.pop(0)
         except IndexError:
             self.host.quit()
         else:
-            self.host.bridge.asyncGetParamA(name, category, profile_key=self.host.profile,
-                                            callback=lambda value: self.showNextValue(label, category, value))
+            try:
+                value = await self.host.bridge.asyncGetParamA(
+                    name, category, profile_key=self.host.profile)
+            except Exception as e:
+                self.disp(f"can't get {name}/{category} param: {e}", error=True)
+                self.host.quit(C.EXIT_BRIDGE_ERRBACK)
+            else:
+                await self.showNextValue(label, category, value)
 
-    def start(self):
+    async def start(self):
         if self.args.show_password:
             self.to_show.append((_("XMPP password"), "Connection", "Password"))
-        self.showNextValue()
+        await self.showNextValue()
 
 
 class ProfileList(base.CommandBase):
@@ -129,54 +188,19 @@
         group.add_argument('-C', '--components', action='store_true', help=('get components profiles only'))
 
 
-    def start(self):
+    async def start(self):
         if self.args.clients:
             clients, components = True, False
         elif self.args.components:
             clients, components = False, True
         else:
             clients, components = True, True
-        self.output(self.host.bridge.profilesListGet(clients, components))
-
-
-class ProfileCreate(base.CommandBase):
-    def __init__(self, host):
-        super(ProfileCreate, self).__init__(host, 'create', use_profile=False, help=('create a new profile'))
-        self.need_loop = True
-
-    def add_parser_options(self):
-        self.parser.add_argument('profile', type=str, help=_('the name of the profile'))
-        self.parser.add_argument('-p', '--password', type=str, default='', help=_('the password of the profile'))
-        self.parser.add_argument('-j', '--jid', type=str, help=_('the jid of the profile'))
-        self.parser.add_argument('-x', '--xmpp-password', type=str, help=_('the password of the XMPP account (use profile password if not specified)'),
-                                 metavar='PASSWORD')
-        self.parser.add_argument('-C', '--component', default='',
-                                 help=_('set to component import name (entry point) if this is a component'))
-
-    def _session_started(self, __):
-        if self.args.jid:
-            self.host.bridge.setParam("JabberID", self.args.jid, "Connection", profile_key=self.args.profile)
-        xmpp_pwd = self.args.password or self.args.xmpp_password
-        if xmpp_pwd:
-            self.host.bridge.setParam("Password", xmpp_pwd, "Connection", profile_key=self.args.profile)
+        await self.output(await self.host.bridge.profilesListGet(clients, components))
         self.host.quit()
 
-    def _profile_created(self):
-        self.host.bridge.profileStartSession(self.args.password, self.args.profile, callback=self._session_started, errback=None)
-
-    def start(self):
-        """Create a new profile"""
-        if self.args.profile in self.host.bridge.profilesListGet():
-            log.error("Profile %s already exists." % self.args.profile)
-            self.host.quit(1)
-        self.host.bridge.profileCreate(self.args.profile, self.args.password, self.args.component,
-                                       callback=self._profile_created,
-                                       errback=partial(self.errback,
-                                                       msg=_("can't create profile: {}"),
-                                                       exit_code=C.EXIT_BRIDGE_ERRBACK))
-
 
 class ProfileModify(base.CommandBase):
+
     def __init__(self, host):
         super(ProfileModify, self).__init__(host, 'modify', need_connect=False, help=_('modify an existing profile'))
 
@@ -189,17 +213,22 @@
                                  metavar='PASSWORD')
         self.parser.add_argument('-D', '--default', action='store_true', help=_('set as default profile'))
 
-    def start(self):
+    async def start(self):
         if self.args.disable_password:
             self.args.password = ''
         if self.args.password is not None:
-            self.host.bridge.setParam("Password", self.args.password, "General", profile_key=self.host.profile)
+            await self.host.bridge.setParam(
+                "Password", self.args.password, "General", profile_key=self.host.profile)
         if self.args.jid is not None:
-            self.host.bridge.setParam("JabberID", self.args.jid, "Connection", profile_key=self.host.profile)
+            await self.host.bridge.setParam(
+                "JabberID", self.args.jid, "Connection", profile_key=self.host.profile)
         if self.args.xmpp_password is not None:
-            self.host.bridge.setParam("Password", self.args.xmpp_password, "Connection", profile_key=self.host.profile)
+            await self.host.bridge.setParam(
+                "Password", self.args.xmpp_password, "Connection", profile_key=self.host.profile)
         if self.args.default:
-            self.host.bridge.profileSetDefault(self.host.profile)
+            await self.host.bridge.profileSetDefault(self.host.profile)
+
+        self.host.quit()
 
 
 class Profile(base.CommandBase):