[v2,5/6] qapi: Allow documentation for features
diff mbox series

Message ID 20190517144232.18965-6-kwolf@redhat.com
State New
Headers show
Series
  • file-posix: Add dynamic-auto-read-only QAPI feature
Related show

Commit Message

Kevin Wolf May 17, 2019, 2:42 p.m. UTC
Features will be documented in a new part introduced by a "Features:"
line, after arguments and before named sections.

Signed-off-by: Kevin Wolf <kwolf@redhat.com>
---
 scripts/qapi/common.py | 43 ++++++++++++++++++++++++++++++++++++++----
 scripts/qapi/doc.py    | 11 +++++++++++
 2 files changed, 50 insertions(+), 4 deletions(-)

Comments

Markus Armbruster May 27, 2019, 8:02 a.m. UTC | #1
Kevin Wolf <kwolf@redhat.com> writes:

> Features will be documented in a new part introduced by a "Features:"
> line, after arguments and before named sections.
>
> Signed-off-by: Kevin Wolf <kwolf@redhat.com>
> ---
>  scripts/qapi/common.py | 43 ++++++++++++++++++++++++++++++++++++++----
>  scripts/qapi/doc.py    | 11 +++++++++++
>  2 files changed, 50 insertions(+), 4 deletions(-)
>
> diff --git a/scripts/qapi/common.py b/scripts/qapi/common.py
> index 1d0f4847db..6a1ec87d41 100644
> --- a/scripts/qapi/common.py
> +++ b/scripts/qapi/common.py
> @@ -132,6 +132,9 @@ class QAPIDoc(object):
>          ARGS means that we're parsing the arguments section. Any symbol name is
>          interpreted as an argument and an ArgSection is created for it.
>  
> +        FEATURES means that we're parsing features sections. Any symbol name is
> +        interpreted as a feature.
> +
>          VARIOUS is the final part where freeform sections may appear. This
>          includes named sections such as "Return:" as well as unnamed
>          paragraphs. No symbols are allowed any more in this part.
> @@ -139,7 +142,8 @@ class QAPIDoc(object):
>          # Can't make it a subclass of Enum because of Python 2
>          BODY = 0
>          ARGS = 1
> -        VARIOUS = 2
> +        FEATURES = 2
> +        VARIOUS = 3
>  
>      def __init__(self, parser, info):
>          # self._parser is used to report errors with QAPIParseError.  The
> @@ -152,6 +156,7 @@ class QAPIDoc(object):
>          self.body = QAPIDoc.Section()
>          # dict mapping parameter name to ArgSection
>          self.args = OrderedDict()
> +        self.features = OrderedDict()
>          # a list of Section
>          self.sections = []
>          # the current section
> @@ -180,6 +185,8 @@ class QAPIDoc(object):
>              self._append_body_line(line)
>          elif self._part == QAPIDoc.SymbolPart.ARGS:
>              self._append_args_line(line)
> +        elif self._part == QAPIDoc.SymbolPart.FEATURES:
> +            self._append_features_line(line)
>          elif self._part == QAPIDoc.SymbolPart.VARIOUS:
>              self._append_various_line(line)
>          else:
> @@ -215,6 +222,8 @@ class QAPIDoc(object):
>              if name.startswith('@') and name.endswith(':'):
>                  self._part = QAPIDoc.SymbolPart.ARGS
>                  self._append_args_line(line)
> +            elif line == 'Features:':
> +                self._part = QAPIDoc.SymbolPart.FEATURES
>              elif self.symbol and self._check_named_section(line, name):
>                  self._append_various_line(line)
>              else:
> @@ -231,6 +240,26 @@ class QAPIDoc(object):
>              self._start_args_section(name[1:-1])
>          elif self._check_named_section(line, name):
>              return self._append_various_line(line)

Here you return something...

> +        elif (self._section.text.endswith('\n\n')
> +              and line and not line[0].isspace()):
> +            if line == 'Features:':
> +                self._part = QAPIDoc.SymbolPart.FEATURES
> +                return

... and here you don't.

> +            else:

Unnecessary else after return.  Let's scratch the else.

