John Snow <js...@redhat.com> writes: > The idea here is to combine 'TopLevelExpr' and 'ParsedExpression' into > one type that accomplishes the purposes of both types; > > 1. TopLevelExpr is meant to represent a JSON Object, but only those that > represent what qapi-schema calls a TOP-LEVEL-EXPR, i.e. definitions, > pragmas, and includes. > > 2. ParsedExpression is meant to represent a container around the above > type, alongside QAPI-specific metadata -- the QAPISourceInfo and QAPIDoc > objects. > > We can actually just roll these up into one type: A python mapping that > has the metadata embedded directly inside of it. > > NB: This necessitates a change of typing for check_if() and > check_keys(), because mypy does not believe UserDict[str, object] ⊆ > Dict[str, object]. It will, however, accept Mapping or > MutableMapping. In this case, the immutable form is preferred as an > input parameter because we don't actually mutate the input. > > Without this change, we will observe: > qapi/expr.py:631: error: Argument 1 to "check_keys" has incompatible > type "QAPIExpression"; expected "Dict[str, object]" > > Signed-off-by: John Snow <js...@redhat.com>
[...] > diff --git a/scripts/qapi/parser.py b/scripts/qapi/parser.py > index f897dffbfd4..88f6fdfa67b 100644 > --- a/scripts/qapi/parser.py > +++ b/scripts/qapi/parser.py [...] > @@ -38,21 +38,32 @@ > 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 ParsedExpression(NamedTuple): > - expr: TopLevelExpr > - info: QAPISourceInfo > - doc: Optional['QAPIDoc'] > + > +# 3.6 workaround: can be removed when Python 3.7+ is our required version. > +if TYPE_CHECKING: > + _UserDict = UserDict[str, object] > +else: > + _UserDict = UserDict > + > + > +class QAPIExpression(_UserDict): > + def __init__( > + self, > + initialdata: Mapping[str, object], > + info: QAPISourceInfo, > + doc: Optional['QAPIDoc'] = None, > + ): Style nitpick: doc: Optional['QAPIDoc'] = None): > + super().__init__(initialdata) > + self.info = info > + self.doc: Optional['QAPIDoc'] = doc > > > class QAPIParseError(QAPISourceError): [...]