[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: [PATCH v6 26/36] qapi/gen.py: Fix edge-case of _is_user_module
From: |
Markus Armbruster |
Subject: |
Re: [PATCH v6 26/36] qapi/gen.py: Fix edge-case of _is_user_module |
Date: |
Sat, 10 Oct 2020 08:57:44 +0200 |
User-agent: |
Gnus/5.13 (Gnus v5.13) Emacs/27.1 (gnu/linux) |
Eduardo Habkost <ehabkost@redhat.com> writes:
> On Fri, Oct 09, 2020 at 07:26:02PM +0200, Markus Armbruster wrote:
>> John Snow <jsnow@redhat.com> writes:
>>
>> > The edge case is that if the name is '', this expression returns a
>> > string instead of a bool, which violates our declared type.
>> > In practice, module names are not allowed to be the empty string, but
>> > this constraint is not modeled for the type system.
>> >
>> > Signed-off-by: John Snow <jsnow@redhat.com>
>> > Reviewed-by: Cleber Rosa <crosa@redhat.com>
>> > Reviewed-by: Eduardo Habkost <ehabkost@redhat.com>
>> > Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
Actually:
1. We also map None to None, which is also not bool.
2. There is no declared type to violate until the next patch.
3. The subject's claim 'Fix edge-case' is misleading: this is a cleanup,
not a bug fix.
Easy enough to fix:
qapi/gen: Make _is_user_module() return bool
_is_user_module() returns thruth values. The next commit wants it to
return bool. Make it so.
>> > ---
>> > scripts/qapi/gen.py | 2 +-
>> > 1 file changed, 1 insertion(+), 1 deletion(-)
>> >
>> > diff --git a/scripts/qapi/gen.py b/scripts/qapi/gen.py
>> > index fff0c0acb6d..2c305c4f82c 100644
>> > --- a/scripts/qapi/gen.py
>> > +++ b/scripts/qapi/gen.py
>> > @@ -241,7 +241,7 @@ def __init__(self, prefix, what, user_blurb,
>> > builtin_blurb, pydoc):
>> >
>> > @staticmethod
>> > def _is_user_module(name):
>> > - return name and not name.startswith('./')
>> > + return bool(name and not name.startswith('./'))
>>
>> return not (name is None or name.startswith('./')
>>
>> Looks slightly clearer to me.
>
> That would have exactly the same behavior as the
> name is not None and name.startswith('./')
> expression we had in v1.
True.
Let's review what this function should do, and what it does.
The function should return whether @name is a user module name.
Returning truthy and falsy is fine; the callers expect no more.
system module names are either pathnames starting with './' (see
_add_system_module(), or None.
user module names are pathnames not starting with './' (see
_module_name()).
Before the patch:
if @name is falsy, i.e. None or '', return @name
else return name.startswith('./')
Thus, the function maps
None -> None (1)
'' -> '' (2)
'./' + any string -> False (3)
any other string -> True (4)
This is correct. Case (2) can't actually happen ('' is not a pathname).
John's version of the patch normalizes case (1) and (2) to
None -> False (1)
'' -> False (2)
so the next patch can declare the function returns bool. Safe, because
it doesn't change "thruthiness".
My version of the patch
if @name is None, return False,
else return not name.startswith('./')
Now the function maps
None -> False (1)
'' -> True (2)
'./' + any string -> False (3)
any other string -> True (4)
The only difference to John's patch is case (2). That case is
impossible, so no difference in actual behavior. Nevertheless, mapping
'' to True is unclean: it claims '' is a user module name, which it
isn't.
This would be clean:
@staticmethod
def _is_system_module(name):
return name is None or name.startswith('./')
Adjusting callers would be straightforward.
Not worth it right now. Taking John's patch with the rewritten commit
message.
Eduardo, thanks for making me think!
- [PATCH v6 16/36] qapi/common.py: Convert comments into docstrings, and elaborate, (continued)
- [PATCH v6 16/36] qapi/common.py: Convert comments into docstrings, and elaborate, John Snow, 2020/10/09
- [PATCH v6 14/36] qapi/common.py: check with pylint, John Snow, 2020/10/09
- [PATCH v6 17/36] qapi/common.py: move build_params into gen.py, John Snow, 2020/10/09
- [PATCH v6 19/36] qapi/events.py: add type hint annotations, John Snow, 2020/10/09
- [PATCH v6 18/36] qapi: establish mypy type-checking baseline, John Snow, 2020/10/09
- [PATCH v6 23/36] qapi/commands.py: enable checking with mypy, John Snow, 2020/10/09
- [PATCH v6 24/36] qapi/source.py: add type hint annotations, John Snow, 2020/10/09
- [PATCH v6 26/36] qapi/gen.py: Fix edge-case of _is_user_module, John Snow, 2020/10/09
- [PATCH v6 22/36] qapi/commands.py: add type hint annotations, John Snow, 2020/10/09
- [PATCH v6 25/36] qapi/source.py: delint with pylint, John Snow, 2020/10/09
- [PATCH v6 21/36] qapi/commands.py: Don't re-bind to variable of different type, John Snow, 2020/10/09
- [PATCH v6 28/36] qapi/gen.py: Enable checking with mypy, John Snow, 2020/10/09
- [PATCH v6 27/36] qapi/gen.py: add type hint annotations, John Snow, 2020/10/09
- [PATCH v6 30/36] qapi/gen.py: update write() to be more idiomatic, John Snow, 2020/10/09
- [PATCH v6 33/36] qapi/types.py: remove one-letter variables, John Snow, 2020/10/09
- [PATCH v6 29/36] qapi/gen.py: Remove unused parameter, John Snow, 2020/10/09
- [PATCH v6 35/36] qapi/visit.py: remove unused parameters from gen_visit_object, John Snow, 2020/10/09
- [PATCH v6 34/36] qapi/visit.py: assert tag_member contains a QAPISchemaEnumType, John Snow, 2020/10/09