|
From: | John Snow |
Subject: | Re: [PATCH v5 11/36] qapi/common.py: Add indent manager |
Date: | Wed, 7 Oct 2020 14:08:33 -0400 |
User-agent: | Mozilla/5.0 (X11; Linux x86_64; rv:68.0) Gecko/20100101 Thunderbird/68.11.0 |
On 10/7/20 4:50 AM, Markus Armbruster wrote:
John Snow <jsnow@redhat.com> writes:Code style tools really dislike the use of global keywords, because it generally involves re-binding the name at runtime which can have strange effects depending on when and how that global name is referenced in other modules. Make a little indent level manager instead. Signed-off-by: John Snow <jsnow@redhat.com> Reviewed-by: Eduardo Habkost <ehabkost@redhat.com> Reviewed-by: Cleber Rosa <crosa@redhat.com>Intentation is a job for QAPIGen (and its subtypes). But if this patch is easier to achieve this series' goal, I don't mind.
I agree, but refactoring it properly is beyond my capacity right now.This was the dumbest thing I could do to get pylint/mypy passing, which required the elimination (or suppression) of the global keyword.
Creating a stateful object was the fastest way from A to B.
--- scripts/qapi/common.py | 49 ++++++++++++++++++++++++++++-------------- scripts/qapi/visit.py | 7 +++--- 2 files changed, 36 insertions(+), 20 deletions(-) diff --git a/scripts/qapi/common.py b/scripts/qapi/common.py index cee63eb95c7..b35318b72cf 100644 --- a/scripts/qapi/common.py +++ b/scripts/qapi/common.py @@ -93,33 +93,50 @@ def c_name(name, protect=True): pointer_suffix = ' *' + eatspace-def genindent(count):- ret = '' - for _ in range(count): - ret += ' ' - return ret +class Indentation: + """ + Indentation level management.+ :param initial: Initial number of spaces, default 0.+ """ + def __init__(self, initial: int = 0) -> None: + self._level = initial-indent_level = 0+ def __int__(self) -> int: + return self._level+ def __repr__(self) -> str:+ return "{}({:d})".format(type(self).__name__, self._level)-def push_indent(indent_amount=4):- global indent_level - indent_level += indent_amount + def __str__(self) -> str: + """Return the current indentation as a string of spaces.""" + return ' ' * self._level+ def __bool__(self) -> bool:+ """True when there is a non-zero indentation.""" + return bool(self._level)-def pop_indent(indent_amount=4):- global indent_level - indent_level -= indent_amount + def increase(self, amount: int = 4) -> None: + """Increase the indentation level by ``amount``, default 4.""" + self._level += amount + + def decrease(self, amount: int = 4) -> None: + """Decrease the indentation level by ``amount``, default 4.""" + if self._level < amount: + raise ArithmeticError( + f"Can't remove {amount:d} spaces from {self!r}")Raise a fancy error when there's an actual need for it. You're not coding a framework thousands of people you never heard of will put to uses you cannot imagine.
It's not fancy, it's just a normal built-in exception, like AssertionError or any other:
Traceback (most recent call last): File "<stdin>", line 1, in <module> ArithmeticError: Can't remove 4 spaces from Indent(0) vs Traceback (most recent call last): File "<stdin>", line 1, in <module> AssertionError: Can't remove 4 spaces from Indent(0)I feel like it's kind of a lateral move? I realize you feel this is an overfancy class doing what we hope is a temporary job, and that I have overengineered the hell out of a tiny do-nothing class... but I suppose that's also why I feel weird changing it around so much to accomplish so little.
Differences in style, I suppose.Feel free to change it around to suit your tastes, I don't think it's worth spending a lot of ping-pong time on this paintsink in particular.
--js
+ self._level -= amount + + +indent = Indentation()# Generate @code with @kwds interpolated.-# Obey indent_level, and strip eatspace. +# Obey indent, and strip eatspace. def cgen(code, **kwds): raw = code % kwds - if indent_level: - indent = genindent(indent_level) - raw = re.sub(r'^(?!(#|$))', indent, raw, flags=re.MULTILINE) + if indent: + raw = re.sub(r'^(?!(#|$))', str(indent), raw, flags=re.MULTILINE) return re.sub(re.escape(eatspace) + r' *', '', raw)diff --git a/scripts/qapi/visit.py b/scripts/qapi/visit.pyindex 808410d6f1b..14f30c228b7 100644 --- a/scripts/qapi/visit.py +++ b/scripts/qapi/visit.py @@ -18,9 +18,8 @@ c_name, gen_endif, gen_if, + indent, mcgen, - pop_indent, - push_indent, ) from .gen import QAPISchemaModularCVisitor, ifcontext from .schema import QAPISchemaObjectType @@ -69,7 +68,7 @@ def gen_visit_object_members(name, base, members, variants): if (visit_optional(v, "%(name)s", &obj->has_%(c_name)s)) { ''', name=memb.name, c_name=c_name(memb.name)) - push_indent() + indent.increase() ret += mcgen(''' if (!visit_type_%(c_type)s(v, "%(name)s", &obj->%(c_name)s, errp)) { return false; @@ -78,7 +77,7 @@ def gen_visit_object_members(name, base, members, variants): c_type=memb.type.c_name(), name=memb.name, c_name=c_name(memb.name)) if memb.optional: - pop_indent() + indent.decrease() ret += mcgen(''' } ''')
[Prev in Thread] | Current Thread | [Next in Thread] |