diff mbox series

[2/5] python: qmp_shell: refactor the parsing error handling

Message ID 20220221155519.2367-3-damien.hedde@greensocs.com
State New
Headers show
Series qmp-shell modifications for non-interactive use | expand

Commit Message

Damien Hedde Feb. 21, 2022, 3:55 p.m. UTC
Instead of handling these error in _excute_cmd(), now
raise the exception and let read_exec_command() handle it.

Introduce QMPShellParseError (subclass of QMPShellError)
to replace QMPShellError. In next commit we will introduce
another subclass.

Introduce _print_parse_error() method because QMPShell
and HMPShell handle the printing differently.

Signed-off-by: Damien Hedde <damien.hedde@greensocs.com>
---
 python/qemu/aqmp/qmp_shell.py | 51 +++++++++++++++++++++--------------
 1 file changed, 31 insertions(+), 20 deletions(-)
diff mbox series

Patch

diff --git a/python/qemu/aqmp/qmp_shell.py b/python/qemu/aqmp/qmp_shell.py
index a6e0f5af42..a1bd7d5630 100644
--- a/python/qemu/aqmp/qmp_shell.py
+++ b/python/qemu/aqmp/qmp_shell.py
@@ -136,6 +136,12 @@  class QMPShellError(QMPError):
     """
 
 
+class QMPShellParseError(QMPShellError):
+    """
+    QMP Shell Parse error class.
+    """
+
+
 class FuzzyJSON(ast.NodeTransformer):
     """
     This extension of ast.NodeTransformer filters literal "true/false/null"
@@ -246,7 +252,7 @@  def _cli_expr(self,
         for arg in tokens:
             (key, sep, val) = arg.partition('=')
             if sep != '=':
-                raise QMPShellError(
+                raise QMPShellParseError(
                     f"Expected a key=value pair, got '{arg!s}'"
                 )
 
@@ -258,14 +264,14 @@  def _cli_expr(self,
                 obj = parent.get(path, {})
                 if not isinstance(obj, dict):
                     msg = 'Cannot use "{:s}" as both leaf and non-leaf key'
-                    raise QMPShellError(msg.format('.'.join(curpath)))
+                    raise QMPShellParseError(msg.format('.'.join(curpath)))
                 parent[path] = obj
                 parent = obj
             if optpath[-1] in parent:
                 if isinstance(parent[optpath[-1]], dict):
                     msg = 'Cannot use "{:s}" as both leaf and non-leaf key'
-                    raise QMPShellError(msg.format('.'.join(curpath)))
-                raise QMPShellError(f'Cannot set "{key}" multiple times')
+                    raise QMPShellParseError(msg.format('.'.join(curpath)))
+                raise QMPShellParseError(f'Cannot set "{key}" multiple times')
             parent[optpath[-1]] = value
 
     def _build_cmd(self, cmdline: str) -> Optional[QMPMessage]:
@@ -290,7 +296,7 @@  def _build_cmd(self, cmdline: str) -> Optional[QMPMessage]:
             self._transmode = False
             if len(cmdargs) > 1:
                 msg = 'Unexpected input after close of Transaction sub-shell'
-                raise QMPShellError(msg)
+                raise QMPShellParseError(msg)
             qmpcmd = {
                 'execute': 'transaction',
                 'arguments': {'actions': self._actions}
@@ -323,17 +329,17 @@  def _print(self, qmp_message: object) -> None:
                            sort_keys=self.pretty)
         print(str(jsobj))
 
+    def _print_parse_error(self, err: QMPShellParseError) -> None:
+        print(
+            f"Error while parsing command line: {err!s}\n"
+            "command format: <command-name> "
+            "[arg-name1=arg1] ... [arg-nameN=argN",
+            file=sys.stderr
+        )
+
     def _execute_cmd(self, cmdline: str) -> bool:
-        try:
-            qmpcmd = self._build_cmd(cmdline)
-        except QMPShellError as err:
-            print(
-                f"Error while parsing command line: {err!s}\n"
-                "command format: <command-name> "
-                "[arg-name1=arg1] ... [arg-nameN=argN",
-                file=sys.stderr
-            )
-            return True
+        qmpcmd = self._build_cmd(cmdline)
+
         # For transaction mode, we may have just cached the action:
         if qmpcmd is None:
             return True
@@ -390,7 +396,11 @@  def read_exec_command(self) -> bool:
                 print(event)
             return True
 
-        return self._execute_cmd(cmdline)
+        try:
+            return self._execute_cmd(cmdline)
+        except QMPShellParseError as err:
+            self._print_parse_error(err)
+        return True
 
     def repl(self) -> Iterator[None]:
         """
@@ -456,18 +466,19 @@  def _cmd_passthrough(self, cmdline: str,
             }
         })
 
+    def _print_parse_error(self, err: QMPShellParseError) -> None:
+        print(f"{err!s}")
+
     def _execute_cmd(self, cmdline: str) -> bool:
         if cmdline.split()[0] == "cpu":
             # trap the cpu command, it requires special setting
             try:
                 idx = int(cmdline.split()[1])
                 if 'return' not in self._cmd_passthrough('info version', idx):
-                    print('bad CPU index')
-                    return True
+                    raise QMPShellParseError('bad CPU index')
                 self._cpu_index = idx
             except ValueError:
-                print('cpu command takes an integer argument')
-                return True
+                raise QMPShellParseError('cpu command takes an integer argument')
         resp = self._cmd_passthrough(cmdline, self._cpu_index)
         if resp is None:
             print('Disconnected')