All of lore.kernel.org
 help / color / mirror / Atom feed
From: John Snow <jsnow@redhat.com>
To: qemu-devel@nongnu.org
Cc: Peter Maydell <peter.maydell@linaro.org>,
	Markus Armbruster <armbru@redhat.com>,
	John Snow <jsnow@redhat.com>,
	Eduardo Habkost <ehabkost@redhat.com>,
	Cleber Rosa <crosa@redhat.com>
Subject: [PULL 57/72] scripts/qmp-shell: add mypy types
Date: Fri, 18 Jun 2021 19:04:40 -0400	[thread overview]
Message-ID: <20210618230455.2891199-58-jsnow@redhat.com> (raw)
In-Reply-To: <20210618230455.2891199-1-jsnow@redhat.com>

As per my usual, this patch is annotations only. Any changes with side
effects are done elsewhere.

Note: pylint does not understand the subscripts for Collection in Python 3.6,
so use the stronger Sequence type as a workaround.
Signed-off-by: John Snow <jsnow@redhat.com>
Message-id: 20210607200649.1840382-28-jsnow@redhat.com
Signed-off-by: John Snow <jsnow@redhat.com>
---
 scripts/qmp/qmp-shell | 67 ++++++++++++++++++++++++++-----------------
 1 file changed, 41 insertions(+), 26 deletions(-)

diff --git a/scripts/qmp/qmp-shell b/scripts/qmp/qmp-shell
index 670361322c..2d0e85b5f7 100755
--- a/scripts/qmp/qmp-shell
+++ b/scripts/qmp/qmp-shell
@@ -72,10 +72,18 @@ import os
 import re
 import readline
 import sys
+from typing import (
+    Iterator,
+    List,
+    NoReturn,
+    Optional,
+    Sequence,
+)
 
 
 sys.path.append(os.path.join(os.path.dirname(__file__), '..', '..', 'python'))
 from qemu import qmp
+from qemu.qmp import QMPMessage
 
 
 class QMPCompleter:
@@ -122,25 +130,26 @@ class FuzzyJSON(ast.NodeTransformer):
 # TODO: QMPShell's interface is a bit ugly (eg. _fill_completion() and
 #       _execute_cmd()). Let's design a better one.
 class QMPShell(qmp.QEMUMonitorProtocol):
-    def __init__(self, address, pretty=False, verbose=False):
+    def __init__(self, address: str, pretty: bool = False,
+                 verbose: bool = False):
         super().__init__(self.parse_address(address))
-        self._greeting = None
+        self._greeting: Optional[QMPMessage] = None
         self._completer = QMPCompleter()
         self._pretty = pretty
         self._transmode = False
-        self._actions = list()
+        self._actions: List[QMPMessage] = []
         self._histfile = os.path.join(os.path.expanduser('~'),
                                       '.qmp-shell_history')
         self.verbose = verbose
 
-    def _fill_completion(self):
+    def _fill_completion(self) -> None:
         cmds = self.cmd('query-commands')
         if 'error' in cmds:
             return
         for cmd in cmds['return']:
             self._completer.append(cmd['name'])
 
-    def __completer_setup(self):
+    def __completer_setup(self) -> None:
         self._completer = QMPCompleter()
         self._fill_completion()
         readline.set_history_length(1024)
@@ -157,14 +166,14 @@ class QMPShell(qmp.QEMUMonitorProtocol):
             print(f"Failed to read history '{self._histfile}': {err!s}")
         atexit.register(self.__save_history)
 
-    def __save_history(self):
+    def __save_history(self) -> None:
         try:
             readline.write_history_file(self._histfile)
         except IOError as err:
             print(f"Failed to save history file '{self._histfile}': {err!s}")
 
     @classmethod
-    def __parse_value(cls, val):
+    def __parse_value(cls, val: str) -> object:
         try:
             return int(val)
         except ValueError:
@@ -189,7 +198,9 @@ class QMPShell(qmp.QEMUMonitorProtocol):
                 pass
         return val
 
-    def __cli_expr(self, tokens, parent):
+    def __cli_expr(self,
+                   tokens: Sequence[str],
+                   parent: qmp.QMPObject) -> None:
         for arg in tokens:
             (key, sep, val) = arg.partition('=')
             if sep != '=':
@@ -215,7 +226,7 @@ class QMPShell(qmp.QEMUMonitorProtocol):
                 raise QMPShellError(f'Cannot set "{key}" multiple times')
             parent[optpath[-1]] = value
 
-    def __build_cmd(self, cmdline):
+    def __build_cmd(self, cmdline: str) -> Optional[QMPMessage]:
         """
         Build a QMP input object from a user provided command-line in the
         following format:
@@ -224,6 +235,7 @@ class QMPShell(qmp.QEMUMonitorProtocol):
         """
         argument_regex = r'''(?:[^\s"']|"(?:\\.|[^"])*"|'(?:\\.|[^'])*')+'''
         cmdargs = re.findall(argument_regex, cmdline)
