[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: [PATCH v3 08/16] qapi/expr.py: add type hint annotations
From: |
Markus Armbruster |
Subject: |
Re: [PATCH v3 08/16] qapi/expr.py: add type hint annotations |
Date: |
Tue, 02 Mar 2021 06:29:46 +0100 |
User-agent: |
Gnus/5.13 (Gnus v5.13) Emacs/27.1 (gnu/linux) |
John Snow <jsnow@redhat.com> writes:
> On 2/25/21 8:56 AM, Markus Armbruster wrote:
>> John Snow <jsnow@redhat.com> writes:
>>
>>> Annotations do not change runtime behavior.
>>> This commit *only* adds annotations.
>>>
>>> Signed-off-by: John Snow <jsnow@redhat.com>
>>> Reviewed-by: Eduardo Habkost <ehabkost@redhat.com>
>>> Reviewed-by: Cleber Rosa <crosa@redhat.com>
>>> ---
>>> scripts/qapi/expr.py | 71 ++++++++++++++++++++++++++++---------------
>>> scripts/qapi/mypy.ini | 5 ---
>>> 2 files changed, 46 insertions(+), 30 deletions(-)
>>>
>>> diff --git a/scripts/qapi/expr.py b/scripts/qapi/expr.py
>>> index f45d6be1f4c..df6c64950fa 100644
>>> --- a/scripts/qapi/expr.py
>>> +++ b/scripts/qapi/expr.py
>>> @@ -15,7 +15,14 @@
>>> # See the COPYING file in the top-level directory.
>>>
>>> import re
>>> -from typing import MutableMapping, Optional, cast
>>> +from typing import (
>>> + Iterable,
>>> + List,
>>> + MutableMapping,
>>> + Optional,
>>> + Union,
>>> + cast,
>>> +)
>>>
>>> from .common import c_name
>>> from .error import QAPISemError
>>> @@ -23,9 +30,10 @@
>>> from .source import QAPISourceInfo
>>>
>>>
>>> -# Expressions in their raw form are JSON-like structures with arbitrary
>>> forms.
>>> -# Minimally, their top-level form must be a mapping of strings to values.
>>> -Expression = MutableMapping[str, object]
>>> +# Arbitrary form for a JSON-like object.
>>> +_JSObject = MutableMapping[str, object]
>>> +# Expressions in their raw form are (just) JSON-like objects.
>>> +Expression = _JSObject
>>
>> We solved a similar, slightly more involved typing problem in
>> introspect.py.
>>
>> Whereas expr.py uses Python dict, list, and scalars to represent the
>> output of a JSON parser, introspect.py uses them to represent the input
>> of a quasi-JSON formatter ("quasi-JSON" because it spits out a C
>> initializer for a C representation of JSON, but that's detail).
>>
>> introspect.py additionally supports comments and #if conditionals.
>>
>> This is the solution we're using in introspect.py. The Annotated[] part
>> is for comments and conditionals; ignore that.
>>
>> # This module constructs a tree data structure that is used to
>> # generate the introspection information for QEMU. It is shaped
>> # like a JSON value.
>> #
>> # A complexity over JSON is that our values may or may not be annotated.
>> #
>> # Un-annotated values may be:
>> # Scalar: str, bool, None.
>> # Non-scalar: List, Dict
>> # _value = Union[str, bool, None, Dict[str, JSONValue], List[JSONValue]]
>> #
>> # With optional annotations, the type of all values is:
>> # JSONValue = Union[_Value, Annotated[_Value]]
>> #
>> # Sadly, mypy does not support recursive types; so the _Stub alias is
>> used to
>> # mark the imprecision in the type model where we'd otherwise use
>> JSONValue.
>> _Stub = Any
>> _Scalar = Union[str, bool, None]
>> _NonScalar = Union[Dict[str, _Stub], List[_Stub]]
>> _Value = Union[_Scalar, _NonScalar]
>> JSONValue = Union[_Value, 'Annotated[_Value]']
>>
>> introspect.py then adds some more type aliases to convey meaning:
>>
>> # These types are based on structures defined in QEMU's schema, so we
>> # lack precise types for them here. Python 3.6 does not offer
>> # TypedDict constructs, so they are broadly typed here as simple
>> # Python Dicts.
>> SchemaInfo = Dict[str, object]
>> SchemaInfoObject = Dict[str, object]
>> SchemaInfoObjectVariant = Dict[str, object]
>> SchemaInfoObjectMember = Dict[str, object]
>> SchemaInfoCommand = Dict[str, object]
>>
>> I'm not asking you to factor out common typing.
>>
>> I'm not even asking you to rework expr.py to maximize similarity.
>>
>> I am asking you to consider stealing applicable parts from
>> introspect.py's comments.
>>
>> _JSObject seems to serve the same purpose as JSONValue. Correct?
>>
>> Expression seems to serve a comparable purpose as SchemaInfo. Correct?
>>
>> [...]
>>
>
> Similar, indeed.
>
> Without annotations:
>
> _Stub = Any
> _Scalar = Union[str, bool, None]
> _NonScalar = Union[Dict[str, _Stub], List[_Stub]]
> _Value = Union[_Scalar, _NonScalar]
> JSONValue = _Value
>
> (Or skip the intermediate _Value name. No matter.)
>
> Though expr.py has no use of anything except the Object form itself,
> because it is inherently a validator and it doesn't actually really
> require any specific type, necessarily.
>
> So I only really needed the object form, which we never named in
> introspect.py. We actually avoided naming it.
>
> All I really need is, I think:
>
> _JSONObject = Dict[str, object]
>
> with a comment explaining that object can be any arbitrary JSONValue
> (within limit for what parser.py is capable of producing), and that the
> exact form of such will be evaluated by the various check_definition()
> functions.
>
> Is that suitable, or do you have something else in mind?
Sounds good.
[Prev in Thread] |
Current Thread |
[Next in Thread] |
- Re: [PATCH v3 08/16] qapi/expr.py: add type hint annotations,
Markus Armbruster <=