Mercurial > libervia-backend
comparison sat_frontends/jp/cmd_debug.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 | cf843dd7c345 |
comparison
equal
deleted
inserted
replaced
3039:a1bc34f90fa5 | 3040:fee60f17ebac |
---|---|
46 | 46 |
47 class Method(base.CommandBase, BridgeCommon): | 47 class Method(base.CommandBase, BridgeCommon): |
48 def __init__(self, host): | 48 def __init__(self, host): |
49 base.CommandBase.__init__(self, host, "method", help=_("call a bridge method")) | 49 base.CommandBase.__init__(self, host, "method", help=_("call a bridge method")) |
50 BridgeCommon.__init__(self) | 50 BridgeCommon.__init__(self) |
51 self.need_loop = True | |
52 | 51 |
53 def add_parser_options(self): | 52 def add_parser_options(self): |
54 self.parser.add_argument( | 53 self.parser.add_argument( |
55 "method", type=str, help=_("name of the method to execute") | 54 "method", type=str, help=_("name of the method to execute") |
56 ) | 55 ) |
57 self.parser.add_argument( | 56 self.parser.add_argument( |
58 "arg", nargs="*", help=_("argument of the method") | 57 "arg", nargs="*", help=_("argument of the method") |
59 ) | 58 ) |
60 | 59 |
61 def method_cb(self, ret=None): | 60 async def start(self): |
62 if ret is not None: | 61 method = getattr(self.host.bridge, self.args.method) |
63 self.disp(str(ret)) | 62 import inspect |
64 self.host.quit() | 63 argspec = inspect.getargspec(method) |
65 | 64 |
66 def method_eb(self, failure): | 65 kwargs = {} |
67 self.disp( | 66 if 'profile_key' in argspec.args: |
68 _("Error while executing {}: {}".format(self.args.method, failure)), | 67 kwargs['profile_key'] = self.profile |
69 error=True, | 68 elif 'profile' in argspec.args: |
70 ) | 69 kwargs['profile'] = self.profile |
71 self.host.quit(C.EXIT_ERROR) | |
72 | 70 |
73 def start(self): | |
74 method = getattr(self.host.bridge, self.args.method) | |
75 args = self.evalArgs() | 71 args = self.evalArgs() |
72 | |
76 try: | 73 try: |
77 method( | 74 ret = await method( |
78 *args, | 75 *args, |
79 profile=self.profile, | 76 **kwargs, |
80 callback=self.method_cb, | |
81 errback=self.method_eb | |
82 ) | 77 ) |
83 except TypeError: | 78 except Exception as e: |
84 # maybe the method doesn't need a profile ? | 79 self.disp(_(f"Error while executing {self.args.method}: {e}"), error=True) |
85 try: | 80 self.host.quit(C.EXIT_ERROR) |
86 method(*args, callback=self.method_cb, errback=self.method_eb) | 81 else: |
87 except TypeError: | 82 if ret is not None: |
88 self.method_eb(_("bad arguments")) | 83 self.disp(str(ret)) |
84 self.host.quit() | |
89 | 85 |
90 | 86 |
91 class Signal(base.CommandBase, BridgeCommon): | 87 class Signal(base.CommandBase, BridgeCommon): |
92 def __init__(self, host): | 88 def __init__(self, host): |
93 base.CommandBase.__init__( | 89 base.CommandBase.__init__( |
101 ) | 97 ) |
102 self.parser.add_argument( | 98 self.parser.add_argument( |
103 "arg", nargs="*", help=_("argument of the signal") | 99 "arg", nargs="*", help=_("argument of the signal") |
104 ) | 100 ) |
105 | 101 |
106 def start(self): | 102 async def start(self): |
107 args = self.evalArgs() | 103 args = self.evalArgs() |
108 json_args = json.dumps(args) | 104 json_args = json.dumps(args) |
109 # XXX: we use self.args.profile and not self.profile | 105 # XXX: we use self.args.profile and not self.profile |
110 # because we want the raw profile_key (so plugin handle C.PROF_KEY_NONE) | 106 # because we want the raw profile_key (so plugin handle C.PROF_KEY_NONE) |
111 self.host.bridge.debugFakeSignal(self.args.signal, json_args, self.args.profile) | 107 try: |
108 await self.host.bridge.debugFakeSignal(self.args.signal, json_args, self.args.profile) | |
109 except Exception as e: | |
110 self.disp(_(f"Can't send fake signal: {e}"), error=True) | |
111 self.host.quit(C.EXIT_ERROR) | |
112 else: | |
113 self.host.quit() | |
112 | 114 |
113 | 115 |
114 class Bridge(base.CommandBase): | 116 class Bridge(base.CommandBase): |
115 subcommands = (Method, Signal) | 117 subcommands = (Method, Signal) |
116 | 118 |
128 use_verbose=True, | 130 use_verbose=True, |
129 use_profile=False, | 131 use_profile=False, |
130 use_output=C.OUTPUT_XML, | 132 use_output=C.OUTPUT_XML, |
131 help=_("monitor XML stream"), | 133 help=_("monitor XML stream"), |
132 ) | 134 ) |
133 self.need_loop = True | |
134 | 135 |
135 def add_parser_options(self): | 136 def add_parser_options(self): |
136 self.parser.add_argument( | 137 self.parser.add_argument( |
137 "-d", | 138 "-d", |
138 "--direction", | 139 "--direction", |
139 choices=("in", "out", "both"), | 140 choices=("in", "out", "both"), |
140 default="both", | 141 default="both", |
141 help=_("stream direction filter"), | 142 help=_("stream direction filter"), |
142 ) | 143 ) |
143 | 144 |
144 def printXML(self, direction, xml_data, profile): | 145 async def printXML(self, direction, xml_data, profile): |
145 if self.args.direction == "in" and direction != "IN": | 146 if self.args.direction == "in" and direction != "IN": |
146 return | 147 return |
147 if self.args.direction == "out" and direction != "OUT": | 148 if self.args.direction == "out" and direction != "OUT": |
148 return | 149 return |
149 verbosity = self.host.verbosity | 150 verbosity = self.host.verbosity |
153 whiteping = True | 154 whiteping = True |
154 else: | 155 else: |
155 whiteping = False | 156 whiteping = False |
156 | 157 |
157 if verbosity: | 158 if verbosity: |
158 profile_disp = " ({})".format(profile) if verbosity > 1 else "" | 159 profile_disp = f" ({profile})" if verbosity > 1 else "" |
159 if direction == "IN": | 160 if direction == "IN": |
160 self.disp( | 161 self.disp( |
161 A.color( | 162 A.color( |
162 A.BOLD, A.FG_YELLOW, "<<<===== IN ====", A.FG_WHITE, profile_disp | 163 A.BOLD, A.FG_YELLOW, "<<<===== IN ====", A.FG_WHITE, profile_disp |
163 ) | 164 ) |
170 ) | 171 ) |
171 if whiteping: | 172 if whiteping: |
172 self.disp("[WHITESPACE PING]") | 173 self.disp("[WHITESPACE PING]") |
173 else: | 174 else: |
174 try: | 175 try: |
175 self.output(xml_data) | 176 await self.output(xml_data) |
176 except Exception: | 177 except Exception: |
177 # initial stream is not valid XML, | 178 # initial stream is not valid XML, |
178 # in this case we print directly to data | 179 # in this case we print directly to data |
179 # FIXME: we should test directly lxml.etree.XMLSyntaxError | 180 # FIXME: we should test directly lxml.etree.XMLSyntaxError |
180 # but importing lxml directly here is not clean | 181 # but importing lxml directly here is not clean |
181 # should be wrapped in a custom Exception | 182 # should be wrapped in a custom Exception |
182 self.disp(xml_data) | 183 self.disp(xml_data) |
183 self.disp("") | 184 self.disp("") |
184 | 185 |
185 def start(self): | 186 async def start(self): |
186 self.host.bridge.register_signal("xmlLog", self.printXML, "plugin") | 187 self.host.bridge.register_signal("xmlLog", self.printXML, "plugin") |
187 | 188 |
188 | 189 |
189 class Debug(base.CommandBase): | 190 class Debug(base.CommandBase): |
190 subcommands = (Bridge, Monitor) | 191 subcommands = (Bridge, Monitor) |