> +                self._start_section()
> +                self._part = QAPIDoc.SymbolPart.VARIOUS
> +                return self._append_various_line(line)
> +
> +        self._append_freeform(line.strip())
> +
> +    def _append_features_line(self, line):
> +        name = line.split(' ', 1)[0]
> +
> +        if name.startswith('@') and name.endswith(':'):
> +            line = line[len(name)+1:]
> +            self._start_features_section(name[1:-1])
> +        elif self._check_named_section(line, name):
> +            return self._append_various_line(line)
>          elif (self._section.text.endswith('\n\n')
>                and line and not line[0].isspace()):
>              self._start_section()
> @@ -256,17 +285,23 @@ class QAPIDoc(object):
>  
>          self._append_freeform(line)
>  
> -    def _start_args_section(self, name):
> +    def _start_symbol_section(self, symbols_dict, name):
>          # FIXME invalid names other than the empty string aren't flagged
>          if not name:
>              raise QAPIParseError(self._parser, "Invalid parameter name")
> -        if name in self.args:
> +        if name in symbols_dict:
>              raise QAPIParseError(self._parser,
>                                   "'%s' parameter name duplicated" % name)
>          assert not self.sections
>          self._end_section()
>          self._section = QAPIDoc.ArgSection(name)
> -        self.args[name] = self._section
> +        symbols_dict[name] = self._section
> +
> +    def _start_args_section(self, name):
> +        self._start_symbol_section(self.args, name)
> +
> +    def _start_features_section(self, name):
> +        self._start_symbol_section(self.features, name)
>  
>      def _start_section(self, name=None):
>          if name in ('Returns', 'Since') and self.has_section(name):
> diff --git a/scripts/qapi/doc.py b/scripts/qapi/doc.py
> index 433e9fcbfb..8e799b9e0b 100755
> --- a/scripts/qapi/doc.py
> +++ b/scripts/qapi/doc.py
> @@ -181,6 +181,16 @@ def texi_members(doc, what, base, variants, member_func):
>          return ''
>      return '\n@b{%s:}\n@table @asis\n%s@end table\n' % (what, items)
>  
> +def texi_features(doc):
> +    """Format the table of features"""
> +    items = ''
> +    for section in doc.features.values():
> +        desc = texi_format(section.text)
> +        items += '@item @code{%s}\n%s' % (section.name, desc)
> +    if not items:
> +        return ''
> +    return '\n@b{Features:}\n@table @asis\n%s@end table\n' % (items)
> +
>  
>  def texi_sections(doc, ifcond):
>      """Format additional sections following arguments"""
> @@ -201,6 +211,7 @@ def texi_entity(doc, what, ifcond, base=None, variants=None,
>                  member_func=texi_member):
>      return (texi_body(doc)
>              + texi_members(doc, what, base, variants, member_func)
> +            + texi_features(doc)
>              + texi_sections(doc, ifcond))

Patch
diff mbox series

diff --git a/scripts/qapi/common.py b/scripts/qapi/common.py
index 1d0f4847db..6a1ec87d41 100644
--- a/scripts/qapi/common.py
+++ b/scripts/qapi/common.py
@@ -132,6 +132,9 @@  class QAPIDoc(object):
         ARGS means that we're parsing the arguments section. Any symbol name is
         interpreted as an argument and an ArgSection is created for it.
 
+        FEATURES means that we're parsing features sections. Any symbol name is
+        interpreted as a feature.
+
         VARIOUS is the final part where freeform sections may appear. This
         includes named sections such as "Return:" as well as unnamed
         paragraphs. No symbols are allowed any more in this part.
@@ -139,7 +142,8 @@  class QAPIDoc(object):
         # Can't make it a subclass of Enum because of Python 2
         BODY = 0
         ARGS = 1
-        VARIOUS = 2
+        FEATURES = 2
+        VARIOUS = 3
 
     def __init__(self, parser, info):
         # self._parser is used to report errors with QAPIParseError.  The
@@ -152,6 +156,7 @@  class QAPIDoc(object):
         self.body = QAPIDoc.Section()
         # dict mapping parameter name to ArgSection
         self.args = OrderedDict()
