[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[PATCH 13/26] qapi/parser.py: add type hint annotations
From: |
John Snow |
Subject: |
[PATCH 13/26] qapi/parser.py: add type hint annotations |
Date: |
Tue, 22 Sep 2020 18:35:12 -0400 |
Annotations do not change runtime behavior.
This commit *only* adds annotations.
Annotations for QAPIDoc are in a later commit.
Signed-off-by: John Snow <jsnow@redhat.com>
---
scripts/qapi/parser.py | 69 ++++++++++++++++++++++++++++++------------
1 file changed, 49 insertions(+), 20 deletions(-)
diff --git a/scripts/qapi/parser.py b/scripts/qapi/parser.py
index 9a1007f779..d9aae4ddb7 100644
--- a/scripts/qapi/parser.py
+++ b/scripts/qapi/parser.py
@@ -14,18 +14,35 @@
# This work is licensed under the terms of the GNU GPL, version 2.
# See the COPYING file in the top-level directory.
+
+from collections import OrderedDict
import os
import re
-from collections import OrderedDict
-from typing import List, Type, TypeVar, cast
+from typing import (
+ Any,
+ Dict,
+ List,
+ Optional,
+ Set,
+ Type,
+ TypeVar,
+ Union,
+ cast,
+)
from .error import QAPIError, QAPISourceError, QAPISemError
from .source import QAPISourceInfo
+Expression = Dict[str, Any]
+_Value = Union[List[object], 'OrderedDict[str, object]', str, bool]
+# Necessary imprecision: mypy does not (yet?) support recursive types;
+# so we must stub out that recursion with 'object'.
+# Note, we do not support numerics or null in this parser.
+
+
class QAPIParseError(QAPISourceError):
"""Error class for all QAPI schema parsing errors."""
-
T = TypeVar('T', bound='QAPIParseError')
@classmethod
@@ -45,22 +62,25 @@ class QAPIDocError(QAPIError):
class QAPISchemaParser:
- def __init__(self, fname, previously_included=None, incl_info=None):
+ def __init__(self,
+ fname: str,
+ previously_included: Optional[Set[str]] = None,
+ incl_info: Optional[QAPISourceInfo] = None):
self._fname = fname
self._included = previously_included or set()
self._included.add(os.path.abspath(self._fname))
# Lexer state (see `accept` for details):
- self.tok = None
+ self.tok: Optional[str] = None
self.pos = 0
self.cursor = 0
- self.val = None
+ self.val: Optional[Union[bool, str]] = None
self.info = QAPISourceInfo(self._fname, parent=incl_info)
self.line_pos = 0
# Parser output:
- self.exprs = []
- self.docs = []
+ self.exprs: List[Expression] = []
+ self.docs: List[QAPIDoc] = []
# Showtime!
try:
@@ -76,7 +96,7 @@ def __init__(self, fname, previously_included=None,
incl_info=None):
raise QAPIParseError(context, msg) from e
self._parse()
- def _parse(self):
+ def _parse(self) -> None:
cur_doc = None
# Prime the lexer:
@@ -140,7 +160,7 @@ def _parse_error(self, msg: str) -> QAPIParseError:
return QAPIParseError.make(self, msg)
@classmethod
- def reject_expr_doc(cls, doc):
+ def reject_expr_doc(cls, doc: Optional['QAPIDoc']) -> None:
if doc and doc.symbol:
raise QAPISemError(
doc.info,
@@ -148,7 +168,12 @@ def reject_expr_doc(cls, doc):
% doc.symbol)
@classmethod
- def _include(cls, include, info, incl_fname, previously_included):
+ def _include(cls,
+ include: str,
+ info: QAPISourceInfo,
+ incl_fname: str,
+ previously_included: Set[str]
+ ) -> Optional['QAPISchemaParser']:
incl_abs_fname = os.path.abspath(incl_fname)
# catch inclusion cycle
inf = info
@@ -164,7 +189,10 @@ def _include(cls, include, info, incl_fname,
previously_included):
return QAPISchemaParser(incl_fname, previously_included, info)
@classmethod
- def _pragma(cls, name, value, info):
+ def _pragma(cls,
+ name: str,
+ value: object,
+ info: QAPISourceInfo) -> None:
if name == 'doc-required':
if not isinstance(value, bool):
raise QAPISemError(info,
@@ -187,7 +215,7 @@ def _pragma(cls, name, value, info):
else:
raise QAPISemError(info, "unknown pragma '%s'" % name)
- def accept(self, skip_comment=True):
+ def accept(self, skip_comment: bool = True) -> None:
while True:
self.tok = self.src[self.cursor]
self.pos = self.cursor
@@ -249,8 +277,8 @@ def accept(self, skip_comment=True):
self.src[self.cursor-1:])
raise self._parse_error("stray '%s'" % match.group(0))
- def get_members(self):
- expr = OrderedDict()
+ def get_members(self) -> 'OrderedDict[str, object]':
+ expr: 'OrderedDict[str, object]' = OrderedDict()
if self.tok == '}':
self.accept()
return expr
@@ -276,8 +304,8 @@ def get_members(self):
if self.tok != "'":
raise self._parse_error("expected string")
- def get_values(self):
- expr = []
+ def get_values(self) -> List[object]:
+ expr: List[object] = []
if self.tok == ']':
self.accept()
return expr
@@ -293,7 +321,8 @@ def get_values(self):
raise self._parse_error("expected ',' or ']'")
self.accept()
- def get_expr(self, nested):
+ def get_expr(self, nested: bool = False) -> _Value:
+ expr: _Value
if self.tok != '{' and not nested:
raise self._parse_error("expected '{'")
if self.tok == '{':
@@ -310,7 +339,7 @@ def get_expr(self, nested):
"expected '{', '[', string, or boolean")
return expr
- def _get_doc(self, info):
+ def _get_doc(self, info: QAPISourceInfo) -> List['QAPIDoc']:
if self.val != '##':
raise self._parse_error(
"junk after '##' at start of documentation comment")
@@ -342,7 +371,7 @@ def _get_doc(self, info):
raise self._parse_error("documentation comment must end with '##'")
- def get_doc(self, info):
+ def get_doc(self, info: QAPISourceInfo) -> List['QAPIDoc']:
try:
return self._get_doc(info)
except QAPIDocError as err:
--
2.26.2
- [PATCH 04/26] qapi/source.py: Add default arguments to QAPISourceInfo, (continued)
- [PATCH 04/26] qapi/source.py: Add default arguments to QAPISourceInfo, John Snow, 2020/09/22
- [PATCH 01/26] qapi/parser.py: refactor parsing routine into method, John Snow, 2020/09/22
- [PATCH 05/26] qapi/parser.py: start source info at line 0, John Snow, 2020/09/22
- [PATCH 07/26] qapi/parser.py: fully remove 'null' constant, John Snow, 2020/09/22
- [PATCH 08/26] qapi/parser.py: Assert lexer value is a string, John Snow, 2020/09/22
- [PATCH 06/26] qapi/parser.py: raise QAPIParseError during file opening, John Snow, 2020/09/22
- [PATCH 09/26] qapi/parser.py: assert get_expr returns object in outer loop, John Snow, 2020/09/22
- [PATCH 10/26] qapi/parser.py: assert object keys are strings, John Snow, 2020/09/22
- [PATCH 11/26] qapi/parser.py: Convert several methods to @classmethod, John Snow, 2020/09/22
- [PATCH 12/26] qapi/parser.py: add casts to pragma checks, John Snow, 2020/09/22
- [PATCH 13/26] qapi/parser.py: add type hint annotations,
John Snow <=
- [PATCH 14/26] qapi/parser.py: add docstrings, John Snow, 2020/09/22
- [PATCH 15/26] qapi/parser.py: add ParsedExpression type, John Snow, 2020/09/22
- [PATCH 16/26] qapi/pragma.py: Move QAPISchemaPragma into its own module, John Snow, 2020/09/22
- [PATCH 18/26] qapi/parser.py: Modify _include() to use parser state, John Snow, 2020/09/22
- [PATCH 17/26] qapi/pragma.py: Move pragma parsing out of parser.py, John Snow, 2020/09/22
- [PATCH 20/26] qapi/parser.py: remove unused check_args_section arguments, John Snow, 2020/09/22
- [PATCH 21/26] qapi/parser.py: QAPIDoc: convert @staticmethod to @classmethod, John Snow, 2020/09/22
- [PATCH 19/26] qapi/parser.py: add parent argument, John Snow, 2020/09/22
- [PATCH 23/26] qapi/parser.py: enable mypy checks, John Snow, 2020/09/22
- [PATCH 24/26] qapi/parser.py: remove one and two-letter variables, John Snow, 2020/09/22