+        qmpcmd: QMPMessage
 
         # Transactional CLI entry/exit:
         if cmdargs[0] == 'transaction(':
@@ -261,14 +273,14 @@ class QMPShell(qmp.QEMUMonitorProtocol):
         self.__cli_expr(cmdargs[1:], qmpcmd['arguments'])
         return qmpcmd
 
-    def _print(self, qmp_message):
+    def _print(self, qmp_message: object) -> None:
         indent = None
         if self._pretty:
             indent = 4
         jsobj = json.dumps(qmp_message, indent=indent, sort_keys=self._pretty)
         print(str(jsobj))
 
-    def _execute_cmd(self, cmdline):
+    def _execute_cmd(self, cmdline: str) -> bool:
         try:
             qmpcmd = self.__build_cmd(cmdline)
         except Exception as err:
@@ -288,11 +300,12 @@ class QMPShell(qmp.QEMUMonitorProtocol):
         self._print(resp)
         return True
 
-    def connect(self, negotiate: bool = True):
+    def connect(self, negotiate: bool = True) -> None:
         self._greeting = super().connect(negotiate)
         self.__completer_setup()
 
-    def show_banner(self, msg='Welcome to the QMP low-level shell!'):
+    def show_banner(self,
+                    msg: str = 'Welcome to the QMP low-level shell!') -> None:
         print(msg)
         if not self._greeting:
             print('Connected')
@@ -301,12 +314,12 @@ class QMPShell(qmp.QEMUMonitorProtocol):
         print("Connected to QEMU {major}.{minor}.{micro}\n".format(**version))
 
     @property
-    def prompt(self):
+    def prompt(self) -> str:
         if self._transmode:
             return 'TRANS> '
         return '(QEMU) '
 
