Mercurial > libervia-backend
diff sat_frontends/jp/cmd_event.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 | 040ca99e25fe |
line wrap: on
line diff
--- a/sat_frontends/jp/cmd_event.py Wed Sep 25 08:53:38 2019 +0200 +++ b/sat_frontends/jp/cmd_event.py Wed Sep 25 08:56:41 2019 +0200 @@ -23,7 +23,6 @@ from sat.tools.common.ansi import ANSI as A from sat_frontends.jp.constants import Const as C from sat_frontends.jp import common -from functools import partial from dateutil import parser as du_parser import calendar import time @@ -47,30 +46,26 @@ use_verbose=True, help=_("get event data"), ) - self.need_loop = True def add_parser_options(self): pass - def eventInviteeGetCb(self, result): - event_date, event_data = result - event_data["date"] = event_date - self.output(event_data) - self.host.quit() - - def start(self): - self.host.bridge.eventGet( - self.args.service, - self.args.node, - self.args.item, - self.profile, - callback=self.eventInviteeGetCb, - errback=partial( - self.errback, - msg=_("can't get event data: {}"), - exit_code=C.EXIT_BRIDGE_ERRBACK, - ), - ) + async def start(self): + try: + event_tuple = await self.host.bridge.eventGet( + self.args.service, + self.args.node, + self.args.item, + self.profile, + ) + except Exception as e: + self.disp(f"can't get event data: {e}", error=True) + self.host.quit(C.EXIT_BRIDGE_ERRBACK) + else: + event_date, event_data = event_tuple + event_data["date"] = event_date + await self.output(event_data) + self.host.quit() class EventBase(object): @@ -126,29 +121,25 @@ help=_("create or replace event"), ) EventBase.__init__(self) - self.need_loop = True - def eventCreateCb(self, node): - self.disp(_("Event created successfuly on node {node}").format(node=node)) - self.host.quit() - - def start(self): + async def start(self): fields = self.parseFields() date = self.parseDate() - self.host.bridge.eventCreate( - date, - fields, - self.args.service, - self.args.node, - self.args.id, - self.profile, - callback=self.eventCreateCb, - errback=partial( - self.errback, - msg=_("can't create event: {}"), - exit_code=C.EXIT_BRIDGE_ERRBACK, - ), - ) + try: + node = await self.host.bridge.eventCreate( + date, + fields, + self.args.service, + self.args.node, + self.args.id, + self.profile, + ) + except Exception as e: + self.disp(f"can't create event: {e}", error=True) + self.host.quit(C.EXIT_BRIDGE_ERRBACK) + else: + self.disp(_(f"Event created successfuly on node {node}")) + self.host.quit() class Modify(EventBase, base.CommandBase): @@ -161,25 +152,24 @@ help=_("modify an existing event"), ) EventBase.__init__(self) - self.need_loop = True - def start(self): + async def start(self): fields = self.parseFields() date = 0 if not self.args.date else self.parseDate() - self.host.bridge.eventModify( - self.args.service, - self.args.node, - self.args.id, - date, - fields, - self.profile, - callback=self.host.quit, - errback=partial( - self.errback, - msg=_("can't update event data: {}"), - exit_code=C.EXIT_BRIDGE_ERRBACK, - ), - ) + try: + self.host.bridge.eventModify( + self.args.service, + self.args.node, + self.args.id, + date, + fields, + self.profile, + ) + except Exception as e: + self.disp(f"can't update event data: {e}", error=True) + self.host.quit(C.EXIT_BRIDGE_ERRBACK) + else: + self.host.quit() class InviteeGet(base.CommandBase): @@ -190,31 +180,30 @@ "get", use_output=C.OUTPUT_DICT, use_pubsub=True, - pubsub_flags={C.NODE, C.ITEM, C.SINGLE_ITEM}, + pubsub_flags={C.NODE}, use_verbose=True, help=_("get event attendance"), ) - self.need_loop = True def add_parser_options(self): - pass - - def eventInviteeGetCb(self, event_data): - self.output(event_data) - self.host.quit() + self.parser.add_argument( + "-j", "--jid", default="", help=_("bare jid of the invitee") + ) - def start(self): - self.host.bridge.eventInviteeGet( - self.args.service, - self.args.node, - self.profile, - callback=self.eventInviteeGetCb, - errback=partial( - self.errback, - msg=_("can't get event data: {}"), - exit_code=C.EXIT_BRIDGE_ERRBACK, - ), - ) + async def start(self): + try: + event_data = await self.host.bridge.eventInviteeGet( + self.args.service, + self.args.node, + self.args.jid, + self.profile, + ) + except Exception as e: + self.disp(f"can't get event data: {e}", error=True) + self.host.quit(C.EXIT_BRIDGE_ERRBACK) + else: + await self.output(event_data) + self.host.quit() class InviteeSet(base.CommandBase): @@ -227,7 +216,6 @@ pubsub_flags={C.NODE}, help=_("set event attendance"), ) - self.need_loop = True def add_parser_options(self): self.parser.add_argument( @@ -240,20 +228,20 @@ help=_("configuration field to set"), ) - def start(self): + async def start(self): fields = dict(self.args.fields) if self.args.fields else {} - self.host.bridge.eventInviteeSet( - self.args.service, - self.args.node, - fields, - self.profile, - callback=self.host.quit, - errback=partial( - self.errback, - msg=_("can't set event data: {}"), - exit_code=C.EXIT_BRIDGE_ERRBACK, - ), - ) + try: + self.host.bridge.eventInviteeSet( + self.args.service, + self.args.node, + fields, + self.profile, + ) + except Exception as e: + self.disp(f"can't set event data: {e}", error=True) + self.host.quit(C.EXIT_BRIDGE_ERRBACK) + else: + self.host.quit() class InviteesList(base.CommandBase): @@ -270,7 +258,6 @@ use_verbose=True, help=_("get event attendance"), ) - self.need_loop = True def add_parser_options(self): self.parser.add_argument( @@ -399,72 +386,68 @@ ) ) - def eventInviteesListCb(self, event_data, prefilled_data): - """fill nicknames and keep only requested people - - @param event_data(dict): R.S.V.P. answers - @param prefilled_data(dict): prefilled data with all people - only filled if --missing is used - """ - if self.args.no_rsvp: - for jid_ in event_data: - # if there is a jid in event_data - # it must be there in prefilled_data too - # so no need to check for KeyError - del prefilled_data[jid_] - else: - # we replace empty dicts for existing people with R.S.V.P. data - prefilled_data.update(event_data) - - # we get nicknames for everybody, make it easier for organisers - for jid_, data in prefilled_data.items(): - id_data = self.host.bridge.identityGet(jid_, self.profile) - data["nick"] = id_data.get("nick", "") - - self.output(prefilled_data) - self.host.quit() - - def getList(self, prefilled_data={}): - self.host.bridge.eventInviteesList( - self.args.service, - self.args.node, - self.profile, - callback=partial(self.eventInviteesListCb, prefilled_data=prefilled_data), - errback=partial( - self.errback, - msg=_("can't get event data: {}"), - exit_code=C.EXIT_BRIDGE_ERRBACK, - ), - ) - - def psNodeAffiliationsGetCb(self, affiliations): - # we fill all affiliations with empty data - # answered one will be filled in eventInviteesListCb - # we only consider people with "publisher" affiliation as invited, creators are not, and members can just observe - prefilled = { - jid_: {} - for jid_, affiliation in affiliations.items() - if affiliation in ("publisher",) - } - self.getList(prefilled) - - def start(self): + async def start(self): if self.args.no_rsvp and not self.args.missing: self.parser.error(_("you need to use --missing if you use --no-rsvp")) - if self.args.missing: - self.host.bridge.psNodeAffiliationsGet( + if not self.args.missing: + prefilled = {} + else: + # we get prefilled data with all people + try: + affiliations = await self.host.bridge.psNodeAffiliationsGet( + self.args.service, + self.args.node, + self.profile, + ) + except Exception as e: + self.disp(f"can't get node affiliations: {e}", error=True) + self.host.quit(C.EXIT_BRIDGE_ERRBACK) + else: + # we fill all affiliations with empty data, answered one will be filled + # below. We only consider people with "publisher" affiliation as invited, + # creators are not, and members can just observe + prefilled = { + jid_: {} + for jid_, affiliation in affiliations.items() + if affiliation in ("publisher",) + } + + try: + event_data = await self.host.bridge.eventInviteesList( self.args.service, self.args.node, self.profile, - callback=self.psNodeAffiliationsGetCb, - errback=partial( - self.errback, - msg=_("can't get event data: {}"), - exit_code=C.EXIT_BRIDGE_ERRBACK, - ), ) + except Exception as e: + self.disp(f"can't get event data: {e}", error=True) + self.host.quit(C.EXIT_BRIDGE_ERRBACK) + + # we fill nicknames and keep only requested people + + if self.args.no_rsvp: + for jid_ in event_data: + # if there is a jid in event_data it must be there in prefilled too + # otherwie somebody is not on the invitees list + try: + del prefilled[jid_] + except KeyError: + self.disp(A.color( + C.A_WARNING, + f"We got a RSVP from somebody who was not in invitees " + f"list: {jid_}" + ), + error=True) else: - self.getList() + # we replace empty dicts for existing people with R.S.V.P. data + prefilled.update(event_data) + + # we get nicknames for everybody, make it easier for organisers + for jid_, data in prefilled.items(): + id_data = await self.host.bridge.identityGet(jid_, self.profile) + data["nick"] = id_data.get("nick", "") + + await self.output(prefilled) + self.host.quit() class InviteeInvite(base.CommandBase): @@ -477,7 +460,6 @@ pubsub_flags={C.NODE, C.SINGLE_ITEM}, help=_("invite someone to the event through email"), ) - self.need_loop = True def add_parser_options(self): self.parser.add_argument( @@ -524,30 +506,30 @@ help="body of the invitation email (default: generic body)", ) - def start(self): + async def start(self): email = self.args.email[0] if self.args.email else None emails_extra = self.args.email[1:] - self.host.bridge.eventInviteByEmail( - self.args.service, - self.args.node, - self.args.item, - email, - emails_extra, - self.args.name, - self.args.host_name, - self.args.lang, - self.args.url_template, - self.args.subject, - self.args.body, - self.args.profile, - callback=self.host.quit, - errback=partial( - self.errback, - msg=_("can't create invitation: {}"), - exit_code=C.EXIT_BRIDGE_ERRBACK, - ), - ) + try: + await self.host.bridge.eventInviteByEmail( + self.args.service, + self.args.node, + self.args.item, + email, + emails_extra, + self.args.name, + self.args.host_name, + self.args.lang, + self.args.url_template, + self.args.subject, + self.args.body, + self.args.profile, + ) + except Exception as e: + self.disp(f"can't create invitation: {e}", error=True) + self.host.quit(C.EXIT_BRIDGE_ERRBACK) + else: + self.host.quit() class Invitee(base.CommandBase):