Message ID | 20210223003408.964543-5-jsnow@redhat.com (mailing list archive) |
---|---|
State | New, archived |
Headers | show |
Series | qapi: static typing conversion, pt3 | expand |
John Snow <jsnow@redhat.com> writes: > mypy isn't fond of allowing you to check for bool membership in a > collection of str elements. Guard this lookup for precisely when we were > given a name. > > 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 | 4 +++- > 1 file changed, 3 insertions(+), 1 deletion(-) > > diff --git a/scripts/qapi/expr.py b/scripts/qapi/expr.py > index 783282b53ce..138fab0711f 100644 > --- a/scripts/qapi/expr.py > +++ b/scripts/qapi/expr.py > @@ -173,7 +173,9 @@ def check_type(value, info, source, > raise QAPISemError(info, > "%s should be an object or type name" % source) > > - permit_upper = allow_dict in info.pragma.name_case_whitelist > + permit_upper = False > + if isinstance(allow_dict, str): > + permit_upper = allow_dict in info.pragma.name_case_whitelist > > # value is a dictionary, check that each member is okay > for (key, arg) in value.items(): Busy-work like this can make me doubt typing is worth the notational overhead. There must a less awkward way to plumb "upper case okay" through check_type() to check_name_is_str(). But we're typing what we have.
On 2/24/21 5:35 AM, Markus Armbruster wrote: > John Snow <jsnow@redhat.com> writes: > >> mypy isn't fond of allowing you to check for bool membership in a >> collection of str elements. Guard this lookup for precisely when we were >> given a name. >> >> 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 | 4 +++- >> 1 file changed, 3 insertions(+), 1 deletion(-) >> >> diff --git a/scripts/qapi/expr.py b/scripts/qapi/expr.py >> index 783282b53ce..138fab0711f 100644 >> --- a/scripts/qapi/expr.py >> +++ b/scripts/qapi/expr.py >> @@ -173,7 +173,9 @@ def check_type(value, info, source, >> raise QAPISemError(info, >> "%s should be an object or type name" % source) >> >> - permit_upper = allow_dict in info.pragma.name_case_whitelist >> + permit_upper = False >> + if isinstance(allow_dict, str): >> + permit_upper = allow_dict in info.pragma.name_case_whitelist >> >> # value is a dictionary, check that each member is okay >> for (key, arg) in value.items(): > > Busy-work like this can make me doubt typing is worth the notational > overhead. > Or it's a good exercise in finding weird code smells. It was strange to promote an argument named "allow_dict" to actually store a name value, but it weren't me who did that. > There must a less awkward way to plumb "upper case okay" through > check_type() to check_name_is_str(). But we're typing what we have. > I rather suspect that Schema is the place to do it instead of in expr.py, but I've been focused on getting the typing in instead of doing my weirder cleanups. I'd like to remove Pragma stuff from expr.py entirely. Not a now-thing. --js
On 2/24/21 5:35 AM, Markus Armbruster wrote: > John Snow <jsnow@redhat.com> writes: > >> mypy isn't fond of allowing you to check for bool membership in a >> collection of str elements. Guard this lookup for precisely when we were >> given a name. >> >> 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 | 4 +++- >> 1 file changed, 3 insertions(+), 1 deletion(-) >> >> diff --git a/scripts/qapi/expr.py b/scripts/qapi/expr.py >> index 783282b53ce..138fab0711f 100644 >> --- a/scripts/qapi/expr.py >> +++ b/scripts/qapi/expr.py >> @@ -173,7 +173,9 @@ def check_type(value, info, source, >> raise QAPISemError(info, >> "%s should be an object or type name" % source) >> >> - permit_upper = allow_dict in info.pragma.name_case_whitelist >> + permit_upper = False >> + if isinstance(allow_dict, str): >> + permit_upper = allow_dict in info.pragma.name_case_whitelist >> >> # value is a dictionary, check that each member is okay >> for (key, arg) in value.items(): > > Busy-work like this can make me doubt typing is worth the notational > overhead. > > There must a less awkward way to plumb "upper case okay" through > check_type() to check_name_is_str(). But we're typing what we have. > Leaving this as-is for now. There's something I'd like to do about it, but it has to happen later. (I think all the pragma checks should happen in schema.py, and not in expr.py. They are by their essence not context-free, since they depend on the context of the pragma.)
John Snow <jsnow@redhat.com> writes: > On 2/24/21 5:35 AM, Markus Armbruster wrote: >> John Snow <jsnow@redhat.com> writes: >> >>> mypy isn't fond of allowing you to check for bool membership in a >>> collection of str elements. Guard this lookup for precisely when we were >>> given a name. >>> >>> 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 | 4 +++- >>> 1 file changed, 3 insertions(+), 1 deletion(-) >>> >>> diff --git a/scripts/qapi/expr.py b/scripts/qapi/expr.py >>> index 783282b53ce..138fab0711f 100644 >>> --- a/scripts/qapi/expr.py >>> +++ b/scripts/qapi/expr.py >>> @@ -173,7 +173,9 @@ def check_type(value, info, source, >>> raise QAPISemError(info, >>> "%s should be an object or type name" % source) >>> - permit_upper = allow_dict in info.pragma.name_case_whitelist >>> + permit_upper = False >>> + if isinstance(allow_dict, str): >>> + permit_upper = allow_dict in info.pragma.name_case_whitelist >>> # value is a dictionary, check that each member is okay >>> for (key, arg) in value.items(): >> >> Busy-work like this can make me doubt typing is worth the notational >> overhead. >> There must a less awkward way to plumb "upper case okay" through >> check_type() to check_name_is_str(). But we're typing what we have. > > Leaving this as-is for now. There's something I'd like to do about it, > but it has to happen later. > > (I think all the pragma checks should happen in schema.py, and not in > expr.py. They are by their essence not context-free, since they depend > on the context of the pragma.) True. Pragmas other than doc-required are an ugly consequence of us having made a a bit of a mess in the schema. The oldest parts of the schema were set in stone before we decided on certain rules, and then we kept failing at manually enforcing these rules. To get automatic enforcement, we needed a way to give a pass to existing rule breakers. Preferably without rearchitecting the frontend. Pragmas solve that problem. The solution is as ugly as the problem. Without pragmas, the name checks are context-free. That's why they are where they are.
On 3/25/21 1:46 AM, Markus Armbruster wrote: > John Snow <jsnow@redhat.com> writes: > >> On 2/24/21 5:35 AM, Markus Armbruster wrote: >>> John Snow <jsnow@redhat.com> writes: >>> >>>> mypy isn't fond of allowing you to check for bool membership in a >>>> collection of str elements. Guard this lookup for precisely when we were >>>> given a name. >>>> >>>> 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 | 4 +++- >>>> 1 file changed, 3 insertions(+), 1 deletion(-) >>>> >>>> diff --git a/scripts/qapi/expr.py b/scripts/qapi/expr.py >>>> index 783282b53ce..138fab0711f 100644 >>>> --- a/scripts/qapi/expr.py >>>> +++ b/scripts/qapi/expr.py >>>> @@ -173,7 +173,9 @@ def check_type(value, info, source, >>>> raise QAPISemError(info, >>>> "%s should be an object or type name" % source) >>>> - permit_upper = allow_dict in info.pragma.name_case_whitelist >>>> + permit_upper = False >>>> + if isinstance(allow_dict, str): >>>> + permit_upper = allow_dict in info.pragma.name_case_whitelist >>>> # value is a dictionary, check that each member is okay >>>> for (key, arg) in value.items(): >>> >>> Busy-work like this can make me doubt typing is worth the notational >>> overhead. >>> There must a less awkward way to plumb "upper case okay" through >>> check_type() to check_name_is_str(). But we're typing what we have. >> >> Leaving this as-is for now. There's something I'd like to do about it, >> but it has to happen later. >> >> (I think all the pragma checks should happen in schema.py, and not in >> expr.py. They are by their essence not context-free, since they depend >> on the context of the pragma.) > > True. > > Pragmas other than doc-required are an ugly consequence of us having > made a a bit of a mess in the schema. The oldest parts of the schema > were set in stone before we decided on certain rules, and then we kept > failing at manually enforcing these rules. To get automatic > enforcement, we needed a way to give a pass to existing rule breakers. > Preferably without rearchitecting the frontend. Pragmas solve that > problem. The solution is as ugly as the problem. > > Without pragmas, the name checks are context-free. That's why they are > where they are. > It's not a judgment in the sense that I am disappointed it isn't already like that, but I am giving you the opportunity to explicitly reject my proposal of how I'd like to eventually fix it. I want to decouple it from QAPISourceInfo and do the checks in schema.py instead. This may mean less restrictive checks in expr.py as an acknowledgment of what the "actual" grammar is. In exchange, schema.py has to apply some of these checks itself, but it now has the semantic context of the Pragma and the benefit of a fully normalized structure to work against. Over time, semantic restrictions that have exceptions that we remove can be transported back to the grammatical validation layer. --js
diff --git a/scripts/qapi/expr.py b/scripts/qapi/expr.py index 783282b53ce..138fab0711f 100644 --- a/scripts/qapi/expr.py +++ b/scripts/qapi/expr.py @@ -173,7 +173,9 @@ def check_type(value, info, source, raise QAPISemError(info, "%s should be an object or type name" % source) - permit_upper = allow_dict in info.pragma.name_case_whitelist + permit_upper = False + if isinstance(allow_dict, str): + permit_upper = allow_dict in info.pragma.name_case_whitelist # value is a dictionary, check that each member is okay for (key, arg) in value.items():