|
13 | 13 | from pyobs.comm import Comm, Proxy |
14 | 14 | from pyobs.events import ModuleOpenedEvent, Event, ModuleClosedEvent |
15 | 15 | from pyobs.utils import exceptions as exc |
| 16 | +from pyobs.utils.shellcommand import ShellCommand |
16 | 17 | from pyobs.vfs import VirtualFileSystem |
17 | 18 | from .base import BaseWidget |
18 | 19 | from .qt.shellwidget_ui import Ui_ShellWidget |
@@ -172,133 +173,23 @@ def _add_command_log(self, msg: str, color: str | None = None) -> None: |
172 | 173 | msg = '<span style="color:%s;">%s</span>' % (color, msg) |
173 | 174 | self.add_command_log.emit(msg) |
174 | 175 |
|
175 | | - def _parse_command(self, cmd: str) -> tuple[str, str, list[Any]]: |
176 | | - # tokenize command |
177 | | - tokens = tokenize.tokenize(BytesIO(cmd.encode("utf-8")).readline) |
178 | | - |
179 | | - # init values |
180 | | - module: str | None = None |
181 | | - command: str | None = None |
182 | | - params: list[Any] = [] |
183 | | - sign = 1 |
184 | | - |
185 | | - # we start here |
186 | | - state = ParserState.START |
187 | | - |
188 | | - # loop tokens |
189 | | - for t in tokens: |
190 | | - if state == ParserState.START: |
191 | | - # first token is always ENCODING |
192 | | - if t.type != tokenize.ENCODING: |
193 | | - raise ValueError("Invalid command.") |
194 | | - state = ParserState.MODULE |
195 | | - |
196 | | - elif state == ParserState.MODULE: |
197 | | - # 2nd token is always a NAME with the command |
198 | | - if t.type != tokenize.NAME: |
199 | | - raise ValueError("Invalid command.") |
200 | | - module = t.string |
201 | | - state = ParserState.MODSEP |
202 | | - |
203 | | - elif state == ParserState.MODSEP: |
204 | | - # 3rd token is always a point |
205 | | - if t.type != tokenize.OP or t.string != ".": |
206 | | - raise ValueError("Invalid command.") |
207 | | - state = ParserState.COMMAND |
208 | | - |
209 | | - elif state == ParserState.COMMAND: |
210 | | - # 4th token is always a NAME with the command |
211 | | - if t.type != tokenize.NAME: |
212 | | - raise ValueError("Invalid command.") |
213 | | - command = t.string |
214 | | - state = ParserState.OPEN |
215 | | - |
216 | | - elif state == ParserState.OPEN: |
217 | | - # 5th token is always an OP with an opening bracket |
218 | | - if t.type != tokenize.OP or t.string != "(": |
219 | | - raise ValueError("Invalid parameters.") |
220 | | - state = ParserState.PARAM |
221 | | - |
222 | | - elif state == ParserState.PARAM: |
223 | | - # if params list is empty, we accept an OP with a closing bracket, otherwise it must be |
224 | | - # a NUMBER or STRING |
225 | | - if len(params) == 0 and t.type == tokenize.OP and t.string == ")": |
226 | | - state = ParserState.CLOSE |
227 | | - elif t.type == tokenize.OP and t.string == "-": |
228 | | - sign = -1 |
229 | | - elif t.type == tokenize.NUMBER or t.type == tokenize.STRING: |
230 | | - if t.type == tokenize.STRING: |
231 | | - if t.string[0] == t.string[-1] and t.string[0] in ['"', '"']: |
232 | | - params.append(t.string[1:-1]) |
233 | | - else: |
234 | | - params.append(t.string) |
235 | | - else: |
236 | | - params.append(sign * float(t.string)) |
237 | | - sign = 1 |
238 | | - state = ParserState.PARAMSEP |
239 | | - else: |
240 | | - raise ValueError("Invalid parameters.") |
241 | | - |
242 | | - elif state == ParserState.PARAMSEP: |
243 | | - # following a PARAM, there must be an OP, either a comma, or a closing bracket |
244 | | - if t.type != tokenize.OP: |
245 | | - raise ValueError("Invalid parameters.") |
246 | | - if t.string == ",": |
247 | | - state = ParserState.PARAM |
248 | | - elif t.string == ")": |
249 | | - state = ParserState.CLOSE |
250 | | - else: |
251 | | - raise ValueError("Invalid parameters.") |
252 | | - |
253 | | - elif state == ParserState.CLOSE: |
254 | | - # must be a closing bracket |
255 | | - if t.type not in [tokenize.NEWLINE, tokenize.ENDMARKER]: |
256 | | - raise ValueError("Expecting end of command after closing bracket.") |
257 | | - |
258 | | - # return results |
259 | | - if module is None or command is None: |
260 | | - raise ValueError("Found end of command without module and/or command.") |
261 | | - return module, command, params |
262 | | - |
263 | | - # if we came here, something went wrong |
264 | | - raise ValueError("Invalid parameters.") |
265 | | - |
266 | 176 | def execute_command(self, command: str) -> None: |
267 | 177 | asyncio.create_task(self._execute_command(command)) |
268 | 178 |
|
269 | 179 | async def _execute_command(self, command: str) -> None: |
270 | | - # log command |
271 | | - self.command_number += 1 |
272 | | - self._add_command_log("$ (#%d) %s" % (self.command_number, command)) |
273 | | - |
274 | | - # parse command |
275 | 180 | try: |
276 | | - client, command, params = self._parse_command(command) |
| 181 | + cmd = ShellCommand.parse(command) |
| 182 | + self._add_command_log(str(cmd)) |
277 | 183 | except Exception as e: |
278 | | - self._add_command_log("(#%d): %s" % (self.command_number, str(e)), "red") |
279 | | - return |
280 | | - |
281 | | - # get proxy |
282 | | - try: |
283 | | - proxy = await self.comm.proxy(client) |
284 | | - except ValueError: |
285 | | - self._add_command_log(f"(#{self.command_number}): Could not find module: {str(client)}", "red") |
| 184 | + self._add_command_log(f"$ {command}") |
| 185 | + self._add_command_log(f"{str(e)}", "red") |
286 | 186 | return |
287 | 187 |
|
288 | 188 | # execute command |
289 | | - try: |
290 | | - response = await proxy.execute(command, *params) |
291 | | - except ValueError as e: |
292 | | - log.exception(f"(#{self.command_number}): Something has gone wrong.") |
293 | | - self._add_command_log(f"(#{self.command_number}): Invalid parameter: {str(e)}", "red") |
294 | | - return |
295 | | - except exc.RemoteError as e: |
296 | | - self._add_command_log(f"(#{self.command_number}) Exception raised: {str(e)}", "red") |
297 | | - return |
| 189 | + response = await cmd.execute(self.comm) |
298 | 190 |
|
299 | 191 | # log response |
300 | | - msg = "OK" if response is None else pprint.pformat(response) |
301 | | - self._add_command_log("(#%d) %s" % (self.command_number, msg), "lime") |
| 192 | + self._add_command_log(str(response), response.color) |
302 | 193 |
|
303 | 194 | def _update_docs(self) -> None: |
304 | 195 | return |
|
0 commit comments