All of lore.kernel.org
 help / color / mirror / Atom feed
From: John Snow <jsnow@redhat.com>
To: Markus Armbruster <armbru@redhat.com>
Cc: qemu-devel@nongnu.org, Cleber Rosa <crosa@redhat.com>,
	John Snow <jsnow@redhat.com>,
	Michael Roth <mdroth@linux.vnet.ibm.com>,
	Eduardo Habkost <ehabkost@redhat.com>
Subject: [PATCH 06/14] qapi/doc.py: Add type hint annotations
Date: Tue, 22 Sep 2020 17:17:54 -0400	[thread overview]
Message-ID: <20200922211802.4083666-7-jsnow@redhat.com> (raw)
In-Reply-To: <20200922211802.4083666-1-jsnow@redhat.com>

Annotations do not change runtime behavior.
This commit *only* adds annotations.

Signed-off-by: John Snow <jsnow@redhat.com>
---
 scripts/qapi/doc.py | 119 ++++++++++++++++++++++++++++++++------------
 1 file changed, 87 insertions(+), 32 deletions(-)

diff --git a/scripts/qapi/doc.py b/scripts/qapi/doc.py
index 9a02cf2f27..43943575da 100644
--- a/scripts/qapi/doc.py
+++ b/scripts/qapi/doc.py
@@ -5,14 +5,24 @@
 """This script produces the documentation of a qapi schema in texinfo format"""
 
 import re
-from typing import Optional
+from typing import Callable, List, Optional
 
 from .gen import QAPIGenDoc
+from .parser import QAPIDoc
 from .schema import (
+    QAPISchema,
+    QAPISchemaEntity,
     QAPISchemaEnumMember,
+    QAPISchemaFeature,
+    QAPISchemaMember,
+    QAPISchemaObjectType,
     QAPISchemaObjectTypeMember,
+    QAPISchemaType,
+    QAPISchemaVariants,
     QAPISchemaVisitor,
 )
+from .source import QAPISourceInfo
+
 
 MSG_FMT = """
 @deftypefn {type} {{}} {name}
@@ -36,27 +46,27 @@
 """.format
 
 
-def subst_strong(doc):
+def subst_strong(doc: str) -> str:
     """Replaces *foo* by @strong{foo}"""
     return re.sub(r'\*([^*\n]+)\*', r'@strong{\1}', doc)
 
 
-def subst_emph(doc):
+def subst_emph(doc: str) -> str:
     """Replaces _foo_ by @emph{foo}"""
     return re.sub(r'\b_([^_\n]+)_\b', r'@emph{\1}', doc)
 
 
-def subst_vars(doc):
+def subst_vars(doc: str) -> str:
     """Replaces @var by @code{var}"""
     return re.sub(r'@([\w-]+)', r'@code{\1}', doc)
 
 
-def subst_braces(doc):
+def subst_braces(doc: str) -> str:
     """Replaces {} with @{ @}"""
     return doc.replace('{', '@{').replace('}', '@}')
 
 
-def texi_example(doc):
+def texi_example(doc: str) -> str:
     """Format @example"""
     # TODO: Neglects to escape @ characters.
     # We should probably escape them in subst_braces(), and rename the
@@ -66,7 +76,7 @@ def texi_example(doc):
     return EXAMPLE_FMT(code=doc)
 
 
-def texi_format(doc):
+def texi_format(doc: str) -> str:
     """
     Format documentation
 
@@ -126,19 +136,26 @@ def texi_format(doc):
     return ret
 
 
-def texi_body(doc):
+def texi_body(doc: QAPIDoc) -> str:
     """Format the main documentation body"""
     return texi_format(doc.body.text)
 
 
-def texi_if(ifcond, prefix='\n', suffix='\n'):
+def texi_if(ifcond: Optional[List[str]],
+            prefix: str = '\n',
+            suffix: str = '\n') -> str:
     """Format the #if condition"""
     if not ifcond:
         return ''
     return '%s@b{If:} @code{%s}%s' % (prefix, ', '.join(ifcond), suffix)
 
 
-def texi_enum_value(value, desc, suffix):
+TexiMemberCallback = Callable[[QAPISchemaMember, str, str], str]
+
+
+def texi_enum_value(value: QAPISchemaMember,
+                    desc: str,
+                    suffix: str) -> str:
     """Format a table of members item for an enumeration value"""
     assert isinstance(value, QAPISchemaEnumMember)
     assert suffix == '', "Ignored suffix for texi_enum_value"
@@ -146,7 +163,9 @@ def texi_enum_value(value, desc, suffix):
         value.name, desc, texi_if(value.ifcond, prefix='@*'))
 
 
-def texi_member(member, desc, suffix):
+def texi_member(member: QAPISchemaMember,
+                desc: str,
+                suffix: str) -> str:
     """Format a table of members item for an object type member"""
     assert isinstance(member, QAPISchemaObjectTypeMember)
     typ = member.type.doc_type()