+        self.features = OrderedDict()
         # a list of Section
         self.sections = []
         # the current section
@@ -180,6 +185,8 @@  class QAPIDoc(object):
             self._append_body_line(line)
         elif self._part == QAPIDoc.SymbolPart.ARGS:
             self._append_args_line(line)
+        elif self._part == QAPIDoc.SymbolPart.FEATURES:
+            self._append_features_line(line)
         elif self._part == QAPIDoc.SymbolPart.VARIOUS:
             self._append_various_line(line)
         else:
@@ -215,6 +222,8 @@  class QAPIDoc(object):
             if name.startswith('@') and name.endswith(':'):
                 self._part = QAPIDoc.SymbolPart.ARGS
                 self._append_args_line(line)
+            elif line == 'Features:':
+                self._part = QAPIDoc.SymbolPart.FEATURES
             elif self.symbol and self._check_named_section(line, name):
                 self._append_various_line(line)
             else:
@@ -231,6 +240,26 @@  class QAPIDoc(object):
             self._start_args_section(name[1:-1])
         elif self._check_named_section(line, name):
             return self._append_various_line(line)
+        elif (self._section.text.endswith('\n\n')
+              and line and not line[0].isspace()):
+            if line == 'Features:':
+                self._part = QAPIDoc.SymbolPart.FEATURES
+                return
+            else:
+                self._start_section()
+                self._part = QAPIDoc.SymbolPart.VARIOUS
+                return self._append_various_line(line)
+
+        self._append_freeform(line.strip())
+
+    def _append_features_line(self, line):
+        name = line.split(' ', 1)[0]
+
+        if name.startswith('@') and name.endswith(':'):
+            line = line[len(name)+1:]
+            self._start_features_section(name[1:-1])
+        elif self._check_named_section(line, name):
+            return self._append_various_line(line)
         elif (self._section.text.endswith('\n\n')
               and line and not line[0].isspace()):
             self._start_section()
@@ -256,17 +285,23 @@  class QAPIDoc(object):
 
         self._append_freeform(line)
 
-    def _start_args_section(self, name):
+    def _start_symbol_section(self, symbols_dict, name):
         # FIXME invalid names other than the empty string aren't flagged
         if not name:
             raise QAPIParseError(self._parser, "Invalid parameter name")
-        if name in self.args:
+        if name in symbols_dict:
             raise QAPIParseError(self._parser,
                                  "'%s' parameter name duplicated" % name)
         assert not self.sections
         self._end_section()
         self._section = QAPIDoc.ArgSection(name)
-        self.args[name] = self._section
+        symbols_dict[name] = self._section
+
+    def _start_args_section(self, name):
+        self._start_symbol_section(self.args, name)
+
+    def _start_features_section(self, name):
+        self._start_symbol_section(self.features, name)
 
     def _start_section(self, name=None):
         if name in ('Returns', 'Since') and self.has_section(name):
diff --git a/scripts/qapi/doc.py b/scripts/qapi/doc.py
index 433e9fcbfb..8e799b9e0b 100755
--- a/scripts/qapi/doc.py
+++ b/scripts/qapi/doc.py
@@ -181,6 +181,16 @@  def texi_members(doc, what, base, variants, member_func):
         return ''
     return '\n@b{%s:}\n@table @asis\n%s@end table\n' % (what, items)
 
+def texi_features(doc):
+    """Format the table of features"""
+    items = ''
+    for section in doc.features.values():
+        desc = texi_format(section.text)
+        items += '@item @code{%s}\n%s' % (section.name, desc)
+    if not items:
+        return ''
+    return '\n@b{Features:}\n@table @asis\n%s@end table\n' % (items)
+
 
 def texi_sections(doc, ifcond):
     """Format additional sections following arguments"""
@@ -201,6 +211,7 @@  def texi_entity(doc, what, ifcond, base=None, variants=None,
                 member_func=texi_member):
     return (texi_body(doc)
             + texi_members(doc, what, base, variants, member_func)
+            + texi_features(doc)
             + texi_sections(doc, ifcond))