comparison sat_frontends/jp/base.py @ 4037:524856bd7b19

massive refactoring to switch from camelCase to snake_case: historically, Libervia (SàT before) was using camelCase as allowed by PEP8 when using a pre-PEP8 code, to use the same coding style as in Twisted. However, snake_case is more readable and it's better to follow PEP8 best practices, so it has been decided to move on full snake_case. Because Libervia has a huge codebase, this ended with a ugly mix of camelCase and snake_case. To fix that, this patch does a big refactoring by renaming every function and method (including bridge) that are not coming from Twisted or Wokkel, to use fully snake_case. This is a massive change, and may result in some bugs.
author Goffi <goffi@goffi.org>
date Sat, 08 Apr 2023 13:54:42 +0200
parents 6939594ba77e
children 2594e1951cf7
comparison
equal deleted inserted replaced
4036:c4464d7ae97b 4037:524856bd7b19
44 from sat.tools.common import utils 44 from sat.tools.common import utils
45 from sat.tools.common import data_format 45 from sat.tools.common import data_format
46 from sat.tools.common.ansi import ANSI as A 46 from sat.tools.common.ansi import ANSI as A
47 from sat.core import exceptions 47 from sat.core import exceptions
48 import sat_frontends.jp 48 import sat_frontends.jp
49 from sat_frontends.jp.loops import QuitException, getJPLoop 49 from sat_frontends.jp.loops import QuitException, get_jp_loop
50 from sat_frontends.jp.constants import Const as C 50 from sat_frontends.jp.constants import Const as C
51 from sat_frontends.bridge.bridge_frontend import BridgeException 51 from sat_frontends.bridge.bridge_frontend import BridgeException
52 from sat_frontends.tools import misc 52 from sat_frontends.tools import misc
53 import xml.etree.ElementTree as ET # FIXME: used temporarily to manage XMLUI 53 import xml.etree.ElementTree as ET # FIXME: used temporarily to manage XMLUI
54 from collections import OrderedDict 54 from collections import OrderedDict
55 55
56 ## bridge handling 56 ## bridge handling
57 # we get bridge name from conf and initialise the right class accordingly 57 # we get bridge name from conf and initialise the right class accordingly
58 main_config = config.parseMainConf() 58 main_config = config.parse_main_conf()
59 bridge_name = config.getConfig(main_config, '', 'bridge', 'dbus') 59 bridge_name = config.config_get(main_config, '', 'bridge', 'dbus')
60 JPLoop = getJPLoop(bridge_name) 60 JPLoop = get_jp_loop(bridge_name)
61 61
62 62
63 try: 63 try:
64 import progressbar 64 import progressbar
65 except ImportError: 65 except ImportError:
116 self.bridge = bridge_module.AIOBridge() 116 self.bridge = bridge_module.AIOBridge()
117 self._onQuitCallbacks = [] 117 self._onQuitCallbacks = []
118 118
119 def get_config(self, name, section=C.CONFIG_SECTION, default=None): 119 def get_config(self, name, section=C.CONFIG_SECTION, default=None):
120 """Retrieve a setting value from sat.conf""" 120 """Retrieve a setting value from sat.conf"""
121 return config.getConfig(self.sat_conf, section, name, default=default) 121 return config.config_get(self.sat_conf, section, name, default=default)
122 122
123 def guess_background(self): 123 def guess_background(self):
124 # cf. https://unix.stackexchange.com/a/245568 (thanks!) 124 # cf. https://unix.stackexchange.com/a/245568 (thanks!)
125 try: 125 try:
126 # for VTE based terminals 126 # for VTE based terminals
202 C.A_PROMPT_PATH = A.FG_BLUE 202 C.A_PROMPT_PATH = A.FG_BLUE
203 C.A_PROMPT_SUF = A.BOLD 203 C.A_PROMPT_SUF = A.BOLD
204 C.A_DIRECTORY = A.BOLD + A.FG_MAGENTA 204 C.A_DIRECTORY = A.BOLD + A.FG_MAGENTA
205 C.A_FILE = A.FG_BLACK 205 C.A_FILE = A.FG_BLACK
206 206
207 def _bridgeConnected(self): 207 def _bridge_connected(self):
208 self.parser = argparse.ArgumentParser( 208 self.parser = argparse.ArgumentParser(
209 formatter_class=argparse.RawDescriptionHelpFormatter, description=DESCRIPTION) 209 formatter_class=argparse.RawDescriptionHelpFormatter, description=DESCRIPTION)
210 self._make_parents() 210 self._make_parents()
211 self.add_parser_options() 211 self.add_parser_options()
212 self.subparsers = self.parser.add_subparsers( 212 self.subparsers = self.parser.add_subparsers(
229 return self._progress_id 229 return self._progress_id
230 230
231 async def set_progress_id(self, progress_id): 231 async def set_progress_id(self, progress_id):
232 # because we use async, we need an explicit setter 232 # because we use async, we need an explicit setter
233 self._progress_id = progress_id 233 self._progress_id = progress_id
234 await self.replayCache('progress_ids_cache') 234 await self.replay_cache('progress_ids_cache')
235 235
236 @property 236 @property
237 def watch_progress(self): 237 def watch_progress(self):
238 try: 238 try:
239 self.pbar 239 self.pbar
252 try: 252 try:
253 return self.args.verbose 253 return self.args.verbose
254 except AttributeError: 254 except AttributeError:
255 return 0 255 return 0
256 256
257 async def replayCache(self, cache_attribute): 257 async def replay_cache(self, cache_attribute):
258 """Replay cached signals 258 """Replay cached signals
259 259
260 @param cache_attribute(str): name of the attribute containing the cache 260 @param cache_attribute(str): name of the attribute containing the cache
261 if the attribute doesn't exist, there is no cache and the call is ignored 261 if the attribute doesn't exist, there is no cache and the call is ignored
262 else the cache must be a list of tuples containing the replay callback as 262 else the cache must be a list of tuples containing the replay callback as
292 292
293 ret = method(data) 293 ret = method(data)
294 if inspect.isawaitable(ret): 294 if inspect.isawaitable(ret):
295 await ret 295 await ret
296 296
297 def addOnQuitCallback(self, callback, *args, **kwargs): 297 def add_on_quit_callback(self, callback, *args, **kwargs):
298 """Add a callback which will be called on quit command 298 """Add a callback which will be called on quit command
299 299
300 @param callback(callback): method to call 300 @param callback(callback): method to call
301 """ 301 """
302 self._onQuitCallbacks.append((callback, args, kwargs)) 302 self._onQuitCallbacks.append((callback, args, kwargs))
303 303
304 def getOutputChoices(self, output_type): 304 def get_output_choices(self, output_type):
305 """Return valid output filters for output_type 305 """Return valid output filters for output_type
306 306
307 @param output_type: True for default, 307 @param output_type: True for default,
308 else can be any registered type 308 else can be any registered type
309 """ 309 """
610 if url.startswith('http'): 610 if url.startswith('http'):
611 # http(s) URL, we try to retrieve xmpp one from there 611 # http(s) URL, we try to retrieve xmpp one from there
612 url = self.get_xmpp_uri_from_http(url) 612 url = self.get_xmpp_uri_from_http(url)
613 613
614 try: 614 try:
615 uri_data = uri.parseXMPPUri(url) 615 uri_data = uri.parse_xmpp_uri(url)
616 except ValueError: 616 except ValueError:
617 self.parser.error(_('invalid XMPP URL: {url}').format(url=url)) 617 self.parser.error(_('invalid XMPP URL: {url}').format(url=url))
618 else: 618 else:
619 if uri_data['type'] == 'pubsub': 619 if uri_data['type'] == 'pubsub':
620 # URL is alright, we only set data not already set by other options 620 # URL is alright, we only set data not already set by other options
692 if self.args.max is None: 692 if self.args.max is None:
693 self.args.max = C.NO_LIMIT 693 self.args.max = C.NO_LIMIT
694 694
695 async def main(self, args, namespace): 695 async def main(self, args, namespace):
696 try: 696 try:
697 await self.bridge.bridgeConnect() 697 await self.bridge.bridge_connect()
698 except Exception as e: 698 except Exception as e:
699 if isinstance(e, exceptions.BridgeExceptionNoService): 699 if isinstance(e, exceptions.BridgeExceptionNoService):
700 print( 700 print(
701 _("Can't connect to Libervia backend, are you sure that it's " 701 _("Can't connect to Libervia backend, are you sure that it's "
702 "launched ?") 702 "launched ?")
709 print( 709 print(
710 _("Error while initialising bridge: {e}").format(e=e) 710 _("Error while initialising bridge: {e}").format(e=e)
711 ) 711 )
712 self.quit(C.EXIT_BRIDGE_ERROR, raise_exc=False) 712 self.quit(C.EXIT_BRIDGE_ERROR, raise_exc=False)
713 return 713 return
714 await self.bridge.getReady() 714 await self.bridge.ready_get()
715 self.version = await self.bridge.getVersion() 715 self.version = await self.bridge.version_get()
716 self._bridgeConnected() 716 self._bridge_connected()
717 self.import_plugins() 717 self.import_plugins()
718 try: 718 try:
719 self.args = self.parser.parse_args(args, namespace=None) 719 self.args = self.parser.parse_args(args, namespace=None)
720 if self.args._cmd._use_pubsub: 720 if self.args._cmd._use_pubsub:
721 self.parse_pubsub_args() 721 self.parse_pubsub_args()
754 async def confirm(self, message): 754 async def confirm(self, message):
755 """Request user to confirm action, return answer as boolean""" 755 """Request user to confirm action, return answer as boolean"""
756 res = await self.ainput(f"{message} (y/N)? ") 756 res = await self.ainput(f"{message} (y/N)? ")
757 return res in ("y", "Y") 757 return res in ("y", "Y")
758 758
759 async def confirmOrQuit(self, message, cancel_message=_("action cancelled by user")): 759 async def confirm_or_quit(self, message, cancel_message=_("action cancelled by user")):
760 """Request user to confirm action, and quit if he doesn't""" 760 """Request user to confirm action, and quit if he doesn't"""
761 confirmed = await self.confirm(message) 761 confirmed = await self.confirm(message)
762 if not confirmed: 762 if not confirmed:
763 self.disp(cancel_message) 763 self.disp(cancel_message)
764 self.quit(C.EXIT_USER_CANCELLED) 764 self.quit(C.EXIT_USER_CANCELLED)
765 765
766 def quitFromSignal(self, exit_code=0): 766 def quit_from_signal(self, exit_code=0):
767 r"""Same as self.quit, but from a signal handler 767 r"""Same as self.quit, but from a signal handler
768 768
769 /!\: return must be used after calling this method ! 769 /!\: return must be used after calling this method !
770 """ 770 """
771 # XXX: python-dbus will show a traceback if we exit in a signal handler 771 # XXX: python-dbus will show a traceback if we exit in a signal handler
803 """ 803 """
804 names2jid = {} 804 names2jid = {}
805 nodes2jid = {} 805 nodes2jid = {}
806 806
807 try: 807 try:
808 contacts = await self.bridge.getContacts(self.profile) 808 contacts = await self.bridge.contacts_get(self.profile)
809 except BridgeException as e: 809 except BridgeException as e:
810 if e.classname == "AttributeError": 810 if e.classname == "AttributeError":
811 # we may get an AttributeError if we use a component profile 811 # we may get an AttributeError if we use a component profile
812 # as components don't have roster 812 # as components don't have roster
813 contacts = [] 813 contacts = []
870 termios.tcsetattr(stdin_fd, tcsetattr_flags, old) 870 termios.tcsetattr(stdin_fd, tcsetattr_flags, old)
871 sys.stderr.flush() 871 sys.stderr.flush()
872 self.disp('') 872 self.disp('')
873 return pwd 873 return pwd
874 874
875 async def connectOrPrompt(self, method, err_msg=None): 875 async def connect_or_prompt(self, method, err_msg=None):
876 """Try to connect/start profile session and prompt for password if needed 876 """Try to connect/start profile session and prompt for password if needed
877 877
878 @param method(callable): bridge method to either connect or start profile session 878 @param method(callable): bridge method to either connect or start profile session
879 It will be called with password as sole argument, use lambda to do the call 879 It will be called with password as sole argument, use lambda to do the call
880 properly 880 properly
905 - 1 when the profile doesn't exists 905 - 1 when the profile doesn't exists
906 - 1 when there is a connection error 906 - 1 when there is a connection error
907 """ 907 """
908 # FIXME: need better exit codes 908 # FIXME: need better exit codes
909 909
910 self.profile = await self.bridge.profileNameGet(self.args.profile) 910 self.profile = await self.bridge.profile_name_get(self.args.profile)
911 911
912 if not self.profile: 912 if not self.profile:
913 log.error( 913 log.error(
914 _("The profile [{profile}] doesn't exist") 914 _("The profile [{profile}] doesn't exist")
915 .format(profile=self.args.profile) 915 .format(profile=self.args.profile)
920 start_session = self.args.start_session 920 start_session = self.args.start_session
921 except AttributeError: 921 except AttributeError:
922 pass 922 pass
923 else: 923 else:
924 if start_session: 924 if start_session:
925 await self.connectOrPrompt( 925 await self.connect_or_prompt(
926 lambda pwd: self.bridge.profileStartSession(pwd, self.profile), 926 lambda pwd: self.bridge.profile_start_session(pwd, self.profile),
927 err_msg="Can't start {profile}'s session: {e}" 927 err_msg="Can't start {profile}'s session: {e}"
928 ) 928 )
929 return 929 return
930 elif not await self.bridge.profileIsSessionStarted(self.profile): 930 elif not await self.bridge.profile_is_session_started(self.profile):
931 if not self.args.connect: 931 if not self.args.connect:
932 self.disp(_( 932 self.disp(_(
933 "Session for [{profile}] is not started, please start it " 933 "Session for [{profile}] is not started, please start it "
934 "before using jp, or use either --start-session or --connect " 934 "before using jp, or use either --start-session or --connect "
935 "option" 935 "option"
943 if not hasattr(self.args, 'connect'): 943 if not hasattr(self.args, 'connect'):
944 # a profile can be present without connect option (e.g. on profile 944 # a profile can be present without connect option (e.g. on profile
945 # creation/deletion) 945 # creation/deletion)
946 return 946 return
947 elif self.args.connect is True: # if connection is asked, we connect the profile 947 elif self.args.connect is True: # if connection is asked, we connect the profile
948 await self.connectOrPrompt( 948 await self.connect_or_prompt(
949 lambda pwd: self.bridge.connect(self.profile, pwd, {}), 949 lambda pwd: self.bridge.connect(self.profile, pwd, {}),
950 err_msg = 'Can\'t connect profile "{profile!s}": {e}' 950 err_msg = 'Can\'t connect profile "{profile!s}": {e}'
951 ) 951 )
952 return 952 return
953 else: 953 else:
954 if not await self.bridge.isConnected(self.profile): 954 if not await self.bridge.is_connected(self.profile):
955 log.error( 955 log.error(
956 _("Profile [{profile}] is not connected, please connect it " 956 _("Profile [{profile}] is not connected, please connect it "
957 "before using jp, or use --connect option") 957 "before using jp, or use --connect option")
958 .format(profile=self.profile) 958 .format(profile=self.profile)
959 ) 959 )
964 # TODO: to be removed, bare jid should work with all commands, notably for file 964 # TODO: to be removed, bare jid should work with all commands, notably for file
965 # as backend now handle jingles message initiation 965 # as backend now handle jingles message initiation
966 _jid = JID(param_jid) 966 _jid = JID(param_jid)
967 if not _jid.resource: 967 if not _jid.resource:
968 #if the resource is not given, we try to add the main resource 968 #if the resource is not given, we try to add the main resource
969 main_resource = await self.bridge.getMainResource(param_jid, self.profile) 969 main_resource = await self.bridge.main_resource_get(param_jid, self.profile)
970 if main_resource: 970 if main_resource:
971 return f"{_jid.bare}/{main_resource}" 971 return f"{_jid.bare}/{main_resource}"
972 return param_jid 972 return param_jid
973 973
974 async def get_profile_jid(self): 974 async def get_profile_jid(self):
975 """Retrieve current profile bare JID if possible""" 975 """Retrieve current profile bare JID if possible"""
976 full_jid = await self.bridge.asyncGetParamA( 976 full_jid = await self.bridge.param_get_a_async(
977 "JabberID", "Connection", profile_key=self.profile 977 "JabberID", "Connection", profile_key=self.profile
978 ) 978 )
979 return full_jid.rsplit("/", 1)[0] 979 return full_jid.rsplit("/", 1)[0]
980 980
981 981
1052 if use_output == True: 1052 if use_output == True:
1053 use_output = C.OUTPUT_TEXT 1053 use_output = C.OUTPUT_TEXT
1054 assert use_output in C.OUTPUT_TYPES 1054 assert use_output in C.OUTPUT_TYPES
1055 self._output_type = use_output 1055 self._output_type = use_output
1056 output_parent = argparse.ArgumentParser(add_help=False) 1056 output_parent = argparse.ArgumentParser(add_help=False)
1057 choices = set(self.host.getOutputChoices(use_output)) 1057 choices = set(self.host.get_output_choices(use_output))
1058 choices.update(extra_outputs) 1058 choices.update(extra_outputs)
1059 if not choices: 1059 if not choices:
1060 raise exceptions.InternalError( 1060 raise exceptions.InternalError(
1061 "No choice found for {} output type".format(use_output)) 1061 "No choice found for {} output type".format(use_output))
1062 try: 1062 try:
1123 return self.host.progress_id 1123 return self.host.progress_id
1124 1124
1125 async def set_progress_id(self, progress_id): 1125 async def set_progress_id(self, progress_id):
1126 return await self.host.set_progress_id(progress_id) 1126 return await self.host.set_progress_id(progress_id)
1127 1127
1128 async def progressStartedHandler(self, uid, metadata, profile): 1128 async def progress_started_handler(self, uid, metadata, profile):
1129 if profile != self.profile: 1129 if profile != self.profile:
1130 return 1130 return
1131 if self.progress_id is None: 1131 if self.progress_id is None:
1132 # the progress started message can be received before the id 1132 # the progress started message can be received before the id
1133 # so we keep progressStarted signals in cache to replay they 1133 # so we keep progress_started signals in cache to replay they
1134 # when the progress_id is received 1134 # when the progress_id is received
1135 cache_data = (self.progressStartedHandler, uid, metadata, profile) 1135 cache_data = (self.progress_started_handler, uid, metadata, profile)
1136 try: 1136 try:
1137 cache = self.host.progress_ids_cache 1137 cache = self.host.progress_ids_cache
1138 except AttributeError: 1138 except AttributeError:
1139 cache = self.host.progress_ids_cache = [] 1139 cache = self.host.progress_ids_cache = []
1140 cache.append(cache_data) 1140 cache.append(cache_data)
1141 else: 1141 else:
1142 if self.host.watch_progress and uid == self.progress_id: 1142 if self.host.watch_progress and uid == self.progress_id:
1143 await self.onProgressStarted(metadata) 1143 await self.on_progress_started(metadata)
1144 while True: 1144 while True:
1145 await asyncio.sleep(PROGRESS_DELAY) 1145 await asyncio.sleep(PROGRESS_DELAY)
1146 cont = await self.progressUpdate() 1146 cont = await self.progress_update()
1147 if not cont: 1147 if not cont:
1148 break 1148 break
1149 1149
1150 async def progressFinishedHandler(self, uid, metadata, profile): 1150 async def progress_finished_handler(self, uid, metadata, profile):
1151 if profile != self.profile: 1151 if profile != self.profile:
1152 return 1152 return
1153 if uid == self.progress_id: 1153 if uid == self.progress_id:
1154 try: 1154 try:
1155 self.host.pbar.finish() 1155 self.host.pbar.finish()
1156 except AttributeError: 1156 except AttributeError:
1157 pass 1157 pass
1158 await self.onProgressFinished(metadata) 1158 await self.on_progress_finished(metadata)
1159 if self.host.quit_on_progress_end: 1159 if self.host.quit_on_progress_end:
1160 self.host.quitFromSignal() 1160 self.host.quit_from_signal()
1161 1161
1162 async def progressErrorHandler(self, uid, message, profile): 1162 async def progress_error_handler(self, uid, message, profile):
1163 if profile != self.profile: 1163 if profile != self.profile:
1164 return 1164 return
1165 if uid == self.progress_id: 1165 if uid == self.progress_id:
1166 if self.args.progress: 1166 if self.args.progress:
1167 self.disp('') # progress is not finished, so we skip a line 1167 self.disp('') # progress is not finished, so we skip a line
1168 if self.host.quit_on_progress_end: 1168 if self.host.quit_on_progress_end:
1169 await self.onProgressError(message) 1169 await self.on_progress_error(message)
1170 self.host.quitFromSignal(C.EXIT_ERROR) 1170 self.host.quit_from_signal(C.EXIT_ERROR)
1171 1171
1172 async def progressUpdate(self): 1172 async def progress_update(self):
1173 """This method is continualy called to update the progress bar 1173 """This method is continualy called to update the progress bar
1174 1174
1175 @return (bool): False to stop being called 1175 @return (bool): False to stop being called
1176 """ 1176 """
1177 data = await self.host.bridge.progressGet(self.progress_id, self.profile) 1177 data = await self.host.bridge.progress_get(self.progress_id, self.profile)
1178 if data: 1178 if data:
1179 try: 1179 try:
1180 size = data['size'] 1180 size = data['size']
1181 except KeyError: 1181 except KeyError:
1182 self.disp(_("file size is not known, we can't show a progress bar"), 1, 1182 self.disp(_("file size is not known, we can't show a progress bar"), 1,
1212 self.host.pbar.update(int(data['position'])) 1212 self.host.pbar.update(int(data['position']))
1213 1213
1214 elif self.host.pbar is not None: 1214 elif self.host.pbar is not None:
1215 return False 1215 return False
1216 1216
1217 await self.onProgressUpdate(data) 1217 await self.on_progress_update(data)
1218 1218
1219 return True 1219 return True
1220 1220
1221 async def onProgressStarted(self, metadata): 1221 async def on_progress_started(self, metadata):
1222 """Called when progress has just started 1222 """Called when progress has just started
1223 1223
1224 can be overidden by a command 1224 can be overidden by a command
1225 @param metadata(dict): metadata as sent by bridge.progressStarted 1225 @param metadata(dict): metadata as sent by bridge.progress_started
1226 """ 1226 """
1227 self.disp(_("Operation started"), 2) 1227 self.disp(_("Operation started"), 2)
1228 1228
1229 async def onProgressUpdate(self, metadata): 1229 async def on_progress_update(self, metadata):
1230 """Method called on each progress updata 1230 """Method called on each progress updata
1231 1231
1232 can be overidden by a command to handle progress metadata 1232 can be overidden by a command to handle progress metadata
1233 @para metadata(dict): metadata as returned by bridge.progressGet 1233 @para metadata(dict): metadata as returned by bridge.progress_get
1234 """ 1234 """
1235 pass 1235 pass
1236 1236
1237 async def onProgressFinished(self, metadata): 1237 async def on_progress_finished(self, metadata):
1238 """Called when progress has just finished 1238 """Called when progress has just finished
1239 1239
1240 can be overidden by a command 1240 can be overidden by a command
1241 @param metadata(dict): metadata as sent by bridge.progressFinished 1241 @param metadata(dict): metadata as sent by bridge.progress_finished
1242 """ 1242 """
1243 self.disp(_("Operation successfully finished"), 2) 1243 self.disp(_("Operation successfully finished"), 2)
1244 1244
1245 async def onProgressError(self, e): 1245 async def on_progress_error(self, e):
1246 """Called when a progress failed 1246 """Called when a progress failed
1247 1247
1248 @param error_msg(unicode): error message as sent by bridge.progressError 1248 @param error_msg(unicode): error message as sent by bridge.progress_error
1249 """ 1249 """
1250 self.disp(_("Error while doing operation: {e}").format(e=e), error=True) 1250 self.disp(_("Error while doing operation: {e}").format(e=e), error=True)
1251 1251
1252 def disp(self, msg, verbosity=0, error=False, end='\n'): 1252 def disp(self, msg, verbosity=0, error=False, end='\n'):
1253 return self.host.disp(msg, verbosity, error, end) 1253 return self.host.disp(msg, verbosity, error, end)
1258 except AttributeError: 1258 except AttributeError:
1259 raise exceptions.InternalError( 1259 raise exceptions.InternalError(
1260 _('trying to use output when use_output has not been set')) 1260 _('trying to use output when use_output has not been set'))
1261 return self.host.output(output_type, self.args.output, self.extra_outputs, data) 1261 return self.host.output(output_type, self.args.output, self.extra_outputs, data)
1262 1262
1263 def getPubsubExtra(self, extra: Optional[dict] = None) -> str: 1263 def get_pubsub_extra(self, extra: Optional[dict] = None) -> str:
1264 """Helper method to compute extra data from pubsub arguments 1264 """Helper method to compute extra data from pubsub arguments
1265 1265
1266 @param extra: base extra dict, or None to generate a new one 1266 @param extra: base extra dict, or None to generate a new one
1267 @return: serialised dict which can be used directly in the bridge for pubsub 1267 @return: serialised dict which can be used directly in the bridge for pubsub
1268 """ 1268 """
1326 1326
1327 # now we add subcommands to ourself 1327 # now we add subcommands to ourself
1328 for cls in subcommands: 1328 for cls in subcommands:
1329 cls(self) 1329 cls(self)
1330 1330
1331 def overridePubsubFlags(self, new_flags: Set[str]) -> None: 1331 def override_pubsub_flags(self, new_flags: Set[str]) -> None:
1332 """Replace pubsub_flags given in __init__ 1332 """Replace pubsub_flags given in __init__
1333 1333
1334 useful when a command is extending an other command (e.g. blog command which does 1334 useful when a command is extending an other command (e.g. blog command which does
1335 the same as pubsub command, but with a default node) 1335 the same as pubsub command, but with a default node)
1336 """ 1336 """
1354 if show_progress: 1354 if show_progress:
1355 self.host.watch_progress = True 1355 self.host.watch_progress = True
1356 # we need to register the following signal even if we don't display the 1356 # we need to register the following signal even if we don't display the
1357 # progress bar 1357 # progress bar
1358 self.host.bridge.register_signal( 1358 self.host.bridge.register_signal(
1359 "progressStarted", self.progressStartedHandler) 1359 "progress_started", self.progress_started_handler)
1360 self.host.bridge.register_signal( 1360 self.host.bridge.register_signal(
1361 "progressFinished", self.progressFinishedHandler) 1361 "progress_finished", self.progress_finished_handler)
1362 self.host.bridge.register_signal( 1362 self.host.bridge.register_signal(
1363 "progressError", self.progressErrorHandler) 1363 "progress_error", self.progress_error_handler)
1364 1364
1365 if self.need_connect is not None: 1365 if self.need_connect is not None:
1366 await self.host.connect_profile() 1366 await self.host.connect_profile()
1367 await self.start() 1367 await self.start()
1368 1368
1385 # already managed when callback is called 1385 # already managed when callback is called
1386 1386
1387 def __init__(self, *args, **kwargs): 1387 def __init__(self, *args, **kwargs):
1388 super(CommandAnswering, self).__init__(*args, **kwargs) 1388 super(CommandAnswering, self).__init__(*args, **kwargs)
1389 1389
1390 async def onActionNew(self, action_data, action_id, security_limit, profile): 1390 async def on_action_new(self, action_data, action_id, security_limit, profile):
1391 if profile != self.profile: 1391 if profile != self.profile:
1392 return 1392 return
1393 try: 1393 try:
1394 action_type = action_data['meta_type'] 1394 action_type = action_data['meta_type']
1395 except KeyError: 1395 except KeyError:
1396 try: 1396 try:
1397 xml_ui = action_data["xmlui"] 1397 xml_ui = action_data["xmlui"]
1398 except KeyError: 1398 except KeyError:
1399 pass 1399 pass
1400 else: 1400 else:
1401 self.onXMLUI(xml_ui) 1401 self.on_xmlui(xml_ui)
1402 else: 1402 else:
1403 try: 1403 try:
1404 callback = self.action_callbacks[action_type] 1404 callback = self.action_callbacks[action_type]
1405 except KeyError: 1405 except KeyError:
1406 pass 1406 pass
1407 else: 1407 else:
1408 await callback(action_data, action_id, security_limit, profile) 1408 await callback(action_data, action_id, security_limit, profile)
1409 1409
1410 def onXMLUI(self, xml_ui): 1410 def on_xmlui(self, xml_ui):
1411 """Display a dialog received from the backend. 1411 """Display a dialog received from the backend.
1412 1412
1413 @param xml_ui (unicode): dialog XML representation 1413 @param xml_ui (unicode): dialog XML representation
1414 """ 1414 """
1415 # FIXME: we temporarily use ElementTree, but a real XMLUI managing module 1415 # FIXME: we temporarily use ElementTree, but a real XMLUI managing module
1420 if dialog is not None: 1420 if dialog is not None:
1421 self.disp(dialog.findtext("message"), error=dialog.get("level") == "error") 1421 self.disp(dialog.findtext("message"), error=dialog.get("level") == "error")
1422 1422
1423 async def start_answering(self): 1423 async def start_answering(self):
1424 """Auto reply to confirmation requests""" 1424 """Auto reply to confirmation requests"""
1425 self.host.bridge.register_signal("actionNew", self.onActionNew) 1425 self.host.bridge.register_signal("action_new", self.on_action_new)
1426 actions = await self.host.bridge.actionsGet(self.profile) 1426 actions = await self.host.bridge.actions_get(self.profile)
1427 for action_data, action_id, security_limit in actions: 1427 for action_data, action_id, security_limit in actions:
1428 await self.onActionNew(action_data, action_id, security_limit, self.profile) 1428 await self.on_action_new(action_data, action_id, security_limit, self.profile)