-    def read_exec_command(self):
+    def read_exec_command(self) -> bool:
         """
         Read and execute a command.
 
@@ -326,7 +339,7 @@ class QMPShell(qmp.QEMUMonitorProtocol):
 
         return self._execute_cmd(cmdline)
 
-    def repl(self):
+    def repl(self) -> Iterator[None]:
         self.show_banner()
         while self.read_exec_command():
             yield
@@ -334,11 +347,12 @@ class QMPShell(qmp.QEMUMonitorProtocol):
 
 
 class HMPShell(QMPShell):
-    def __init__(self, address, pretty=False, verbose=False):
+    def __init__(self, address: str,
+                 pretty: bool = False, verbose: bool = False):
         super().__init__(address, pretty, verbose)
         self.__cpu_index = 0
 
-    def __cmd_completion(self):
+    def __cmd_completion(self) -> None:
         for cmd in self.__cmd_passthrough('help')['return'].split('\r\n'):
             if cmd and cmd[0] != '[' and cmd[0] != '\t':
                 name = cmd.split()[0]  # drop help text
@@ -355,21 +369,22 @@ class HMPShell(QMPShell):
                 self._completer.append(name)
                 self._completer.append('help ' + name)  # help completion
 
-    def __info_completion(self):
+    def __info_completion(self) -> None:
         for cmd in self.__cmd_passthrough('info')['return'].split('\r\n'):
             if cmd:
                 self._completer.append('info ' + cmd.split()[1])
 
-    def __other_completion(self):
+    def __other_completion(self) -> None:
         # special cases
         self._completer.append('help info')
 
-    def _fill_completion(self):
+    def _fill_completion(self) -> None:
         self.__cmd_completion()
         self.__info_completion()
         self.__other_completion()
 
-    def __cmd_passthrough(self, cmdline, cpu_index=0):
+    def __cmd_passthrough(self, cmdline: str,
+                          cpu_index: int = 0) -> QMPMessage:
         return self.cmd_obj({
             'execute': 'human-monitor-command',
             'arguments': {
@@ -378,7 +393,7 @@ class HMPShell(QMPShell):
             }
         })
 
-    def _execute_cmd(self, cmdline):
+    def _execute_cmd(self, cmdline: str) -> bool:
         if cmdline.split()[0] == "cpu":
             # trap the cpu command, it requires special setting
             try:
@@ -404,16 +419,16 @@ class HMPShell(QMPShell):
             print('%s: %s' % (resp['error']['class'], resp['error']['desc']))
         return True
 
-    def show_banner(self, msg='Welcome to the HMP shell!'):
+    def show_banner(self, msg: str = 'Welcome to the HMP shell!') -> None:
         QMPShell.show_banner(self, msg)
 
 
-def die(msg):
+def die(msg: str) -> NoReturn:
     sys.stderr.write('ERROR: %s\n' % msg)
     sys.exit(1)
 
 
-def main():
+def main() -> None:
     parser = argparse.ArgumentParser()
     parser.add_argument('-H', '--hmp', action='store_true',
                         help='Use HMP interface')
-- 
2.31.1



  parent reply	other threads:[~2021-06-18 23:37 UTC|newest]

Thread overview: 75+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2021-06-18 23:03 [PULL 00/72] Python patches John Snow
2021-06-18 23:03 ` [PULL 01/72] python/pipenv: Update Pipfile.lock John Snow
2021-06-18 23:03 ` [PULL 02/72] python/qmp: Fix type of SocketAddrT John Snow
2021-06-18 23:03 ` [PULL 03/72] python/qmp: add parse_address classmethod John Snow
2021-06-18 23:03 ` [PULL 04/72] python/qmp: Add qom script rewrites John Snow
2021-06-18 23:03 ` [PULL 05/72] python/qmp: add qom script entry points John Snow
2021-06-18 23:03 ` [PULL 06/72] scripts/qmp: redirect qom-xxx scripts to python/qemu/qmp/ John Snow
2021-06-18 23:03 ` [PULL 07/72] scripts/qom-fuse: apply isort rules John Snow
2021-06-18 23:03 ` [PULL 08/72] scripts/qom-fuse: apply flake8 rules John Snow
2021-06-18 23:03 ` [PULL 09/72] python: Add 'fh' to known-good variable names John Snow
2021-06-18 23:03 ` [PULL 10/72] scripts/qom-fuse: Apply pylint rules John Snow
2021-06-18 23:03 ` [PULL 11/72] scripts/qom-fuse: Add docstrings John Snow
2021-06-18 23:03 ` [PULL 12/72] scripts/qom-fuse: Convert to QOMCommand John Snow
2021-06-18 23:03 ` [PULL 13/72] scripts/qom-fuse: use QOMCommand.qom_list() John Snow
2021-06-18 23:03 ` [PULL 14/72] scripts/qom-fuse: ensure QOMFuse.read always returns bytes John Snow
2021-06-18 23:03 ` [PULL 15/72] scripts/qom-fuse: add static type hints John Snow
2021-06-18 23:03 ` [PULL 16/72] python: add optional FUSE dependencies John Snow
2021-06-18 23:04 ` [PULL 17/72] scripts/qom-fuse: move to python/qemu/qmp/qom_fuse.py John Snow
2021-06-18 23:04 ` [PULL 18/72] scripts/qom-fuse: add redirection shim to python/qemu/qmp/qom-fuse.py John Snow
2021-06-18 23:04 ` [PULL 19/72] python/qmp: add fuse command to 'qom' tools John Snow
2021-06-18 23:04 ` [PULL 20/72] scripts/qemu-ga-client: apply isort rules John Snow
2021-06-18 23:04 ` [PULL 21/72] scripts/qemu-ga-client: apply (most) flake8 rules John Snow
2021-06-18 23:04 ` [PULL 22/72] scripts/qemu-ga-client: Fix exception handling John Snow
2021-06-18 23:04 ` [PULL 23/72] scripts/qemu-ga-client: replace deprecated optparse with argparse John Snow
2021-06-18 23:04 ` [PULL 24/72] scripts/qemu-ga-client: add module docstring John Snow
2021-06-18 23:04 ` [PULL 25/72] scripts/qemu-ga-client: apply (most) pylint rules John Snow
2021-06-18 23:04 ` [PULL 26/72] python/qmp: Correct type of QMPReturnValue John Snow
2021-06-18 23:04 ` [PULL 27/72] scripts/qemu-ga-client: add mypy type hints John Snow
2021-06-18 23:04 ` [PULL 28/72] scripts/qemu-ga-client: move to python/qemu/qmp/qemu_ga_client.py John Snow
2021-06-18 23:04 ` [PULL 29/72] python/qemu-ga-client: add entry point John Snow
2021-06-18 23:04 ` [PULL 30/72] scripts/qemu-ga-client: Add forwarder shim John Snow
2021-06-18 23:04 ` [PULL 31/72] scripts/qmp-shell: apply isort rules John Snow
2021-06-18 23:04 ` [PULL 32/72] scripts/qmp-shell: Apply flake8 rules John Snow
2021-06-18 23:04 ` [PULL 33/72] scripts/qmp-shell: fix show_banner signature John Snow
2021-06-18 23:04 ` [PULL 34/72] scripts/qmp-shell: fix exception handling John Snow
2021-06-18 23:04 ` [PULL 35/72] scripts/qmp-shell: fix connect method signature John Snow
2021-06-18 23:04 ` [PULL 36/72] scripts/qmp-shell: remove shadowed variable from _print() John Snow
2021-06-18 23:04 ` [PULL 37/72] scripts/qmp-shell: use @classmethod where appropriate John Snow
2021-06-18 23:04 ` [PULL 38/72] scripts/qmp-shell: Use python3-style super() John Snow
2021-06-18 23:04 ` [PULL 39/72] scripts/qmp-shell: declare verbose in __init__ John Snow
2021-06-18 23:04 ` [PULL 40/72] scripts/qmp-shell: use triple-double-quote docstring style John Snow
2021-06-18 23:04 ` [PULL 41/72] scripts/qmp-shell: ignore visit_Name name John Snow
2021-06-18 23:04 ` [PULL 42/72] scripts/qmp-shell: make QMPCompleter returns explicit John Snow
2021-06-18 23:04 ` [PULL 43/72] scripts/qmp-shell: rename one and two-letter variables John Snow
2021-06-18 23:04 ` [PULL 44/72] scripts/qmp-shell: fix shell history exception handling John Snow
2021-06-18 23:04 ` [PULL 45/72] scripts/qmp-shell: remove if-raise-else patterns John Snow
2021-06-18 23:04 ` [PULL 46/72] scripts/qmp-shell: use isinstance() instead of type() John Snow
2021-06-18 23:04 ` [PULL 47/72] scripts/qmp-shell: use argparse John Snow
2021-06-18 23:04 ` [PULL 48/72] scripts/qmp-shell: Add pretty attribute to HMP shell John Snow
2021-06-18 23:04 ` [PULL 49/72] scripts/qmp-shell: Make verbose a public attribute John Snow
2021-06-18 23:04 ` [PULL 50/72] scripts/qmp-shell: move get_prompt() to prompt property John Snow
2021-06-18 23:04 ` [PULL 51/72] scripts/qmp-shell: remove prompt argument from read_exec_command John Snow
2021-06-18 23:04 ` [PULL 52/72] scripts/qmp-shell: move the REPL functionality into QMPShell John Snow
2021-06-18 23:04 ` [PULL 53/72] scripts/qmp-shell: Fix "FuzzyJSON" parser John Snow
2021-06-18 23:04 ` [PULL 54/72] scripts/qmp-shell: refactor QMPCompleter John Snow
2021-06-18 23:04 ` [PULL 55/72] scripts/qmp-shell: initialize completer early John Snow
2021-06-18 23:04 ` [PULL 56/72] python/qmp: add QMPObject type alias John Snow
2021-06-18 23:04 ` John Snow [this message]
2021-06-18 23:04 ` [PULL 58/72] scripts/qmp-shell: Accept SocketAddrT instead of string John Snow
2021-06-18 23:04 ` [PULL 59/72] scripts/qmp-shell: unprivatize 'pretty' property John Snow
2021-06-18 23:04 ` [PULL 60/72] python/qmp: return generic type from context manager John Snow
2021-06-18 23:04 ` [PULL 61/72] scripts/qmp-shell: Use context manager instead of atexit John Snow
2021-06-18 23:04 ` [PULL 62/72] scripts/qmp-shell: use logging to show warnings John Snow
2021-06-18 23:04 ` [PULL 63/72] scripts/qmp-shell: remove TODO John Snow
2021-06-18 23:04 ` [PULL 64/72] scripts/qmp-shell: Fix empty-transaction invocation John Snow
2021-06-18 23:04 ` [PULL 65/72] scripts/qmp-shell: Remove too-broad-exception John Snow
2021-06-18 23:04 ` [PULL 66/72] scripts/qmp-shell: convert usage comment to docstring John Snow
2021-06-18 23:04 ` [PULL 67/72] scripts/qmp-shell: remove double-underscores John Snow
2021-06-18 23:04 ` [PULL 68/72] scripts/qmp-shell: make QMPShellError inherit QMPError John Snow
2021-06-18 23:04 ` [PULL 69/72] scripts/qmp-shell: add docstrings John Snow
2021-06-18 23:04 ` [PULL 70/72] scripts/qmp-shell: move to python/qemu/qmp/qmp_shell.py John Snow
2021-06-18 23:04 ` [PULL 71/72] python: add qmp-shell entry point John Snow
2021-06-18 23:04 ` [PULL 72/72] scripts/qmp-shell: add redirection shim John Snow
2021-06-21 19:42 ` [PULL 00/72] Python patches Peter Maydell
2021-06-22 13:34   ` John Snow

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20210618230455.2891199-58-jsnow@redhat.com \
    --to=jsnow@redhat.com \
    --cc=armbru@redhat.com \
    --cc=crosa@redhat.com \
    --cc=ehabkost@redhat.com \
    --cc=peter.maydell@linaro.org \
    --cc=qemu-devel@nongnu.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.