@@ -157,8 +176,11 @@ def texi_member(member, desc, suffix):
         suffix, desc, texi_if(member.ifcond, prefix='@*'))
 
 
-def texi_members(doc, what, base=None, variants=None,
-                 member_func=texi_member):
+def texi_members(doc: QAPIDoc,
+                 what: str,
+                 base: Optional[QAPISchemaObjectType] = None,
+                 variants: Optional[QAPISchemaVariants] = None,
+                 member_func: TexiMemberCallback = texi_member) -> str:
     """Format the table of members"""
     items = ''
     for section in doc.args.values():
@@ -195,7 +217,8 @@ def texi_members(doc, what, base=None, variants=None,
     return '\n@b{%s:}\n@table @asis\n%s@end table\n' % (what, items)
 
 
-def texi_arguments(doc, boxed_arg_type):
+def texi_arguments(doc: QAPIDoc,
+                   boxed_arg_type: Optional[QAPISchemaObjectType]) -> str:
     if boxed_arg_type:
         assert not doc.args
         return ('\n@b{Arguments:} the members of @code{%s}\n'
@@ -203,7 +226,7 @@ def texi_arguments(doc, boxed_arg_type):
     return texi_members(doc, 'Arguments')
 
 
-def texi_features(doc):
+def texi_features(doc: QAPIDoc) -> str:
     """Format the table of features"""
     items = ''
     for section in doc.features.values():
@@ -214,7 +237,7 @@ def texi_features(doc):
     return '\n@b{Features:}\n@table @asis\n%s@end table\n' % (items)
 
 
-def texi_sections(doc, ifcond):
+def texi_sections(doc: QAPIDoc, ifcond: Optional[List[str]]) -> str:
     """Format additional sections following arguments"""
     body = ''
     for section in doc.sections:
@@ -229,7 +252,7 @@ def texi_sections(doc, ifcond):
     return body
 
 
-def texi_type(typ, doc, ifcond, members):
+def texi_type(typ: str, doc: QAPIDoc, ifcond: List[str], members: str) -> str:
     return TYPE_FMT(type=typ,
                     name=doc.symbol,
                     body=texi_body(doc),
@@ -238,7 +261,7 @@ def texi_type(typ, doc, ifcond, members):
                     sections=texi_sections(doc, ifcond))
 
 
-def texi_msg(typ, doc, ifcond, members):
+def texi_msg(typ: str, doc: QAPIDoc, ifcond: List[str], members: str) -> str:
     return MSG_FMT(type=typ,
                    name=doc.symbol,
                    body=texi_body(doc),
@@ -248,60 +271,92 @@ def texi_msg(typ, doc, ifcond, members):
 
 
 class QAPISchemaGenDocVisitor(QAPISchemaVisitor):
-    def __init__(self, prefix):
+    def __init__(self, prefix: str):
         self._prefix = prefix
         self._gen = QAPIGenDoc(self._prefix + 'qapi-doc.texi')
-        self.cur_doc = None
+        self.cur_doc: Optional[QAPIDoc] = None
 
-    def write(self, output_dir):
+    def write(self, output_dir: str) -> None:
         self._gen.write(output_dir)
 
-    def visit_enum_type(self, name, info, ifcond, features, members, prefix):
+    def visit_enum_type(self,
+                        name: str,
+                        info: QAPISourceInfo,
+                        ifcond: List[str],
+                        features: List[QAPISchemaFeature],
+                        members: List[QAPISchemaEnumMember],
+                        prefix: Optional[str]) -> None:
         doc = self.cur_doc
         self._gen.add(texi_type('Enum', doc, ifcond,
                                 texi_members(doc, 'Values',
                                              member_func=texi_enum_value)))
 
-    def visit_object_type(self, name, info, ifcond, features,
-                          base, members, variants):
+    def visit_object_type(self,
+                          name: str,
+                          info: QAPISourceInfo,
+                          ifcond: List[str],
+                          features: List[QAPISchemaFeature],
+                          base: Optional[QAPISchemaObjectType],
+                          members: List[QAPISchemaObjectTypeMember],
+                          variants: Optional[QAPISchemaVariants]) -> None:
         doc = self.cur_doc
         if base and base.is_implicit():
             base = None
         self._gen.add(texi_type('Object', doc, ifcond,
                                 texi_members(doc, 'Members', base, variants)))
 
-    def visit_alternate_type(self, name, info, ifcond, features, variants):
+    def visit_alternate_type(self,
+                             name: str,
+                             info: QAPISourceInfo,
+                             ifcond: List[str],
+                             features: List[QAPISchemaFeature],
+                             variants: QAPISchemaVariants) -> None:
         doc = self.cur_doc
         self._gen.add(texi_type('Alternate', doc, ifcond,
                                 texi_members(doc, 'Members')))
 
-    def visit_command(self, name, info, ifcond, features,
-                      arg_type, ret_type, gen, success_response, boxed,
-                      allow_oob, allow_preconfig):
+    def visit_command(self,
+                      name: str,
+                      info: QAPISourceInfo,
+                      ifcond: List[str],
+                      features: List[QAPISchemaFeature],
+                      arg_type: QAPISchemaObjectType,
+                      ret_type: QAPISchemaType,
+                      gen: bool,
+                      success_response: bool,
+                      boxed: bool,
+                      allow_oob: bool,
+                      allow_preconfig: bool) -> None:
         doc = self.cur_doc
         members = texi_arguments(doc, arg_type if boxed else None)
         self._gen.add(texi_msg('Command', doc, ifcond, members))
 
-    def visit_event(self, name, info, ifcond, features, arg_type, boxed):
+    def visit_event(self,
+                    name: str,
+                    info: QAPISourceInfo,
+                    ifcond: List[str],
+                    features: List[QAPISchemaFeature],
+                    arg_type: QAPISchemaObjectType,
+                    boxed: bool) -> None:
         doc = self.cur_doc
         members = texi_arguments(doc, arg_type if boxed else None)
         self._gen.add(texi_msg('Event', doc, ifcond, members))
 
-    def symbol(self, doc, entity):
+    def symbol(self, doc: QAPIDoc, entity: QAPISchemaEntity) -> None:
         if self._gen._body:
             self._gen.add('\n')
         self.cur_doc = doc
         entity.visit(self)
         self.cur_doc = None
 
-    def freeform(self, doc):
+    def freeform(self, doc: QAPIDoc) -> None:
         assert not doc.args
         if self._gen._body:
             self._gen.add('\n')
         self._gen.add(texi_body(doc) + texi_sections(doc, None))
 
 
-def gen_doc(schema, output_dir, prefix):
+def gen_doc(schema: QAPISchema, output_dir: str, prefix: str) -> None:
     vis = QAPISchemaGenDocVisitor(prefix)
     vis.visit_begin(schema)
     for doc in schema.docs:
-- 
2.26.2



  parent reply	other threads:[~2020-09-22 22:08 UTC|newest]

Thread overview: 29+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2020-09-22 21:17 [PATCH 00/14] qapi: static typing conversion, pt3 John Snow
2020-09-22 21:17 ` [PATCH 01/14] qapi/doc.py: stash long temporary locals in named locals John Snow
2020-09-23 20:46   ` Eduardo Habkost
2020-09-22 21:17 ` [PATCH 02/14] qapi/doc.py: avoid unnecessary keyword arguments John Snow
2020-09-23 20:46   ` Eduardo Habkost
2020-09-22 21:17 ` [PATCH 03/14] qapi/doc.py: Add assertion on section.member John Snow
2020-09-23 20:46   ` Eduardo Habkost
2020-09-22 21:17 ` [PATCH 04/14] qapi/doc.py: assert correct types in member_func callbacks John Snow
2020-09-23 20:46   ` Eduardo Habkost
2020-09-22 21:17 ` [PATCH 05/14] qapi/doc.py: Assert no suffix given for enum members John Snow
2020-09-23 20:47   ` Eduardo Habkost
2020-09-22 21:17 ` John Snow [this message]
2020-09-23 20:47   ` [PATCH 06/14] qapi/doc.py: Add type hint annotations Eduardo Habkost
2020-09-22 21:17 ` [PATCH 07/14] qapi/doc.py: enable mypy checks John Snow
2020-09-23 20:47   ` Eduardo Habkost
2020-09-22 21:17 ` [PATCH 08/14] qapi/doc.py: Add generic texi_member callback John Snow
2020-09-22 21:17 ` [PATCH 09/14] qapi/doc.py: Remove one-letter variables John Snow
2020-09-23 21:00   ` Eduardo Habkost
2020-09-22 21:17 ` [PATCH 10/14] qapi/gen.py: Add __bool__ dunder method to QAPIGen John Snow
2020-09-23 21:05   ` Eduardo Habkost
2020-09-22 21:17 ` [PATCH 11/14] qapi/doc.py: Don't use private attributes of QAPIGen property John Snow
2020-09-23 21:05   ` Eduardo Habkost
2020-09-22 21:18 ` [PATCH 12/14] qapi/doc.py: Assert tag member is Enum type John Snow
2020-09-23 21:07   ` Eduardo Habkost
2020-09-22 21:18 ` [PATCH 13/14] qapi/doc.py: Assert type of object variant John Snow
2020-09-23 21:08   ` Eduardo Habkost
2020-09-22 21:18 ` [PATCH 14/14] qapi/doc.py: enable pylint checks John Snow
2020-09-23 21:09   ` Eduardo Habkost
2020-09-30  4:44 ` [PATCH 00/14] qapi: static typing conversion, pt3 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=20200922211802.4083666-7-jsnow@redhat.com \
    --to=jsnow@redhat.com \
    --cc=armbru@redhat.com \
    --cc=crosa@redhat.com \
    --cc=ehabkost@redhat.com \
    --cc=mdroth@linux.vnet.ibm.com \
    --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.