comparison sat_frontends/jp/cmd_invitation.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
comparison
equal deleted inserted replaced
3039:a1bc34f90fa5 3040:fee60f17ebac
21 from . import base 21 from . import base
22 from sat.core.i18n import _ 22 from sat.core.i18n import _
23 from sat_frontends.jp.constants import Const as C 23 from sat_frontends.jp.constants import Const as C
24 from sat.tools.common.ansi import ANSI as A 24 from sat.tools.common.ansi import ANSI as A
25 from sat.tools.common import data_format 25 from sat.tools.common import data_format
26 from functools import partial
27 26
28 __commands__ = ["Invitation"] 27 __commands__ = ["Invitation"]
29 28
30 29
31 class Create(base.CommandBase): 30 class Create(base.CommandBase):
36 "create", 35 "create",
37 use_profile=False, 36 use_profile=False,
38 use_output=C.OUTPUT_DICT, 37 use_output=C.OUTPUT_DICT,
39 help=_("create and send an invitation"), 38 help=_("create and send an invitation"),
40 ) 39 )
41 self.need_loop = True
42 40
43 def add_parser_options(self): 41 def add_parser_options(self):
44 self.parser.add_argument( 42 self.parser.add_argument(
45 "-j", 43 "-j",
46 "--jid", 44 "--jid",
113 "--profile", 111 "--profile",
114 default="", 112 default="",
115 help="profile doing the invitation (default: don't associate profile)", 113 help="profile doing the invitation (default: don't associate profile)",
116 ) 114 )
117 115
118 def invitationCreateCb(self, invitation_data): 116 async def start(self):
119 self.output(invitation_data)
120 self.host.quit(C.EXIT_OK)
121
122 def invitationCreateEb(self, failure_):
123 self.disp(
124 "can't create invitation: {reason}".format(reason=failure_), error=True
125 )
126 self.host.quit(C.EXIT_BRIDGE_ERRBACK)
127
128 def start(self):
129 extra = dict(self.args.extra) 117 extra = dict(self.args.extra)
130 email = self.args.email[0] if self.args.email else None 118 email = self.args.email[0] if self.args.email else None
131 emails_extra = self.args.email[1:] 119 emails_extra = self.args.email[1:]
132 if self.args.no_email: 120 if self.args.no_email:
133 if email: 121 if email:
137 if not email: 125 if not email:
138 self.parser.error( 126 self.parser.error(
139 _("you need to specify an email address to send email invitation") 127 _("you need to specify an email address to send email invitation")
140 ) 128 )
141 129
142 self.host.bridge.invitationCreate( 130 try:
143 email, 131 invitation_data = await self.host.bridge.invitationCreate(
144 emails_extra, 132 email,
145 self.args.jid, 133 emails_extra,
146 self.args.password, 134 self.args.jid,
147 self.args.name, 135 self.args.password,
148 self.args.host_name, 136 self.args.name,
149 self.args.lang, 137 self.args.host_name,
150 self.args.url, 138 self.args.lang,
151 self.args.subject, 139 self.args.url,
152 self.args.body, 140 self.args.subject,
153 extra, 141 self.args.body,
154 self.args.profile, 142 extra,
155 callback=self.invitationCreateCb, 143 self.args.profile,
156 errback=self.invitationCreateEb, 144 )
157 ) 145 except Exception as e:
146 self.disp(f"can't create invitation: {e}", error=True)
147 self.host.quit(C.EXIT_BRIDGE_ERRBACK)
148 else:
149 await self.output(invitation_data)
150 self.host.quit(C.EXIT_OK)
158 151
159 152
160 class Get(base.CommandBase): 153 class Get(base.CommandBase):
161 def __init__(self, host): 154 def __init__(self, host):
162 base.CommandBase.__init__( 155 base.CommandBase.__init__(
165 "get", 158 "get",
166 use_profile=False, 159 use_profile=False,
167 use_output=C.OUTPUT_DICT, 160 use_output=C.OUTPUT_DICT,
168 help=_("get invitation data"), 161 help=_("get invitation data"),
169 ) 162 )
170 self.need_loop = True
171 163
172 def add_parser_options(self): 164 def add_parser_options(self):
173 self.parser.add_argument( 165 self.parser.add_argument(
174 "id", help=_("invitation UUID") 166 "id", help=_("invitation UUID")
175 ) 167 )
178 "--with-jid", 170 "--with-jid",
179 action="store_true", 171 action="store_true",
180 help=_("start profile session and retrieve jid"), 172 help=_("start profile session and retrieve jid"),
181 ) 173 )
182 174
183 def output_data(self, data, jid_=None): 175 async def output_data(self, data, jid_=None):
184 if jid_ is not None: 176 if jid_ is not None:
185 data["jid"] = jid_ 177 data["jid"] = jid_
186 self.output(data) 178 await self.output(data)
187 self.host.quit() 179 self.host.quit()
188 180
189 def invitationGetCb(self, invitation_data): 181 async def start(self):
190 if self.args.with_jid: 182 try:
183 invitation_data = await self.host.bridge.invitationGet(
184 self.args.id,
185 )
186 except Exception as e:
187 self.disp(msg=_(f"can't get invitation data: {e}"), error=True)
188 self.host.quit(C.EXIT_BRIDGE_ERRBACK)
189
190 if not self.args.with_jid:
191 await self.output_data(invitation_data)
192 else:
191 profile = invitation_data["guest_profile"] 193 profile = invitation_data["guest_profile"]
192 194 try:
193 def session_started(__): 195 await self.host.bridge.profileStartSession(
194 self.host.bridge.asyncGetParamA( 196 invitation_data["password"],
197 profile,
198 )
199 except Exception as e:
200 self.disp(msg=_(f"can't start session: {e}"), error=True)
201 self.host.quit(C.EXIT_BRIDGE_ERRBACK)
202
203 try:
204 jid_ = await self.host.bridge.asyncGetParamA(
195 "JabberID", 205 "JabberID",
196 "Connection", 206 "Connection",
197 profile_key=profile, 207 profile_key=profile,
198 callback=lambda jid_: self.output_data(invitation_data, jid_),
199 errback=partial(
200 self.errback,
201 msg=_("can't retrieve jid: {}"),
202 exit_code=C.EXIT_BRIDGE_ERRBACK,
203 ),
204 ) 208 )
205 209 except Exception as e:
206 self.host.bridge.profileStartSession( 210 self.disp(msg=_(f"can't retrieve jid: {e}"), error=True)
207 invitation_data["password"], 211 self.host.quit(C.EXIT_BRIDGE_ERRBACK)
208 profile, 212
209 callback=session_started, 213 await self.output_data(invitation_data, jid_)
210 errback=partial(
211 self.errback,
212 msg=_("can't start session: {}"),
213 exit_code=C.EXIT_BRIDGE_ERRBACK,
214 ),
215 )
216 else:
217 self.output_data(invitation_data)
218
219 def start(self):
220 self.host.bridge.invitationGet(
221 self.args.id,
222 callback=self.invitationGetCb,
223 errback=partial(
224 self.errback,
225 msg=_("can't get invitation data: {}"),
226 exit_code=C.EXIT_BRIDGE_ERRBACK,
227 ),
228 )
229 214
230 215
231 class Modify(base.CommandBase): 216 class Modify(base.CommandBase):
232 def __init__(self, host): 217 def __init__(self, host):
233 base.CommandBase.__init__( 218 base.CommandBase.__init__(
234 self, host, "modify", use_profile=False, help=_("modify existing invitation") 219 self, host, "modify", use_profile=False, help=_("modify existing invitation")
235 ) 220 )
236 self.need_loop = True
237 221
238 def add_parser_options(self): 222 def add_parser_options(self):
239 self.parser.add_argument( 223 self.parser.add_argument(
240 "--replace", action="store_true", help="replace the whole data" 224 "--replace", action="store_true", help="replace the whole data"
241 ) 225 )
281 ) 265 )
282 self.parser.add_argument( 266 self.parser.add_argument(
283 "id", help=_("invitation UUID") 267 "id", help=_("invitation UUID")
284 ) 268 )
285 269
286 def invitationModifyCb(self): 270 async def start(self):
287 self.disp(_("invitations have been modified correctly"))
288 self.host.quit(C.EXIT_OK)
289
290 def invitationModifyEb(self, failure_):
291 self.disp(
292 "can't create invitation: {reason}".format(reason=failure_), error=True
293 )
294 self.host.quit(C.EXIT_BRIDGE_ERRBACK)
295
296 def start(self):
297 extra = dict(self.args.extra) 271 extra = dict(self.args.extra)
298 for arg_name in ("name", "host_name", "email", "language", "profile"): 272 for arg_name in ("name", "host_name", "email", "language", "profile"):
299 value = getattr(self.args, arg_name) 273 value = getattr(self.args, arg_name)
300 if not value: 274 if not value:
301 continue 275 continue
302 if arg_name in extra: 276 if arg_name in extra:
303 self.parser.error( 277 self.parser.error(
304 _( 278 _(f"you can't set {arg_name} in both optional argument and extra")
305 "you can't set {arg_name} in both optional argument and extra"
306 ).format(arg_name=arg_name)
307 ) 279 )
308 extra[arg_name] = value 280 extra[arg_name] = value
309 self.host.bridge.invitationModify( 281 try:
310 self.args.id, 282 await self.host.bridge.invitationModify(
311 extra, 283 self.args.id,
312 self.args.replace, 284 extra,
313 callback=self.invitationModifyCb, 285 self.args.replace,
314 errback=self.invitationModifyEb, 286 )
315 ) 287 except Exception as e:
288 self.disp(
289 f"can't modify invitation: {e}", error=True
290 )
291 self.host.quit(C.EXIT_BRIDGE_ERRBACK)
292 else:
293 self.disp(_("invitations have been modified successfuly"))
294 self.host.quit(C.EXIT_OK)
316 295
317 296
318 class List(base.CommandBase): 297 class List(base.CommandBase):
319 def __init__(self, host): 298 def __init__(self, host):
320 extra_outputs = {"default": self.default_output} 299 extra_outputs = {"default": self.default_output}
325 use_profile=False, 304 use_profile=False,
326 use_output=C.OUTPUT_COMPLEX, 305 use_output=C.OUTPUT_COMPLEX,
327 extra_outputs=extra_outputs, 306 extra_outputs=extra_outputs,
328 help=_("list invitations data"), 307 help=_("list invitations data"),
329 ) 308 )
330 self.need_loop = True
331 309
332 def default_output(self, data): 310 def default_output(self, data):
333 for idx, datum in enumerate(data.items()): 311 for idx, datum in enumerate(data.items()):
334 if idx: 312 if idx:
335 self.disp("\n") 313 self.disp("\n")
345 "--profile", 323 "--profile",
346 default=C.PROF_KEY_NONE, 324 default=C.PROF_KEY_NONE,
347 help=_("return only invitations linked to this profile"), 325 help=_("return only invitations linked to this profile"),
348 ) 326 )
349 327
350 def invitationListCb(self, data): 328 async def start(self):
351 self.output(data) 329 try:
352 self.host.quit() 330 data = await self.host.bridge.invitationList(
353 331 self.args.profile,
354 def start(self): 332 )
355 self.host.bridge.invitationList( 333 except Exception as e:
356 self.args.profile, 334 self.disp(f"return only invitations linked to this profile: {e}", error=True)
357 callback=self.invitationListCb, 335 self.host.quit(C.EXIT_BRIDGE_ERRBACK)
358 errback=partial( 336 else:
359 self.errback, 337 await self.output(data)
360 msg=_("can't list invitations: {}"), 338 self.host.quit()
361 exit_code=C.EXIT_BRIDGE_ERRBACK,
362 ),
363 )
364 339
365 340
366 class Invitation(base.CommandBase): 341 class Invitation(base.CommandBase):
367 subcommands = (Create, Get, Modify, List) 342 subcommands = (Create, Get, Modify, List)
368 343