From 67ab1ce9263f77b352faea1104f0ebc2e50a3d42 Mon Sep 17 00:00:00 2001 From: Markus Armbruster Date: Mon, 2 Oct 2017 16:13:32 +0200 Subject: qapi: Stop rejecting #optional MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Commit 1d8bda1 got rid of #optional tags, and added a check to keep them from getting added back, to make sure patches then in flight don't add them back. It's been six months, time to drop that check. Signed-off-by: Markus Armbruster Message-Id: <20171002141341.24616-3-armbru@redhat.com> Reviewed-by: Marc-André Lureau --- scripts/qapi.py | 4 ---- 1 file changed, 4 deletions(-) (limited to 'scripts/qapi.py') diff --git a/scripts/qapi.py b/scripts/qapi.py index 62dc52ed6e..dc92bca620 100644 --- a/scripts/qapi.py +++ b/scripts/qapi.py @@ -234,10 +234,6 @@ class QAPIDoc(object): raise QAPIParseError(self.parser, "'%s' not allowed in free-form documentation" % match.group(1)) - # TODO Drop this once the dust has settled - if (isinstance(self.section, QAPIDoc.ArgSection) - and '#optional' in line): - raise QAPISemError(self.info, "Please drop the #optional tag") self.section.append(line) def connect_member(self, member): -- cgit 1.4.1 From 2281d00c3d75e684d9c0051169a6ac1cc60b66cd Mon Sep 17 00:00:00 2001 From: Markus Armbruster Date: Mon, 2 Oct 2017 16:13:33 +0200 Subject: qapi: Eliminate QAPISchemaParser.__init__()'s local fname MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Markus Armbruster Message-Id: <20171002141341.24616-4-armbru@redhat.com> Reviewed-by: Marc-André Lureau --- scripts/qapi.py | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) (limited to 'scripts/qapi.py') diff --git a/scripts/qapi.py b/scripts/qapi.py index dc92bca620..6c8001e96d 100644 --- a/scripts/qapi.py +++ b/scripts/qapi.py @@ -261,8 +261,7 @@ class QAPISchemaParser(object): def __init__(self, fp, previously_included=[], incl_info=None): abs_fname = os.path.abspath(fp.name) - fname = fp.name - self.fname = fname + self.fname = fp.name previously_included.append(abs_fname) self.incl_info = incl_info self.src = fp.read() @@ -277,7 +276,7 @@ class QAPISchemaParser(object): self.accept() while self.tok is not None: - info = {'file': fname, 'line': self.line, + info = {'file': self.fname, 'line': self.line, 'parent': self.incl_info} if self.tok == '#': self.reject_expr_doc() -- cgit 1.4.1 From 64d6033b203b32f02d0986220af5dc3cd1301ba6 Mon Sep 17 00:00:00 2001 From: Markus Armbruster Date: Mon, 2 Oct 2017 16:13:34 +0200 Subject: qapi: Make cur_doc local to QAPISchemaParser.__init__() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit QAPISchemaParser.cur_doc is used only by .__init__() and its helper .reject_expr_doc(). Make it local to __init__() and pass it to .reject_expr_doc() explicitly. Signed-off-by: Markus Armbruster Message-Id: <20171002141341.24616-5-armbru@redhat.com> Reviewed-by: Marc-André Lureau --- scripts/qapi.py | 34 +++++++++++++++++----------------- 1 file changed, 17 insertions(+), 17 deletions(-) (limited to 'scripts/qapi.py') diff --git a/scripts/qapi.py b/scripts/qapi.py index 6c8001e96d..2f2738f562 100644 --- a/scripts/qapi.py +++ b/scripts/qapi.py @@ -272,21 +272,21 @@ class QAPISchemaParser(object): self.line_pos = 0 self.exprs = [] self.docs = [] - self.cur_doc = None self.accept() + cur_doc = None while self.tok is not None: info = {'file': self.fname, 'line': self.line, 'parent': self.incl_info} if self.tok == '#': - self.reject_expr_doc() - self.cur_doc = self.get_doc(info) - self.docs.append(self.cur_doc) + self.reject_expr_doc(cur_doc) + cur_doc = self.get_doc(info) + self.docs.append(cur_doc) continue expr = self.get_expr(False) if 'include' in expr: - self.reject_expr_doc() + self.reject_expr_doc(cur_doc) if len(expr) != 1: raise QAPISemError(info, "Invalid 'include' directive") include = expr['include'] @@ -296,7 +296,7 @@ class QAPISchemaParser(object): self._include(include, info, os.path.dirname(abs_fname), previously_included) elif "pragma" in expr: - self.reject_expr_doc() + self.reject_expr_doc(cur_doc) if len(expr) != 1: raise QAPISemError(info, "Invalid 'pragma' directive") pragma = expr['pragma'] @@ -308,22 +308,22 @@ class QAPISchemaParser(object): else: expr_elem = {'expr': expr, 'info': info} - if self.cur_doc: - if not self.cur_doc.symbol: + if cur_doc: + if not cur_doc.symbol: raise QAPISemError( - self.cur_doc.info, - "Expression documentation required") - expr_elem['doc'] = self.cur_doc + cur_doc.info, "Expression documentation required") + expr_elem['doc'] = cur_doc self.exprs.append(expr_elem) - self.cur_doc = None - self.reject_expr_doc() + cur_doc = None + self.reject_expr_doc(cur_doc) - def reject_expr_doc(self): - if self.cur_doc and self.cur_doc.symbol: + @staticmethod + def reject_expr_doc(doc): + if doc and doc.symbol: raise QAPISemError( - self.cur_doc.info, + doc.info, "Documentation for '%s' is not followed by the definition" - % self.cur_doc.symbol) + % doc.symbol) def _include(self, include, info, base_dir, previously_included): incl_abs_fname = os.path.join(base_dir, include) -- cgit 1.4.1 From fc3f0df18711121ddbcd04bac3a6abb3fb9392be Mon Sep 17 00:00:00 2001 From: Markus Armbruster Date: Mon, 2 Oct 2017 16:13:37 +0200 Subject: qapi: Unify representation of doc section without name MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit We have two representations of sections without a name: the main section uses name=None, the others name=''. Standardize on name=None. Signed-off-by: Markus Armbruster Message-Id: <20171002141341.24616-8-armbru@redhat.com> Reviewed-by: Marc-André Lureau --- scripts/qapi.py | 2 +- scripts/qapi2texi.py | 2 +- tests/qapi-schema/doc-bad-section.out | 2 +- tests/qapi-schema/doc-good.out | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) (limited to 'scripts/qapi.py') diff --git a/scripts/qapi.py b/scripts/qapi.py index 2f2738f562..2137067b48 100644 --- a/scripts/qapi.py +++ b/scripts/qapi.py @@ -204,7 +204,7 @@ class QAPIDoc(object): self.section = QAPIDoc.ArgSection(name) self.args[name] = self.section - def _start_section(self, name=''): + def _start_section(self, name=None): if name in ('Returns', 'Since') and self.has_section(name): raise QAPIParseError(self.parser, "Duplicated '%s' section" % name) diff --git a/scripts/qapi2texi.py b/scripts/qapi2texi.py index f876d9a174..f16fa1ba53 100755 --- a/scripts/qapi2texi.py +++ b/scripts/qapi2texi.py @@ -184,7 +184,7 @@ def texi_sections(doc): # prefer @b over @strong, so txt doesn't translate it to *Foo:* body += '\n\n@b{%s:}\n' % section.name text = str(section) - if section.name.startswith('Example'): + if section.name and section.name.startswith('Example'): body += texi_example(text) else: body += texi_format(text) diff --git a/tests/qapi-schema/doc-bad-section.out b/tests/qapi-schema/doc-bad-section.out index 6fce84dd34..089bde1381 100644 --- a/tests/qapi-schema/doc-bad-section.out +++ b/tests/qapi-schema/doc-bad-section.out @@ -9,5 +9,5 @@ doc symbol=Enum The _one_ {and only} arg=two - section= + section=None @two is undocumented diff --git a/tests/qapi-schema/doc-good.out b/tests/qapi-schema/doc-good.out index c55e394e8a..1d2c250527 100644 --- a/tests/qapi-schema/doc-good.out +++ b/tests/qapi-schema/doc-good.out @@ -82,7 +82,7 @@ doc symbol=Enum The _one_ {and only} arg=two - section= + section=None @two is undocumented doc symbol=Base body= -- cgit 1.4.1 From 09331fced1c4e04109ccc9d6852f29e0453cf583 Mon Sep 17 00:00:00 2001 From: Markus Armbruster Date: Mon, 2 Oct 2017 16:13:38 +0200 Subject: qapi: Simplify representation of QAPIDoc section text MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Use a string instead of a list of strings. This makes qapi2texi.py generate additional blank lines. They're harmless, and the next commit will get rid of them again. Signed-off-by: Markus Armbruster Message-Id: <20171002141341.24616-9-armbru@redhat.com> Reviewed-by: Marc-André Lureau --- scripts/qapi.py | 16 ++++++---------- scripts/qapi2texi.py | 14 +++++++------- tests/qapi-schema/doc-good.texi | 1 + tests/qapi-schema/test-qapi.py | 6 +++--- 4 files changed, 17 insertions(+), 20 deletions(-) (limited to 'scripts/qapi.py') diff --git a/scripts/qapi.py b/scripts/qapi.py index 2137067b48..e338868a52 100644 --- a/scripts/qapi.py +++ b/scripts/qapi.py @@ -106,13 +106,10 @@ class QAPIDoc(object): # optional section name (argument/member or section name) self.name = name # the list of lines for this section - self.content = [] + self.text = '' def append(self, line): - self.content.append(line) - - def __repr__(self): - return '\n'.join(self.content).strip() + self.text += line.rstrip() + '\n' class ArgSection(Section): def __init__(self, name): @@ -160,7 +157,7 @@ class QAPIDoc(object): # recognized, and get silently treated as ordinary text if self.symbol: self._append_symbol_line(line) - elif not self.body.content and line.startswith('@'): + elif not self.body.text and line.startswith('@'): if not line.endswith(':'): raise QAPIParseError(self.parser, "Line should end with :") self.symbol = line[1:-1] @@ -214,16 +211,15 @@ class QAPIDoc(object): def _end_section(self): if self.section: - contents = str(self.section) - if self.section.name and (not contents or contents.isspace()): + text = self.section.text = self.section.text.strip() + if self.section.name and (not text or text.isspace()): raise QAPIParseError(self.parser, "Empty doc section '%s'" % self.section.name) self.section = None def _append_freeform(self, line): in_arg = isinstance(self.section, QAPIDoc.ArgSection) - if (in_arg and self.section.content - and not self.section.content[-1] + if (in_arg and self.section.text.endswith('\n\n') and line and not line[0].isspace()): self._start_section() if (in_arg or not self.section.name diff --git a/scripts/qapi2texi.py b/scripts/qapi2texi.py index f16fa1ba53..379d27643d 100755 --- a/scripts/qapi2texi.py +++ b/scripts/qapi2texi.py @@ -125,7 +125,7 @@ def texi_format(doc): def texi_body(doc): """Format the main documentation body""" - return texi_format(str(doc.body)) + '\n' + return texi_format(doc.body.text) + '\n' def texi_enum_value(value): @@ -149,8 +149,8 @@ def texi_members(doc, what, base, variants, member_func): items = '' for section in doc.args.itervalues(): # TODO Drop fallbacks when undocumented members are outlawed - if section.content: - desc = texi_format(str(section)) + if section.text: + desc = texi_format(section.text) elif (variants and variants.tag_member == section.member and not section.member.type.doc_type()): values = section.member.type.member_names() @@ -183,11 +183,10 @@ def texi_sections(doc): if section.name: # prefer @b over @strong, so txt doesn't translate it to *Foo:* body += '\n\n@b{%s:}\n' % section.name - text = str(section) if section.name and section.name.startswith('Example'): - body += texi_example(text) + body += texi_example(section.text) else: - body += texi_format(text) + body += texi_format(section.text) return body @@ -240,7 +239,8 @@ class QAPISchemaGenDocVisitor(qapi.QAPISchemaVisitor): self.out += '\n' if boxed: body = texi_body(doc) - body += '\n@b{Arguments:} the members of @code{%s}' % arg_type.name + body += ('\n@b{Arguments:} the members of @code{%s}\n' + % arg_type.name) body += texi_sections(doc) else: body = texi_entity(doc, 'Arguments') diff --git a/tests/qapi-schema/doc-good.texi b/tests/qapi-schema/doc-good.texi index a331349756..c032f23fc1 100644 --- a/tests/qapi-schema/doc-good.texi +++ b/tests/qapi-schema/doc-good.texi @@ -230,6 +230,7 @@ If you're bored enough to read this, go see a video of boxed cats @b{Arguments:} the members of @code{Object} + @b{Example:} @example -> in diff --git a/tests/qapi-schema/test-qapi.py b/tests/qapi-schema/test-qapi.py index c7724d3437..fe0ca08d78 100644 --- a/tests/qapi-schema/test-qapi.py +++ b/tests/qapi-schema/test-qapi.py @@ -61,8 +61,8 @@ for doc in schema.docs: print 'doc symbol=%s' % doc.symbol else: print 'doc freeform' - print ' body=\n%s' % doc.body + print ' body=\n%s' % doc.body.text for arg, section in doc.args.iteritems(): - print ' arg=%s\n%s' % (arg, section) + print ' arg=%s\n%s' % (arg, section.text) for section in doc.sections: - print ' section=%s\n%s' % (section.name, section) + print ' section=%s\n%s' % (section.name, section.text) -- cgit 1.4.1 From 8cbf1a537a61b2a1832948f20582839cebdb69de Mon Sep 17 00:00:00 2001 From: Markus Armbruster Date: Mon, 2 Oct 2017 16:13:40 +0200 Subject: qapi: Rename QAPIDoc.parser, .section to ._parser, ._section MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Markus Armbruster Message-Id: <20171002141341.24616-11-armbru@redhat.com> Reviewed-by: Marc-André Lureau --- scripts/qapi.py | 52 ++++++++++++++++++++++++++-------------------------- 1 file changed, 26 insertions(+), 26 deletions(-) (limited to 'scripts/qapi.py') diff --git a/scripts/qapi.py b/scripts/qapi.py index e338868a52..43a54bf40f 100644 --- a/scripts/qapi.py +++ b/scripts/qapi.py @@ -120,11 +120,11 @@ class QAPIDoc(object): self.member = member def __init__(self, parser, info): - # self.parser is used to report errors with QAPIParseError. The + # self._parser is used to report errors with QAPIParseError. The # resulting error position depends on the state of the parser. # It happens to be the beginning of the comment. More or less # servicable, but action at a distance. - self.parser = parser + self._parser = parser self.info = info self.symbol = None self.body = QAPIDoc.Section() @@ -133,7 +133,7 @@ class QAPIDoc(object): # a list of Section self.sections = [] # the current section - self.section = self.body + self._section = self.body def has_section(self, name): """Return True if we have a section with this name.""" @@ -150,7 +150,7 @@ class QAPIDoc(object): return if line[0] != ' ': - raise QAPIParseError(self.parser, "Missing space after #") + raise QAPIParseError(self._parser, "Missing space after #") line = line[1:] # FIXME not nice: things like '# @foo:' and '# @foo: ' aren't @@ -159,11 +159,11 @@ class QAPIDoc(object): self._append_symbol_line(line) elif not self.body.text and line.startswith('@'): if not line.endswith(':'): - raise QAPIParseError(self.parser, "Line should end with :") + raise QAPIParseError(self._parser, "Line should end with :") self.symbol = line[1:-1] # FIXME invalid names other than the empty string aren't flagged if not self.symbol: - raise QAPIParseError(self.parser, "Invalid name") + raise QAPIParseError(self._parser, "Invalid name") else: self._append_freeform(line) @@ -189,48 +189,48 @@ class QAPIDoc(object): def _start_args_section(self, name): # FIXME invalid names other than the empty string aren't flagged if not name: - raise QAPIParseError(self.parser, "Invalid parameter name") + raise QAPIParseError(self._parser, "Invalid parameter name") if name in self.args: - raise QAPIParseError(self.parser, + raise QAPIParseError(self._parser, "'%s' parameter name duplicated" % name) if self.sections: - raise QAPIParseError(self.parser, + raise QAPIParseError(self._parser, "'@%s:' can't follow '%s' section" % (name, self.sections[0].name)) self._end_section() - self.section = QAPIDoc.ArgSection(name) - self.args[name] = self.section + self._section = QAPIDoc.ArgSection(name) + self.args[name] = self._section def _start_section(self, name=None): if name in ('Returns', 'Since') and self.has_section(name): - raise QAPIParseError(self.parser, + raise QAPIParseError(self._parser, "Duplicated '%s' section" % name) self._end_section() - self.section = QAPIDoc.Section(name) - self.sections.append(self.section) + self._section = QAPIDoc.Section(name) + self.sections.append(self._section) def _end_section(self): - if self.section: - text = self.section.text = self.section.text.strip() - if self.section.name and (not text or text.isspace()): - raise QAPIParseError(self.parser, "Empty doc section '%s'" - % self.section.name) - self.section = None + if self._section: + text = self._section.text = self._section.text.strip() + if self._section.name and (not text or text.isspace()): + raise QAPIParseError(self._parser, "Empty doc section '%s'" + % self._section.name) + self._section = None def _append_freeform(self, line): - in_arg = isinstance(self.section, QAPIDoc.ArgSection) - if (in_arg and self.section.text.endswith('\n\n') + in_arg = isinstance(self._section, QAPIDoc.ArgSection) + if (in_arg and self._section.text.endswith('\n\n') and line and not line[0].isspace()): self._start_section() - if (in_arg or not self.section.name - or not self.section.name.startswith('Example')): + if (in_arg or not self._section.name + or not self._section.name.startswith('Example')): line = line.strip() match = re.match(r'(@\S+:)', line) if match: - raise QAPIParseError(self.parser, + raise QAPIParseError(self._parser, "'%s' not allowed in free-form documentation" % match.group(1)) - self.section.append(line) + self._section.append(line) def connect_member(self, member): if member.name not in self.args: -- cgit 1.4.1