mirror of
https://github.com/Motorhead1991/qemu.git
synced 2025-07-27 04:13:53 -06:00
qapi/parser: add QAPIExpression type
This patch creates a new type, QAPIExpression, which represents a parsed expression complete with QAPIDoc and QAPISourceInfo. This patch turns parser.exprs into a list of QAPIExpression instead, and adjusts expr.py to match. This allows the types we specify in parser.py to be "remembered" all the way through expr.py and into schema.py. Several assertions around packing and unpacking this data can be removed as a result. It also corrects a harmless typing error. Before the patch, check_exprs() allegedly takes a List[_JSONObject]. It actually takes a list of dicts of the form {'expr': E, 'info': I, 'doc': D} where E is of type _ExprValue, I is of type QAPISourceInfo, and D is of type QAPIDoc. Key 'doc' is optional. This is not a _JSONObject! Passes type checking anyway, because _JSONObject is Dict[str, object]. Signed-off-by: John Snow <jsnow@redhat.com> Message-Id: <20230215000011.1725012-5-jsnow@redhat.com> Reviewed-by: Markus Armbruster <armbru@redhat.com> [Commit message amended to point out the typing fix]
This commit is contained in:
parent
c60caf8086
commit
420110591c
3 changed files with 100 additions and 100 deletions
|
@ -21,6 +21,7 @@ from typing import (
|
|||
TYPE_CHECKING,
|
||||
Dict,
|
||||
List,
|
||||
Mapping,
|
||||
Optional,
|
||||
Set,
|
||||
Union,
|
||||
|
@ -37,15 +38,24 @@ if TYPE_CHECKING:
|
|||
from .schema import QAPISchemaFeature, QAPISchemaMember
|
||||
|
||||
|
||||
#: Represents a single Top Level QAPI schema expression.
|
||||
TopLevelExpr = Dict[str, object]
|
||||
|
||||
# Return value alias for get_expr().
|
||||
_ExprValue = Union[List[object], Dict[str, object], str, bool]
|
||||
|
||||
# FIXME: Consolidate and centralize definitions for TopLevelExpr,
|
||||
# _ExprValue, _JSONValue, and _JSONObject; currently scattered across
|
||||
# several modules.
|
||||
|
||||
# FIXME: Consolidate and centralize definitions for _ExprValue,
|
||||
# JSONValue, and _JSONObject; currently scattered across several
|
||||
# modules.
|
||||
|
||||
|
||||
class QAPIExpression(Dict[str, object]):
|
||||
# pylint: disable=too-few-public-methods
|
||||
def __init__(self,
|
||||
data: Mapping[str, object],
|
||||
info: QAPISourceInfo,
|
||||
doc: Optional['QAPIDoc'] = None):
|
||||
super().__init__(data)
|
||||
self.info = info
|
||||
self.doc: Optional['QAPIDoc'] = doc
|
||||
|
||||
|
||||
class QAPIParseError(QAPISourceError):
|
||||
|
@ -100,7 +110,7 @@ class QAPISchemaParser:
|
|||
self.line_pos = 0
|
||||
|
||||
# Parser output:
|
||||
self.exprs: List[Dict[str, object]] = []
|
||||
self.exprs: List[QAPIExpression] = []
|
||||
self.docs: List[QAPIDoc] = []
|
||||
|
||||
# Showtime!
|
||||
|
@ -147,8 +157,7 @@ class QAPISchemaParser:
|
|||
"value of 'include' must be a string")
|
||||
incl_fname = os.path.join(os.path.dirname(self._fname),
|
||||
include)
|
||||
self.exprs.append({'expr': {'include': incl_fname},
|
||||
'info': info})
|
||||
self._add_expr(OrderedDict({'include': incl_fname}), info)
|
||||
exprs_include = self._include(include, info, incl_fname,
|
||||
self._included)
|
||||
if exprs_include:
|
||||
|
@ -165,17 +174,18 @@ class QAPISchemaParser:
|
|||
for name, value in pragma.items():
|
||||
self._pragma(name, value, info)
|
||||
else:
|
||||
expr_elem = {'expr': expr,
|
||||
'info': info}
|
||||
if cur_doc:
|
||||
if not cur_doc.symbol:
|
||||
raise QAPISemError(
|
||||
cur_doc.info, "definition documentation required")
|
||||
expr_elem['doc'] = cur_doc
|
||||
self.exprs.append(expr_elem)
|
||||
if cur_doc and not cur_doc.symbol:
|
||||
raise QAPISemError(
|
||||
cur_doc.info, "definition documentation required")
|
||||
self._add_expr(expr, info, cur_doc)
|
||||
cur_doc = None
|
||||
self.reject_expr_doc(cur_doc)
|
||||
|
||||
def _add_expr(self, expr: Mapping[str, object],
|
||||
info: QAPISourceInfo,
|
||||
doc: Optional['QAPIDoc'] = None) -> None:
|
||||
self.exprs.append(QAPIExpression(expr, info, doc))
|
||||
|
||||
@staticmethod
|
||||
def reject_expr_doc(doc: Optional['QAPIDoc']) -> None:
|
||||
if doc and doc.symbol:
|
||||
|
@ -784,7 +794,7 @@ class QAPIDoc:
|
|||
% feature.name)
|
||||
self.features[feature.name].connect(feature)
|
||||
|
||||
def check_expr(self, expr: TopLevelExpr) -> None:
|
||||
def check_expr(self, expr: QAPIExpression) -> None:
|
||||
if self.has_section('Returns') and 'command' not in expr:
|
||||
raise QAPISemError(self.info,
|
||||
"'Returns:' is only valid for commands")
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue