Mercurial > libervia-backend
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) |