* [PATCH 01/26] rv/rvgen: introduce AutomataError exception class
2026-01-19 20:45 [PATCH 00/26] rv/rvgen: Robustness, modernization, and fixes Wander Lairson Costa
@ 2026-01-19 20:45 ` Wander Lairson Costa
2026-01-20 7:33 ` Gabriele Monaco
2026-01-19 20:45 ` [PATCH 02/26] rv/rvgen: remove bare except clauses in generator Wander Lairson Costa
` (25 subsequent siblings)
26 siblings, 1 reply; 95+ messages in thread
From: Wander Lairson Costa @ 2026-01-19 20:45 UTC (permalink / raw)
To: Steven Rostedt, Gabriele Monaco, Nam Cao, Wander Lairson Costa,
open list, open list:RUNTIME VERIFICATION (RV)
Replace generic Exception usage with a custom AutomataError class
that inherits from OSError throughout the rvgen tool. This change
provides more precise exception handling for automata parsing and
validation errors while avoiding overly broad exception catches that
could mask programming errors like SyntaxError or TypeError.
The AutomataError class inherits from OSError rather than Exception
because most error conditions involve file I/O operations such as
reading DOT files or handling file access issues. This semantic
alignment makes exception handling more specific and appropriate.
The exception is raised when DOT file processing fails due to invalid
format, I/O errors, or malformed automaton definitions.
Additionally, remove the broad try-except block from __main__.py that
was catching all exceptions. This allows Python's default exception
handling to provide complete stack traces, making debugging
significantly easier by showing exact error types and locations.
Signed-off-by: Wander Lairson Costa <wander@redhat.com>
---
tools/verification/rvgen/__main__.py | 25 +++++++++------------
tools/verification/rvgen/rvgen/automata.py | 17 +++++++++-----
tools/verification/rvgen/rvgen/dot2c.py | 4 ++--
tools/verification/rvgen/rvgen/generator.py | 7 ++----
4 files changed, 26 insertions(+), 27 deletions(-)
diff --git a/tools/verification/rvgen/__main__.py b/tools/verification/rvgen/__main__.py
index fa6fc1f4de2f7..768b11a1e978b 100644
--- a/tools/verification/rvgen/__main__.py
+++ b/tools/verification/rvgen/__main__.py
@@ -39,22 +39,17 @@ if __name__ == '__main__':
params = parser.parse_args()
- try:
- if params.subcmd == "monitor":
- print("Opening and parsing the specification file %s" % params.spec)
- if params.monitor_class == "da":
- monitor = dot2k(params.spec, params.monitor_type, vars(params))
- elif params.monitor_class == "ltl":
- monitor = ltl2k(params.spec, params.monitor_type, vars(params))
- else:
- print("Unknown monitor class:", params.monitor_class)
- sys.exit(1)
+ if params.subcmd == "monitor":
+ print("Opening and parsing the specification file %s" % params.spec)
+ if params.monitor_class == "da":
+ monitor = dot2k(params.spec, params.monitor_type, vars(params))
+ elif params.monitor_class == "ltl":
+ monitor = ltl2k(params.spec, params.monitor_type, vars(params))
else:
- monitor = Container(vars(params))
- except Exception as e:
- print('Error: '+ str(e))
- print("Sorry : :-(")
- sys.exit(1)
+ print("Unknown monitor class:", params.monitor_class)
+ sys.exit(1)
+ else:
+ monitor = Container(vars(params))
print("Writing the monitor into the directory %s" % monitor.name)
monitor.print_files()
diff --git a/tools/verification/rvgen/rvgen/automata.py b/tools/verification/rvgen/rvgen/automata.py
index d9a3fe2b74bf2..8d88c3b65d00d 100644
--- a/tools/verification/rvgen/rvgen/automata.py
+++ b/tools/verification/rvgen/rvgen/automata.py
@@ -10,6 +10,13 @@
import ntpath
+class AutomataError(OSError):
+ """Exception raised for errors in automata parsing and validation.
+
+ Raised when DOT file processing fails due to invalid format, I/O errors,
+ or malformed automaton definitions.
+ """
+
class Automata:
"""Automata class: Reads a dot file and part it as an automata.
@@ -32,11 +39,11 @@ class Automata:
basename = ntpath.basename(self.__dot_path)
if not basename.endswith(".dot") and not basename.endswith(".gv"):
print("not a dot file")
- raise Exception("not a dot file: %s" % self.__dot_path)
+ raise AutomataError("not a dot file: %s" % self.__dot_path)
model_name = ntpath.splitext(basename)[0]
if model_name.__len__() == 0:
- raise Exception("not a dot file: %s" % self.__dot_path)
+ raise AutomataError("not a dot file: %s" % self.__dot_path)
return model_name
@@ -45,8 +52,8 @@ class Automata:
dot_lines = []
try:
dot_file = open(self.__dot_path)
- except:
- raise Exception("Cannot open the file: %s" % self.__dot_path)
+ except OSError as exc:
+ raise AutomataError(f"Cannot open the file: {self.__dot_path}") from exc
dot_lines = dot_file.read().splitlines()
dot_file.close()
@@ -55,7 +62,7 @@ class Automata:
line = dot_lines[cursor].split()
if (line[0] != "digraph") and (line[1] != "state_automaton"):
- raise Exception("Not a valid .dot format: %s" % self.__dot_path)
+ raise AutomataError("Not a valid .dot format: %s" % self.__dot_path)
else:
cursor += 1
return dot_lines
diff --git a/tools/verification/rvgen/rvgen/dot2c.py b/tools/verification/rvgen/rvgen/dot2c.py
index b9b6f14cc536a..1a1770e7f20c0 100644
--- a/tools/verification/rvgen/rvgen/dot2c.py
+++ b/tools/verification/rvgen/rvgen/dot2c.py
@@ -13,7 +13,7 @@
# For further information, see:
# Documentation/trace/rv/deterministic_automata.rst
-from .automata import Automata
+from .automata import Automata, AutomataError
class Dot2c(Automata):
enum_suffix = ""
@@ -93,7 +93,7 @@ class Dot2c(Automata):
min_type = "unsigned int"
if self.states.__len__() > 1000000:
- raise Exception("Too many states: %d" % self.states.__len__())
+ raise AutomataError("Too many states: %d" % self.states.__len__())
return min_type
diff --git a/tools/verification/rvgen/rvgen/generator.py b/tools/verification/rvgen/rvgen/generator.py
index 3441385c11770..a7bee6b1ea70c 100644
--- a/tools/verification/rvgen/rvgen/generator.py
+++ b/tools/verification/rvgen/rvgen/generator.py
@@ -51,10 +51,7 @@ class RVGenerator:
raise FileNotFoundError("Could not find the rv directory, do you have the kernel source installed?")
def _read_file(self, path):
- try:
- fd = open(path, 'r')
- except OSError:
- raise Exception("Cannot open the file: %s" % path)
+ fd = open(path, 'r')
content = fd.read()
@@ -65,7 +62,7 @@ class RVGenerator:
try:
path = os.path.join(self.abs_template_dir, file)
return self._read_file(path)
- except Exception:
+ except OSError:
# Specific template file not found. Try the generic template file in the template/
# directory, which is one level up
path = os.path.join(self.abs_template_dir, "..", file)
--
2.52.0
^ permalink raw reply related [flat|nested] 95+ messages in thread* Re: [PATCH 01/26] rv/rvgen: introduce AutomataError exception class
2026-01-19 20:45 ` [PATCH 01/26] rv/rvgen: introduce AutomataError exception class Wander Lairson Costa
@ 2026-01-20 7:33 ` Gabriele Monaco
2026-01-20 12:39 ` Wander Lairson Costa
0 siblings, 1 reply; 95+ messages in thread
From: Gabriele Monaco @ 2026-01-20 7:33 UTC (permalink / raw)
To: Wander Lairson Costa, Nam Cao
Cc: Steven Rostedt, open list, open list:RUNTIME VERIFICATION (RV)
On Mon, 2026-01-19 at 17:45 -0300, Wander Lairson Costa wrote:
> Replace generic Exception usage with a custom AutomataError class
> that inherits from OSError throughout the rvgen tool. This change
> provides more precise exception handling for automata parsing and
> validation errors while avoiding overly broad exception catches that
> could mask programming errors like SyntaxError or TypeError.
>
> The AutomataError class inherits from OSError rather than Exception
> because most error conditions involve file I/O operations such as
> reading DOT files or handling file access issues. This semantic
> alignment makes exception handling more specific and appropriate.
> The exception is raised when DOT file processing fails due to invalid
> format, I/O errors, or malformed automaton definitions.
>
> Additionally, remove the broad try-except block from __main__.py that
> was catching all exceptions. This allows Python's default exception
> handling to provide complete stack traces, making debugging
> significantly easier by showing exact error types and locations.
>
> Signed-off-by: Wander Lairson Costa <wander@redhat.com>
Thanks for the extensive series!
See my comments below.
Mind that I likely know python less than you do, so just call me out when I
start babbling.
> ---
> tools/verification/rvgen/__main__.py | 25 +++++++++------------
> tools/verification/rvgen/rvgen/automata.py | 17 +++++++++-----
> tools/verification/rvgen/rvgen/dot2c.py | 4 ++--
> tools/verification/rvgen/rvgen/generator.py | 7 ++----
> 4 files changed, 26 insertions(+), 27 deletions(-)
>
> diff --git a/tools/verification/rvgen/__main__.py
> b/tools/verification/rvgen/__main__.py
> index fa6fc1f4de2f7..768b11a1e978b 100644
> --- a/tools/verification/rvgen/__main__.py
> +++ b/tools/verification/rvgen/__main__.py
> @@ -39,22 +39,17 @@ if __name__ == '__main__':
>
> params = parser.parse_args()
>
> - try:
> - if params.subcmd == "monitor":
> - print("Opening and parsing the specification file %s" %
> params.spec)
> - if params.monitor_class == "da":
> - monitor = dot2k(params.spec, params.monitor_type,
> vars(params))
> - elif params.monitor_class == "ltl":
> - monitor = ltl2k(params.spec, params.monitor_type,
> vars(params))
> - else:
> - print("Unknown monitor class:", params.monitor_class)
> - sys.exit(1)
> + if params.subcmd == "monitor":
> + print("Opening and parsing the specification file %s" % params.spec)
> + if params.monitor_class == "da":
> + monitor = dot2k(params.spec, params.monitor_type, vars(params))
> + elif params.monitor_class == "ltl":
> + monitor = ltl2k(params.spec, params.monitor_type, vars(params))
> else:
> - monitor = Container(vars(params))
> - except Exception as e:
> - print('Error: '+ str(e))
> - print("Sorry : :-(")
> - sys.exit(1)
> + print("Unknown monitor class:", params.monitor_class)
> + sys.exit(1)
> + else:
> + monitor = Container(vars(params))
>
I agree catching all exceptions like this is quite detrimental while debugging,
but I see the original intent.
When you run commands written in python, you normally don't expect them to blurt
a stack trace when doing relatively normal things, like opening a wrong file.
Sure that might be useful when debugging, but for a user-facing tool we want to
write a meaningful error message and gracefully fail.
Other story is when the exception is something unexpected (that's why leaving a
generic Exception here is bad).
> print("Writing the monitor into the directory %s" % monitor.name)
> monitor.print_files()
> diff --git a/tools/verification/rvgen/rvgen/automata.py
> b/tools/verification/rvgen/rvgen/automata.py
> index d9a3fe2b74bf2..8d88c3b65d00d 100644
> --- a/tools/verification/rvgen/rvgen/automata.py
> +++ b/tools/verification/rvgen/rvgen/automata.py
> @@ -10,6 +10,13 @@
>
> import ntpath
>
> +class AutomataError(OSError):
> + """Exception raised for errors in automata parsing and validation.
> +
> + Raised when DOT file processing fails due to invalid format, I/O errors,
> + or malformed automaton definitions.
> + """
> +
I'm not quite familiar with modern python best practices (so again, take my
comments with a grain of salt ;) ), but what is the advantage of using this
custom exception instead of using pre-existing specific exception types?
Although the difference is minimal, here you're throwing an OSError for
something that quite isn't (e.g. wrong format for the dot file).
A ValueError feels more appropriate to me in most of the instances here.
All in all, I would do something like:
* throw a ValueError (or a custom one based on that) whenever we expect wrong
data not dependent on OS features
* throw OSError whenever that was the exception, perhaps changing the message to
something more meaningful to us (like you're already doing here)
* intercept only those errors in main.py and print the message without stack
trace (if the message is clear enough we shouldn't need it).
Does it make sense to you?
Thanks,
Gabriele
> class Automata:
> """Automata class: Reads a dot file and part it as an automata.
>
> @@ -32,11 +39,11 @@ class Automata:
> basename = ntpath.basename(self.__dot_path)
> if not basename.endswith(".dot") and not basename.endswith(".gv"):
> print("not a dot file")
> - raise Exception("not a dot file: %s" % self.__dot_path)
> + raise AutomataError("not a dot file: %s" % self.__dot_path)
>
> model_name = ntpath.splitext(basename)[0]
> if model_name.__len__() == 0:
> - raise Exception("not a dot file: %s" % self.__dot_path)
> + raise AutomataError("not a dot file: %s" % self.__dot_path)
>
> return model_name
>
> @@ -45,8 +52,8 @@ class Automata:
> dot_lines = []
> try:
> dot_file = open(self.__dot_path)
> - except:
> - raise Exception("Cannot open the file: %s" % self.__dot_path)
> + except OSError as exc:
> + raise AutomataError(f"Cannot open the file: {self.__dot_path}")
> from exc
>
> dot_lines = dot_file.read().splitlines()
> dot_file.close()
> @@ -55,7 +62,7 @@ class Automata:
> line = dot_lines[cursor].split()
>
> if (line[0] != "digraph") and (line[1] != "state_automaton"):
> - raise Exception("Not a valid .dot format: %s" % self.__dot_path)
> + raise AutomataError("Not a valid .dot format: %s" %
> self.__dot_path)
> else:
> cursor += 1
> return dot_lines
> diff --git a/tools/verification/rvgen/rvgen/dot2c.py
> b/tools/verification/rvgen/rvgen/dot2c.py
> index b9b6f14cc536a..1a1770e7f20c0 100644
> --- a/tools/verification/rvgen/rvgen/dot2c.py
> +++ b/tools/verification/rvgen/rvgen/dot2c.py
> @@ -13,7 +13,7 @@
> # For further information, see:
> # Documentation/trace/rv/deterministic_automata.rst
>
> -from .automata import Automata
> +from .automata import Automata, AutomataError
>
> class Dot2c(Automata):
> enum_suffix = ""
> @@ -93,7 +93,7 @@ class Dot2c(Automata):
> min_type = "unsigned int"
>
> if self.states.__len__() > 1000000:
> - raise Exception("Too many states: %d" % self.states.__len__())
> + raise AutomataError("Too many states: %d" %
> self.states.__len__())
>
> return min_type
>
> diff --git a/tools/verification/rvgen/rvgen/generator.py
> b/tools/verification/rvgen/rvgen/generator.py
> index 3441385c11770..a7bee6b1ea70c 100644
> --- a/tools/verification/rvgen/rvgen/generator.py
> +++ b/tools/verification/rvgen/rvgen/generator.py
> @@ -51,10 +51,7 @@ class RVGenerator:
> raise FileNotFoundError("Could not find the rv directory, do you have
> the kernel source installed?")
>
> def _read_file(self, path):
> - try:
> - fd = open(path, 'r')
> - except OSError:
> - raise Exception("Cannot open the file: %s" % path)
> + fd = open(path, 'r')
>
> content = fd.read()
>
> @@ -65,7 +62,7 @@ class RVGenerator:
> try:
> path = os.path.join(self.abs_template_dir, file)
> return self._read_file(path)
> - except Exception:
> + except OSError:
> # Specific template file not found. Try the generic template file
> in the template/
> # directory, which is one level up
> path = os.path.join(self.abs_template_dir, "..", file)
^ permalink raw reply [flat|nested] 95+ messages in thread* Re: [PATCH 01/26] rv/rvgen: introduce AutomataError exception class
2026-01-20 7:33 ` Gabriele Monaco
@ 2026-01-20 12:39 ` Wander Lairson Costa
2026-01-20 15:08 ` Gabriele Monaco
0 siblings, 1 reply; 95+ messages in thread
From: Wander Lairson Costa @ 2026-01-20 12:39 UTC (permalink / raw)
To: Gabriele Monaco
Cc: Nam Cao, Steven Rostedt, open list,
open list:RUNTIME VERIFICATION (RV)
On Tue, Jan 20, 2026 at 08:33:10AM +0100, Gabriele Monaco wrote:
> On Mon, 2026-01-19 at 17:45 -0300, Wander Lairson Costa wrote:
> > Replace generic Exception usage with a custom AutomataError class
> > that inherits from OSError throughout the rvgen tool. This change
> > provides more precise exception handling for automata parsing and
> > validation errors while avoiding overly broad exception catches that
> > could mask programming errors like SyntaxError or TypeError.
> >
> > The AutomataError class inherits from OSError rather than Exception
> > because most error conditions involve file I/O operations such as
> > reading DOT files or handling file access issues. This semantic
> > alignment makes exception handling more specific and appropriate.
> > The exception is raised when DOT file processing fails due to invalid
> > format, I/O errors, or malformed automaton definitions.
> >
> > Additionally, remove the broad try-except block from __main__.py that
> > was catching all exceptions. This allows Python's default exception
> > handling to provide complete stack traces, making debugging
> > significantly easier by showing exact error types and locations.
> >
> > Signed-off-by: Wander Lairson Costa <wander@redhat.com>
>
> Thanks for the extensive series!
> See my comments below.
> Mind that I likely know python less than you do, so just call me out when I
> start babbling.
>
> > ---
> > tools/verification/rvgen/__main__.py | 25 +++++++++------------
> > tools/verification/rvgen/rvgen/automata.py | 17 +++++++++-----
> > tools/verification/rvgen/rvgen/dot2c.py | 4 ++--
> > tools/verification/rvgen/rvgen/generator.py | 7 ++----
> > 4 files changed, 26 insertions(+), 27 deletions(-)
> >
> > diff --git a/tools/verification/rvgen/__main__.py
> > b/tools/verification/rvgen/__main__.py
> > index fa6fc1f4de2f7..768b11a1e978b 100644
> > --- a/tools/verification/rvgen/__main__.py
> > +++ b/tools/verification/rvgen/__main__.py
> > @@ -39,22 +39,17 @@ if __name__ == '__main__':
> >
> > params = parser.parse_args()
> >
> > - try:
> > - if params.subcmd == "monitor":
> > - print("Opening and parsing the specification file %s" %
> > params.spec)
> > - if params.monitor_class == "da":
> > - monitor = dot2k(params.spec, params.monitor_type,
> > vars(params))
> > - elif params.monitor_class == "ltl":
> > - monitor = ltl2k(params.spec, params.monitor_type,
> > vars(params))
> > - else:
> > - print("Unknown monitor class:", params.monitor_class)
> > - sys.exit(1)
> > + if params.subcmd == "monitor":
> > + print("Opening and parsing the specification file %s" % params.spec)
> > + if params.monitor_class == "da":
> > + monitor = dot2k(params.spec, params.monitor_type, vars(params))
> > + elif params.monitor_class == "ltl":
> > + monitor = ltl2k(params.spec, params.monitor_type, vars(params))
> > else:
> > - monitor = Container(vars(params))
> > - except Exception as e:
> > - print('Error: '+ str(e))
> > - print("Sorry : :-(")
> > - sys.exit(1)
> > + print("Unknown monitor class:", params.monitor_class)
> > + sys.exit(1)
> > + else:
> > + monitor = Container(vars(params))
> >
>
> I agree catching all exceptions like this is quite detrimental while debugging,
> but I see the original intent.
> When you run commands written in python, you normally don't expect them to blurt
> a stack trace when doing relatively normal things, like opening a wrong file.
> Sure that might be useful when debugging, but for a user-facing tool we want to
> write a meaningful error message and gracefully fail.
>
One option I thought was to keep it as it is but adding a --debug option
which would reraise the exception and then print the stack trace.
But as the users are developers themselves, leaving the exception
unchaught would help them identify the error (although I am strongly
against doing this in server side code). Another reason is the case
when the code itself has a bug. That would facilitate bug reports.
Perhaps we could catch more specific exceptions that would indicate a
problem with the dot files instead of Exception. Like
try: ...
except AutomataError as e:
print(f"There was a problem processing {dot_file}: {str(e)}",
file=sys.stderr)
sys.exit(1)
Which would be a common case. And leaving other types of exceptions
unchaught.
> Other story is when the exception is something unexpected (that's why leaving a
> generic Exception here is bad).
>
> > print("Writing the monitor into the directory %s" % monitor.name)
> > monitor.print_files()
> > diff --git a/tools/verification/rvgen/rvgen/automata.py
> > b/tools/verification/rvgen/rvgen/automata.py
> > index d9a3fe2b74bf2..8d88c3b65d00d 100644
> > --- a/tools/verification/rvgen/rvgen/automata.py
> > +++ b/tools/verification/rvgen/rvgen/automata.py
> > @@ -10,6 +10,13 @@
> >
> > import ntpath
> >
> > +class AutomataError(OSError):
> > + """Exception raised for errors in automata parsing and validation.
> > +
> > + Raised when DOT file processing fails due to invalid format, I/O errors,
> > + or malformed automaton definitions.
> > + """
> > +
>
> I'm not quite familiar with modern python best practices (so again, take my
> comments with a grain of salt ;) ), but what is the advantage of using this
> custom exception instead of using pre-existing specific exception types?
>
> Although the difference is minimal, here you're throwing an OSError for
> something that quite isn't (e.g. wrong format for the dot file).
> A ValueError feels more appropriate to me in most of the instances here.
>
> All in all, I would do something like:
> * throw a ValueError (or a custom one based on that) whenever we expect wrong
> data not dependent on OS features
> * throw OSError whenever that was the exception, perhaps changing the message to
> something more meaningful to us (like you're already doing here)
> * intercept only those errors in main.py and print the message without stack
> trace (if the message is clear enough we shouldn't need it).
>
> Does it make sense to you?
>
The reasoning behind specific exception types is to allow the calling code
process diferent exceptions in more specialized code paths, like the
example above.
AutomataError could derive from both OSError and ValueError.
class AutomataError(OSError, ValueError): ...
Which would address your (valid) point. This way, the calling code could
either process specific automata related errors with AutomataError, or
handle general file error, like that:
try...
except OSError as e:
print(f"File error: {str(e)", file=sys.stderr)
except AutomataError as e:
print(f"Ill formed dot file: {str(e)", file=stderr)
> Thanks,
> Gabriele
>
> > class Automata:
> > """Automata class: Reads a dot file and part it as an automata.
> >
> > @@ -32,11 +39,11 @@ class Automata:
> > basename = ntpath.basename(self.__dot_path)
> > if not basename.endswith(".dot") and not basename.endswith(".gv"):
> > print("not a dot file")
> > - raise Exception("not a dot file: %s" % self.__dot_path)
> > + raise AutomataError("not a dot file: %s" % self.__dot_path)
> >
> > model_name = ntpath.splitext(basename)[0]
> > if model_name.__len__() == 0:
> > - raise Exception("not a dot file: %s" % self.__dot_path)
> > + raise AutomataError("not a dot file: %s" % self.__dot_path)
> >
> > return model_name
> >
> > @@ -45,8 +52,8 @@ class Automata:
> > dot_lines = []
> > try:
> > dot_file = open(self.__dot_path)
> > - except:
> > - raise Exception("Cannot open the file: %s" % self.__dot_path)
> > + except OSError as exc:
> > + raise AutomataError(f"Cannot open the file: {self.__dot_path}")
> > from exc
> >
> > dot_lines = dot_file.read().splitlines()
> > dot_file.close()
> > @@ -55,7 +62,7 @@ class Automata:
> > line = dot_lines[cursor].split()
> >
> > if (line[0] != "digraph") and (line[1] != "state_automaton"):
> > - raise Exception("Not a valid .dot format: %s" % self.__dot_path)
> > + raise AutomataError("Not a valid .dot format: %s" %
> > self.__dot_path)
> > else:
> > cursor += 1
> > return dot_lines
> > diff --git a/tools/verification/rvgen/rvgen/dot2c.py
> > b/tools/verification/rvgen/rvgen/dot2c.py
> > index b9b6f14cc536a..1a1770e7f20c0 100644
> > --- a/tools/verification/rvgen/rvgen/dot2c.py
> > +++ b/tools/verification/rvgen/rvgen/dot2c.py
> > @@ -13,7 +13,7 @@
> > # For further information, see:
> > # Documentation/trace/rv/deterministic_automata.rst
> >
> > -from .automata import Automata
> > +from .automata import Automata, AutomataError
> >
> > class Dot2c(Automata):
> > enum_suffix = ""
> > @@ -93,7 +93,7 @@ class Dot2c(Automata):
> > min_type = "unsigned int"
> >
> > if self.states.__len__() > 1000000:
> > - raise Exception("Too many states: %d" % self.states.__len__())
> > + raise AutomataError("Too many states: %d" %
> > self.states.__len__())
> >
> > return min_type
> >
> > diff --git a/tools/verification/rvgen/rvgen/generator.py
> > b/tools/verification/rvgen/rvgen/generator.py
> > index 3441385c11770..a7bee6b1ea70c 100644
> > --- a/tools/verification/rvgen/rvgen/generator.py
> > +++ b/tools/verification/rvgen/rvgen/generator.py
> > @@ -51,10 +51,7 @@ class RVGenerator:
> > raise FileNotFoundError("Could not find the rv directory, do you have
> > the kernel source installed?")
> >
> > def _read_file(self, path):
> > - try:
> > - fd = open(path, 'r')
> > - except OSError:
> > - raise Exception("Cannot open the file: %s" % path)
> > + fd = open(path, 'r')
> >
> > content = fd.read()
> >
> > @@ -65,7 +62,7 @@ class RVGenerator:
> > try:
> > path = os.path.join(self.abs_template_dir, file)
> > return self._read_file(path)
> > - except Exception:
> > + except OSError:
> > # Specific template file not found. Try the generic template file
> > in the template/
> > # directory, which is one level up
> > path = os.path.join(self.abs_template_dir, "..", file)
>
^ permalink raw reply [flat|nested] 95+ messages in thread* Re: [PATCH 01/26] rv/rvgen: introduce AutomataError exception class
2026-01-20 12:39 ` Wander Lairson Costa
@ 2026-01-20 15:08 ` Gabriele Monaco
2026-01-22 14:39 ` Nam Cao
0 siblings, 1 reply; 95+ messages in thread
From: Gabriele Monaco @ 2026-01-20 15:08 UTC (permalink / raw)
To: Wander Lairson Costa
Cc: Nam Cao, Steven Rostedt, open list,
open list:RUNTIME VERIFICATION (RV)
On Tue, 2026-01-20 at 09:39 -0300, Wander Lairson Costa wrote:
> On Tue, Jan 20, 2026 at 08:33:10AM +0100, Gabriele Monaco wrote:
> > I agree catching all exceptions like this is quite detrimental while
> > debugging,
> > but I see the original intent.
> > When you run commands written in python, you normally don't expect them to
> > blurt
> > a stack trace when doing relatively normal things, like opening a wrong
> > file.
> > Sure that might be useful when debugging, but for a user-facing tool we want
> > to
> > write a meaningful error message and gracefully fail.
> >
>
> One option I thought was to keep it as it is but adding a --debug option
> which would reraise the exception and then print the stack trace.
> But as the users are developers themselves, leaving the exception
> unchaught would help them identify the error (although I am strongly
> against doing this in server side code). Another reason is the case
> when the code itself has a bug. That would facilitate bug reports.
That could be a good tradeoff. Users are developer but (although I'm not sure if
it really happened yet) are not the rvgen developers, they don't need to know
where exactly the code complained, unless it really broke.
All errors that are expected (OSError or wrong format) should have a meaningful
message for the user, I believe by doing that we'd have a pretty clear idea
where the error came from in the code too (e.g. event parsing, opening a file,
etc.).
If the code has a bug, then yes we should throw the exception as is, that's why
I think it's good not to catch Exception, but to catch only the few exceptions
we know can happen, all others would be bugs.
>
> Perhaps we could catch more specific exceptions that would indicate a
> problem with the dot files instead of Exception. Like
>
> try: ...
> except AutomataError as e:
> print(f"There was a problem processing {dot_file}: {str(e)}",
> file=sys.stderr)
> sys.exit(1)
>
> Which would be a common case. And leaving other types of exceptions
> unchaught.
Yeah pretty much
>
> > Other story is when the exception is something unexpected (that's why
> > leaving a
> > generic Exception here is bad).
> >
> > > print("Writing the monitor into the directory %s" % monitor.name)
> > > monitor.print_files()
> > > diff --git a/tools/verification/rvgen/rvgen/automata.py
> > > b/tools/verification/rvgen/rvgen/automata.py
> > > index d9a3fe2b74bf2..8d88c3b65d00d 100644
> > > --- a/tools/verification/rvgen/rvgen/automata.py
> > > +++ b/tools/verification/rvgen/rvgen/automata.py
> > > @@ -10,6 +10,13 @@
> > >
> > > import ntpath
> > >
> > > +class AutomataError(OSError):
> > > + """Exception raised for errors in automata parsing and validation.
> > > +
> > > + Raised when DOT file processing fails due to invalid format, I/O
> > > errors,
> > > + or malformed automaton definitions.
> > > + """
> > > +
> >
> > I'm not quite familiar with modern python best practices (so again, take my
> > comments with a grain of salt ;) ), but what is the advantage of using this
> > custom exception instead of using pre-existing specific exception types?
> >
> > Although the difference is minimal, here you're throwing an OSError for
> > something that quite isn't (e.g. wrong format for the dot file).
> > A ValueError feels more appropriate to me in most of the instances here.
> >
> > All in all, I would do something like:
> > * throw a ValueError (or a custom one based on that) whenever we expect
> > wrong
> > data not dependent on OS features
> > * throw OSError whenever that was the exception, perhaps changing the
> > message to
> > something more meaningful to us (like you're already doing here)
> > * intercept only those errors in main.py and print the message without stack
> > trace (if the message is clear enough we shouldn't need it).
> >
> > Does it make sense to you?
> >
>
> The reasoning behind specific exception types is to allow the calling code
> process diferent exceptions in more specialized code paths, like the
> example above.
>
> AutomataError could derive from both OSError and ValueError.
>
> class AutomataError(OSError, ValueError): ...
>
> Which would address your (valid) point. This way, the calling code could
> either process specific automata related errors with AutomataError, or
> handle general file error, like that:
>
> try...
> except OSError as e:
> print(f"File error: {str(e)", file=sys.stderr)
> except AutomataError as e:
> print(f"Ill formed dot file: {str(e)", file=stderr)
>
Yes! That's exactly what I mean, those are exceptions we expect, so no splat,
all others can just propagate.
Thanks,
Gabriele
> > Thanks,
> > Gabriele
> >
> > > class Automata:
> > > """Automata class: Reads a dot file and part it as an automata.
> > >
> > > @@ -32,11 +39,11 @@ class Automata:
> > > basename = ntpath.basename(self.__dot_path)
> > > if not basename.endswith(".dot") and not
> > > basename.endswith(".gv"):
> > > print("not a dot file")
> > > - raise Exception("not a dot file: %s" % self.__dot_path)
> > > + raise AutomataError("not a dot file: %s" % self.__dot_path)
> > >
> > > model_name = ntpath.splitext(basename)[0]
> > > if model_name.__len__() == 0:
> > > - raise Exception("not a dot file: %s" % self.__dot_path)
> > > + raise AutomataError("not a dot file: %s" % self.__dot_path)
> > >
> > > return model_name
> > >
> > > @@ -45,8 +52,8 @@ class Automata:
> > > dot_lines = []
> > > try:
> > > dot_file = open(self.__dot_path)
> > > - except:
> > > - raise Exception("Cannot open the file: %s" % self.__dot_path)
> > > + except OSError as exc:
> > > + raise AutomataError(f"Cannot open the file:
> > > {self.__dot_path}")
> > > from exc
> > >
> > > dot_lines = dot_file.read().splitlines()
> > > dot_file.close()
> > > @@ -55,7 +62,7 @@ class Automata:
> > > line = dot_lines[cursor].split()
> > >
> > > if (line[0] != "digraph") and (line[1] != "state_automaton"):
> > > - raise Exception("Not a valid .dot format: %s" %
> > > self.__dot_path)
> > > + raise AutomataError("Not a valid .dot format: %s" %
> > > self.__dot_path)
> > > else:
> > > cursor += 1
> > > return dot_lines
> > > diff --git a/tools/verification/rvgen/rvgen/dot2c.py
> > > b/tools/verification/rvgen/rvgen/dot2c.py
> > > index b9b6f14cc536a..1a1770e7f20c0 100644
> > > --- a/tools/verification/rvgen/rvgen/dot2c.py
> > > +++ b/tools/verification/rvgen/rvgen/dot2c.py
> > > @@ -13,7 +13,7 @@
> > > # For further information, see:
> > > # Documentation/trace/rv/deterministic_automata.rst
> > >
> > > -from .automata import Automata
> > > +from .automata import Automata, AutomataError
> > >
> > > class Dot2c(Automata):
> > > enum_suffix = ""
> > > @@ -93,7 +93,7 @@ class Dot2c(Automata):
> > > min_type = "unsigned int"
> > >
> > > if self.states.__len__() > 1000000:
> > > - raise Exception("Too many states: %d" %
> > > self.states.__len__())
> > > + raise AutomataError("Too many states: %d" %
> > > self.states.__len__())
> > >
> > > return min_type
> > >
> > > diff --git a/tools/verification/rvgen/rvgen/generator.py
> > > b/tools/verification/rvgen/rvgen/generator.py
> > > index 3441385c11770..a7bee6b1ea70c 100644
> > > --- a/tools/verification/rvgen/rvgen/generator.py
> > > +++ b/tools/verification/rvgen/rvgen/generator.py
> > > @@ -51,10 +51,7 @@ class RVGenerator:
> > > raise FileNotFoundError("Could not find the rv directory, do you
> > > have
> > > the kernel source installed?")
> > >
> > > def _read_file(self, path):
> > > - try:
> > > - fd = open(path, 'r')
> > > - except OSError:
> > > - raise Exception("Cannot open the file: %s" % path)
> > > + fd = open(path, 'r')
> > >
> > > content = fd.read()
> > >
> > > @@ -65,7 +62,7 @@ class RVGenerator:
> > > try:
> > > path = os.path.join(self.abs_template_dir, file)
> > > return self._read_file(path)
> > > - except Exception:
> > > + except OSError:
> > > # Specific template file not found. Try the generic template
> > > file
> > > in the template/
> > > # directory, which is one level up
> > > path = os.path.join(self.abs_template_dir, "..", file)
> >
^ permalink raw reply [flat|nested] 95+ messages in thread* Re: [PATCH 01/26] rv/rvgen: introduce AutomataError exception class
2026-01-20 15:08 ` Gabriele Monaco
@ 2026-01-22 14:39 ` Nam Cao
0 siblings, 0 replies; 95+ messages in thread
From: Nam Cao @ 2026-01-22 14:39 UTC (permalink / raw)
To: Gabriele Monaco, Wander Lairson Costa
Cc: Steven Rostedt, open list, open list:RUNTIME VERIFICATION (RV)
Gabriele Monaco <gmonaco@redhat.com> writes:
> That could be a good tradeoff. Users are developer but (although I'm not sure if
> it really happened yet) are not the rvgen developers, they don't need to know
> where exactly the code complained, unless it really broke.
> All errors that are expected (OSError or wrong format) should have a meaningful
> message for the user, I believe by doing that we'd have a pretty clear idea
> where the error came from in the code too (e.g. event parsing, opening a file,
> etc.).
>
> If the code has a bug, then yes we should throw the exception as is, that's why
> I think it's good not to catch Exception, but to catch only the few exceptions
> we know can happen, all others would be bugs.
I second this. We should only catch expected exceptions (e.g. the .dot
file is malformed) and print meaningful message. Otherwise, just leave
it uncaught.
While working with rvgen, I usually just remove the try-catch, because
it takes away all the useful debug information while not offering
anything else.
Nam
^ permalink raw reply [flat|nested] 95+ messages in thread
* [PATCH 02/26] rv/rvgen: remove bare except clauses in generator
2026-01-19 20:45 [PATCH 00/26] rv/rvgen: Robustness, modernization, and fixes Wander Lairson Costa
2026-01-19 20:45 ` [PATCH 01/26] rv/rvgen: introduce AutomataError exception class Wander Lairson Costa
@ 2026-01-19 20:45 ` Wander Lairson Costa
2026-01-20 10:05 ` Gabriele Monaco
2026-01-22 14:43 ` Nam Cao
2026-01-19 20:45 ` [PATCH 03/26] rv/rvgen: replace % string formatting with f-strings Wander Lairson Costa
` (24 subsequent siblings)
26 siblings, 2 replies; 95+ messages in thread
From: Wander Lairson Costa @ 2026-01-19 20:45 UTC (permalink / raw)
To: Steven Rostedt, Gabriele Monaco, Nam Cao, Wander Lairson Costa,
open list, open list:RUNTIME VERIFICATION (RV)
Remove bare except clauses from the generator module that were
catching all exceptions including KeyboardInterrupt and SystemExit.
This follows the same exception handling improvements made in the
previous AutomataError commit and addresses PEP 8 violations.
The bare except clause in __create_directory was silently catching
and ignoring all errors after printing a message, which could mask
serious issues. For __write_file, the bare except created a critical
bug where the file variable could remain undefined if open() failed,
causing a NameError when attempting to write to or close the file.
These methods now let OSError propagate naturally, allowing callers
to handle file system errors appropriately. This provides clearer
error reporting and allows Python's exception handling to show
complete stack traces with proper error types and locations.
Signed-off-by: Wander Lairson Costa <wander@redhat.com>
---
tools/verification/rvgen/rvgen/generator.py | 9 +--------
1 file changed, 1 insertion(+), 8 deletions(-)
diff --git a/tools/verification/rvgen/rvgen/generator.py b/tools/verification/rvgen/rvgen/generator.py
index a7bee6b1ea70c..af1662e2c20a7 100644
--- a/tools/verification/rvgen/rvgen/generator.py
+++ b/tools/verification/rvgen/rvgen/generator.py
@@ -198,17 +198,10 @@ obj-$(CONFIG_RV_MON_%s) += monitors/%s/%s.o
os.mkdir(path)
except FileExistsError:
return
- except:
- print("Fail creating the output dir: %s" % self.name)
def __write_file(self, file_name, content):
- try:
- file = open(file_name, 'w')
- except:
- print("Fail writing to file: %s" % file_name)
-
+ file = open(file_name, 'w')
file.write(content)
-
file.close()
def _create_file(self, file_name, content):
--
2.52.0
^ permalink raw reply related [flat|nested] 95+ messages in thread* Re: [PATCH 02/26] rv/rvgen: remove bare except clauses in generator
2026-01-19 20:45 ` [PATCH 02/26] rv/rvgen: remove bare except clauses in generator Wander Lairson Costa
@ 2026-01-20 10:05 ` Gabriele Monaco
2026-01-22 14:43 ` Nam Cao
1 sibling, 0 replies; 95+ messages in thread
From: Gabriele Monaco @ 2026-01-20 10:05 UTC (permalink / raw)
To: Wander Lairson Costa
Cc: Steven Rostedt, Nam Cao, open list,
open list:RUNTIME VERIFICATION (RV)
On Mon, 2026-01-19 at 17:45 -0300, Wander Lairson Costa wrote:
> Remove bare except clauses from the generator module that were
> catching all exceptions including KeyboardInterrupt and SystemExit.
> This follows the same exception handling improvements made in the
> previous AutomataError commit and addresses PEP 8 violations.
>
> The bare except clause in __create_directory was silently catching
> and ignoring all errors after printing a message, which could mask
> serious issues. For __write_file, the bare except created a critical
> bug where the file variable could remain undefined if open() failed,
> causing a NameError when attempting to write to or close the file.
>
> These methods now let OSError propagate naturally, allowing callers
> to handle file system errors appropriately. This provides clearer
> error reporting and allows Python's exception handling to show
> complete stack traces with proper error types and locations.
>
> Signed-off-by: Wander Lairson Costa <wander@redhat.com>
Looks good to me, thanks!
Reviewed-by: Gabriele Monaco <gmonaco@redhat.com>
> ---
> tools/verification/rvgen/rvgen/generator.py | 9 +--------
> 1 file changed, 1 insertion(+), 8 deletions(-)
>
> diff --git a/tools/verification/rvgen/rvgen/generator.py
> b/tools/verification/rvgen/rvgen/generator.py
> index a7bee6b1ea70c..af1662e2c20a7 100644
> --- a/tools/verification/rvgen/rvgen/generator.py
> +++ b/tools/verification/rvgen/rvgen/generator.py
> @@ -198,17 +198,10 @@ obj-$(CONFIG_RV_MON_%s) += monitors/%s/%s.o
> os.mkdir(path)
> except FileExistsError:
> return
> - except:
> - print("Fail creating the output dir: %s" % self.name)
>
> def __write_file(self, file_name, content):
> - try:
> - file = open(file_name, 'w')
> - except:
> - print("Fail writing to file: %s" % file_name)
> -
> + file = open(file_name, 'w')
> file.write(content)
> -
> file.close()
>
> def _create_file(self, file_name, content):
^ permalink raw reply [flat|nested] 95+ messages in thread* Re: [PATCH 02/26] rv/rvgen: remove bare except clauses in generator
2026-01-19 20:45 ` [PATCH 02/26] rv/rvgen: remove bare except clauses in generator Wander Lairson Costa
2026-01-20 10:05 ` Gabriele Monaco
@ 2026-01-22 14:43 ` Nam Cao
1 sibling, 0 replies; 95+ messages in thread
From: Nam Cao @ 2026-01-22 14:43 UTC (permalink / raw)
To: Wander Lairson Costa, Steven Rostedt, Gabriele Monaco,
Wander Lairson Costa, open list,
open list:RUNTIME VERIFICATION (RV)
Wander Lairson Costa <wander@redhat.com> writes:
> Remove bare except clauses from the generator module that were
> catching all exceptions including KeyboardInterrupt and SystemExit.
> This follows the same exception handling improvements made in the
> previous AutomataError commit and addresses PEP 8 violations.
>
> The bare except clause in __create_directory was silently catching
> and ignoring all errors after printing a message, which could mask
> serious issues. For __write_file, the bare except created a critical
> bug where the file variable could remain undefined if open() failed,
> causing a NameError when attempting to write to or close the file.
>
> These methods now let OSError propagate naturally, allowing callers
> to handle file system errors appropriately. This provides clearer
> error reporting and allows Python's exception handling to show
> complete stack traces with proper error types and locations.
>
> Signed-off-by: Wander Lairson Costa <wander@redhat.com>
Reviewed-by: Nam Cao <namcao@linutronix.de>
^ permalink raw reply [flat|nested] 95+ messages in thread
* [PATCH 03/26] rv/rvgen: replace % string formatting with f-strings
2026-01-19 20:45 [PATCH 00/26] rv/rvgen: Robustness, modernization, and fixes Wander Lairson Costa
2026-01-19 20:45 ` [PATCH 01/26] rv/rvgen: introduce AutomataError exception class Wander Lairson Costa
2026-01-19 20:45 ` [PATCH 02/26] rv/rvgen: remove bare except clauses in generator Wander Lairson Costa
@ 2026-01-19 20:45 ` Wander Lairson Costa
2026-01-20 10:02 ` Gabriele Monaco
2026-01-22 14:46 ` Nam Cao
2026-01-19 20:45 ` [PATCH 04/26] rv/rvgen: replace __len__() calls with len() Wander Lairson Costa
` (23 subsequent siblings)
26 siblings, 2 replies; 95+ messages in thread
From: Wander Lairson Costa @ 2026-01-19 20:45 UTC (permalink / raw)
To: Steven Rostedt, Gabriele Monaco, Nam Cao, Wander Lairson Costa,
open list, open list:RUNTIME VERIFICATION (RV)
Replace all instances of percent-style string formatting with
f-strings across the rvgen codebase. This modernizes the string
formatting to use Python 3.6+ features, providing clearer and more
maintainable code while improving runtime performance.
The conversion handles all formatting cases including simple variable
substitution, multi-variable formatting, and complex format specifiers.
Dynamic width formatting is converted from "%*s" to "{var:>{width}}"
using proper alignment syntax. Template strings for generated C code
properly escape braces using double-brace syntax to produce literal
braces in the output.
F-strings provide approximately 2x performance improvement over percent
formatting and are the recommended approach in modern Python.
Signed-off-by: Wander Lairson Costa <wander@redhat.com>
---
tools/verification/rvgen/__main__.py | 6 +--
tools/verification/rvgen/rvgen/automata.py | 6 +--
tools/verification/rvgen/rvgen/dot2c.py | 40 +++++++-------
tools/verification/rvgen/rvgen/dot2k.py | 26 ++++-----
tools/verification/rvgen/rvgen/generator.py | 59 ++++++++++-----------
tools/verification/rvgen/rvgen/ltl2k.py | 30 +++++------
6 files changed, 82 insertions(+), 85 deletions(-)
diff --git a/tools/verification/rvgen/__main__.py b/tools/verification/rvgen/__main__.py
index 768b11a1e978b..eeeccf81d4b90 100644
--- a/tools/verification/rvgen/__main__.py
+++ b/tools/verification/rvgen/__main__.py
@@ -40,7 +40,7 @@ if __name__ == '__main__':
params = parser.parse_args()
if params.subcmd == "monitor":
- print("Opening and parsing the specification file %s" % params.spec)
+ print(f"Opening and parsing the specification file {params.spec}")
if params.monitor_class == "da":
monitor = dot2k(params.spec, params.monitor_type, vars(params))
elif params.monitor_class == "ltl":
@@ -51,11 +51,11 @@ if __name__ == '__main__':
else:
monitor = Container(vars(params))
- print("Writing the monitor into the directory %s" % monitor.name)
+ print(f"Writing the monitor into the directory {monitor.name}")
monitor.print_files()
print("Almost done, checklist")
if params.subcmd == "monitor":
- print(" - Edit the %s/%s.c to add the instrumentation" % (monitor.name, monitor.name))
+ print(f" - Edit the {monitor.name}/{monitor.name}.c to add the instrumentation")
print(monitor.fill_tracepoint_tooltip())
print(monitor.fill_makefile_tooltip())
print(monitor.fill_kconfig_tooltip())
diff --git a/tools/verification/rvgen/rvgen/automata.py b/tools/verification/rvgen/rvgen/automata.py
index 8d88c3b65d00d..3e24313a2eaec 100644
--- a/tools/verification/rvgen/rvgen/automata.py
+++ b/tools/verification/rvgen/rvgen/automata.py
@@ -39,11 +39,11 @@ class Automata:
basename = ntpath.basename(self.__dot_path)
if not basename.endswith(".dot") and not basename.endswith(".gv"):
print("not a dot file")
- raise AutomataError("not a dot file: %s" % self.__dot_path)
+ raise AutomataError(f"not a dot file: {self.__dot_path}")
model_name = ntpath.splitext(basename)[0]
if model_name.__len__() == 0:
- raise AutomataError("not a dot file: %s" % self.__dot_path)
+ raise AutomataError(f"not a dot file: {self.__dot_path}")
return model_name
@@ -62,7 +62,7 @@ class Automata:
line = dot_lines[cursor].split()
if (line[0] != "digraph") and (line[1] != "state_automaton"):
- raise AutomataError("Not a valid .dot format: %s" % self.__dot_path)
+ raise AutomataError(f"Not a valid .dot format: {self.__dot_path}")
else:
cursor += 1
return dot_lines
diff --git a/tools/verification/rvgen/rvgen/dot2c.py b/tools/verification/rvgen/rvgen/dot2c.py
index 1a1770e7f20c0..78959d345c26e 100644
--- a/tools/verification/rvgen/rvgen/dot2c.py
+++ b/tools/verification/rvgen/rvgen/dot2c.py
@@ -37,11 +37,11 @@ class Dot2c(Automata):
def __get_enum_states_content(self):
buff = []
- buff.append("\t%s%s = 0," % (self.initial_state, self.enum_suffix))
+ buff.append(f"\t{self.initial_state}{self.enum_suffix} = 0,")
for state in self.states:
if state != self.initial_state:
- buff.append("\t%s%s," % (state, self.enum_suffix))
- buff.append("\tstate_max%s" % (self.enum_suffix))
+ buff.append(f"\t{state}{self.enum_suffix},")
+ buff.append(f"\tstate_max{self.enum_suffix}")
return buff
@@ -51,7 +51,7 @@ class Dot2c(Automata):
def format_states_enum(self):
buff = []
- buff.append("enum %s {" % self.enum_states_def)
+ buff.append(f"enum {self.enum_states_def} {{")
buff.append(self.get_enum_states_string())
buff.append("};\n")
@@ -62,12 +62,12 @@ class Dot2c(Automata):
first = True
for event in self.events:
if first:
- buff.append("\t%s%s = 0," % (event, self.enum_suffix))
+ buff.append(f"\t{event}{self.enum_suffix} = 0,")
first = False
else:
- buff.append("\t%s%s," % (event, self.enum_suffix))
+ buff.append(f"\t{event}{self.enum_suffix},")
- buff.append("\tevent_max%s" % self.enum_suffix)
+ buff.append(f"\tevent_max{self.enum_suffix}")
return buff
@@ -77,7 +77,7 @@ class Dot2c(Automata):
def format_events_enum(self):
buff = []
- buff.append("enum %s {" % self.enum_events_def)
+ buff.append(f"enum {self.enum_events_def} {{")
buff.append(self.get_enum_events_string())
buff.append("};\n")
@@ -93,25 +93,25 @@ class Dot2c(Automata):
min_type = "unsigned int"
if self.states.__len__() > 1000000:
- raise AutomataError("Too many states: %d" % self.states.__len__())
+ raise AutomataError(f"Too many states: {self.states.__len__()}")
return min_type
def format_automaton_definition(self):
min_type = self.get_minimun_type()
buff = []
- buff.append("struct %s {" % self.struct_automaton_def)
- buff.append("\tchar *state_names[state_max%s];" % (self.enum_suffix))
- buff.append("\tchar *event_names[event_max%s];" % (self.enum_suffix))
- buff.append("\t%s function[state_max%s][event_max%s];" % (min_type, self.enum_suffix, self.enum_suffix))
- buff.append("\t%s initial_state;" % min_type)
- buff.append("\tbool final_states[state_max%s];" % (self.enum_suffix))
+ buff.append(f"struct {self.struct_automaton_def} {{")
+ buff.append(f"\tchar *state_names[state_max{self.enum_suffix}];")
+ buff.append(f"\tchar *event_names[event_max{self.enum_suffix}];")
+ buff.append(f"\t{min_type} function[state_max{self.enum_suffix}][event_max{self.enum_suffix}];")
+ buff.append(f"\t{min_type} initial_state;")
+ buff.append(f"\tbool final_states[state_max{self.enum_suffix}];")
buff.append("};\n")
return buff
def format_aut_init_header(self):
buff = []
- buff.append("static const struct %s %s = {" % (self.struct_automaton_def, self.var_automaton_def))
+ buff.append(f"static const struct {self.struct_automaton_def} {self.var_automaton_def} = {{")
return buff
def __get_string_vector_per_line_content(self, buff):
@@ -169,9 +169,9 @@ class Dot2c(Automata):
next_state = self.function[x][y] + self.enum_suffix
if linetoolong:
- line += "\t\t\t%s" % next_state
+ line += f"\t\t\t{next_state}"
else:
- line += "%*s" % (maxlen, next_state)
+ line += f"{next_state:>{maxlen}}"
if y != nr_events-1:
line += ",\n" if linetoolong else ", "
else:
@@ -215,7 +215,7 @@ class Dot2c(Automata):
def format_aut_init_final_states(self):
buff = []
- buff.append("\t.final_states = { %s }," % self.get_aut_init_final_states())
+ buff.append(f"\t.final_states = {{ {self.get_aut_init_final_states()} }},")
return buff
@@ -231,7 +231,7 @@ class Dot2c(Automata):
def format_invalid_state(self):
buff = []
- buff.append("#define %s state_max%s\n" % (self.invalid_state_str, self.enum_suffix))
+ buff.append(f"#define {self.invalid_state_str} state_max{self.enum_suffix}\n")
return buff
diff --git a/tools/verification/rvgen/rvgen/dot2k.py b/tools/verification/rvgen/rvgen/dot2k.py
index ed0a3c9011069..1c0d0235bdf62 100644
--- a/tools/verification/rvgen/rvgen/dot2k.py
+++ b/tools/verification/rvgen/rvgen/dot2k.py
@@ -19,7 +19,7 @@ class dot2k(Monitor, Dot2c):
self.monitor_type = MonitorType
Monitor.__init__(self, extra_params)
Dot2c.__init__(self, file_path, extra_params.get("model_name"))
- self.enum_suffix = "_%s" % self.name
+ self.enum_suffix = f"_{self.name}"
def fill_monitor_type(self):
return self.monitor_type.upper()
@@ -27,7 +27,7 @@ class dot2k(Monitor, Dot2c):
def fill_tracepoint_handlers_skel(self):
buff = []
for event in self.events:
- buff.append("static void handle_%s(void *data, /* XXX: fill header */)" % event)
+ buff.append(f"static void handle_{event}(void *data, /* XXX: fill header */)")
buff.append("{")
handle = "handle_event"
if self.is_start_event(event):
@@ -38,9 +38,9 @@ class dot2k(Monitor, Dot2c):
handle = "handle_start_run_event"
if self.monitor_type == "per_task":
buff.append("\tstruct task_struct *p = /* XXX: how do I get p? */;");
- buff.append("\tda_%s_%s(p, %s%s);" % (handle, self.name, event, self.enum_suffix));
+ buff.append(f"\tda_{handle}_{self.name}(p, {event}{self.enum_suffix});");
else:
- buff.append("\tda_%s_%s(%s%s);" % (handle, self.name, event, self.enum_suffix));
+ buff.append(f"\tda_{handle}_{self.name}({event}{self.enum_suffix});");
buff.append("}")
buff.append("")
return '\n'.join(buff)
@@ -48,20 +48,20 @@ class dot2k(Monitor, Dot2c):
def fill_tracepoint_attach_probe(self):
buff = []
for event in self.events:
- buff.append("\trv_attach_trace_probe(\"%s\", /* XXX: tracepoint */, handle_%s);" % (self.name, event))
+ buff.append(f"\trv_attach_trace_probe(\"{self.name}\", /* XXX: tracepoint */, handle_{event});")
return '\n'.join(buff)
def fill_tracepoint_detach_helper(self):
buff = []
for event in self.events:
- buff.append("\trv_detach_trace_probe(\"%s\", /* XXX: tracepoint */, handle_%s);" % (self.name, event))
+ buff.append(f"\trv_detach_trace_probe(\"{self.name}\", /* XXX: tracepoint */, handle_{event});")
return '\n'.join(buff)
def fill_model_h_header(self):
buff = []
buff.append("/* SPDX-License-Identifier: GPL-2.0 */")
buff.append("/*")
- buff.append(" * Automatically generated C representation of %s automaton" % (self.name))
+ buff.append(f" * Automatically generated C representation of {self.name} automaton")
buff.append(" * For further information about this format, see kernel documentation:")
buff.append(" * Documentation/trace/rv/deterministic_automata.rst")
buff.append(" */")
@@ -73,10 +73,10 @@ class dot2k(Monitor, Dot2c):
#
# Adjust the definition names
#
- self.enum_states_def = "states_%s" % self.name
- self.enum_events_def = "events_%s" % self.name
- self.struct_automaton_def = "automaton_%s" % self.name
- self.var_automaton_def = "automaton_%s" % self.name
+ self.enum_states_def = f"states_{self.name}"
+ self.enum_events_def = f"events_{self.name}"
+ self.struct_automaton_def = f"automaton_{self.name}"
+ self.var_automaton_def = f"automaton_{self.name}"
buff = self.fill_model_h_header()
buff += self.format_model()
@@ -111,8 +111,8 @@ class dot2k(Monitor, Dot2c):
tp_args.insert(0, tp_args_id)
tp_proto_c = ", ".join([a+b for a,b in tp_args])
tp_args_c = ", ".join([b for a,b in tp_args])
- buff.append(" TP_PROTO(%s)," % tp_proto_c)
- buff.append(" TP_ARGS(%s)" % tp_args_c)
+ buff.append(f" TP_PROTO({tp_proto_c}),")
+ buff.append(f" TP_ARGS({tp_args_c})")
return '\n'.join(buff)
def fill_main_c(self):
diff --git a/tools/verification/rvgen/rvgen/generator.py b/tools/verification/rvgen/rvgen/generator.py
index af1662e2c20a7..6d16fb68798a7 100644
--- a/tools/verification/rvgen/rvgen/generator.py
+++ b/tools/verification/rvgen/rvgen/generator.py
@@ -40,7 +40,7 @@ class RVGenerator:
if platform.system() != "Linux":
raise OSError("I can only run on Linux.")
- kernel_path = os.path.join("/lib/modules/%s/build" % platform.release(), self.rv_dir)
+ kernel_path = os.path.join(f"/lib/modules/{platform.release()}/build", self.rv_dir)
# if the current kernel is from a distro this may not be a full kernel tree
# verify that one of the files we are going to modify is available
@@ -69,11 +69,11 @@ class RVGenerator:
return self._read_file(path)
def fill_parent(self):
- return "&rv_%s" % self.parent if self.parent else "NULL"
+ return f"&rv_{self.parent}" if self.parent else "NULL"
def fill_include_parent(self):
if self.parent:
- return "#include <monitors/%s/%s.h>\n" % (self.parent, self.parent)
+ return f"#include <monitors/{self.parent}/{self.parent}.h>\n"
return ""
def fill_tracepoint_handlers_skel(self):
@@ -119,7 +119,7 @@ class RVGenerator:
buff = []
buff.append(" # XXX: add dependencies if there")
if self.parent:
- buff.append(" depends on RV_MON_%s" % self.parent.upper())
+ buff.append(f" depends on RV_MON_{self.parent.upper()}")
buff.append(" default y")
return '\n'.join(buff)
@@ -145,31 +145,30 @@ class RVGenerator:
monitor_class_type = self.fill_monitor_class_type()
if self.auto_patch:
self._patch_file("rv_trace.h",
- "// Add new monitors based on CONFIG_%s here" % monitor_class_type,
- "#include <monitors/%s/%s_trace.h>" % (self.name, self.name))
- return " - Patching %s/rv_trace.h, double check the result" % self.rv_dir
+ f"// Add new monitors based on CONFIG_{monitor_class_type} here",
+ f"#include <monitors/{self.name}/{self.name}_trace.h>")
+ return f" - Patching {self.rv_dir}/rv_trace.h, double check the result"
- return """ - Edit %s/rv_trace.h:
-Add this line where other tracepoints are included and %s is defined:
-#include <monitors/%s/%s_trace.h>
-""" % (self.rv_dir, monitor_class_type, self.name, self.name)
+ return f""" - Edit {self.rv_dir}/rv_trace.h:
+Add this line where other tracepoints are included and {monitor_class_type} is defined:
+#include <monitors/{self.name}/{self.name}_trace.h>
+"""
def _kconfig_marker(self, container=None) -> str:
- return "# Add new %smonitors here" % (container + " "
- if container else "")
+ return f"# Add new {container + ' ' if container else ''}monitors here"
def fill_kconfig_tooltip(self):
if self.auto_patch:
# monitors with a container should stay together in the Kconfig
self._patch_file("Kconfig",
self._kconfig_marker(self.parent),
- "source \"kernel/trace/rv/monitors/%s/Kconfig\"" % (self.name))
- return " - Patching %s/Kconfig, double check the result" % self.rv_dir
+ f"source \"kernel/trace/rv/monitors/{self.name}/Kconfig\"")
+ return f" - Patching {self.rv_dir}/Kconfig, double check the result"
- return """ - Edit %s/Kconfig:
+ return f""" - Edit {self.rv_dir}/Kconfig:
Add this line where other monitors are included:
-source \"kernel/trace/rv/monitors/%s/Kconfig\"
-""" % (self.rv_dir, self.name)
+source \"kernel/trace/rv/monitors/{self.name}/Kconfig\"
+"""
def fill_makefile_tooltip(self):
name = self.name
@@ -177,18 +176,18 @@ source \"kernel/trace/rv/monitors/%s/Kconfig\"
if self.auto_patch:
self._patch_file("Makefile",
"# Add new monitors here",
- "obj-$(CONFIG_RV_MON_%s) += monitors/%s/%s.o" % (name_up, name, name))
- return " - Patching %s/Makefile, double check the result" % self.rv_dir
+ f"obj-$(CONFIG_RV_MON_{name_up}) += monitors/{name}/{name}.o")
+ return f" - Patching {self.rv_dir}/Makefile, double check the result"
- return """ - Edit %s/Makefile:
+ return f""" - Edit {self.rv_dir}/Makefile:
Add this line where other monitors are included:
-obj-$(CONFIG_RV_MON_%s) += monitors/%s/%s.o
-""" % (self.rv_dir, name_up, name, name)
+obj-$(CONFIG_RV_MON_{name_up}) += monitors/{name}/{name}.o
+"""
def fill_monitor_tooltip(self):
if self.auto_patch:
- return " - Monitor created in %s/monitors/%s" % (self.rv_dir, self. name)
- return " - Move %s/ to the kernel's monitor directory (%s/monitors)" % (self.name, self.rv_dir)
+ return f" - Monitor created in {self.rv_dir}/monitors/{self.name}"
+ return f" - Move {self.name}/ to the kernel's monitor directory ({self.rv_dir}/monitors)"
def __create_directory(self):
path = self.name
@@ -205,13 +204,13 @@ obj-$(CONFIG_RV_MON_%s) += monitors/%s/%s.o
file.close()
def _create_file(self, file_name, content):
- path = "%s/%s" % (self.name, file_name)
+ path = f"{self.name}/{file_name}"
if self.auto_patch:
path = os.path.join(self.rv_dir, "monitors", path)
self.__write_file(path, content)
def __get_main_name(self):
- path = "%s/%s" % (self.name, "main.c")
+ path = f"{self.name}/main.c"
if not os.path.exists(path):
return "main.c"
return "__main.c"
@@ -221,11 +220,11 @@ obj-$(CONFIG_RV_MON_%s) += monitors/%s/%s.o
self.__create_directory()
- path = "%s.c" % self.name
+ path = f"{self.name}.c"
self._create_file(path, main_c)
model_h = self.fill_model_h()
- path = "%s.h" % self.name
+ path = f"{self.name}.h"
self._create_file(path, model_h)
kconfig = self.fill_kconfig()
@@ -256,5 +255,5 @@ class Monitor(RVGenerator):
def print_files(self):
super().print_files()
trace_h = self.fill_trace_h()
- path = "%s_trace.h" % self.name
+ path = f"{self.name}_trace.h"
self._create_file(path, trace_h)
diff --git a/tools/verification/rvgen/rvgen/ltl2k.py b/tools/verification/rvgen/rvgen/ltl2k.py
index b075f98d50c47..fa9ea6d597095 100644
--- a/tools/verification/rvgen/rvgen/ltl2k.py
+++ b/tools/verification/rvgen/rvgen/ltl2k.py
@@ -73,7 +73,7 @@ class ltl2k(generator.Monitor):
]
for node in self.ba:
- buf.append("\tS%i," % node.id)
+ buf.append(f"\tS{node.id},")
buf.append("\tRV_NUM_BA_STATES")
buf.append("};")
buf.append("static_assert(RV_NUM_BA_STATES <= RV_MAX_BA_STATES);")
@@ -82,7 +82,7 @@ class ltl2k(generator.Monitor):
def _fill_atoms(self):
buf = ["enum ltl_atom {"]
for a in sorted(self.atoms):
- buf.append("\tLTL_%s," % a)
+ buf.append(f"\tLTL_{a},")
buf.append("\tLTL_NUM_ATOM")
buf.append("};")
buf.append("static_assert(LTL_NUM_ATOM <= RV_MAX_LTL_ATOM);")
@@ -96,7 +96,7 @@ class ltl2k(generator.Monitor):
]
for name in self.atoms_abbr:
- buf.append("\t\t\"%s\"," % name)
+ buf.append(f"\t\t\"{name}\",")
buf.extend([
"\t};",
@@ -113,19 +113,19 @@ class ltl2k(generator.Monitor):
continue
if isinstance(node.op, ltl2ba.AndOp):
- buf.append("\tbool %s = %s && %s;" % (node, node.op.left, node.op.right))
+ buf.append(f"\tbool {node} = {node.op.left} && {node.op.right};")
required_values |= {str(node.op.left), str(node.op.right)}
elif isinstance(node.op, ltl2ba.OrOp):
- buf.append("\tbool %s = %s || %s;" % (node, node.op.left, node.op.right))
+ buf.append(f"\tbool {node} = {node.op.left} || {node.op.right};")
required_values |= {str(node.op.left), str(node.op.right)}
elif isinstance(node.op, ltl2ba.NotOp):
- buf.append("\tbool %s = !%s;" % (node, node.op.child))
+ buf.append(f"\tbool {node} = !{node.op.child};")
required_values.add(str(node.op.child))
for atom in self.atoms:
if atom.lower() not in required_values:
continue
- buf.append("\tbool %s = test_bit(LTL_%s, mon->atoms);" % (atom.lower(), atom))
+ buf.append(f"\tbool {atom.lower()} = test_bit(LTL_{atom}, mon->atoms);")
buf.reverse()
@@ -153,7 +153,7 @@ class ltl2k(generator.Monitor):
])
for node in self.ba:
- buf.append("\tcase S%i:" % node.id)
+ buf.append(f"\tcase S{node.id}:")
for o in sorted(node.outgoing):
line = "\t\tif "
@@ -163,7 +163,7 @@ class ltl2k(generator.Monitor):
lines = break_long_line(line, indent)
buf.extend(lines)
- buf.append("\t\t\t__set_bit(S%i, next);" % o.id)
+ buf.append(f"\t\t\t__set_bit(S{o.id}, next);")
buf.append("\t\tbreak;")
buf.extend([
"\t}",
@@ -197,7 +197,7 @@ class ltl2k(generator.Monitor):
lines = break_long_line(line, indent)
buf.extend(lines)
- buf.append("\t\t__set_bit(S%i, mon->states);" % node.id)
+ buf.append(f"\t\t__set_bit(S{node.id}, mon->states);")
buf.append("}")
return buf
@@ -205,23 +205,21 @@ class ltl2k(generator.Monitor):
buff = []
buff.append("static void handle_example_event(void *data, /* XXX: fill header */)")
buff.append("{")
- buff.append("\tltl_atom_update(task, LTL_%s, true/false);" % self.atoms[0])
+ buff.append(f"\tltl_atom_update(task, LTL_{self.atoms[0]}, true/false);")
buff.append("}")
buff.append("")
return '\n'.join(buff)
def fill_tracepoint_attach_probe(self):
- return "\trv_attach_trace_probe(\"%s\", /* XXX: tracepoint */, handle_example_event);" \
- % self.name
+ return f"\trv_attach_trace_probe(\"{self.name}\", /* XXX: tracepoint */, handle_example_event);"
def fill_tracepoint_detach_helper(self):
- return "\trv_detach_trace_probe(\"%s\", /* XXX: tracepoint */, handle_sample_event);" \
- % self.name
+ return f"\trv_detach_trace_probe(\"{self.name}\", /* XXX: tracepoint */, handle_sample_event);"
def fill_atoms_init(self):
buff = []
for a in self.atoms:
- buff.append("\tltl_atom_set(mon, LTL_%s, true/false);" % a)
+ buff.append(f"\tltl_atom_set(mon, LTL_{a}, true/false);")
return '\n'.join(buff)
def fill_model_h(self):
--
2.52.0
^ permalink raw reply related [flat|nested] 95+ messages in thread* Re: [PATCH 03/26] rv/rvgen: replace % string formatting with f-strings
2026-01-19 20:45 ` [PATCH 03/26] rv/rvgen: replace % string formatting with f-strings Wander Lairson Costa
@ 2026-01-20 10:02 ` Gabriele Monaco
2026-01-22 14:46 ` Nam Cao
1 sibling, 0 replies; 95+ messages in thread
From: Gabriele Monaco @ 2026-01-20 10:02 UTC (permalink / raw)
To: Wander Lairson Costa
Cc: Steven Rostedt, Nam Cao, open list,
open list:RUNTIME VERIFICATION (RV)
On Mon, 2026-01-19 at 17:45 -0300, Wander Lairson Costa wrote:
> Replace all instances of percent-style string formatting with
> f-strings across the rvgen codebase. This modernizes the string
> formatting to use Python 3.6+ features, providing clearer and more
> maintainable code while improving runtime performance.
>
> The conversion handles all formatting cases including simple variable
> substitution, multi-variable formatting, and complex format specifiers.
> Dynamic width formatting is converted from "%*s" to "{var:>{width}}"
> using proper alignment syntax. Template strings for generated C code
> properly escape braces using double-brace syntax to produce literal
> braces in the output.
>
> F-strings provide approximately 2x performance improvement over percent
> formatting and are the recommended approach in modern Python.
>
> Signed-off-by: Wander Lairson Costa <wander@redhat.com>
Sad to see the printf-style things go, but it's for better. Thanks.
Reviewed-by: Gabriele Monaco <gmonaco@redhat.com>
> ---
> tools/verification/rvgen/__main__.py | 6 +--
> tools/verification/rvgen/rvgen/automata.py | 6 +--
> tools/verification/rvgen/rvgen/dot2c.py | 40 +++++++-------
> tools/verification/rvgen/rvgen/dot2k.py | 26 ++++-----
> tools/verification/rvgen/rvgen/generator.py | 59 ++++++++++-----------
> tools/verification/rvgen/rvgen/ltl2k.py | 30 +++++------
> 6 files changed, 82 insertions(+), 85 deletions(-)
>
> diff --git a/tools/verification/rvgen/__main__.py
> b/tools/verification/rvgen/__main__.py
> index 768b11a1e978b..eeeccf81d4b90 100644
> --- a/tools/verification/rvgen/__main__.py
> +++ b/tools/verification/rvgen/__main__.py
> @@ -40,7 +40,7 @@ if __name__ == '__main__':
> params = parser.parse_args()
>
> if params.subcmd == "monitor":
> - print("Opening and parsing the specification file %s" % params.spec)
> + print(f"Opening and parsing the specification file {params.spec}")
> if params.monitor_class == "da":
> monitor = dot2k(params.spec, params.monitor_type, vars(params))
> elif params.monitor_class == "ltl":
> @@ -51,11 +51,11 @@ if __name__ == '__main__':
> else:
> monitor = Container(vars(params))
>
> - print("Writing the monitor into the directory %s" % monitor.name)
> + print(f"Writing the monitor into the directory {monitor.name}")
> monitor.print_files()
> print("Almost done, checklist")
> if params.subcmd == "monitor":
> - print(" - Edit the %s/%s.c to add the instrumentation" %
> (monitor.name, monitor.name))
> + print(f" - Edit the {monitor.name}/{monitor.name}.c to add the
> instrumentation")
> print(monitor.fill_tracepoint_tooltip())
> print(monitor.fill_makefile_tooltip())
> print(monitor.fill_kconfig_tooltip())
> diff --git a/tools/verification/rvgen/rvgen/automata.py
> b/tools/verification/rvgen/rvgen/automata.py
> index 8d88c3b65d00d..3e24313a2eaec 100644
> --- a/tools/verification/rvgen/rvgen/automata.py
> +++ b/tools/verification/rvgen/rvgen/automata.py
> @@ -39,11 +39,11 @@ class Automata:
> basename = ntpath.basename(self.__dot_path)
> if not basename.endswith(".dot") and not basename.endswith(".gv"):
> print("not a dot file")
> - raise AutomataError("not a dot file: %s" % self.__dot_path)
> + raise AutomataError(f"not a dot file: {self.__dot_path}")
>
> model_name = ntpath.splitext(basename)[0]
> if model_name.__len__() == 0:
> - raise AutomataError("not a dot file: %s" % self.__dot_path)
> + raise AutomataError(f"not a dot file: {self.__dot_path}")
>
> return model_name
>
> @@ -62,7 +62,7 @@ class Automata:
> line = dot_lines[cursor].split()
>
> if (line[0] != "digraph") and (line[1] != "state_automaton"):
> - raise AutomataError("Not a valid .dot format: %s" %
> self.__dot_path)
> + raise AutomataError(f"Not a valid .dot format:
> {self.__dot_path}")
> else:
> cursor += 1
> return dot_lines
> diff --git a/tools/verification/rvgen/rvgen/dot2c.py
> b/tools/verification/rvgen/rvgen/dot2c.py
> index 1a1770e7f20c0..78959d345c26e 100644
> --- a/tools/verification/rvgen/rvgen/dot2c.py
> +++ b/tools/verification/rvgen/rvgen/dot2c.py
> @@ -37,11 +37,11 @@ class Dot2c(Automata):
>
> def __get_enum_states_content(self):
> buff = []
> - buff.append("\t%s%s = 0," % (self.initial_state, self.enum_suffix))
> + buff.append(f"\t{self.initial_state}{self.enum_suffix} = 0,")
> for state in self.states:
> if state != self.initial_state:
> - buff.append("\t%s%s," % (state, self.enum_suffix))
> - buff.append("\tstate_max%s" % (self.enum_suffix))
> + buff.append(f"\t{state}{self.enum_suffix},")
> + buff.append(f"\tstate_max{self.enum_suffix}")
>
> return buff
>
> @@ -51,7 +51,7 @@ class Dot2c(Automata):
>
> def format_states_enum(self):
> buff = []
> - buff.append("enum %s {" % self.enum_states_def)
> + buff.append(f"enum {self.enum_states_def} {{")
> buff.append(self.get_enum_states_string())
> buff.append("};\n")
>
> @@ -62,12 +62,12 @@ class Dot2c(Automata):
> first = True
> for event in self.events:
> if first:
> - buff.append("\t%s%s = 0," % (event, self.enum_suffix))
> + buff.append(f"\t{event}{self.enum_suffix} = 0,")
> first = False
> else:
> - buff.append("\t%s%s," % (event, self.enum_suffix))
> + buff.append(f"\t{event}{self.enum_suffix},")
>
> - buff.append("\tevent_max%s" % self.enum_suffix)
> + buff.append(f"\tevent_max{self.enum_suffix}")
>
> return buff
>
> @@ -77,7 +77,7 @@ class Dot2c(Automata):
>
> def format_events_enum(self):
> buff = []
> - buff.append("enum %s {" % self.enum_events_def)
> + buff.append(f"enum {self.enum_events_def} {{")
> buff.append(self.get_enum_events_string())
> buff.append("};\n")
>
> @@ -93,25 +93,25 @@ class Dot2c(Automata):
> min_type = "unsigned int"
>
> if self.states.__len__() > 1000000:
> - raise AutomataError("Too many states: %d" %
> self.states.__len__())
> + raise AutomataError(f"Too many states: {self.states.__len__()}")
>
> return min_type
>
> def format_automaton_definition(self):
> min_type = self.get_minimun_type()
> buff = []
> - buff.append("struct %s {" % self.struct_automaton_def)
> - buff.append("\tchar *state_names[state_max%s];" % (self.enum_suffix))
> - buff.append("\tchar *event_names[event_max%s];" % (self.enum_suffix))
> - buff.append("\t%s function[state_max%s][event_max%s];" % (min_type,
> self.enum_suffix, self.enum_suffix))
> - buff.append("\t%s initial_state;" % min_type)
> - buff.append("\tbool final_states[state_max%s];" % (self.enum_suffix))
> + buff.append(f"struct {self.struct_automaton_def} {{")
> + buff.append(f"\tchar *state_names[state_max{self.enum_suffix}];")
> + buff.append(f"\tchar *event_names[event_max{self.enum_suffix}];")
> + buff.append(f"\t{min_type}
> function[state_max{self.enum_suffix}][event_max{self.enum_suffix}];")
> + buff.append(f"\t{min_type} initial_state;")
> + buff.append(f"\tbool final_states[state_max{self.enum_suffix}];")
> buff.append("};\n")
> return buff
>
> def format_aut_init_header(self):
> buff = []
> - buff.append("static const struct %s %s = {" %
> (self.struct_automaton_def, self.var_automaton_def))
> + buff.append(f"static const struct {self.struct_automaton_def}
> {self.var_automaton_def} = {{")
> return buff
>
> def __get_string_vector_per_line_content(self, buff):
> @@ -169,9 +169,9 @@ class Dot2c(Automata):
> next_state = self.function[x][y] + self.enum_suffix
>
> if linetoolong:
> - line += "\t\t\t%s" % next_state
> + line += f"\t\t\t{next_state}"
> else:
> - line += "%*s" % (maxlen, next_state)
> + line += f"{next_state:>{maxlen}}"
> if y != nr_events-1:
> line += ",\n" if linetoolong else ", "
> else:
> @@ -215,7 +215,7 @@ class Dot2c(Automata):
>
> def format_aut_init_final_states(self):
> buff = []
> - buff.append("\t.final_states = { %s }," %
> self.get_aut_init_final_states())
> + buff.append(f"\t.final_states = {{ {self.get_aut_init_final_states()}
> }},")
>
> return buff
>
> @@ -231,7 +231,7 @@ class Dot2c(Automata):
>
> def format_invalid_state(self):
> buff = []
> - buff.append("#define %s state_max%s\n" % (self.invalid_state_str,
> self.enum_suffix))
> + buff.append(f"#define {self.invalid_state_str}
> state_max{self.enum_suffix}\n")
>
> return buff
>
> diff --git a/tools/verification/rvgen/rvgen/dot2k.py
> b/tools/verification/rvgen/rvgen/dot2k.py
> index ed0a3c9011069..1c0d0235bdf62 100644
> --- a/tools/verification/rvgen/rvgen/dot2k.py
> +++ b/tools/verification/rvgen/rvgen/dot2k.py
> @@ -19,7 +19,7 @@ class dot2k(Monitor, Dot2c):
> self.monitor_type = MonitorType
> Monitor.__init__(self, extra_params)
> Dot2c.__init__(self, file_path, extra_params.get("model_name"))
> - self.enum_suffix = "_%s" % self.name
> + self.enum_suffix = f"_{self.name}"
>
> def fill_monitor_type(self):
> return self.monitor_type.upper()
> @@ -27,7 +27,7 @@ class dot2k(Monitor, Dot2c):
> def fill_tracepoint_handlers_skel(self):
> buff = []
> for event in self.events:
> - buff.append("static void handle_%s(void *data, /* XXX: fill
> header */)" % event)
> + buff.append(f"static void handle_{event}(void *data, /* XXX: fill
> header */)")
> buff.append("{")
> handle = "handle_event"
> if self.is_start_event(event):
> @@ -38,9 +38,9 @@ class dot2k(Monitor, Dot2c):
> handle = "handle_start_run_event"
> if self.monitor_type == "per_task":
> buff.append("\tstruct task_struct *p = /* XXX: how do I get
> p? */;");
> - buff.append("\tda_%s_%s(p, %s%s);" % (handle, self.name,
> event, self.enum_suffix));
> + buff.append(f"\tda_{handle}_{self.name}(p,
> {event}{self.enum_suffix});");
> else:
> - buff.append("\tda_%s_%s(%s%s);" % (handle, self.name, event,
> self.enum_suffix));
> +
> buff.append(f"\tda_{handle}_{self.name}({event}{self.enum_suffix});");
> buff.append("}")
> buff.append("")
> return '\n'.join(buff)
> @@ -48,20 +48,20 @@ class dot2k(Monitor, Dot2c):
> def fill_tracepoint_attach_probe(self):
> buff = []
> for event in self.events:
> - buff.append("\trv_attach_trace_probe(\"%s\", /* XXX: tracepoint
> */, handle_%s);" % (self.name, event))
> + buff.append(f"\trv_attach_trace_probe(\"{self.name}\", /* XXX:
> tracepoint */, handle_{event});")
> return '\n'.join(buff)
>
> def fill_tracepoint_detach_helper(self):
> buff = []
> for event in self.events:
> - buff.append("\trv_detach_trace_probe(\"%s\", /* XXX: tracepoint
> */, handle_%s);" % (self.name, event))
> + buff.append(f"\trv_detach_trace_probe(\"{self.name}\", /* XXX:
> tracepoint */, handle_{event});")
> return '\n'.join(buff)
>
> def fill_model_h_header(self):
> buff = []
> buff.append("/* SPDX-License-Identifier: GPL-2.0 */")
> buff.append("/*")
> - buff.append(" * Automatically generated C representation of %s
> automaton" % (self.name))
> + buff.append(f" * Automatically generated C representation of
> {self.name} automaton")
> buff.append(" * For further information about this format, see kernel
> documentation:")
> buff.append(" * Documentation/trace/rv/deterministic_automata.rst")
> buff.append(" */")
> @@ -73,10 +73,10 @@ class dot2k(Monitor, Dot2c):
> #
> # Adjust the definition names
> #
> - self.enum_states_def = "states_%s" % self.name
> - self.enum_events_def = "events_%s" % self.name
> - self.struct_automaton_def = "automaton_%s" % self.name
> - self.var_automaton_def = "automaton_%s" % self.name
> + self.enum_states_def = f"states_{self.name}"
> + self.enum_events_def = f"events_{self.name}"
> + self.struct_automaton_def = f"automaton_{self.name}"
> + self.var_automaton_def = f"automaton_{self.name}"
>
> buff = self.fill_model_h_header()
> buff += self.format_model()
> @@ -111,8 +111,8 @@ class dot2k(Monitor, Dot2c):
> tp_args.insert(0, tp_args_id)
> tp_proto_c = ", ".join([a+b for a,b in tp_args])
> tp_args_c = ", ".join([b for a,b in tp_args])
> - buff.append(" TP_PROTO(%s)," % tp_proto_c)
> - buff.append(" TP_ARGS(%s)" % tp_args_c)
> + buff.append(f" TP_PROTO({tp_proto_c}),")
> + buff.append(f" TP_ARGS({tp_args_c})")
> return '\n'.join(buff)
>
> def fill_main_c(self):
> diff --git a/tools/verification/rvgen/rvgen/generator.py
> b/tools/verification/rvgen/rvgen/generator.py
> index af1662e2c20a7..6d16fb68798a7 100644
> --- a/tools/verification/rvgen/rvgen/generator.py
> +++ b/tools/verification/rvgen/rvgen/generator.py
> @@ -40,7 +40,7 @@ class RVGenerator:
> if platform.system() != "Linux":
> raise OSError("I can only run on Linux.")
>
> - kernel_path = os.path.join("/lib/modules/%s/build" %
> platform.release(), self.rv_dir)
> + kernel_path =
> os.path.join(f"/lib/modules/{platform.release()}/build", self.rv_dir)
>
> # if the current kernel is from a distro this may not be a full
> kernel tree
> # verify that one of the files we are going to modify is available
> @@ -69,11 +69,11 @@ class RVGenerator:
> return self._read_file(path)
>
> def fill_parent(self):
> - return "&rv_%s" % self.parent if self.parent else "NULL"
> + return f"&rv_{self.parent}" if self.parent else "NULL"
>
> def fill_include_parent(self):
> if self.parent:
> - return "#include <monitors/%s/%s.h>\n" % (self.parent,
> self.parent)
> + return f"#include <monitors/{self.parent}/{self.parent}.h>\n"
> return ""
>
> def fill_tracepoint_handlers_skel(self):
> @@ -119,7 +119,7 @@ class RVGenerator:
> buff = []
> buff.append(" # XXX: add dependencies if there")
> if self.parent:
> - buff.append(" depends on RV_MON_%s" % self.parent.upper())
> + buff.append(f" depends on RV_MON_{self.parent.upper()}")
> buff.append(" default y")
> return '\n'.join(buff)
>
> @@ -145,31 +145,30 @@ class RVGenerator:
> monitor_class_type = self.fill_monitor_class_type()
> if self.auto_patch:
> self._patch_file("rv_trace.h",
> - "// Add new monitors based on CONFIG_%s here" %
> monitor_class_type,
> - "#include <monitors/%s/%s_trace.h>" % (self.name,
> self.name))
> - return " - Patching %s/rv_trace.h, double check the result" %
> self.rv_dir
> + f"// Add new monitors based on
> CONFIG_{monitor_class_type} here",
> + f"#include
> <monitors/{self.name}/{self.name}_trace.h>")
> + return f" - Patching {self.rv_dir}/rv_trace.h, double check the
> result"
>
> - return """ - Edit %s/rv_trace.h:
> -Add this line where other tracepoints are included and %s is defined:
> -#include <monitors/%s/%s_trace.h>
> -""" % (self.rv_dir, monitor_class_type, self.name, self.name)
> + return f""" - Edit {self.rv_dir}/rv_trace.h:
> +Add this line where other tracepoints are included and {monitor_class_type}
> is defined:
> +#include <monitors/{self.name}/{self.name}_trace.h>
> +"""
>
> def _kconfig_marker(self, container=None) -> str:
> - return "# Add new %smonitors here" % (container + " "
> - if container else "")
> + return f"# Add new {container + ' ' if container else ''}monitors
> here"
>
> def fill_kconfig_tooltip(self):
> if self.auto_patch:
> # monitors with a container should stay together in the Kconfig
> self._patch_file("Kconfig",
> self._kconfig_marker(self.parent),
> - "source \"kernel/trace/rv/monitors/%s/Kconfig\""
> % (self.name))
> - return " - Patching %s/Kconfig, double check the result" %
> self.rv_dir
> + f"source
> \"kernel/trace/rv/monitors/{self.name}/Kconfig\"")
> + return f" - Patching {self.rv_dir}/Kconfig, double check the
> result"
>
> - return """ - Edit %s/Kconfig:
> + return f""" - Edit {self.rv_dir}/Kconfig:
> Add this line where other monitors are included:
> -source \"kernel/trace/rv/monitors/%s/Kconfig\"
> -""" % (self.rv_dir, self.name)
> +source \"kernel/trace/rv/monitors/{self.name}/Kconfig\"
> +"""
>
> def fill_makefile_tooltip(self):
> name = self.name
> @@ -177,18 +176,18 @@ source \"kernel/trace/rv/monitors/%s/Kconfig\"
> if self.auto_patch:
> self._patch_file("Makefile",
> "# Add new monitors here",
> - "obj-$(CONFIG_RV_MON_%s) += monitors/%s/%s.o" %
> (name_up, name, name))
> - return " - Patching %s/Makefile, double check the result" %
> self.rv_dir
> + f"obj-$(CONFIG_RV_MON_{name_up}) +=
> monitors/{name}/{name}.o")
> + return f" - Patching {self.rv_dir}/Makefile, double check the
> result"
>
> - return """ - Edit %s/Makefile:
> + return f""" - Edit {self.rv_dir}/Makefile:
> Add this line where other monitors are included:
> -obj-$(CONFIG_RV_MON_%s) += monitors/%s/%s.o
> -""" % (self.rv_dir, name_up, name, name)
> +obj-$(CONFIG_RV_MON_{name_up}) += monitors/{name}/{name}.o
> +"""
>
> def fill_monitor_tooltip(self):
> if self.auto_patch:
> - return " - Monitor created in %s/monitors/%s" % (self.rv_dir,
> self. name)
> - return " - Move %s/ to the kernel's monitor directory (%s/monitors)"
> % (self.name, self.rv_dir)
> + return f" - Monitor created in
> {self.rv_dir}/monitors/{self.name}"
> + return f" - Move {self.name}/ to the kernel's monitor directory
> ({self.rv_dir}/monitors)"
>
> def __create_directory(self):
> path = self.name
> @@ -205,13 +204,13 @@ obj-$(CONFIG_RV_MON_%s) += monitors/%s/%s.o
> file.close()
>
> def _create_file(self, file_name, content):
> - path = "%s/%s" % (self.name, file_name)
> + path = f"{self.name}/{file_name}"
> if self.auto_patch:
> path = os.path.join(self.rv_dir, "monitors", path)
> self.__write_file(path, content)
>
> def __get_main_name(self):
> - path = "%s/%s" % (self.name, "main.c")
> + path = f"{self.name}/main.c"
> if not os.path.exists(path):
> return "main.c"
> return "__main.c"
> @@ -221,11 +220,11 @@ obj-$(CONFIG_RV_MON_%s) += monitors/%s/%s.o
>
> self.__create_directory()
>
> - path = "%s.c" % self.name
> + path = f"{self.name}.c"
> self._create_file(path, main_c)
>
> model_h = self.fill_model_h()
> - path = "%s.h" % self.name
> + path = f"{self.name}.h"
> self._create_file(path, model_h)
>
> kconfig = self.fill_kconfig()
> @@ -256,5 +255,5 @@ class Monitor(RVGenerator):
> def print_files(self):
> super().print_files()
> trace_h = self.fill_trace_h()
> - path = "%s_trace.h" % self.name
> + path = f"{self.name}_trace.h"
> self._create_file(path, trace_h)
> diff --git a/tools/verification/rvgen/rvgen/ltl2k.py
> b/tools/verification/rvgen/rvgen/ltl2k.py
> index b075f98d50c47..fa9ea6d597095 100644
> --- a/tools/verification/rvgen/rvgen/ltl2k.py
> +++ b/tools/verification/rvgen/rvgen/ltl2k.py
> @@ -73,7 +73,7 @@ class ltl2k(generator.Monitor):
> ]
>
> for node in self.ba:
> - buf.append("\tS%i," % node.id)
> + buf.append(f"\tS{node.id},")
> buf.append("\tRV_NUM_BA_STATES")
> buf.append("};")
> buf.append("static_assert(RV_NUM_BA_STATES <= RV_MAX_BA_STATES);")
> @@ -82,7 +82,7 @@ class ltl2k(generator.Monitor):
> def _fill_atoms(self):
> buf = ["enum ltl_atom {"]
> for a in sorted(self.atoms):
> - buf.append("\tLTL_%s," % a)
> + buf.append(f"\tLTL_{a},")
> buf.append("\tLTL_NUM_ATOM")
> buf.append("};")
> buf.append("static_assert(LTL_NUM_ATOM <= RV_MAX_LTL_ATOM);")
> @@ -96,7 +96,7 @@ class ltl2k(generator.Monitor):
> ]
>
> for name in self.atoms_abbr:
> - buf.append("\t\t\"%s\"," % name)
> + buf.append(f"\t\t\"{name}\",")
>
> buf.extend([
> "\t};",
> @@ -113,19 +113,19 @@ class ltl2k(generator.Monitor):
> continue
>
> if isinstance(node.op, ltl2ba.AndOp):
> - buf.append("\tbool %s = %s && %s;" % (node, node.op.left,
> node.op.right))
> + buf.append(f"\tbool {node} = {node.op.left} &&
> {node.op.right};")
> required_values |= {str(node.op.left), str(node.op.right)}
> elif isinstance(node.op, ltl2ba.OrOp):
> - buf.append("\tbool %s = %s || %s;" % (node, node.op.left,
> node.op.right))
> + buf.append(f"\tbool {node} = {node.op.left} ||
> {node.op.right};")
> required_values |= {str(node.op.left), str(node.op.right)}
> elif isinstance(node.op, ltl2ba.NotOp):
> - buf.append("\tbool %s = !%s;" % (node, node.op.child))
> + buf.append(f"\tbool {node} = !{node.op.child};")
> required_values.add(str(node.op.child))
>
> for atom in self.atoms:
> if atom.lower() not in required_values:
> continue
> - buf.append("\tbool %s = test_bit(LTL_%s, mon->atoms);" %
> (atom.lower(), atom))
> + buf.append(f"\tbool {atom.lower()} = test_bit(LTL_{atom}, mon-
> >atoms);")
>
> buf.reverse()
>
> @@ -153,7 +153,7 @@ class ltl2k(generator.Monitor):
> ])
>
> for node in self.ba:
> - buf.append("\tcase S%i:" % node.id)
> + buf.append(f"\tcase S{node.id}:")
>
> for o in sorted(node.outgoing):
> line = "\t\tif "
> @@ -163,7 +163,7 @@ class ltl2k(generator.Monitor):
> lines = break_long_line(line, indent)
> buf.extend(lines)
>
> - buf.append("\t\t\t__set_bit(S%i, next);" % o.id)
> + buf.append(f"\t\t\t__set_bit(S{o.id}, next);")
> buf.append("\t\tbreak;")
> buf.extend([
> "\t}",
> @@ -197,7 +197,7 @@ class ltl2k(generator.Monitor):
> lines = break_long_line(line, indent)
> buf.extend(lines)
>
> - buf.append("\t\t__set_bit(S%i, mon->states);" % node.id)
> + buf.append(f"\t\t__set_bit(S{node.id}, mon->states);")
> buf.append("}")
> return buf
>
> @@ -205,23 +205,21 @@ class ltl2k(generator.Monitor):
> buff = []
> buff.append("static void handle_example_event(void *data, /* XXX:
> fill header */)")
> buff.append("{")
> - buff.append("\tltl_atom_update(task, LTL_%s, true/false);" %
> self.atoms[0])
> + buff.append(f"\tltl_atom_update(task, LTL_{self.atoms[0]},
> true/false);")
> buff.append("}")
> buff.append("")
> return '\n'.join(buff)
>
> def fill_tracepoint_attach_probe(self):
> - return "\trv_attach_trace_probe(\"%s\", /* XXX: tracepoint */,
> handle_example_event);" \
> - % self.name
> + return f"\trv_attach_trace_probe(\"{self.name}\", /* XXX: tracepoint
> */, handle_example_event);"
>
> def fill_tracepoint_detach_helper(self):
> - return "\trv_detach_trace_probe(\"%s\", /* XXX: tracepoint */,
> handle_sample_event);" \
> - % self.name
> + return f"\trv_detach_trace_probe(\"{self.name}\", /* XXX: tracepoint
> */, handle_sample_event);"
>
> def fill_atoms_init(self):
> buff = []
> for a in self.atoms:
> - buff.append("\tltl_atom_set(mon, LTL_%s, true/false);" % a)
> + buff.append(f"\tltl_atom_set(mon, LTL_{a}, true/false);")
> return '\n'.join(buff)
>
> def fill_model_h(self):
^ permalink raw reply [flat|nested] 95+ messages in thread* Re: [PATCH 03/26] rv/rvgen: replace % string formatting with f-strings
2026-01-19 20:45 ` [PATCH 03/26] rv/rvgen: replace % string formatting with f-strings Wander Lairson Costa
2026-01-20 10:02 ` Gabriele Monaco
@ 2026-01-22 14:46 ` Nam Cao
1 sibling, 0 replies; 95+ messages in thread
From: Nam Cao @ 2026-01-22 14:46 UTC (permalink / raw)
To: Wander Lairson Costa, Steven Rostedt, Gabriele Monaco,
Wander Lairson Costa, open list,
open list:RUNTIME VERIFICATION (RV)
Wander Lairson Costa <wander@redhat.com> writes:
> Replace all instances of percent-style string formatting with
> f-strings across the rvgen codebase. This modernizes the string
> formatting to use Python 3.6+ features, providing clearer and more
> maintainable code while improving runtime performance.
>
> The conversion handles all formatting cases including simple variable
> substitution, multi-variable formatting, and complex format specifiers.
> Dynamic width formatting is converted from "%*s" to "{var:>{width}}"
> using proper alignment syntax. Template strings for generated C code
> properly escape braces using double-brace syntax to produce literal
> braces in the output.
>
> F-strings provide approximately 2x performance improvement over percent
> formatting and are the recommended approach in modern Python.
>
> Signed-off-by: Wander Lairson Costa <wander@redhat.com>
Reviewed-by: Nam Cao <namcao@linutronix.de>
^ permalink raw reply [flat|nested] 95+ messages in thread
* [PATCH 04/26] rv/rvgen: replace __len__() calls with len()
2026-01-19 20:45 [PATCH 00/26] rv/rvgen: Robustness, modernization, and fixes Wander Lairson Costa
` (2 preceding siblings ...)
2026-01-19 20:45 ` [PATCH 03/26] rv/rvgen: replace % string formatting with f-strings Wander Lairson Costa
@ 2026-01-19 20:45 ` Wander Lairson Costa
2026-01-20 7:41 ` Gabriele Monaco
2026-01-22 14:46 ` Nam Cao
2026-01-19 20:45 ` [PATCH 05/26] rv/rvgen: remove unnecessary semicolons Wander Lairson Costa
` (22 subsequent siblings)
26 siblings, 2 replies; 95+ messages in thread
From: Wander Lairson Costa @ 2026-01-19 20:45 UTC (permalink / raw)
To: Steven Rostedt, Gabriele Monaco, Nam Cao, Wander Lairson Costa,
open list, open list:RUNTIME VERIFICATION (RV)
Replace all direct calls to the __len__() dunder method with the
idiomatic len() built-in function across the rvgen codebase. This
change eliminates a Python anti-pattern where dunder methods are
called directly instead of using their corresponding built-in
functions.
The changes affect nine instances across two files. In automata.py,
the empty string check is further improved by using truthiness
testing instead of explicit length comparison. In dot2c.py, all
length checks in the get_minimun_type, __get_max_strlen_of_states,
and get_aut_init_function methods now use the standard len()
function. Additionally, spacing around keyword arguments has been
corrected to follow PEP 8 guidelines.
Direct calls to dunder methods like __len__() are discouraged in
Python because they bypass the language's abstraction layer and
reduce code readability. Using len() provides the same functionality
while adhering to Python community standards and making the code more
familiar to Python developers.
Signed-off-by: Wander Lairson Costa <wander@redhat.com>
---
tools/verification/rvgen/rvgen/automata.py | 2 +-
tools/verification/rvgen/rvgen/dot2c.py | 16 ++++++++--------
2 files changed, 9 insertions(+), 9 deletions(-)
diff --git a/tools/verification/rvgen/rvgen/automata.py b/tools/verification/rvgen/rvgen/automata.py
index 3e24313a2eaec..ed02d0c69b410 100644
--- a/tools/verification/rvgen/rvgen/automata.py
+++ b/tools/verification/rvgen/rvgen/automata.py
@@ -42,7 +42,7 @@ class Automata:
raise AutomataError(f"not a dot file: {self.__dot_path}")
model_name = ntpath.splitext(basename)[0]
- if model_name.__len__() == 0:
+ if not model_name:
raise AutomataError(f"not a dot file: {self.__dot_path}")
return model_name
diff --git a/tools/verification/rvgen/rvgen/dot2c.py b/tools/verification/rvgen/rvgen/dot2c.py
index 78959d345c26e..0fb3617ad8ce9 100644
--- a/tools/verification/rvgen/rvgen/dot2c.py
+++ b/tools/verification/rvgen/rvgen/dot2c.py
@@ -86,14 +86,14 @@ class Dot2c(Automata):
def get_minimun_type(self):
min_type = "unsigned char"
- if self.states.__len__() > 255:
+ if len(self.states) > 255:
min_type = "unsigned short"
- if self.states.__len__() > 65535:
+ if len(self.states) > 65535:
min_type = "unsigned int"
- if self.states.__len__() > 1000000:
- raise AutomataError(f"Too many states: {self.states.__len__()}")
+ if len(self.states) > 1000000:
+ raise AutomataError(f"Too many states: {len(self.states)}")
return min_type
@@ -149,12 +149,12 @@ class Dot2c(Automata):
return buff
def __get_max_strlen_of_states(self):
- max_state_name = max(self.states, key = len).__len__()
- return max(max_state_name, self.invalid_state_str.__len__())
+ max_state_name = len(max(self.states, key=len))
+ return max(max_state_name, len(self.invalid_state_str))
def get_aut_init_function(self):
- nr_states = self.states.__len__()
- nr_events = self.events.__len__()
+ nr_states = len(self.states)
+ nr_events = len(self.events)
buff = []
maxlen = self.__get_max_strlen_of_states() + len(self.enum_suffix)
--
2.52.0
^ permalink raw reply related [flat|nested] 95+ messages in thread* Re: [PATCH 04/26] rv/rvgen: replace __len__() calls with len()
2026-01-19 20:45 ` [PATCH 04/26] rv/rvgen: replace __len__() calls with len() Wander Lairson Costa
@ 2026-01-20 7:41 ` Gabriele Monaco
2026-01-22 14:46 ` Nam Cao
1 sibling, 0 replies; 95+ messages in thread
From: Gabriele Monaco @ 2026-01-20 7:41 UTC (permalink / raw)
To: Wander Lairson Costa
Cc: Steven Rostedt, Nam Cao, open list,
open list:RUNTIME VERIFICATION (RV)
On Mon, 2026-01-19 at 17:45 -0300, Wander Lairson Costa wrote:
> Replace all direct calls to the __len__() dunder method with the
> idiomatic len() built-in function across the rvgen codebase. This
> change eliminates a Python anti-pattern where dunder methods are
> called directly instead of using their corresponding built-in
> functions.
>
> The changes affect nine instances across two files. In automata.py,
> the empty string check is further improved by using truthiness
> testing instead of explicit length comparison. In dot2c.py, all
> length checks in the get_minimun_type, __get_max_strlen_of_states,
> and get_aut_init_function methods now use the standard len()
> function. Additionally, spacing around keyword arguments has been
> corrected to follow PEP 8 guidelines.
>
> Direct calls to dunder methods like __len__() are discouraged in
> Python because they bypass the language's abstraction layer and
> reduce code readability. Using len() provides the same functionality
> while adhering to Python community standards and making the code more
> familiar to Python developers.
>
> Signed-off-by: Wander Lairson Costa <wander@redhat.com>
> ---
Totally needed.
Reviewed-by: Gabriele Monaco <gmonaco@redhat.com>
Thanks,
Gabriele
> tools/verification/rvgen/rvgen/automata.py | 2 +-
> tools/verification/rvgen/rvgen/dot2c.py | 16 ++++++++--------
> 2 files changed, 9 insertions(+), 9 deletions(-)
>
> diff --git a/tools/verification/rvgen/rvgen/automata.py
> b/tools/verification/rvgen/rvgen/automata.py
> index 3e24313a2eaec..ed02d0c69b410 100644
> --- a/tools/verification/rvgen/rvgen/automata.py
> +++ b/tools/verification/rvgen/rvgen/automata.py
> @@ -42,7 +42,7 @@ class Automata:
> raise AutomataError(f"not a dot file: {self.__dot_path}")
>
> model_name = ntpath.splitext(basename)[0]
> - if model_name.__len__() == 0:
> + if not model_name:
> raise AutomataError(f"not a dot file: {self.__dot_path}")
>
> return model_name
> diff --git a/tools/verification/rvgen/rvgen/dot2c.py
> b/tools/verification/rvgen/rvgen/dot2c.py
> index 78959d345c26e..0fb3617ad8ce9 100644
> --- a/tools/verification/rvgen/rvgen/dot2c.py
> +++ b/tools/verification/rvgen/rvgen/dot2c.py
> @@ -86,14 +86,14 @@ class Dot2c(Automata):
> def get_minimun_type(self):
> min_type = "unsigned char"
>
> - if self.states.__len__() > 255:
> + if len(self.states) > 255:
> min_type = "unsigned short"
>
> - if self.states.__len__() > 65535:
> + if len(self.states) > 65535:
> min_type = "unsigned int"
>
> - if self.states.__len__() > 1000000:
> - raise AutomataError(f"Too many states: {self.states.__len__()}")
> + if len(self.states) > 1000000:
> + raise AutomataError(f"Too many states: {len(self.states)}")
>
> return min_type
>
> @@ -149,12 +149,12 @@ class Dot2c(Automata):
> return buff
>
> def __get_max_strlen_of_states(self):
> - max_state_name = max(self.states, key = len).__len__()
> - return max(max_state_name, self.invalid_state_str.__len__())
> + max_state_name = len(max(self.states, key=len))
> + return max(max_state_name, len(self.invalid_state_str))
>
> def get_aut_init_function(self):
> - nr_states = self.states.__len__()
> - nr_events = self.events.__len__()
> + nr_states = len(self.states)
> + nr_events = len(self.events)
> buff = []
>
> maxlen = self.__get_max_strlen_of_states() + len(self.enum_suffix)
^ permalink raw reply [flat|nested] 95+ messages in thread* Re: [PATCH 04/26] rv/rvgen: replace __len__() calls with len()
2026-01-19 20:45 ` [PATCH 04/26] rv/rvgen: replace __len__() calls with len() Wander Lairson Costa
2026-01-20 7:41 ` Gabriele Monaco
@ 2026-01-22 14:46 ` Nam Cao
1 sibling, 0 replies; 95+ messages in thread
From: Nam Cao @ 2026-01-22 14:46 UTC (permalink / raw)
To: Wander Lairson Costa, Steven Rostedt, Gabriele Monaco,
Wander Lairson Costa, open list,
open list:RUNTIME VERIFICATION (RV)
Wander Lairson Costa <wander@redhat.com> writes:
> Replace all direct calls to the __len__() dunder method with the
> idiomatic len() built-in function across the rvgen codebase. This
> change eliminates a Python anti-pattern where dunder methods are
> called directly instead of using their corresponding built-in
> functions.
>
> The changes affect nine instances across two files. In automata.py,
> the empty string check is further improved by using truthiness
> testing instead of explicit length comparison. In dot2c.py, all
> length checks in the get_minimun_type, __get_max_strlen_of_states,
> and get_aut_init_function methods now use the standard len()
> function. Additionally, spacing around keyword arguments has been
> corrected to follow PEP 8 guidelines.
>
> Direct calls to dunder methods like __len__() are discouraged in
> Python because they bypass the language's abstraction layer and
> reduce code readability. Using len() provides the same functionality
> while adhering to Python community standards and making the code more
> familiar to Python developers.
>
> Signed-off-by: Wander Lairson Costa <wander@redhat.com>
Reviewed-by: Nam Cao <namcao@linutronix.de>
^ permalink raw reply [flat|nested] 95+ messages in thread
* [PATCH 05/26] rv/rvgen: remove unnecessary semicolons
2026-01-19 20:45 [PATCH 00/26] rv/rvgen: Robustness, modernization, and fixes Wander Lairson Costa
` (3 preceding siblings ...)
2026-01-19 20:45 ` [PATCH 04/26] rv/rvgen: replace __len__() calls with len() Wander Lairson Costa
@ 2026-01-19 20:45 ` Wander Lairson Costa
2026-01-20 7:42 ` Gabriele Monaco
2026-01-22 14:47 ` Nam Cao
2026-01-19 20:45 ` [PATCH 06/26] rv/rvgen: use context managers for file operations Wander Lairson Costa
` (21 subsequent siblings)
26 siblings, 2 replies; 95+ messages in thread
From: Wander Lairson Costa @ 2026-01-19 20:45 UTC (permalink / raw)
To: Steven Rostedt, Gabriele Monaco, Nam Cao, Wander Lairson Costa,
open list, open list:RUNTIME VERIFICATION (RV)
Remove unnecessary semicolons from Python code in the rvgen tool.
Python does not require semicolons to terminate statements, and
their presence goes against PEP 8 style guidelines. These semicolons
were likely added out of habit from C-style languages.
The changes affect four instances across two files. In dot2c.py, one
semicolon is removed from a boolean assignment. In dot2k.py, three
semicolons are removed from string append operations that build
generated C code. Note that the semicolons inside the string literals
themselves are correctly preserved as they are part of the C code
being generated, not Python syntax.
This cleanup improves consistency with Python coding standards and
aligns with the recent improvements to remove other Python
anti-patterns from the codebase.
Signed-off-by: Wander Lairson Costa <wander@redhat.com>
---
tools/verification/rvgen/rvgen/dot2c.py | 2 +-
tools/verification/rvgen/rvgen/dot2k.py | 6 +++---
2 files changed, 4 insertions(+), 4 deletions(-)
diff --git a/tools/verification/rvgen/rvgen/dot2c.py b/tools/verification/rvgen/rvgen/dot2c.py
index 0fb3617ad8ce9..b9a2c009a9246 100644
--- a/tools/verification/rvgen/rvgen/dot2c.py
+++ b/tools/verification/rvgen/rvgen/dot2c.py
@@ -120,7 +120,7 @@ class Dot2c(Automata):
for entry in buff:
if first:
string = string + "\t\t\"" + entry
- first = False;
+ first = False
else:
string = string + "\",\n\t\t\"" + entry
string = string + "\""
diff --git a/tools/verification/rvgen/rvgen/dot2k.py b/tools/verification/rvgen/rvgen/dot2k.py
index 1c0d0235bdf62..291385adb2c20 100644
--- a/tools/verification/rvgen/rvgen/dot2k.py
+++ b/tools/verification/rvgen/rvgen/dot2k.py
@@ -37,10 +37,10 @@ class dot2k(Monitor, Dot2c):
buff.append("\t/* XXX: validate that this event is only valid in the initial state */")
handle = "handle_start_run_event"
if self.monitor_type == "per_task":
- buff.append("\tstruct task_struct *p = /* XXX: how do I get p? */;");
- buff.append(f"\tda_{handle}_{self.name}(p, {event}{self.enum_suffix});");
+ buff.append("\tstruct task_struct *p = /* XXX: how do I get p? */;")
+ buff.append(f"\tda_{handle}_{self.name}(p, {event}{self.enum_suffix});")
else:
- buff.append(f"\tda_{handle}_{self.name}({event}{self.enum_suffix});");
+ buff.append(f"\tda_{handle}_{self.name}({event}{self.enum_suffix});")
buff.append("}")
buff.append("")
return '\n'.join(buff)
--
2.52.0
^ permalink raw reply related [flat|nested] 95+ messages in thread* Re: [PATCH 05/26] rv/rvgen: remove unnecessary semicolons
2026-01-19 20:45 ` [PATCH 05/26] rv/rvgen: remove unnecessary semicolons Wander Lairson Costa
@ 2026-01-20 7:42 ` Gabriele Monaco
2026-01-22 14:47 ` Nam Cao
1 sibling, 0 replies; 95+ messages in thread
From: Gabriele Monaco @ 2026-01-20 7:42 UTC (permalink / raw)
To: Wander Lairson Costa, Steven Rostedt, Nam Cao, open list,
open list:RUNTIME VERIFICATION (RV)
On Mon, 2026-01-19 at 17:45 -0300, Wander Lairson Costa wrote:
> Remove unnecessary semicolons from Python code in the rvgen tool.
> Python does not require semicolons to terminate statements, and
> their presence goes against PEP 8 style guidelines. These semicolons
> were likely added out of habit from C-style languages.
>
> The changes affect four instances across two files. In dot2c.py, one
> semicolon is removed from a boolean assignment. In dot2k.py, three
> semicolons are removed from string append operations that build
> generated C code. Note that the semicolons inside the string literals
> themselves are correctly preserved as they are part of the C code
> being generated, not Python syntax.
>
> This cleanup improves consistency with Python coding standards and
> aligns with the recent improvements to remove other Python
> anti-patterns from the codebase.
>
> Signed-off-by: Wander Lairson Costa <wander@redhat.com>
Muscle memory is hard to control. Thanks!
Reviewed-by: Gabriele Monaco <gmonaco@redhat.com>
> ---
> tools/verification/rvgen/rvgen/dot2c.py | 2 +-
> tools/verification/rvgen/rvgen/dot2k.py | 6 +++---
> 2 files changed, 4 insertions(+), 4 deletions(-)
>
> diff --git a/tools/verification/rvgen/rvgen/dot2c.py
> b/tools/verification/rvgen/rvgen/dot2c.py
> index 0fb3617ad8ce9..b9a2c009a9246 100644
> --- a/tools/verification/rvgen/rvgen/dot2c.py
> +++ b/tools/verification/rvgen/rvgen/dot2c.py
> @@ -120,7 +120,7 @@ class Dot2c(Automata):
> for entry in buff:
> if first:
> string = string + "\t\t\"" + entry
> - first = False;
> + first = False
> else:
> string = string + "\",\n\t\t\"" + entry
> string = string + "\""
> diff --git a/tools/verification/rvgen/rvgen/dot2k.py
> b/tools/verification/rvgen/rvgen/dot2k.py
> index 1c0d0235bdf62..291385adb2c20 100644
> --- a/tools/verification/rvgen/rvgen/dot2k.py
> +++ b/tools/verification/rvgen/rvgen/dot2k.py
> @@ -37,10 +37,10 @@ class dot2k(Monitor, Dot2c):
> buff.append("\t/* XXX: validate that this event is only valid
> in the initial state */")
> handle = "handle_start_run_event"
> if self.monitor_type == "per_task":
> - buff.append("\tstruct task_struct *p = /* XXX: how do I get
> p? */;");
> - buff.append(f"\tda_{handle}_{self.name}(p,
> {event}{self.enum_suffix});");
> + buff.append("\tstruct task_struct *p = /* XXX: how do I get
> p? */;")
> + buff.append(f"\tda_{handle}_{self.name}(p,
> {event}{self.enum_suffix});")
> else:
> -
> buff.append(f"\tda_{handle}_{self.name}({event}{self.enum_suffix});");
> +
> buff.append(f"\tda_{handle}_{self.name}({event}{self.enum_suffix});")
> buff.append("}")
> buff.append("")
> return '\n'.join(buff)
^ permalink raw reply [flat|nested] 95+ messages in thread* Re: [PATCH 05/26] rv/rvgen: remove unnecessary semicolons
2026-01-19 20:45 ` [PATCH 05/26] rv/rvgen: remove unnecessary semicolons Wander Lairson Costa
2026-01-20 7:42 ` Gabriele Monaco
@ 2026-01-22 14:47 ` Nam Cao
1 sibling, 0 replies; 95+ messages in thread
From: Nam Cao @ 2026-01-22 14:47 UTC (permalink / raw)
To: Wander Lairson Costa, Steven Rostedt, Gabriele Monaco,
Wander Lairson Costa, open list,
open list:RUNTIME VERIFICATION (RV)
Wander Lairson Costa <wander@redhat.com> writes:
> Remove unnecessary semicolons from Python code in the rvgen tool.
> Python does not require semicolons to terminate statements, and
> their presence goes against PEP 8 style guidelines. These semicolons
> were likely added out of habit from C-style languages.
>
> The changes affect four instances across two files. In dot2c.py, one
> semicolon is removed from a boolean assignment. In dot2k.py, three
> semicolons are removed from string append operations that build
> generated C code. Note that the semicolons inside the string literals
> themselves are correctly preserved as they are part of the C code
> being generated, not Python syntax.
>
> This cleanup improves consistency with Python coding standards and
> aligns with the recent improvements to remove other Python
> anti-patterns from the codebase.
>
> Signed-off-by: Wander Lairson Costa <wander@redhat.com>
Reviewed-by: Nam Cao <namcao@linutronix.de>
^ permalink raw reply [flat|nested] 95+ messages in thread
* [PATCH 06/26] rv/rvgen: use context managers for file operations
2026-01-19 20:45 [PATCH 00/26] rv/rvgen: Robustness, modernization, and fixes Wander Lairson Costa
` (4 preceding siblings ...)
2026-01-19 20:45 ` [PATCH 05/26] rv/rvgen: remove unnecessary semicolons Wander Lairson Costa
@ 2026-01-19 20:45 ` Wander Lairson Costa
2026-01-20 7:44 ` Gabriele Monaco
2026-01-22 14:50 ` Nam Cao
2026-01-19 20:45 ` [PATCH 07/26] rv/rvgen: replace __contains__() with in operator Wander Lairson Costa
` (20 subsequent siblings)
26 siblings, 2 replies; 95+ messages in thread
From: Wander Lairson Costa @ 2026-01-19 20:45 UTC (permalink / raw)
To: Steven Rostedt, Gabriele Monaco, Nam Cao, Wander Lairson Costa,
open list, open list:RUNTIME VERIFICATION (RV)
Replace manual file open and close operations with context managers
throughout the rvgen codebase. The previous implementation used
explicit open() and close() calls, which could lead to resource leaks
if exceptions occurred between opening and closing the file handles.
This change affects three file operations: reading DOT specification
files in the automata parser, reading template files in the generator
base class, and writing generated monitor files. All now use the with
statement to ensure proper resource cleanup even in error conditions.
Context managers provide automatic cleanup through the with statement,
which guarantees that file handles are closed when the with block
exits regardless of whether an exception occurred. This follows PEP
343 recommendations and is the standard Python idiom for resource
management. The change also reduces code verbosity while improving
safety and maintainability.
Signed-off-by: Wander Lairson Costa <wander@redhat.com>
---
tools/verification/rvgen/rvgen/automata.py | 6 ++----
tools/verification/rvgen/rvgen/generator.py | 12 ++++--------
2 files changed, 6 insertions(+), 12 deletions(-)
diff --git a/tools/verification/rvgen/rvgen/automata.py b/tools/verification/rvgen/rvgen/automata.py
index ed02d0c69b410..70ff98abea751 100644
--- a/tools/verification/rvgen/rvgen/automata.py
+++ b/tools/verification/rvgen/rvgen/automata.py
@@ -51,13 +51,11 @@ class Automata:
cursor = 0
dot_lines = []
try:
- dot_file = open(self.__dot_path)
+ with open(self.__dot_path) as dot_file:
+ dot_lines = dot_file.read().splitlines()
except OSError as exc:
raise AutomataError(f"Cannot open the file: {self.__dot_path}") from exc
- dot_lines = dot_file.read().splitlines()
- dot_file.close()
-
# checking the first line:
line = dot_lines[cursor].split()
diff --git a/tools/verification/rvgen/rvgen/generator.py b/tools/verification/rvgen/rvgen/generator.py
index 6d16fb68798a7..ee75e111feef1 100644
--- a/tools/verification/rvgen/rvgen/generator.py
+++ b/tools/verification/rvgen/rvgen/generator.py
@@ -51,11 +51,8 @@ class RVGenerator:
raise FileNotFoundError("Could not find the rv directory, do you have the kernel source installed?")
def _read_file(self, path):
- fd = open(path, 'r')
-
- content = fd.read()
-
- fd.close()
+ with open(path, 'r') as fd:
+ content = fd.read()
return content
def _read_template_file(self, file):
@@ -199,9 +196,8 @@ obj-$(CONFIG_RV_MON_{name_up}) += monitors/{name}/{name}.o
return
def __write_file(self, file_name, content):
- file = open(file_name, 'w')
- file.write(content)
- file.close()
+ with open(file_name, 'w') as file:
+ file.write(content)
def _create_file(self, file_name, content):
path = f"{self.name}/{file_name}"
--
2.52.0
^ permalink raw reply related [flat|nested] 95+ messages in thread* Re: [PATCH 06/26] rv/rvgen: use context managers for file operations
2026-01-19 20:45 ` [PATCH 06/26] rv/rvgen: use context managers for file operations Wander Lairson Costa
@ 2026-01-20 7:44 ` Gabriele Monaco
2026-01-22 14:50 ` Nam Cao
1 sibling, 0 replies; 95+ messages in thread
From: Gabriele Monaco @ 2026-01-20 7:44 UTC (permalink / raw)
To: Wander Lairson Costa, Steven Rostedt, Nam Cao, open list,
open list:RUNTIME VERIFICATION (RV)
On Mon, 2026-01-19 at 17:45 -0300, Wander Lairson Costa wrote:
> Replace manual file open and close operations with context managers
> throughout the rvgen codebase. The previous implementation used
> explicit open() and close() calls, which could lead to resource leaks
> if exceptions occurred between opening and closing the file handles.
>
> This change affects three file operations: reading DOT specification
> files in the automata parser, reading template files in the generator
> base class, and writing generated monitor files. All now use the with
> statement to ensure proper resource cleanup even in error conditions.
>
> Context managers provide automatic cleanup through the with statement,
> which guarantees that file handles are closed when the with block
> exits regardless of whether an exception occurred. This follows PEP
> 343 recommendations and is the standard Python idiom for resource
> management. The change also reduces code verbosity while improving
> safety and maintainability.
>
> Signed-off-by: Wander Lairson Costa <wander@redhat.com>
Looks reasonable, thanks!
Reviewed-by: Gabriele Monaco <gmonaco@redhat.com>
> ---
> tools/verification/rvgen/rvgen/automata.py | 6 ++----
> tools/verification/rvgen/rvgen/generator.py | 12 ++++--------
> 2 files changed, 6 insertions(+), 12 deletions(-)
>
> diff --git a/tools/verification/rvgen/rvgen/automata.py
> b/tools/verification/rvgen/rvgen/automata.py
> index ed02d0c69b410..70ff98abea751 100644
> --- a/tools/verification/rvgen/rvgen/automata.py
> +++ b/tools/verification/rvgen/rvgen/automata.py
> @@ -51,13 +51,11 @@ class Automata:
> cursor = 0
> dot_lines = []
> try:
> - dot_file = open(self.__dot_path)
> + with open(self.__dot_path) as dot_file:
> + dot_lines = dot_file.read().splitlines()
> except OSError as exc:
> raise AutomataError(f"Cannot open the file: {self.__dot_path}")
> from exc
>
> - dot_lines = dot_file.read().splitlines()
> - dot_file.close()
> -
> # checking the first line:
> line = dot_lines[cursor].split()
>
> diff --git a/tools/verification/rvgen/rvgen/generator.py
> b/tools/verification/rvgen/rvgen/generator.py
> index 6d16fb68798a7..ee75e111feef1 100644
> --- a/tools/verification/rvgen/rvgen/generator.py
> +++ b/tools/verification/rvgen/rvgen/generator.py
> @@ -51,11 +51,8 @@ class RVGenerator:
> raise FileNotFoundError("Could not find the rv directory, do you have
> the kernel source installed?")
>
> def _read_file(self, path):
> - fd = open(path, 'r')
> -
> - content = fd.read()
> -
> - fd.close()
> + with open(path, 'r') as fd:
> + content = fd.read()
> return content
>
> def _read_template_file(self, file):
> @@ -199,9 +196,8 @@ obj-$(CONFIG_RV_MON_{name_up}) += monitors/{name}/{name}.o
> return
>
> def __write_file(self, file_name, content):
> - file = open(file_name, 'w')
> - file.write(content)
> - file.close()
> + with open(file_name, 'w') as file:
> + file.write(content)
>
> def _create_file(self, file_name, content):
> path = f"{self.name}/{file_name}"
^ permalink raw reply [flat|nested] 95+ messages in thread* Re: [PATCH 06/26] rv/rvgen: use context managers for file operations
2026-01-19 20:45 ` [PATCH 06/26] rv/rvgen: use context managers for file operations Wander Lairson Costa
2026-01-20 7:44 ` Gabriele Monaco
@ 2026-01-22 14:50 ` Nam Cao
1 sibling, 0 replies; 95+ messages in thread
From: Nam Cao @ 2026-01-22 14:50 UTC (permalink / raw)
To: Wander Lairson Costa, Steven Rostedt, Gabriele Monaco,
Wander Lairson Costa, open list,
open list:RUNTIME VERIFICATION (RV)
Wander Lairson Costa <wander@redhat.com> writes:
> Replace manual file open and close operations with context managers
> throughout the rvgen codebase. The previous implementation used
> explicit open() and close() calls, which could lead to resource leaks
> if exceptions occurred between opening and closing the file handles.
>
> This change affects three file operations: reading DOT specification
> files in the automata parser, reading template files in the generator
> base class, and writing generated monitor files. All now use the with
> statement to ensure proper resource cleanup even in error conditions.
>
> Context managers provide automatic cleanup through the with statement,
> which guarantees that file handles are closed when the with block
> exits regardless of whether an exception occurred. This follows PEP
> 343 recommendations and is the standard Python idiom for resource
> management. The change also reduces code verbosity while improving
> safety and maintainability.
>
> Signed-off-by: Wander Lairson Costa <wander@redhat.com>
Reviewed-by: Nam Cao <namcao@linutronix.de>
^ permalink raw reply [flat|nested] 95+ messages in thread
* [PATCH 07/26] rv/rvgen: replace __contains__() with in operator
2026-01-19 20:45 [PATCH 00/26] rv/rvgen: Robustness, modernization, and fixes Wander Lairson Costa
` (5 preceding siblings ...)
2026-01-19 20:45 ` [PATCH 06/26] rv/rvgen: use context managers for file operations Wander Lairson Costa
@ 2026-01-19 20:45 ` Wander Lairson Costa
2026-01-20 7:45 ` Gabriele Monaco
2026-01-22 14:51 ` Nam Cao
2026-01-19 20:45 ` [PATCH 08/26] rv/rvgen: simplify boolean comparison Wander Lairson Costa
` (19 subsequent siblings)
26 siblings, 2 replies; 95+ messages in thread
From: Wander Lairson Costa @ 2026-01-19 20:45 UTC (permalink / raw)
To: Steven Rostedt, Gabriele Monaco, Nam Cao, Wander Lairson Costa,
open list, open list:RUNTIME VERIFICATION (RV)
Replace the direct call to the __contains__() dunder method with the
idiomatic in operator in the dot2c module. The previous implementation
explicitly called the __contains__() method to check for membership in
the final_states collection, which is not the recommended Python
style.
Python provides the in operator as the proper way to test membership,
which internally calls the __contains__() method. Directly calling
dunder methods bypasses Python's abstraction layer and reduces code
readability. Using the in operator makes the code more natural and
familiar to Python developers while maintaining identical functionality.
Signed-off-by: Wander Lairson Costa <wander@redhat.com>
---
tools/verification/rvgen/rvgen/dot2c.py | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/tools/verification/rvgen/rvgen/dot2c.py b/tools/verification/rvgen/rvgen/dot2c.py
index b9a2c009a9246..c97bb9466af6d 100644
--- a/tools/verification/rvgen/rvgen/dot2c.py
+++ b/tools/verification/rvgen/rvgen/dot2c.py
@@ -207,7 +207,7 @@ class Dot2c(Automata):
else:
first = False
- if self.final_states.__contains__(state):
+ if state in self.final_states:
line = line + '1'
else:
line = line + '0'
--
2.52.0
^ permalink raw reply related [flat|nested] 95+ messages in thread* Re: [PATCH 07/26] rv/rvgen: replace __contains__() with in operator
2026-01-19 20:45 ` [PATCH 07/26] rv/rvgen: replace __contains__() with in operator Wander Lairson Costa
@ 2026-01-20 7:45 ` Gabriele Monaco
2026-01-22 14:51 ` Nam Cao
1 sibling, 0 replies; 95+ messages in thread
From: Gabriele Monaco @ 2026-01-20 7:45 UTC (permalink / raw)
To: Wander Lairson Costa, Steven Rostedt, Nam Cao, open list,
open list:RUNTIME VERIFICATION (RV)
On Mon, 2026-01-19 at 17:45 -0300, Wander Lairson Costa wrote:
> Replace the direct call to the __contains__() dunder method with the
> idiomatic in operator in the dot2c module. The previous implementation
> explicitly called the __contains__() method to check for membership in
> the final_states collection, which is not the recommended Python
> style.
>
> Python provides the in operator as the proper way to test membership,
> which internally calls the __contains__() method. Directly calling
> dunder methods bypasses Python's abstraction layer and reduces code
> readability. Using the in operator makes the code more natural and
> familiar to Python developers while maintaining identical functionality.
>
> Signed-off-by: Wander Lairson Costa <wander@redhat.com>
Neat, thanks!
Reviewed-by: Gabriele Monaco <gmonaco@redhat.com>
> ---
> tools/verification/rvgen/rvgen/dot2c.py | 2 +-
> 1 file changed, 1 insertion(+), 1 deletion(-)
>
> diff --git a/tools/verification/rvgen/rvgen/dot2c.py
> b/tools/verification/rvgen/rvgen/dot2c.py
> index b9a2c009a9246..c97bb9466af6d 100644
> --- a/tools/verification/rvgen/rvgen/dot2c.py
> +++ b/tools/verification/rvgen/rvgen/dot2c.py
> @@ -207,7 +207,7 @@ class Dot2c(Automata):
> else:
> first = False
>
> - if self.final_states.__contains__(state):
> + if state in self.final_states:
> line = line + '1'
> else:
> line = line + '0'
^ permalink raw reply [flat|nested] 95+ messages in thread
* Re: [PATCH 07/26] rv/rvgen: replace __contains__() with in operator
2026-01-19 20:45 ` [PATCH 07/26] rv/rvgen: replace __contains__() with in operator Wander Lairson Costa
2026-01-20 7:45 ` Gabriele Monaco
@ 2026-01-22 14:51 ` Nam Cao
1 sibling, 0 replies; 95+ messages in thread
From: Nam Cao @ 2026-01-22 14:51 UTC (permalink / raw)
To: Wander Lairson Costa, Steven Rostedt, Gabriele Monaco,
Wander Lairson Costa, open list,
open list:RUNTIME VERIFICATION (RV)
Wander Lairson Costa <wander@redhat.com> writes:
> Replace the direct call to the __contains__() dunder method with the
> idiomatic in operator in the dot2c module. The previous implementation
> explicitly called the __contains__() method to check for membership in
> the final_states collection, which is not the recommended Python
> style.
>
> Python provides the in operator as the proper way to test membership,
> which internally calls the __contains__() method. Directly calling
> dunder methods bypasses Python's abstraction layer and reduces code
> readability. Using the in operator makes the code more natural and
> familiar to Python developers while maintaining identical functionality.
>
> Signed-off-by: Wander Lairson Costa <wander@redhat.com>
Reviewed-by: Nam Cao <namcao@linutronix.de>
^ permalink raw reply [flat|nested] 95+ messages in thread
* [PATCH 08/26] rv/rvgen: simplify boolean comparison
2026-01-19 20:45 [PATCH 00/26] rv/rvgen: Robustness, modernization, and fixes Wander Lairson Costa
` (6 preceding siblings ...)
2026-01-19 20:45 ` [PATCH 07/26] rv/rvgen: replace __contains__() with in operator Wander Lairson Costa
@ 2026-01-19 20:45 ` Wander Lairson Costa
2026-01-20 7:48 ` Gabriele Monaco
2026-01-22 14:51 ` Nam Cao
2026-01-19 20:45 ` [PATCH 09/26] rv/rvgen: replace inline NotImplemented with decorator Wander Lairson Costa
` (18 subsequent siblings)
26 siblings, 2 replies; 95+ messages in thread
From: Wander Lairson Costa @ 2026-01-19 20:45 UTC (permalink / raw)
To: Steven Rostedt, Gabriele Monaco, Nam Cao, Wander Lairson Costa,
open list, open list:RUNTIME VERIFICATION (RV)
Replace explicit boolean comparison with truthiness test in the dot2c
module. The previous implementation used the redundant pattern of
comparing a boolean variable directly to False, which is not idiomatic
Python and adds unnecessary verbosity to the code.
Python's truthiness allows for more concise and readable boolean
checks. The expression "if not first" is clearer and more Pythonic
than "if first == False" while maintaining identical semantics. This
pattern is preferred in PEP 8 and is the standard approach in the
Python community.
This change continues the ongoing code quality improvements to align
the codebase with modern Python best practices.
Signed-off-by: Wander Lairson Costa <wander@redhat.com>
---
tools/verification/rvgen/rvgen/dot2c.py | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/tools/verification/rvgen/rvgen/dot2c.py b/tools/verification/rvgen/rvgen/dot2c.py
index c97bb9466af6d..fa9e9ae16640f 100644
--- a/tools/verification/rvgen/rvgen/dot2c.py
+++ b/tools/verification/rvgen/rvgen/dot2c.py
@@ -202,7 +202,7 @@ class Dot2c(Automata):
line = ""
first = True
for state in self.states:
- if first == False:
+ if not first:
line = line + ', '
else:
first = False
--
2.52.0
^ permalink raw reply related [flat|nested] 95+ messages in thread* Re: [PATCH 08/26] rv/rvgen: simplify boolean comparison
2026-01-19 20:45 ` [PATCH 08/26] rv/rvgen: simplify boolean comparison Wander Lairson Costa
@ 2026-01-20 7:48 ` Gabriele Monaco
2026-01-22 14:51 ` Nam Cao
1 sibling, 0 replies; 95+ messages in thread
From: Gabriele Monaco @ 2026-01-20 7:48 UTC (permalink / raw)
To: Wander Lairson Costa
Cc: Steven Rostedt, Nam Cao, open list,
open list:RUNTIME VERIFICATION (RV)
On Mon, 2026-01-19 at 17:45 -0300, Wander Lairson Costa wrote:
> Replace explicit boolean comparison with truthiness test in the dot2c
> module. The previous implementation used the redundant pattern of
> comparing a boolean variable directly to False, which is not idiomatic
> Python and adds unnecessary verbosity to the code.
>
> Python's truthiness allows for more concise and readable boolean
> checks. The expression "if not first" is clearer and more Pythonic
> than "if first == False" while maintaining identical semantics. This
> pattern is preferred in PEP 8 and is the standard approach in the
> Python community.
>
> This change continues the ongoing code quality improvements to align
> the codebase with modern Python best practices.
>
> Signed-off-by: Wander Lairson Costa <wander@redhat.com>
I'm starting to wonder if those simple cleanup patches with a tiny change and 3
paragraph of commit message aren't a bit too noisy. We may put at least the
simple ones together.
Other than that:
Reviewed-by: Gabriele Monaco <gmonaco@redhat.com>
Thanks,
Gabriele
> ---
> tools/verification/rvgen/rvgen/dot2c.py | 2 +-
> 1 file changed, 1 insertion(+), 1 deletion(-)
>
> diff --git a/tools/verification/rvgen/rvgen/dot2c.py
> b/tools/verification/rvgen/rvgen/dot2c.py
> index c97bb9466af6d..fa9e9ae16640f 100644
> --- a/tools/verification/rvgen/rvgen/dot2c.py
> +++ b/tools/verification/rvgen/rvgen/dot2c.py
> @@ -202,7 +202,7 @@ class Dot2c(Automata):
> line = ""
> first = True
> for state in self.states:
> - if first == False:
> + if not first:
> line = line + ', '
> else:
> first = False
^ permalink raw reply [flat|nested] 95+ messages in thread
* Re: [PATCH 08/26] rv/rvgen: simplify boolean comparison
2026-01-19 20:45 ` [PATCH 08/26] rv/rvgen: simplify boolean comparison Wander Lairson Costa
2026-01-20 7:48 ` Gabriele Monaco
@ 2026-01-22 14:51 ` Nam Cao
1 sibling, 0 replies; 95+ messages in thread
From: Nam Cao @ 2026-01-22 14:51 UTC (permalink / raw)
To: Wander Lairson Costa, Steven Rostedt, Gabriele Monaco,
Wander Lairson Costa, open list,
open list:RUNTIME VERIFICATION (RV)
Wander Lairson Costa <wander@redhat.com> writes:
> Replace explicit boolean comparison with truthiness test in the dot2c
> module. The previous implementation used the redundant pattern of
> comparing a boolean variable directly to False, which is not idiomatic
> Python and adds unnecessary verbosity to the code.
>
> Python's truthiness allows for more concise and readable boolean
> checks. The expression "if not first" is clearer and more Pythonic
> than "if first == False" while maintaining identical semantics. This
> pattern is preferred in PEP 8 and is the standard approach in the
> Python community.
>
> This change continues the ongoing code quality improvements to align
> the codebase with modern Python best practices.
>
> Signed-off-by: Wander Lairson Costa <wander@redhat.com>
Reviewed-by: Nam Cao <namcao@linutronix.de>
^ permalink raw reply [flat|nested] 95+ messages in thread
* [PATCH 09/26] rv/rvgen: replace inline NotImplemented with decorator
2026-01-19 20:45 [PATCH 00/26] rv/rvgen: Robustness, modernization, and fixes Wander Lairson Costa
` (7 preceding siblings ...)
2026-01-19 20:45 ` [PATCH 08/26] rv/rvgen: simplify boolean comparison Wander Lairson Costa
@ 2026-01-19 20:45 ` Wander Lairson Costa
2026-01-21 13:43 ` Gabriele Monaco
2026-01-22 14:57 ` Nam Cao
2026-01-19 20:45 ` [PATCH 10/26] rv/rvgen: fix typos in automata docstring and comments Wander Lairson Costa
` (17 subsequent siblings)
26 siblings, 2 replies; 95+ messages in thread
From: Wander Lairson Costa @ 2026-01-19 20:45 UTC (permalink / raw)
To: Steven Rostedt, Gabriele Monaco, Nam Cao, Wander Lairson Costa,
open list, open list:RUNTIME VERIFICATION (RV)
Replace inline NotImplementedError raises with a dedicated decorator in
the ltl2ba module. The previous implementation used explicit raise
statements inside abstract method bodies for BinaryOp and UnaryOp
classes, which required maintaining identical boilerplate across seven
different methods that need to be overridden by subclasses.
All stub methods in generator.py have been converted from returning
strings to using the decorator with ellipsis function bodies, which
is the recommended Python style for marking incomplete interface
methods. This ensures that any attempt to use unimplemented
functionality fails fast with a clear exception rather than silently
propagating string values through the code.
The new @not_implemented decorator consolidates this pattern into a
single reusable definition that clearly marks abstract methods while
reducing code duplication. The decorator creates a wrapper that raises
NotImplementedError with the function name, providing the same runtime
behavior with improved maintainability. Method bodies now use the
ellipsis literal instead of pass statements, which is the preferred
Python convention for stub methods according to PEP 8.
Signed-off-by: Wander Lairson Costa <wander@redhat.com>
---
tools/verification/rvgen/rvgen/generator.py | 29 +++++++++--------
tools/verification/rvgen/rvgen/ltl2ba.py | 25 ++++++++------
tools/verification/rvgen/rvgen/utils.py | 36 +++++++++++++++++++++
3 files changed, 66 insertions(+), 24 deletions(-)
create mode 100644 tools/verification/rvgen/rvgen/utils.py
diff --git a/tools/verification/rvgen/rvgen/generator.py b/tools/verification/rvgen/rvgen/generator.py
index ee75e111feef1..fc9be5f6aaa1f 100644
--- a/tools/verification/rvgen/rvgen/generator.py
+++ b/tools/verification/rvgen/rvgen/generator.py
@@ -7,6 +7,7 @@
import platform
import os
+from .utils import not_implemented
class RVGenerator:
@@ -73,14 +74,14 @@ class RVGenerator:
return f"#include <monitors/{self.parent}/{self.parent}.h>\n"
return ""
- def fill_tracepoint_handlers_skel(self):
- return "NotImplemented"
+ @not_implemented
+ def fill_tracepoint_handlers_skel(self): ...
- def fill_tracepoint_attach_probe(self):
- return "NotImplemented"
+ @not_implemented
+ def fill_tracepoint_attach_probe(self): ...
- def fill_tracepoint_detach_helper(self):
- return "NotImplemented"
+ @not_implemented
+ def fill_tracepoint_detach_helper(self): ...
def fill_main_c(self):
main_c = self.main_c
@@ -100,17 +101,17 @@ class RVGenerator:
return main_c
- def fill_model_h(self):
- return "NotImplemented"
+ @not_implemented
+ def fill_model_h(self): ...
- def fill_monitor_class_type(self):
- return "NotImplemented"
+ @not_implemented
+ def fill_monitor_class_type(self): ...
- def fill_monitor_class(self):
- return "NotImplemented"
+ @not_implemented
+ def fill_monitor_class(self): ...
- def fill_tracepoint_args_skel(self, tp_type):
- return "NotImplemented"
+ @not_implemented
+ def fill_tracepoint_args_skel(self, tp_type): ...
def fill_monitor_deps(self):
buff = []
diff --git a/tools/verification/rvgen/rvgen/ltl2ba.py b/tools/verification/rvgen/rvgen/ltl2ba.py
index f14e6760ac3db..9a3fb7c5f4f65 100644
--- a/tools/verification/rvgen/rvgen/ltl2ba.py
+++ b/tools/verification/rvgen/rvgen/ltl2ba.py
@@ -9,6 +9,7 @@
from ply.lex import lex
from ply.yacc import yacc
+from .utils import not_implemented
# Grammar:
# ltl ::= opd | ( ltl ) | ltl binop ltl | unop ltl
@@ -150,14 +151,14 @@ class BinaryOp:
yield from self.left
yield from self.right
- def normalize(self):
- raise NotImplementedError
+ @not_implemented
+ def normalize(self): ...
- def negate(self):
- raise NotImplementedError
+ @not_implemented
+ def negate(self): ...
- def _is_temporal(self):
- raise NotImplementedError
+ @not_implemented
+ def _is_temporal(self): ...
def is_temporal(self):
if self.left.op.is_temporal():
@@ -167,8 +168,9 @@ class BinaryOp:
return self._is_temporal()
@staticmethod
+ @not_implemented
def expand(n: ASTNode, node: GraphNode, node_set) -> set[GraphNode]:
- raise NotImplementedError
+ ...
class AndOp(BinaryOp):
op_str = '&&'
@@ -288,19 +290,22 @@ class UnaryOp:
def __hash__(self):
return hash(self.child)
+ @not_implemented
def normalize(self):
- raise NotImplementedError
+ ...
+ @not_implemented
def _is_temporal(self):
- raise NotImplementedError
+ ...
def is_temporal(self):
if self.child.op.is_temporal():
return True
return self._is_temporal()
+ @not_implemented
def negate(self):
- raise NotImplementedError
+ ...
class EventuallyOp(UnaryOp):
def __str__(self):
diff --git a/tools/verification/rvgen/rvgen/utils.py b/tools/verification/rvgen/rvgen/utils.py
new file mode 100644
index 0000000000000..e09c943693edf
--- /dev/null
+++ b/tools/verification/rvgen/rvgen/utils.py
@@ -0,0 +1,36 @@
+#!/usr/bin/env python3
+# SPDX-License-Identifier: GPL-2.0-only
+
+
+def not_implemented(func):
+ """
+ Decorator to mark functions as not yet implemented.
+
+ This decorator wraps a function and raises a NotImplementedError when the
+ function is called, rather than executing the function body. This is useful
+ for defining interface methods or placeholder functions that need to be
+ implemented later.
+
+ Args:
+ func: The function to be wrapped.
+
+ Returns:
+ A wrapper function that raises NotImplementedError when called.
+
+ Raises:
+ NotImplementedError: Always raised when the decorated function is called.
+ The exception includes the function name and any arguments that were
+ passed to the function.
+
+ Example:
+ @not_implemented
+ def future_feature(arg1, arg2):
+ pass
+
+ # Calling future_feature will raise:
+ # NotImplementedError('future_feature', arg1_value, arg2_value)
+ """
+ def inner(*args, **kwargs):
+ raise NotImplementedError(func.__name__, *args, **kwargs)
+
+ return inner
--
2.52.0
^ permalink raw reply related [flat|nested] 95+ messages in thread* Re: [PATCH 09/26] rv/rvgen: replace inline NotImplemented with decorator
2026-01-19 20:45 ` [PATCH 09/26] rv/rvgen: replace inline NotImplemented with decorator Wander Lairson Costa
@ 2026-01-21 13:43 ` Gabriele Monaco
2026-01-21 17:49 ` Wander Lairson Costa
2026-01-22 14:57 ` Nam Cao
1 sibling, 1 reply; 95+ messages in thread
From: Gabriele Monaco @ 2026-01-21 13:43 UTC (permalink / raw)
To: Wander Lairson Costa
Cc: Steven Rostedt, Nam Cao, open list,
open list:RUNTIME VERIFICATION (RV)
On Mon, 2026-01-19 at 17:45 -0300, Wander Lairson Costa wrote:
>
[...]
> + @not_implemented
> + def fill_tracepoint_detach_helper(self): ...
[...]
> + @not_implemented
> def normalize(self):
> - raise NotImplementedError
> + ...
Is there a reason why you didn't collapse it all on the same line here (like you
did above)?
@not_implemented
def normalize(self): ...
I see it's probably better to break the line if there is a type annotation
making the line longer. Did you keep it separated because you will add
annotation in a separate patch?
Anyway this is minor and the change is good, thanks.
Reviewed-by: Gabriele Monaco <gmonaco@redhat.com>
> diff --git a/tools/verification/rvgen/rvgen/utils.py
> b/tools/verification/rvgen/rvgen/utils.py
> new file mode 100644
> index 0000000000000..e09c943693edf
> --- /dev/null
> +++ b/tools/verification/rvgen/rvgen/utils.py
> @@ -0,0 +1,36 @@
> +#!/usr/bin/env python3
> +# SPDX-License-Identifier: GPL-2.0-only
> +
> +
> +def not_implemented(func):
> + """
> + Decorator to mark functions as not yet implemented.
> +
> + This decorator wraps a function and raises a NotImplementedError when the
> + function is called, rather than executing the function body. This is
> useful
> + for defining interface methods or placeholder functions that need to be
> + implemented later.
> +
> + Args:
> + func: The function to be wrapped.
> +
> + Returns:
> + A wrapper function that raises NotImplementedError when called.
> +
> + Raises:
> + NotImplementedError: Always raised when the decorated function is
> called.
> + The exception includes the function name and any arguments that
> were
> + passed to the function.
> +
> + Example:
> + @not_implemented
> + def future_feature(arg1, arg2):
> + pass
> +
> + # Calling future_feature will raise:
> + # NotImplementedError('future_feature', arg1_value, arg2_value)
> + """
> + def inner(*args, **kwargs):
> + raise NotImplementedError(func.__name__, *args, **kwargs)
> +
> + return inner
^ permalink raw reply [flat|nested] 95+ messages in thread* Re: [PATCH 09/26] rv/rvgen: replace inline NotImplemented with decorator
2026-01-21 13:43 ` Gabriele Monaco
@ 2026-01-21 17:49 ` Wander Lairson Costa
0 siblings, 0 replies; 95+ messages in thread
From: Wander Lairson Costa @ 2026-01-21 17:49 UTC (permalink / raw)
To: Gabriele Monaco
Cc: Steven Rostedt, Nam Cao, open list,
open list:RUNTIME VERIFICATION (RV)
On Wed, Jan 21, 2026 at 02:43:59PM +0100, Gabriele Monaco wrote:
> On Mon, 2026-01-19 at 17:45 -0300, Wander Lairson Costa wrote:
> >
> [...]
> > + @not_implemented
> > + def fill_tracepoint_detach_helper(self): ...
> [...]
> > + @not_implemented
> > def normalize(self):
> > - raise NotImplementedError
> > + ...
>
> Is there a reason why you didn't collapse it all on the same line here (like you
> did above)?
>
> @not_implemented
> def normalize(self): ...
>
> I see it's probably better to break the line if there is a type annotation
> making the line longer. Did you keep it separated because you will add
> annotation in a separate patch?
>
I did review the commit before sending to make this coeherent among the
changes. This might be have scaped my review.
> Anyway this is minor and the change is good, thanks.
>
> Reviewed-by: Gabriele Monaco <gmonaco@redhat.com>
>
> > diff --git a/tools/verification/rvgen/rvgen/utils.py
> > b/tools/verification/rvgen/rvgen/utils.py
> > new file mode 100644
> > index 0000000000000..e09c943693edf
> > --- /dev/null
> > +++ b/tools/verification/rvgen/rvgen/utils.py
> > @@ -0,0 +1,36 @@
> > +#!/usr/bin/env python3
> > +# SPDX-License-Identifier: GPL-2.0-only
> > +
> > +
> > +def not_implemented(func):
> > + """
> > + Decorator to mark functions as not yet implemented.
> > +
> > + This decorator wraps a function and raises a NotImplementedError when the
> > + function is called, rather than executing the function body. This is
> > useful
> > + for defining interface methods or placeholder functions that need to be
> > + implemented later.
> > +
> > + Args:
> > + func: The function to be wrapped.
> > +
> > + Returns:
> > + A wrapper function that raises NotImplementedError when called.
> > +
> > + Raises:
> > + NotImplementedError: Always raised when the decorated function is
> > called.
> > + The exception includes the function name and any arguments that
> > were
> > + passed to the function.
> > +
> > + Example:
> > + @not_implemented
> > + def future_feature(arg1, arg2):
> > + pass
> > +
> > + # Calling future_feature will raise:
> > + # NotImplementedError('future_feature', arg1_value, arg2_value)
> > + """
> > + def inner(*args, **kwargs):
> > + raise NotImplementedError(func.__name__, *args, **kwargs)
> > +
> > + return inner
>
^ permalink raw reply [flat|nested] 95+ messages in thread
* Re: [PATCH 09/26] rv/rvgen: replace inline NotImplemented with decorator
2026-01-19 20:45 ` [PATCH 09/26] rv/rvgen: replace inline NotImplemented with decorator Wander Lairson Costa
2026-01-21 13:43 ` Gabriele Monaco
@ 2026-01-22 14:57 ` Nam Cao
1 sibling, 0 replies; 95+ messages in thread
From: Nam Cao @ 2026-01-22 14:57 UTC (permalink / raw)
To: Wander Lairson Costa, Steven Rostedt, Gabriele Monaco,
Wander Lairson Costa, open list,
open list:RUNTIME VERIFICATION (RV)
Wander Lairson Costa <wander@redhat.com> writes:
> Replace inline NotImplementedError raises with a dedicated decorator in
> the ltl2ba module. The previous implementation used explicit raise
> statements inside abstract method bodies for BinaryOp and UnaryOp
> classes, which required maintaining identical boilerplate across seven
> different methods that need to be overridden by subclasses.
>
> All stub methods in generator.py have been converted from returning
> strings to using the decorator with ellipsis function bodies, which
> is the recommended Python style for marking incomplete interface
> methods. This ensures that any attempt to use unimplemented
> functionality fails fast with a clear exception rather than silently
> propagating string values through the code.
>
> The new @not_implemented decorator consolidates this pattern into a
> single reusable definition that clearly marks abstract methods while
> reducing code duplication. The decorator creates a wrapper that raises
> NotImplementedError with the function name, providing the same runtime
> behavior with improved maintainability. Method bodies now use the
> ellipsis literal instead of pass statements, which is the preferred
> Python convention for stub methods according to PEP 8.
>
> Signed-off-by: Wander Lairson Costa <wander@redhat.com>
Reviewed-by: Nam Cao <namcao@linutronix.de>
^ permalink raw reply [flat|nested] 95+ messages in thread
* [PATCH 10/26] rv/rvgen: fix typos in automata docstring and comments
2026-01-19 20:45 [PATCH 00/26] rv/rvgen: Robustness, modernization, and fixes Wander Lairson Costa
` (8 preceding siblings ...)
2026-01-19 20:45 ` [PATCH 09/26] rv/rvgen: replace inline NotImplemented with decorator Wander Lairson Costa
@ 2026-01-19 20:45 ` Wander Lairson Costa
2026-01-22 14:58 ` Nam Cao
2026-01-19 20:45 ` [PATCH 11/26] rv/rvgen: fix typo in generator module docstring Wander Lairson Costa
` (16 subsequent siblings)
26 siblings, 1 reply; 95+ messages in thread
From: Wander Lairson Costa @ 2026-01-19 20:45 UTC (permalink / raw)
To: Steven Rostedt, Gabriele Monaco, Nam Cao, Wander Lairson Costa,
open list, open list:RUNTIME VERIFICATION (RV)
Fix two typos in the Automata class documentation that have been
present since the initial implementation. The class docstring
incorrectly stated "part it" instead of "parses it" when
describing how the class processes DOT files. Additionally, a
comment describing transition labels contained the misspelling
"lables" instead of "labels".
Fix a typo in the comment describing the insertion of the initial
state into the states list: "bein og" should be "beginning of".
Signed-off-by: Wander Lairson Costa <wander@redhat.com>
---
tools/verification/rvgen/rvgen/automata.py | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/tools/verification/rvgen/rvgen/automata.py b/tools/verification/rvgen/rvgen/automata.py
index 70ff98abea751..c0c8d13030007 100644
--- a/tools/verification/rvgen/rvgen/automata.py
+++ b/tools/verification/rvgen/rvgen/automata.py
@@ -18,7 +18,7 @@ class AutomataError(OSError):
"""
class Automata:
- """Automata class: Reads a dot file and part it as an automata.
+ """Automata class: Reads a dot file and parses it as an automata.
Attributes:
dot_file: A dot file with an state_automaton definition.
@@ -113,7 +113,7 @@ class Automata:
states = sorted(set(states))
states.remove(initial_state)
- # Insert the initial state at the bein og the states
+ # Insert the initial state at the beginning of the states
states.insert(0, initial_state)
if not has_final_states:
@@ -134,7 +134,7 @@ class Automata:
line = self.__dot_lines[cursor].split()
event = line[-2].replace('"','')
- # when a transition has more than one lables, they are like this
+ # when a transition has more than one labels, they are like this
# "local_irq_enable\nhw_local_irq_enable_n"
# so split them.
--
2.52.0
^ permalink raw reply related [flat|nested] 95+ messages in thread* Re: [PATCH 10/26] rv/rvgen: fix typos in automata docstring and comments
2026-01-19 20:45 ` [PATCH 10/26] rv/rvgen: fix typos in automata docstring and comments Wander Lairson Costa
@ 2026-01-22 14:58 ` Nam Cao
0 siblings, 0 replies; 95+ messages in thread
From: Nam Cao @ 2026-01-22 14:58 UTC (permalink / raw)
To: Wander Lairson Costa, Steven Rostedt, Gabriele Monaco,
Wander Lairson Costa, open list,
open list:RUNTIME VERIFICATION (RV)
Wander Lairson Costa <wander@redhat.com> writes:
> Fix two typos in the Automata class documentation that have been
> present since the initial implementation. The class docstring
> incorrectly stated "part it" instead of "parses it" when
> describing how the class processes DOT files. Additionally, a
> comment describing transition labels contained the misspelling
> "lables" instead of "labels".
>
> Fix a typo in the comment describing the insertion of the initial
> state into the states list: "bein og" should be "beginning of".
>
> Signed-off-by: Wander Lairson Costa <wander@redhat.com>
Reviewed-by: Nam Cao <namcao@linutronix.de>
^ permalink raw reply [flat|nested] 95+ messages in thread
* [PATCH 11/26] rv/rvgen: fix typo in generator module docstring
2026-01-19 20:45 [PATCH 00/26] rv/rvgen: Robustness, modernization, and fixes Wander Lairson Costa
` (9 preceding siblings ...)
2026-01-19 20:45 ` [PATCH 10/26] rv/rvgen: fix typos in automata docstring and comments Wander Lairson Costa
@ 2026-01-19 20:45 ` Wander Lairson Costa
2026-01-20 7:51 ` Gabriele Monaco
2026-01-22 14:59 ` Nam Cao
2026-01-19 20:45 ` [PATCH 12/26] rv/rvgen: fix PEP 8 whitespace violations Wander Lairson Costa
` (15 subsequent siblings)
26 siblings, 2 replies; 95+ messages in thread
From: Wander Lairson Costa @ 2026-01-19 20:45 UTC (permalink / raw)
To: Steven Rostedt, Gabriele Monaco, Nam Cao, Wander Lairson Costa,
open list, open list:RUNTIME VERIFICATION (RV)
Fix typo in the module docstring: "Abtract" should be "Abstract".
Signed-off-by: Wander Lairson Costa <wander@redhat.com>
---
tools/verification/rvgen/rvgen/generator.py | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/tools/verification/rvgen/rvgen/generator.py b/tools/verification/rvgen/rvgen/generator.py
index fc9be5f6aaa1f..ea1fa0f5d818d 100644
--- a/tools/verification/rvgen/rvgen/generator.py
+++ b/tools/verification/rvgen/rvgen/generator.py
@@ -3,7 +3,7 @@
#
# Copyright (C) 2019-2022 Red Hat, Inc. Daniel Bristot de Oliveira <bristot@kernel.org>
#
-# Abtract class for generating kernel runtime verification monitors from specification file
+# Abstract class for generating kernel runtime verification monitors from specification file
import platform
import os
--
2.52.0
^ permalink raw reply related [flat|nested] 95+ messages in thread* Re: [PATCH 11/26] rv/rvgen: fix typo in generator module docstring
2026-01-19 20:45 ` [PATCH 11/26] rv/rvgen: fix typo in generator module docstring Wander Lairson Costa
@ 2026-01-20 7:51 ` Gabriele Monaco
2026-01-22 14:59 ` Nam Cao
1 sibling, 0 replies; 95+ messages in thread
From: Gabriele Monaco @ 2026-01-20 7:51 UTC (permalink / raw)
To: Wander Lairson Costa
Cc: Steven Rostedt, Nam Cao, open list,
open list:RUNTIME VERIFICATION (RV)
On Mon, 2026-01-19 at 17:45 -0300, Wander Lairson Costa wrote:
> Fix typo in the module docstring: "Abtract" should be "Abstract".
>
> Signed-off-by: Wander Lairson Costa <wander@redhat.com>
> ---
> tools/verification/rvgen/rvgen/generator.py | 2 +-
> 1 file changed, 1 insertion(+), 1 deletion(-)
>
> diff --git a/tools/verification/rvgen/rvgen/generator.py
> b/tools/verification/rvgen/rvgen/generator.py
> index fc9be5f6aaa1f..ea1fa0f5d818d 100644
> --- a/tools/verification/rvgen/rvgen/generator.py
> +++ b/tools/verification/rvgen/rvgen/generator.py
> @@ -3,7 +3,7 @@
> #
> # Copyright (C) 2019-2022 Red Hat, Inc. Daniel Bristot de Oliveira
> <bristot@kernel.org>
> #
> -# Abtract class for generating kernel runtime verification monitors from
> specification file
> +# Abstract class for generating kernel runtime verification monitors from
> specification file
>
> import platform
> import os
I believe you can fix typos together in the same patch (i.e. merge 10/26 and
11/26).
Reviewed-by: Gabriele Monaco <gmonaco@redhat.com>
to both.
Thanks,
Gabriele
^ permalink raw reply [flat|nested] 95+ messages in thread
* Re: [PATCH 11/26] rv/rvgen: fix typo in generator module docstring
2026-01-19 20:45 ` [PATCH 11/26] rv/rvgen: fix typo in generator module docstring Wander Lairson Costa
2026-01-20 7:51 ` Gabriele Monaco
@ 2026-01-22 14:59 ` Nam Cao
1 sibling, 0 replies; 95+ messages in thread
From: Nam Cao @ 2026-01-22 14:59 UTC (permalink / raw)
To: Wander Lairson Costa, Steven Rostedt, Gabriele Monaco,
Wander Lairson Costa, open list,
open list:RUNTIME VERIFICATION (RV)
Wander Lairson Costa <wander@redhat.com> writes:
> Fix typo in the module docstring: "Abtract" should be "Abstract".
>
> Signed-off-by: Wander Lairson Costa <wander@redhat.com>
Reviewed-by: Nam Cao <namcao@linutronix.de>
^ permalink raw reply [flat|nested] 95+ messages in thread
* [PATCH 12/26] rv/rvgen: fix PEP 8 whitespace violations
2026-01-19 20:45 [PATCH 00/26] rv/rvgen: Robustness, modernization, and fixes Wander Lairson Costa
` (10 preceding siblings ...)
2026-01-19 20:45 ` [PATCH 11/26] rv/rvgen: fix typo in generator module docstring Wander Lairson Costa
@ 2026-01-19 20:45 ` Wander Lairson Costa
2026-01-20 7:53 ` Gabriele Monaco
2026-01-22 14:59 ` Nam Cao
2026-01-19 20:45 ` [PATCH 13/26] rv/rvgen: fix DOT file validation logic error Wander Lairson Costa
` (14 subsequent siblings)
26 siblings, 2 replies; 95+ messages in thread
From: Wander Lairson Costa @ 2026-01-19 20:45 UTC (permalink / raw)
To: Steven Rostedt, Gabriele Monaco, Nam Cao, Wander Lairson Costa,
open list, open list:RUNTIME VERIFICATION (RV)
Fix whitespace violations throughout the rvgen codebase to comply
with PEP 8 style guidelines. The changes address missing whitespace
after commas, around operators, and in collection literals that
were flagged by pycodestyle.
The fixes include adding whitespace after commas in string replace
chains and function arguments, adding whitespace around arithmetic
operators, removing extra whitespace in list comprehensions, and
fixing dictionary literal spacing. These changes improve code
readability and consistency with Python coding standards.
Signed-off-by: Wander Lairson Costa <wander@redhat.com>
---
tools/verification/rvgen/rvgen/automata.py | 12 ++++++------
tools/verification/rvgen/rvgen/dot2c.py | 2 +-
tools/verification/rvgen/rvgen/dot2k.py | 4 ++--
tools/verification/rvgen/rvgen/generator.py | 2 +-
4 files changed, 10 insertions(+), 10 deletions(-)
diff --git a/tools/verification/rvgen/rvgen/automata.py b/tools/verification/rvgen/rvgen/automata.py
index c0c8d13030007..9e1c097ad0e4a 100644
--- a/tools/verification/rvgen/rvgen/automata.py
+++ b/tools/verification/rvgen/rvgen/automata.py
@@ -95,7 +95,7 @@ class Automata:
raw_state = line[-1]
# "enabled_fired"}; -> enabled_fired
- state = raw_state.replace('"', '').replace('};', '').replace(',','_')
+ state = raw_state.replace('"', '').replace('};', '').replace(',', '_')
if state[0:7] == "__init_":
initial_state = state[7:]
else:
@@ -132,7 +132,7 @@ class Automata:
# ------------ event is here ------------^^^^^
if self.__dot_lines[cursor].split()[1] == "->":
line = self.__dot_lines[cursor].split()
- event = line[-2].replace('"','')
+ event = line[-2].replace('"', '')
# when a transition has more than one labels, they are like this
# "local_irq_enable\nhw_local_irq_enable_n"
@@ -162,7 +162,7 @@ class Automata:
nr_state += 1
# declare the matrix....
- matrix = [[ self.invalid_state_str for x in range(nr_event)] for y in range(nr_state)]
+ matrix = [[self.invalid_state_str for x in range(nr_event)] for y in range(nr_state)]
# and we are back! Let's fill the matrix
cursor = self.__get_cursor_begin_events()
@@ -170,9 +170,9 @@ class Automata:
while self.__dot_lines[cursor].lstrip()[0] == '"':
if self.__dot_lines[cursor].split()[1] == "->":
line = self.__dot_lines[cursor].split()
- origin_state = line[0].replace('"','').replace(',','_')
- dest_state = line[2].replace('"','').replace(',','_')
- possible_events = line[-2].replace('"','').replace("\\n", " ")
+ origin_state = line[0].replace('"', '').replace(',', '_')
+ dest_state = line[2].replace('"', '').replace(',', '_')
+ possible_events = line[-2].replace('"', '').replace("\\n", " ")
for event in possible_events.split():
matrix[states_dict[origin_state]][events_dict[event]] = dest_state
cursor += 1
diff --git a/tools/verification/rvgen/rvgen/dot2c.py b/tools/verification/rvgen/rvgen/dot2c.py
index fa9e9ae16640f..b291c29160fc2 100644
--- a/tools/verification/rvgen/rvgen/dot2c.py
+++ b/tools/verification/rvgen/rvgen/dot2c.py
@@ -172,7 +172,7 @@ class Dot2c(Automata):
line += f"\t\t\t{next_state}"
else:
line += f"{next_state:>{maxlen}}"
- if y != nr_events-1:
+ if y != nr_events - 1:
line += ",\n" if linetoolong else ", "
else:
line += "\n\t\t}," if linetoolong else " },"
diff --git a/tools/verification/rvgen/rvgen/dot2k.py b/tools/verification/rvgen/rvgen/dot2k.py
index 291385adb2c20..de44840f63eda 100644
--- a/tools/verification/rvgen/rvgen/dot2k.py
+++ b/tools/verification/rvgen/rvgen/dot2k.py
@@ -109,8 +109,8 @@ class dot2k(Monitor, Dot2c):
tp_args = tp_args_event if tp_type == "event" else tp_args_error
if self.monitor_type == "per_task":
tp_args.insert(0, tp_args_id)
- tp_proto_c = ", ".join([a+b for a,b in tp_args])
- tp_args_c = ", ".join([b for a,b in tp_args])
+ tp_proto_c = ", ".join([a + b for a, b in tp_args])
+ tp_args_c = ", ".join([b for a, b in tp_args])
buff.append(f" TP_PROTO({tp_proto_c}),")
buff.append(f" TP_ARGS({tp_args_c})")
return '\n'.join(buff)
diff --git a/tools/verification/rvgen/rvgen/generator.py b/tools/verification/rvgen/rvgen/generator.py
index ea1fa0f5d818d..0491f8c9cb0b9 100644
--- a/tools/verification/rvgen/rvgen/generator.py
+++ b/tools/verification/rvgen/rvgen/generator.py
@@ -229,7 +229,7 @@ obj-$(CONFIG_RV_MON_{name_up}) += monitors/{name}/{name}.o
class Monitor(RVGenerator):
- monitor_types = { "global" : 1, "per_cpu" : 2, "per_task" : 3 }
+ monitor_types = {"global": 1, "per_cpu": 2, "per_task": 3}
def __init__(self, extra_params={}):
super().__init__(extra_params)
--
2.52.0
^ permalink raw reply related [flat|nested] 95+ messages in thread* Re: [PATCH 12/26] rv/rvgen: fix PEP 8 whitespace violations
2026-01-19 20:45 ` [PATCH 12/26] rv/rvgen: fix PEP 8 whitespace violations Wander Lairson Costa
@ 2026-01-20 7:53 ` Gabriele Monaco
2026-01-22 14:59 ` Nam Cao
1 sibling, 0 replies; 95+ messages in thread
From: Gabriele Monaco @ 2026-01-20 7:53 UTC (permalink / raw)
To: Wander Lairson Costa
Cc: Steven Rostedt, Nam Cao, open list,
open list:RUNTIME VERIFICATION (RV)
On Mon, 2026-01-19 at 17:45 -0300, Wander Lairson Costa wrote:
> Fix whitespace violations throughout the rvgen codebase to comply
> with PEP 8 style guidelines. The changes address missing whitespace
> after commas, around operators, and in collection literals that
> were flagged by pycodestyle.
>
> The fixes include adding whitespace after commas in string replace
> chains and function arguments, adding whitespace around arithmetic
> operators, removing extra whitespace in list comprehensions, and
> fixing dictionary literal spacing. These changes improve code
> readability and consistency with Python coding standards.
>
> Signed-off-by: Wander Lairson Costa <wander@redhat.com>
Looks good, thanks
Reviewed-by: Gabriele Monaco <gmonaco@redhat.com>
> ---
> tools/verification/rvgen/rvgen/automata.py | 12 ++++++------
> tools/verification/rvgen/rvgen/dot2c.py | 2 +-
> tools/verification/rvgen/rvgen/dot2k.py | 4 ++--
> tools/verification/rvgen/rvgen/generator.py | 2 +-
> 4 files changed, 10 insertions(+), 10 deletions(-)
>
> diff --git a/tools/verification/rvgen/rvgen/automata.py
> b/tools/verification/rvgen/rvgen/automata.py
> index c0c8d13030007..9e1c097ad0e4a 100644
> --- a/tools/verification/rvgen/rvgen/automata.py
> +++ b/tools/verification/rvgen/rvgen/automata.py
> @@ -95,7 +95,7 @@ class Automata:
> raw_state = line[-1]
>
> # "enabled_fired"}; -> enabled_fired
> - state = raw_state.replace('"', '').replace('};',
> '').replace(',','_')
> + state = raw_state.replace('"', '').replace('};', '').replace(',',
> '_')
> if state[0:7] == "__init_":
> initial_state = state[7:]
> else:
> @@ -132,7 +132,7 @@ class Automata:
> # ------------ event is here ------------^^^^^
> if self.__dot_lines[cursor].split()[1] == "->":
> line = self.__dot_lines[cursor].split()
> - event = line[-2].replace('"','')
> + event = line[-2].replace('"', '')
>
> # when a transition has more than one labels, they are like
> this
> # "local_irq_enable\nhw_local_irq_enable_n"
> @@ -162,7 +162,7 @@ class Automata:
> nr_state += 1
>
> # declare the matrix....
> - matrix = [[ self.invalid_state_str for x in range(nr_event)] for y in
> range(nr_state)]
> + matrix = [[self.invalid_state_str for x in range(nr_event)] for y in
> range(nr_state)]
>
> # and we are back! Let's fill the matrix
> cursor = self.__get_cursor_begin_events()
> @@ -170,9 +170,9 @@ class Automata:
> while self.__dot_lines[cursor].lstrip()[0] == '"':
> if self.__dot_lines[cursor].split()[1] == "->":
> line = self.__dot_lines[cursor].split()
> - origin_state = line[0].replace('"','').replace(',','_')
> - dest_state = line[2].replace('"','').replace(',','_')
> - possible_events = line[-2].replace('"','').replace("\\n", "
> ")
> + origin_state = line[0].replace('"', '').replace(',', '_')
> + dest_state = line[2].replace('"', '').replace(',', '_')
> + possible_events = line[-2].replace('"', '').replace("\\n", "
> ")
> for event in possible_events.split():
> matrix[states_dict[origin_state]][events_dict[event]] =
> dest_state
> cursor += 1
> diff --git a/tools/verification/rvgen/rvgen/dot2c.py
> b/tools/verification/rvgen/rvgen/dot2c.py
> index fa9e9ae16640f..b291c29160fc2 100644
> --- a/tools/verification/rvgen/rvgen/dot2c.py
> +++ b/tools/verification/rvgen/rvgen/dot2c.py
> @@ -172,7 +172,7 @@ class Dot2c(Automata):
> line += f"\t\t\t{next_state}"
> else:
> line += f"{next_state:>{maxlen}}"
> - if y != nr_events-1:
> + if y != nr_events - 1:
> line += ",\n" if linetoolong else ", "
> else:
> line += "\n\t\t}," if linetoolong else " },"
> diff --git a/tools/verification/rvgen/rvgen/dot2k.py
> b/tools/verification/rvgen/rvgen/dot2k.py
> index 291385adb2c20..de44840f63eda 100644
> --- a/tools/verification/rvgen/rvgen/dot2k.py
> +++ b/tools/verification/rvgen/rvgen/dot2k.py
> @@ -109,8 +109,8 @@ class dot2k(Monitor, Dot2c):
> tp_args = tp_args_event if tp_type == "event" else tp_args_error
> if self.monitor_type == "per_task":
> tp_args.insert(0, tp_args_id)
> - tp_proto_c = ", ".join([a+b for a,b in tp_args])
> - tp_args_c = ", ".join([b for a,b in tp_args])
> + tp_proto_c = ", ".join([a + b for a, b in tp_args])
> + tp_args_c = ", ".join([b for a, b in tp_args])
> buff.append(f" TP_PROTO({tp_proto_c}),")
> buff.append(f" TP_ARGS({tp_args_c})")
> return '\n'.join(buff)
> diff --git a/tools/verification/rvgen/rvgen/generator.py
> b/tools/verification/rvgen/rvgen/generator.py
> index ea1fa0f5d818d..0491f8c9cb0b9 100644
> --- a/tools/verification/rvgen/rvgen/generator.py
> +++ b/tools/verification/rvgen/rvgen/generator.py
> @@ -229,7 +229,7 @@ obj-$(CONFIG_RV_MON_{name_up}) += monitors/{name}/{name}.o
>
>
> class Monitor(RVGenerator):
> - monitor_types = { "global" : 1, "per_cpu" : 2, "per_task" : 3 }
> + monitor_types = {"global": 1, "per_cpu": 2, "per_task": 3}
>
> def __init__(self, extra_params={}):
> super().__init__(extra_params)
^ permalink raw reply [flat|nested] 95+ messages in thread* Re: [PATCH 12/26] rv/rvgen: fix PEP 8 whitespace violations
2026-01-19 20:45 ` [PATCH 12/26] rv/rvgen: fix PEP 8 whitespace violations Wander Lairson Costa
2026-01-20 7:53 ` Gabriele Monaco
@ 2026-01-22 14:59 ` Nam Cao
1 sibling, 0 replies; 95+ messages in thread
From: Nam Cao @ 2026-01-22 14:59 UTC (permalink / raw)
To: Wander Lairson Costa, Steven Rostedt, Gabriele Monaco,
Wander Lairson Costa, open list,
open list:RUNTIME VERIFICATION (RV)
Wander Lairson Costa <wander@redhat.com> writes:
> Fix whitespace violations throughout the rvgen codebase to comply
> with PEP 8 style guidelines. The changes address missing whitespace
> after commas, around operators, and in collection literals that
> were flagged by pycodestyle.
>
> The fixes include adding whitespace after commas in string replace
> chains and function arguments, adding whitespace around arithmetic
> operators, removing extra whitespace in list comprehensions, and
> fixing dictionary literal spacing. These changes improve code
> readability and consistency with Python coding standards.
>
> Signed-off-by: Wander Lairson Costa <wander@redhat.com>
Reviewed-by: Nam Cao <namcao@linutronix.de>
^ permalink raw reply [flat|nested] 95+ messages in thread
* [PATCH 13/26] rv/rvgen: fix DOT file validation logic error
2026-01-19 20:45 [PATCH 00/26] rv/rvgen: Robustness, modernization, and fixes Wander Lairson Costa
` (11 preceding siblings ...)
2026-01-19 20:45 ` [PATCH 12/26] rv/rvgen: fix PEP 8 whitespace violations Wander Lairson Costa
@ 2026-01-19 20:45 ` Wander Lairson Costa
2026-01-20 7:56 ` Gabriele Monaco
2026-01-22 15:01 ` Nam Cao
2026-01-19 20:45 ` [PATCH 14/26] rv/rvgen: remove redundant initial_state removal Wander Lairson Costa
` (13 subsequent siblings)
26 siblings, 2 replies; 95+ messages in thread
From: Wander Lairson Costa @ 2026-01-19 20:45 UTC (permalink / raw)
To: Steven Rostedt, Gabriele Monaco, Nam Cao, Wander Lairson Costa,
open list, open list:RUNTIME VERIFICATION (RV)
Fix incorrect boolean logic in automata DOT file format validation
that allowed malformed files to pass undetected. The previous
implementation used a logical AND operator where OR was required,
causing the validation to only reject files when both the first
token was not "digraph" AND the second token was not
"state_automaton". This meant a file starting with "digraph" but
having an incorrect second token would incorrectly pass validation.
The corrected logic properly rejects DOT files where either the
first token is not "digraph" or the second token is not
"state_automaton", ensuring that only properly formatted automaton
definition files are accepted for processing. Without this fix,
invalid DOT files could cause downstream parsing failures or
generate incorrect C code for runtime verification monitors.
Signed-off-by: Wander Lairson Costa <wander@redhat.com>
---
tools/verification/rvgen/rvgen/automata.py | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/tools/verification/rvgen/rvgen/automata.py b/tools/verification/rvgen/rvgen/automata.py
index 9e1c097ad0e4a..7841a6e70bad2 100644
--- a/tools/verification/rvgen/rvgen/automata.py
+++ b/tools/verification/rvgen/rvgen/automata.py
@@ -59,7 +59,7 @@ class Automata:
# checking the first line:
line = dot_lines[cursor].split()
- if (line[0] != "digraph") and (line[1] != "state_automaton"):
+ if (line[0] != "digraph") or (line[1] != "state_automaton"):
raise AutomataError(f"Not a valid .dot format: {self.__dot_path}")
else:
cursor += 1
--
2.52.0
^ permalink raw reply related [flat|nested] 95+ messages in thread* Re: [PATCH 13/26] rv/rvgen: fix DOT file validation logic error
2026-01-19 20:45 ` [PATCH 13/26] rv/rvgen: fix DOT file validation logic error Wander Lairson Costa
@ 2026-01-20 7:56 ` Gabriele Monaco
2026-01-22 15:01 ` Nam Cao
1 sibling, 0 replies; 95+ messages in thread
From: Gabriele Monaco @ 2026-01-20 7:56 UTC (permalink / raw)
To: Wander Lairson Costa
Cc: Steven Rostedt, Nam Cao, open list,
open list:RUNTIME VERIFICATION (RV)
On Mon, 2026-01-19 at 17:45 -0300, Wander Lairson Costa wrote:
> Fix incorrect boolean logic in automata DOT file format validation
> that allowed malformed files to pass undetected. The previous
> implementation used a logical AND operator where OR was required,
> causing the validation to only reject files when both the first
> token was not "digraph" AND the second token was not
> "state_automaton". This meant a file starting with "digraph" but
> having an incorrect second token would incorrectly pass validation.
>
> The corrected logic properly rejects DOT files where either the
> first token is not "digraph" or the second token is not
> "state_automaton", ensuring that only properly formatted automaton
> definition files are accepted for processing. Without this fix,
> invalid DOT files could cause downstream parsing failures or
> generate incorrect C code for runtime verification monitors.
>
> Signed-off-by: Wander Lairson Costa <wander@redhat.com>
Right, that slipped. Thanks!
Reviewed-by: Gabriele Monaco <gmonaco@redhat.com>
> ---
> tools/verification/rvgen/rvgen/automata.py | 2 +-
> 1 file changed, 1 insertion(+), 1 deletion(-)
>
> diff --git a/tools/verification/rvgen/rvgen/automata.py
> b/tools/verification/rvgen/rvgen/automata.py
> index 9e1c097ad0e4a..7841a6e70bad2 100644
> --- a/tools/verification/rvgen/rvgen/automata.py
> +++ b/tools/verification/rvgen/rvgen/automata.py
> @@ -59,7 +59,7 @@ class Automata:
> # checking the first line:
> line = dot_lines[cursor].split()
>
> - if (line[0] != "digraph") and (line[1] != "state_automaton"):
> + if (line[0] != "digraph") or (line[1] != "state_automaton"):
> raise AutomataError(f"Not a valid .dot format:
> {self.__dot_path}")
> else:
> cursor += 1
^ permalink raw reply [flat|nested] 95+ messages in thread* Re: [PATCH 13/26] rv/rvgen: fix DOT file validation logic error
2026-01-19 20:45 ` [PATCH 13/26] rv/rvgen: fix DOT file validation logic error Wander Lairson Costa
2026-01-20 7:56 ` Gabriele Monaco
@ 2026-01-22 15:01 ` Nam Cao
1 sibling, 0 replies; 95+ messages in thread
From: Nam Cao @ 2026-01-22 15:01 UTC (permalink / raw)
To: Wander Lairson Costa, Steven Rostedt, Gabriele Monaco,
Wander Lairson Costa, open list,
open list:RUNTIME VERIFICATION (RV)
Wander Lairson Costa <wander@redhat.com> writes:
> Fix incorrect boolean logic in automata DOT file format validation
> that allowed malformed files to pass undetected. The previous
> implementation used a logical AND operator where OR was required,
> causing the validation to only reject files when both the first
> token was not "digraph" AND the second token was not
> "state_automaton". This meant a file starting with "digraph" but
> having an incorrect second token would incorrectly pass validation.
>
> The corrected logic properly rejects DOT files where either the
> first token is not "digraph" or the second token is not
> "state_automaton", ensuring that only properly formatted automaton
> definition files are accepted for processing. Without this fix,
> invalid DOT files could cause downstream parsing failures or
> generate incorrect C code for runtime verification monitors.
>
> Signed-off-by: Wander Lairson Costa <wander@redhat.com>
Reviewed-by: Nam Cao <namcao@linutronix.de>
^ permalink raw reply [flat|nested] 95+ messages in thread
* [PATCH 14/26] rv/rvgen: remove redundant initial_state removal
2026-01-19 20:45 [PATCH 00/26] rv/rvgen: Robustness, modernization, and fixes Wander Lairson Costa
` (12 preceding siblings ...)
2026-01-19 20:45 ` [PATCH 13/26] rv/rvgen: fix DOT file validation logic error Wander Lairson Costa
@ 2026-01-19 20:45 ` Wander Lairson Costa
2026-01-20 8:01 ` Gabriele Monaco
2026-01-19 20:45 ` [PATCH 15/26] rv/rvgen: use class constant for init marker Wander Lairson Costa
` (12 subsequent siblings)
26 siblings, 1 reply; 95+ messages in thread
From: Wander Lairson Costa @ 2026-01-19 20:45 UTC (permalink / raw)
To: Steven Rostedt, Gabriele Monaco, Nam Cao, Wander Lairson Costa,
open list, open list:RUNTIME VERIFICATION (RV)
Remove an unnecessary and incorrect list removal operation in the
automata state variable processing. The code attempted to remove
initial_state from the states list, but this element was never
added to the list in the first place. States with the __init_
prefix are explicitly excluded from the states list during the
parsing loop, with only the initial_state variable being set
from them.
Calling remove() on an element that does not exist in a list
raises a ValueError. This code would have failed during execution
when processing any DOT file containing an initial state marker.
The subsequent insert operation at index 0 correctly adds the
initial_state to the beginning of the states list, making the
removal operation both incorrect and redundant.
Signed-off-by: Wander Lairson Costa <wander@redhat.com>
---
tools/verification/rvgen/rvgen/automata.py | 1 -
1 file changed, 1 deletion(-)
diff --git a/tools/verification/rvgen/rvgen/automata.py b/tools/verification/rvgen/rvgen/automata.py
index 7841a6e70bad2..b302af3e5133e 100644
--- a/tools/verification/rvgen/rvgen/automata.py
+++ b/tools/verification/rvgen/rvgen/automata.py
@@ -111,7 +111,6 @@ class Automata:
cursor += 1
states = sorted(set(states))
- states.remove(initial_state)
# Insert the initial state at the beginning of the states
states.insert(0, initial_state)
--
2.52.0
^ permalink raw reply related [flat|nested] 95+ messages in thread* Re: [PATCH 14/26] rv/rvgen: remove redundant initial_state removal
2026-01-19 20:45 ` [PATCH 14/26] rv/rvgen: remove redundant initial_state removal Wander Lairson Costa
@ 2026-01-20 8:01 ` Gabriele Monaco
2026-01-20 12:05 ` Wander Lairson Costa
0 siblings, 1 reply; 95+ messages in thread
From: Gabriele Monaco @ 2026-01-20 8:01 UTC (permalink / raw)
To: Wander Lairson Costa
Cc: Steven Rostedt, Nam Cao, open list,
open list:RUNTIME VERIFICATION (RV)
On Mon, 2026-01-19 at 17:45 -0300, Wander Lairson Costa wrote:
> Remove an unnecessary and incorrect list removal operation in the
> automata state variable processing. The code attempted to remove
> initial_state from the states list, but this element was never
> added to the list in the first place. States with the __init_
> prefix are explicitly excluded from the states list during the
> parsing loop, with only the initial_state variable being set
> from them.
The initial state is not the state with __init_, but the state pointed to by
that, the purpose of removing it after sorting and putting it back is for it to
be the first (we may argue there are better ways to do that, but it works).
After this change, the initial state is duplicated..
I think we should just drop this.
Thanks,
Gabriele
>
> Calling remove() on an element that does not exist in a list
> raises a ValueError. This code would have failed during execution
> when processing any DOT file containing an initial state marker.
> The subsequent insert operation at index 0 correctly adds the
> initial_state to the beginning of the states list, making the
> removal operation both incorrect and redundant.
>
> Signed-off-by: Wander Lairson Costa <wander@redhat.com>
> ---
> tools/verification/rvgen/rvgen/automata.py | 1 -
> 1 file changed, 1 deletion(-)
>
> diff --git a/tools/verification/rvgen/rvgen/automata.py
> b/tools/verification/rvgen/rvgen/automata.py
> index 7841a6e70bad2..b302af3e5133e 100644
> --- a/tools/verification/rvgen/rvgen/automata.py
> +++ b/tools/verification/rvgen/rvgen/automata.py
> @@ -111,7 +111,6 @@ class Automata:
> cursor += 1
>
> states = sorted(set(states))
> - states.remove(initial_state)
>
> # Insert the initial state at the beginning of the states
> states.insert(0, initial_state)
^ permalink raw reply [flat|nested] 95+ messages in thread
* Re: [PATCH 14/26] rv/rvgen: remove redundant initial_state removal
2026-01-20 8:01 ` Gabriele Monaco
@ 2026-01-20 12:05 ` Wander Lairson Costa
0 siblings, 0 replies; 95+ messages in thread
From: Wander Lairson Costa @ 2026-01-20 12:05 UTC (permalink / raw)
To: Gabriele Monaco
Cc: Steven Rostedt, Nam Cao, open list,
open list:RUNTIME VERIFICATION (RV)
On Tue, Jan 20, 2026 at 09:01:01AM +0100, Gabriele Monaco wrote:
> On Mon, 2026-01-19 at 17:45 -0300, Wander Lairson Costa wrote:
> > Remove an unnecessary and incorrect list removal operation in the
> > automata state variable processing. The code attempted to remove
> > initial_state from the states list, but this element was never
> > added to the list in the first place. States with the __init_
> > prefix are explicitly excluded from the states list during the
> > parsing loop, with only the initial_state variable being set
> > from them.
>
> The initial state is not the state with __init_, but the state pointed to by
> that, the purpose of removing it after sorting and putting it back is for it to
> be the first (we may argue there are better ways to do that, but it works).
>
> After this change, the initial state is duplicated..
> I think we should just drop this.
Ah, now I understood the reasoning, thanks. I will drop the patch.
>
> Thanks,
> Gabriele
>
> >
> > Calling remove() on an element that does not exist in a list
> > raises a ValueError. This code would have failed during execution
> > when processing any DOT file containing an initial state marker.
> > The subsequent insert operation at index 0 correctly adds the
> > initial_state to the beginning of the states list, making the
> > removal operation both incorrect and redundant.
> >
> > Signed-off-by: Wander Lairson Costa <wander@redhat.com>
> > ---
> > tools/verification/rvgen/rvgen/automata.py | 1 -
> > 1 file changed, 1 deletion(-)
> >
> > diff --git a/tools/verification/rvgen/rvgen/automata.py
> > b/tools/verification/rvgen/rvgen/automata.py
> > index 7841a6e70bad2..b302af3e5133e 100644
> > --- a/tools/verification/rvgen/rvgen/automata.py
> > +++ b/tools/verification/rvgen/rvgen/automata.py
> > @@ -111,7 +111,6 @@ class Automata:
> > cursor += 1
> >
> > states = sorted(set(states))
> > - states.remove(initial_state)
> >
> > # Insert the initial state at the beginning of the states
> > states.insert(0, initial_state)
>
^ permalink raw reply [flat|nested] 95+ messages in thread
* [PATCH 15/26] rv/rvgen: use class constant for init marker
2026-01-19 20:45 [PATCH 00/26] rv/rvgen: Robustness, modernization, and fixes Wander Lairson Costa
` (13 preceding siblings ...)
2026-01-19 20:45 ` [PATCH 14/26] rv/rvgen: remove redundant initial_state removal Wander Lairson Costa
@ 2026-01-19 20:45 ` Wander Lairson Costa
2026-01-20 8:06 ` Gabriele Monaco
2026-01-22 15:02 ` Nam Cao
2026-01-19 20:45 ` [PATCH 16/26] rv/rvgen: fix unbound initial_state variable Wander Lairson Costa
` (11 subsequent siblings)
26 siblings, 2 replies; 95+ messages in thread
From: Wander Lairson Costa @ 2026-01-19 20:45 UTC (permalink / raw)
To: Steven Rostedt, Gabriele Monaco, Nam Cao, Wander Lairson Costa,
open list, open list:RUNTIME VERIFICATION (RV)
Replace hardcoded string literal and magic number with a class
constant for the initial state marker in DOT file parsing. The
previous implementation used the magic string "__init_" directly
in the code along with a hardcoded length of 7 for substring
extraction, which made the code less maintainable and harder to
understand.
This change introduces a class constant init_marker to serve as
a single source of truth for the initial state prefix. The code
now uses startswith() for clearer intent and calculates the
substring position dynamically using len(), eliminating the magic
number. If the marker value needs to change in the future, only
the constant definition requires updating rather than multiple
locations in the code.
The refactoring improves code readability and maintainability
while preserving the exact same runtime behavior.
Signed-off-by: Wander Lairson Costa <wander@redhat.com>
---
tools/verification/rvgen/rvgen/automata.py | 5 +++--
1 file changed, 3 insertions(+), 2 deletions(-)
diff --git a/tools/verification/rvgen/rvgen/automata.py b/tools/verification/rvgen/rvgen/automata.py
index b302af3e5133e..8548265955570 100644
--- a/tools/verification/rvgen/rvgen/automata.py
+++ b/tools/verification/rvgen/rvgen/automata.py
@@ -25,6 +25,7 @@ class Automata:
"""
invalid_state_str = "INVALID_STATE"
+ init_marker = "__init_"
def __init__(self, file_path, model_name=None):
self.__dot_path = file_path
@@ -96,8 +97,8 @@ class Automata:
# "enabled_fired"}; -> enabled_fired
state = raw_state.replace('"', '').replace('};', '').replace(',', '_')
- if state[0:7] == "__init_":
- initial_state = state[7:]
+ if state.startswith(self.init_marker):
+ initial_state = state[len(self.init_marker):]
else:
states.append(state)
if "doublecircle" in self.__dot_lines[cursor]:
--
2.52.0
^ permalink raw reply related [flat|nested] 95+ messages in thread* Re: [PATCH 15/26] rv/rvgen: use class constant for init marker
2026-01-19 20:45 ` [PATCH 15/26] rv/rvgen: use class constant for init marker Wander Lairson Costa
@ 2026-01-20 8:06 ` Gabriele Monaco
2026-01-22 15:02 ` Nam Cao
1 sibling, 0 replies; 95+ messages in thread
From: Gabriele Monaco @ 2026-01-20 8:06 UTC (permalink / raw)
To: Wander Lairson Costa
Cc: Steven Rostedt, Nam Cao, open list,
open list:RUNTIME VERIFICATION (RV)
On Mon, 2026-01-19 at 17:45 -0300, Wander Lairson Costa wrote:
> Replace hardcoded string literal and magic number with a class
> constant for the initial state marker in DOT file parsing. The
> previous implementation used the magic string "__init_" directly
> in the code along with a hardcoded length of 7 for substring
> extraction, which made the code less maintainable and harder to
> understand.
>
> This change introduces a class constant init_marker to serve as
> a single source of truth for the initial state prefix. The code
> now uses startswith() for clearer intent and calculates the
> substring position dynamically using len(), eliminating the magic
> number. If the marker value needs to change in the future, only
> the constant definition requires updating rather than multiple
> locations in the code.
>
> The refactoring improves code readability and maintainability
> while preserving the exact same runtime behavior.
>
Looks good, thanks.
Reviewed-by: Gabriele Monaco <gmonaco@redhat.com>
> Signed-off-by: Wander Lairson Costa <wander@redhat.com>
> ---
> tools/verification/rvgen/rvgen/automata.py | 5 +++--
> 1 file changed, 3 insertions(+), 2 deletions(-)
>
> diff --git a/tools/verification/rvgen/rvgen/automata.py
> b/tools/verification/rvgen/rvgen/automata.py
> index b302af3e5133e..8548265955570 100644
> --- a/tools/verification/rvgen/rvgen/automata.py
> +++ b/tools/verification/rvgen/rvgen/automata.py
> @@ -25,6 +25,7 @@ class Automata:
> """
>
> invalid_state_str = "INVALID_STATE"
> + init_marker = "__init_"
>
> def __init__(self, file_path, model_name=None):
> self.__dot_path = file_path
> @@ -96,8 +97,8 @@ class Automata:
>
> # "enabled_fired"}; -> enabled_fired
> state = raw_state.replace('"', '').replace('};', '').replace(',',
> '_')
> - if state[0:7] == "__init_":
> - initial_state = state[7:]
> + if state.startswith(self.init_marker):
> + initial_state = state[len(self.init_marker):]
> else:
> states.append(state)
> if "doublecircle" in self.__dot_lines[cursor]:
^ permalink raw reply [flat|nested] 95+ messages in thread* Re: [PATCH 15/26] rv/rvgen: use class constant for init marker
2026-01-19 20:45 ` [PATCH 15/26] rv/rvgen: use class constant for init marker Wander Lairson Costa
2026-01-20 8:06 ` Gabriele Monaco
@ 2026-01-22 15:02 ` Nam Cao
1 sibling, 0 replies; 95+ messages in thread
From: Nam Cao @ 2026-01-22 15:02 UTC (permalink / raw)
To: Wander Lairson Costa, Steven Rostedt, Gabriele Monaco,
Wander Lairson Costa, open list,
open list:RUNTIME VERIFICATION (RV)
Wander Lairson Costa <wander@redhat.com> writes:
> Replace hardcoded string literal and magic number with a class
> constant for the initial state marker in DOT file parsing. The
> previous implementation used the magic string "__init_" directly
> in the code along with a hardcoded length of 7 for substring
> extraction, which made the code less maintainable and harder to
> understand.
>
> This change introduces a class constant init_marker to serve as
> a single source of truth for the initial state prefix. The code
> now uses startswith() for clearer intent and calculates the
> substring position dynamically using len(), eliminating the magic
> number. If the marker value needs to change in the future, only
> the constant definition requires updating rather than multiple
> locations in the code.
>
> The refactoring improves code readability and maintainability
> while preserving the exact same runtime behavior.
>
> Signed-off-by: Wander Lairson Costa <wander@redhat.com>
Reviewed-by: Nam Cao <namcao@linutronix.de>
^ permalink raw reply [flat|nested] 95+ messages in thread
* [PATCH 16/26] rv/rvgen: fix unbound initial_state variable
2026-01-19 20:45 [PATCH 00/26] rv/rvgen: Robustness, modernization, and fixes Wander Lairson Costa
` (14 preceding siblings ...)
2026-01-19 20:45 ` [PATCH 15/26] rv/rvgen: use class constant for init marker Wander Lairson Costa
@ 2026-01-19 20:45 ` Wander Lairson Costa
2026-01-20 8:21 ` Gabriele Monaco
2026-01-19 20:45 ` [PATCH 17/26] rv/rvgen: fix possibly unbound variable in ltl2k Wander Lairson Costa
` (10 subsequent siblings)
26 siblings, 1 reply; 95+ messages in thread
From: Wander Lairson Costa @ 2026-01-19 20:45 UTC (permalink / raw)
To: Steven Rostedt, Gabriele Monaco, Nam Cao, Wander Lairson Costa,
open list, open list:RUNTIME VERIFICATION (RV)
Initialize initial_state to None and validate its assignment after
parsing DOT file state nodes. The previous implementation left
initial_state uninitialized if the DOT file contained no state with
the init_marker prefix, which would cause an UnboundLocalError when
the code attempted to use the variable at the end of the function.
This bug was identified by pyright static type checker, which correctly
flagged that initial_state could be referenced before assignment. The
fix adds proper initialization and validation, raising a AutomataError if
no initial state marker is found in the automaton definition. This
ensures that malformed DOT files missing an initial state are caught
early with a clear error message rather than causing cryptic runtime
exceptions.
The change also includes minor code formatting improvements to comply
with PEP 8 style guidelines, including consistent use of double quotes
for string literals and proper line length formatting for improved
readability.
Signed-off-by: Wander Lairson Costa <wander@redhat.com>
---
tools/verification/rvgen/rvgen/automata.py | 26 +++++++++++++++-------
1 file changed, 18 insertions(+), 8 deletions(-)
diff --git a/tools/verification/rvgen/rvgen/automata.py b/tools/verification/rvgen/rvgen/automata.py
index 8548265955570..083d0f5cfb773 100644
--- a/tools/verification/rvgen/rvgen/automata.py
+++ b/tools/verification/rvgen/rvgen/automata.py
@@ -10,6 +10,7 @@
import ntpath
+
class AutomataError(OSError):
"""Exception raised for errors in automata parsing and validation.
@@ -17,6 +18,7 @@ class AutomataError(OSError):
or malformed automaton definitions.
"""
+
class Automata:
"""Automata class: Reads a dot file and parses it as an automata.
@@ -31,7 +33,9 @@ class Automata:
self.__dot_path = file_path
self.name = model_name or self.__get_model_name()
self.__dot_lines = self.__open_dot()
- self.states, self.initial_state, self.final_states = self.__get_state_variables()
+ self.states, self.initial_state, self.final_states = (
+ self.__get_state_variables()
+ )
self.events = self.__get_event_variables()
self.function = self.__create_matrix()
self.events_start, self.events_start_run = self.__store_init_events()
@@ -86,6 +90,7 @@ class Automata:
# wait for node declaration
states = []
final_states = []
+ initial_state = None
has_final_states = False
cursor = self.__get_cursor_begin_states()
@@ -96,9 +101,9 @@ class Automata:
raw_state = line[-1]
# "enabled_fired"}; -> enabled_fired
- state = raw_state.replace('"', '').replace('};', '').replace(',', '_')
+ state = raw_state.replace('"', "").replace("};", "").replace(",", "_")
if state.startswith(self.init_marker):
- initial_state = state[len(self.init_marker):]
+ initial_state = state[len(self.init_marker) :]
else:
states.append(state)
if "doublecircle" in self.__dot_lines[cursor]:
@@ -111,6 +116,9 @@ class Automata:
cursor += 1
+ if initial_state is None:
+ raise AutomataError("The automaton doesn't have a initial state")
+
states = sorted(set(states))
# Insert the initial state at the beginning of the states
@@ -132,7 +140,7 @@ class Automata:
# ------------ event is here ------------^^^^^
if self.__dot_lines[cursor].split()[1] == "->":
line = self.__dot_lines[cursor].split()
- event = line[-2].replace('"', '')
+ event = line[-2].replace('"', "")
# when a transition has more than one labels, they are like this
# "local_irq_enable\nhw_local_irq_enable_n"
@@ -162,7 +170,9 @@ class Automata:
nr_state += 1
# declare the matrix....
- matrix = [[self.invalid_state_str for x in range(nr_event)] for y in range(nr_state)]
+ matrix = [
+ [self.invalid_state_str for x in range(nr_event)] for y in range(nr_state)
+ ]
# and we are back! Let's fill the matrix
cursor = self.__get_cursor_begin_events()
@@ -170,9 +180,9 @@ class Automata:
while self.__dot_lines[cursor].lstrip()[0] == '"':
if self.__dot_lines[cursor].split()[1] == "->":
line = self.__dot_lines[cursor].split()
- origin_state = line[0].replace('"', '').replace(',', '_')
- dest_state = line[2].replace('"', '').replace(',', '_')
- possible_events = line[-2].replace('"', '').replace("\\n", " ")
+ origin_state = line[0].replace('"', "").replace(",", "_")
+ dest_state = line[2].replace('"', "").replace(",", "_")
+ possible_events = line[-2].replace('"', "").replace("\\n", " ")
for event in possible_events.split():
matrix[states_dict[origin_state]][events_dict[event]] = dest_state
cursor += 1
--
2.52.0
^ permalink raw reply related [flat|nested] 95+ messages in thread* Re: [PATCH 16/26] rv/rvgen: fix unbound initial_state variable
2026-01-19 20:45 ` [PATCH 16/26] rv/rvgen: fix unbound initial_state variable Wander Lairson Costa
@ 2026-01-20 8:21 ` Gabriele Monaco
2026-01-20 11:42 ` Wander Lairson Costa
0 siblings, 1 reply; 95+ messages in thread
From: Gabriele Monaco @ 2026-01-20 8:21 UTC (permalink / raw)
To: Wander Lairson Costa
Cc: Steven Rostedt, Nam Cao, open list,
open list:RUNTIME VERIFICATION (RV)
On Mon, 2026-01-19 at 17:45 -0300, Wander Lairson Costa wrote:
[...]
> diff --git a/tools/verification/rvgen/rvgen/automata.py
> b/tools/verification/rvgen/rvgen/automata.py
> index 8548265955570..083d0f5cfb773 100644
> --- a/tools/verification/rvgen/rvgen/automata.py
> +++ b/tools/verification/rvgen/rvgen/automata.py
> @@ -10,6 +10,7 @@
>
> import ntpath
>
> +
> class AutomataError(OSError):
> """Exception raised for errors in automata parsing and validation.
>
> @@ -17,6 +18,7 @@ class AutomataError(OSError):
> or malformed automaton definitions.
> """
>
> +
I believe these newlines were added automatically by some tools, not sure if we
really want them but they don't belong in this patch (since 1/26 added this
class).
> class Automata:
> """Automata class: Reads a dot file and parses it as an automata.
>
> @@ -31,7 +33,9 @@ class Automata:
> self.__dot_path = file_path
> self.name = model_name or self.__get_model_name()
> self.__dot_lines = self.__open_dot()
> - self.states, self.initial_state, self.final_states =
> self.__get_state_variables()
> + self.states, self.initial_state, self.final_states = (
> + self.__get_state_variables()
> + )
There is no strict 80 character limit for python code and I personally find this
less readable. Is this again what the tool suggested?
> self.events = self.__get_event_variables()
> self.function = self.__create_matrix()
> self.events_start, self.events_start_run = self.__store_init_events()
> @@ -86,6 +90,7 @@ class Automata:
> # wait for node declaration
> states = []
> final_states = []
> + initial_state = None
>
> has_final_states = False
> cursor = self.__get_cursor_begin_states()
> @@ -96,9 +101,9 @@ class Automata:
> raw_state = line[-1]
>
> # "enabled_fired"}; -> enabled_fired
> - state = raw_state.replace('"', '').replace('};', '').replace(',',
> '_')
> + state = raw_state.replace('"', "").replace("};", "").replace(",",
> "_")
Ok this change is good.
> if state.startswith(self.init_marker):
> - initial_state = state[len(self.init_marker):]
> + initial_state = state[len(self.init_marker) :]
You fixed spacing in 12/26. We could either keep move this change there or just
merge that patch with others touching the same files.
> else:
> states.append(state)
> if "doublecircle" in self.__dot_lines[cursor]:
> @@ -111,6 +116,9 @@ class Automata:
>
> cursor += 1
>
> + if initial_state is None:
> + raise AutomataError("The automaton doesn't have a initial state")
> +
Yeah that's needed.
> states = sorted(set(states))
>
> # Insert the initial state at the beginning of the states
> @@ -132,7 +140,7 @@ class Automata:
> # ------------ event is here ------------^^^^^
> if self.__dot_lines[cursor].split()[1] == "->":
> line = self.__dot_lines[cursor].split()
> - event = line[-2].replace('"', '')
> + event = line[-2].replace('"', "")
>
> # when a transition has more than one labels, they are like
> this
> # "local_irq_enable\nhw_local_irq_enable_n"
> @@ -162,7 +170,9 @@ class Automata:
> nr_state += 1
>
> # declare the matrix....
> - matrix = [[self.invalid_state_str for x in range(nr_event)] for y in
> range(nr_state)]
> + matrix = [
> + [self.invalid_state_str for x in range(nr_event)] for y in
> range(nr_state)
> + ]
>
> # and we are back! Let's fill the matrix
> cursor = self.__get_cursor_begin_events()
> @@ -170,9 +180,9 @@ class Automata:
> while self.__dot_lines[cursor].lstrip()[0] == '"':
> if self.__dot_lines[cursor].split()[1] == "->":
> line = self.__dot_lines[cursor].split()
> - origin_state = line[0].replace('"', '').replace(',', '_')
> - dest_state = line[2].replace('"', '').replace(',', '_')
> - possible_events = line[-2].replace('"', '').replace("\\n", "
> ")
> + origin_state = line[0].replace('"', "").replace(",", "_")
> + dest_state = line[2].replace('"', "").replace(",", "_")
> + possible_events = line[-2].replace('"', "").replace("\\n", "
> ")
All in all looks good, thanks.
Reviewed-by: Gabriele Monaco <gmonaco@redhat.com>
> for event in possible_events.split():
> matrix[states_dict[origin_state]][events_dict[event]] =
> dest_state
> cursor += 1
^ permalink raw reply [flat|nested] 95+ messages in thread* Re: [PATCH 16/26] rv/rvgen: fix unbound initial_state variable
2026-01-20 8:21 ` Gabriele Monaco
@ 2026-01-20 11:42 ` Wander Lairson Costa
2026-01-20 11:53 ` Gabriele Monaco
0 siblings, 1 reply; 95+ messages in thread
From: Wander Lairson Costa @ 2026-01-20 11:42 UTC (permalink / raw)
To: Gabriele Monaco
Cc: Steven Rostedt, Nam Cao, open list,
open list:RUNTIME VERIFICATION (RV)
On Tue, Jan 20, 2026 at 09:21:01AM +0100, Gabriele Monaco wrote:
> On Mon, 2026-01-19 at 17:45 -0300, Wander Lairson Costa wrote:
>
>
> [...]
> > diff --git a/tools/verification/rvgen/rvgen/automata.py
> > b/tools/verification/rvgen/rvgen/automata.py
> > index 8548265955570..083d0f5cfb773 100644
> > --- a/tools/verification/rvgen/rvgen/automata.py
> > +++ b/tools/verification/rvgen/rvgen/automata.py
> > @@ -10,6 +10,7 @@
> >
> > import ntpath
> >
> > +
> > class AutomataError(OSError):
> > """Exception raised for errors in automata parsing and validation.
> >
> > @@ -17,6 +18,7 @@ class AutomataError(OSError):
> > or malformed automaton definitions.
> > """
> >
> > +
>
> I believe these newlines were added automatically by some tools, not sure if we
> really want them but they don't belong in this patch (since 1/26 added this
> class).
>
There are python formatting tools that put 2 lines after a type
definition. Anyway, I can remove it in v2.
> > class Automata:
> > """Automata class: Reads a dot file and parses it as an automata.
> >
> > @@ -31,7 +33,9 @@ class Automata:
> > self.__dot_path = file_path
> > self.name = model_name or self.__get_model_name()
> > self.__dot_lines = self.__open_dot()
> > - self.states, self.initial_state, self.final_states =
> > self.__get_state_variables()
> > + self.states, self.initial_state, self.final_states = (
> > + self.__get_state_variables()
> > + )
>
> There is no strict 80 character limit for python code and I personally find this
> less readable. Is this again what the tool suggested?
>
In general, 100 lines is assumed the to a good limit. Anyway, this is
minor and I can remove the change in v2 if desired.
> > self.events = self.__get_event_variables()
> > self.function = self.__create_matrix()
> > self.events_start, self.events_start_run = self.__store_init_events()
> > @@ -86,6 +90,7 @@ class Automata:
> > # wait for node declaration
> > states = []
> > final_states = []
> > + initial_state = None
> >
> > has_final_states = False
> > cursor = self.__get_cursor_begin_states()
> > @@ -96,9 +101,9 @@ class Automata:
> > raw_state = line[-1]
> >
> > # "enabled_fired"}; -> enabled_fired
> > - state = raw_state.replace('"', '').replace('};', '').replace(',',
> > '_')
> > + state = raw_state.replace('"', "").replace("};", "").replace(",",
> > "_")
>
> Ok this change is good.
>
> > if state.startswith(self.init_marker):
> > - initial_state = state[len(self.init_marker):]
> > + initial_state = state[len(self.init_marker) :]
>
> You fixed spacing in 12/26. We could either keep move this change there or just
> merge that patch with others touching the same files.
>
Np, I can move this change to there.
> > else:
> > states.append(state)
> > if "doublecircle" in self.__dot_lines[cursor]:
> > @@ -111,6 +116,9 @@ class Automata:
> >
> > cursor += 1
> >
> > + if initial_state is None:
> > + raise AutomataError("The automaton doesn't have a initial state")
> > +
>
> Yeah that's needed.
>
> > states = sorted(set(states))
> >
> > # Insert the initial state at the beginning of the states
> > @@ -132,7 +140,7 @@ class Automata:
> > # ------------ event is here ------------^^^^^
> > if self.__dot_lines[cursor].split()[1] == "->":
> > line = self.__dot_lines[cursor].split()
> > - event = line[-2].replace('"', '')
> > + event = line[-2].replace('"', "")
> >
> > # when a transition has more than one labels, they are like
> > this
> > # "local_irq_enable\nhw_local_irq_enable_n"
> > @@ -162,7 +170,9 @@ class Automata:
> > nr_state += 1
> >
> > # declare the matrix....
> > - matrix = [[self.invalid_state_str for x in range(nr_event)] for y in
> > range(nr_state)]
> > + matrix = [
> > + [self.invalid_state_str for x in range(nr_event)] for y in
> > range(nr_state)
> > + ]
> >
> > # and we are back! Let's fill the matrix
> > cursor = self.__get_cursor_begin_events()
> > @@ -170,9 +180,9 @@ class Automata:
> > while self.__dot_lines[cursor].lstrip()[0] == '"':
> > if self.__dot_lines[cursor].split()[1] == "->":
> > line = self.__dot_lines[cursor].split()
> > - origin_state = line[0].replace('"', '').replace(',', '_')
> > - dest_state = line[2].replace('"', '').replace(',', '_')
> > - possible_events = line[-2].replace('"', '').replace("\\n", "
> > ")
> > + origin_state = line[0].replace('"', "").replace(",", "_")
> > + dest_state = line[2].replace('"', "").replace(",", "_")
> > + possible_events = line[-2].replace('"', "").replace("\\n", "
> > ")
>
> All in all looks good, thanks.
>
> Reviewed-by: Gabriele Monaco <gmonaco@redhat.com>
>
> > for event in possible_events.split():
> > matrix[states_dict[origin_state]][events_dict[event]] =
> > dest_state
> > cursor += 1
^ permalink raw reply [flat|nested] 95+ messages in thread* Re: [PATCH 16/26] rv/rvgen: fix unbound initial_state variable
2026-01-20 11:42 ` Wander Lairson Costa
@ 2026-01-20 11:53 ` Gabriele Monaco
0 siblings, 0 replies; 95+ messages in thread
From: Gabriele Monaco @ 2026-01-20 11:53 UTC (permalink / raw)
To: Wander Lairson Costa
Cc: Steven Rostedt, Nam Cao, open list,
open list:RUNTIME VERIFICATION (RV)
On Tue, 2026-01-20 at 08:42 -0300, Wander Lairson Costa wrote:
> On Tue, Jan 20, 2026 at 09:21:01AM +0100, Gabriele Monaco wrote:
>
> >
> > I believe these newlines were added automatically by some tools, not sure if
> > we
> > really want them but they don't belong in this patch (since 1/26 added this
> > class).
> >
> There are python formatting tools that put 2 lines after a type
> definition. Anyway, I can remove it in v2.
If that's common practice I'm fine keeping it, I just would create this class
directly with the newlines separators in 1/26 instead of adding these lines
later in the same series. Just to reduce the noise.
>
> > > class Automata:
> > > """Automata class: Reads a dot file and parses it as an automata.
> > >
> > > @@ -31,7 +33,9 @@ class Automata:
> > > self.__dot_path = file_path
> > > self.name = model_name or self.__get_model_name()
> > > self.__dot_lines = self.__open_dot()
> > > - self.states, self.initial_state, self.final_states =
> > > self.__get_state_variables()
> > > + self.states, self.initial_state, self.final_states = (
> > > + self.__get_state_variables()
> > > + )
> >
> > There is no strict 80 character limit for python code and I personally find
> > this
> > less readable. Is this again what the tool suggested?
> >
>
> In general, 100 lines is assumed the to a good limit. Anyway, this is
> minor and I can remove the change in v2 if desired.
Yeah 100 is probably also what checkpatch.pl uses (although I think it skips
python files), since this is below 90 columns, I wouldn't touch it.
Thanks,
Gabriele
>
> > > self.events = self.__get_event_variables()
> > > self.function = self.__create_matrix()
> > > self.events_start, self.events_start_run =
> > > self.__store_init_events()
> > > @@ -86,6 +90,7 @@ class Automata:
> > > # wait for node declaration
> > > states = []
> > > final_states = []
> > > + initial_state = None
> > >
> > > has_final_states = False
> > > cursor = self.__get_cursor_begin_states()
> > > @@ -96,9 +101,9 @@ class Automata:
> > > raw_state = line[-1]
> > >
> > > # "enabled_fired"}; -> enabled_fired
> > > - state = raw_state.replace('"', '').replace('};',
> > > '').replace(',',
> > > '_')
> > > + state = raw_state.replace('"', "").replace("};",
> > > "").replace(",",
> > > "_")
> >
> > Ok this change is good.
> >
> > > if state.startswith(self.init_marker):
> > > - initial_state = state[len(self.init_marker):]
> > > + initial_state = state[len(self.init_marker) :]
> >
> > You fixed spacing in 12/26. We could either keep move this change there or
> > just
> > merge that patch with others touching the same files.
> >
>
> Np, I can move this change to there.
>
> > > else:
> > > states.append(state)
> > > if "doublecircle" in self.__dot_lines[cursor]:
> > > @@ -111,6 +116,9 @@ class Automata:
> > >
> > > cursor += 1
> > >
> > > + if initial_state is None:
> > > + raise AutomataError("The automaton doesn't have a initial
> > > state")
> > > +
> >
> > Yeah that's needed.
> >
> > > states = sorted(set(states))
> > >
> > > # Insert the initial state at the beginning of the states
> > > @@ -132,7 +140,7 @@ class Automata:
> > > # ------------ event is here ------------^^^^^
> > > if self.__dot_lines[cursor].split()[1] == "->":
> > > line = self.__dot_lines[cursor].split()
> > > - event = line[-2].replace('"', '')
> > > + event = line[-2].replace('"', "")
> > >
> > > # when a transition has more than one labels, they are
> > > like
> > > this
> > > # "local_irq_enable\nhw_local_irq_enable_n"
> > > @@ -162,7 +170,9 @@ class Automata:
> > > nr_state += 1
> > >
> > > # declare the matrix....
> > > - matrix = [[self.invalid_state_str for x in range(nr_event)] for y
> > > in
> > > range(nr_state)]
> > > + matrix = [
> > > + [self.invalid_state_str for x in range(nr_event)] for y in
> > > range(nr_state)
> > > + ]
> > >
> > > # and we are back! Let's fill the matrix
> > > cursor = self.__get_cursor_begin_events()
> > > @@ -170,9 +180,9 @@ class Automata:
> > > while self.__dot_lines[cursor].lstrip()[0] == '"':
> > > if self.__dot_lines[cursor].split()[1] == "->":
> > > line = self.__dot_lines[cursor].split()
> > > - origin_state = line[0].replace('"', '').replace(',', '_')
> > > - dest_state = line[2].replace('"', '').replace(',', '_')
> > > - possible_events = line[-2].replace('"',
> > > '').replace("\\n", "
> > > ")
> > > + origin_state = line[0].replace('"', "").replace(",", "_")
> > > + dest_state = line[2].replace('"', "").replace(",", "_")
> > > + possible_events = line[-2].replace('"',
> > > "").replace("\\n", "
> > > ")
> >
> > All in all looks good, thanks.
> >
> > Reviewed-by: Gabriele Monaco <gmonaco@redhat.com>
> >
> > > for event in possible_events.split():
> > > matrix[states_dict[origin_state]][events_dict[event]]
> > > =
> > > dest_state
> > > cursor += 1
^ permalink raw reply [flat|nested] 95+ messages in thread
* [PATCH 17/26] rv/rvgen: fix possibly unbound variable in ltl2k
2026-01-19 20:45 [PATCH 00/26] rv/rvgen: Robustness, modernization, and fixes Wander Lairson Costa
` (15 preceding siblings ...)
2026-01-19 20:45 ` [PATCH 16/26] rv/rvgen: fix unbound initial_state variable Wander Lairson Costa
@ 2026-01-19 20:45 ` Wander Lairson Costa
2026-01-20 8:59 ` Gabriele Monaco
2026-01-22 15:31 ` Nam Cao
2026-01-19 20:45 ` [PATCH 18/26] rv/rvgen: add fill_tracepoint_args_skel stub to ltl2k Wander Lairson Costa
` (9 subsequent siblings)
26 siblings, 2 replies; 95+ messages in thread
From: Wander Lairson Costa @ 2026-01-19 20:45 UTC (permalink / raw)
To: Steven Rostedt, Gabriele Monaco, Nam Cao, Wander Lairson Costa,
open list, open list:RUNTIME VERIFICATION (RV)
Initialize loop variable `i` before the for loop in abbreviate_atoms
function to fix pyright static type checker error. The previous code
left `i` potentially unbound in edge cases where the range could be
empty, though this would not occur in practice since the loop always
executes at least once with the given range parameters.
The initialization to zero ensures that `i` has a defined value before
entering the loop scope, satisfying static analysis requirements
while preserving the existing logic. The for loop immediately assigns
i to the first value from the range, so the initialization value is
never actually used in normal execution paths.
This change resolves the pyright reportPossiblyUnbound error without
altering the function's behavior or performance characteristics.
Signed-off-by: Wander Lairson Costa <wander@redhat.com>
---
tools/verification/rvgen/rvgen/ltl2k.py | 1 +
1 file changed, 1 insertion(+)
diff --git a/tools/verification/rvgen/rvgen/ltl2k.py b/tools/verification/rvgen/rvgen/ltl2k.py
index fa9ea6d597095..94dc64af1716d 100644
--- a/tools/verification/rvgen/rvgen/ltl2k.py
+++ b/tools/verification/rvgen/rvgen/ltl2k.py
@@ -45,6 +45,7 @@ def abbreviate_atoms(atoms: list[str]) -> list[str]:
abbrs = []
for atom in atoms:
+ i = 0
for i in range(len(atom), -1, -1):
if sum(a.startswith(atom[:i]) for a in atoms) > 1:
break
--
2.52.0
^ permalink raw reply related [flat|nested] 95+ messages in thread* Re: [PATCH 17/26] rv/rvgen: fix possibly unbound variable in ltl2k
2026-01-19 20:45 ` [PATCH 17/26] rv/rvgen: fix possibly unbound variable in ltl2k Wander Lairson Costa
@ 2026-01-20 8:59 ` Gabriele Monaco
2026-01-20 11:37 ` Wander Lairson Costa
2026-01-22 15:31 ` Nam Cao
1 sibling, 1 reply; 95+ messages in thread
From: Gabriele Monaco @ 2026-01-20 8:59 UTC (permalink / raw)
To: Wander Lairson Costa
Cc: Steven Rostedt, Nam Cao, open list,
open list:RUNTIME VERIFICATION (RV)
On Mon, 2026-01-19 at 17:45 -0300, Wander Lairson Costa wrote:
> Initialize loop variable `i` before the for loop in abbreviate_atoms
> function to fix pyright static type checker error. The previous code
> left `i` potentially unbound in edge cases where the range could be
> empty, though this would not occur in practice since the loop always
> executes at least once with the given range parameters.
>
> The initialization to zero ensures that `i` has a defined value before
> entering the loop scope, satisfying static analysis requirements
> while preserving the existing logic. The for loop immediately assigns
> i to the first value from the range, so the initialization value is
> never actually used in normal execution paths.
>
> This change resolves the pyright reportPossiblyUnbound error without
> altering the function's behavior or performance characteristics.
So are we just pleasing the tool or is there a real implication of this?
Apparently code like
for i in range(len([]), -1, -1):
pass
print(i)
works just fine since range() returns at least 0 (as you mentioned in the commit
message) and i is not used before assignation in the loop, so I don't really see
a problem.
Apparently pyright devs don't want ([1]) to implement a logic to sort out the
/possibly/ unbound error here.
From what I understand, this code is already not pythonic, so rather than
silence the warning to please this tool I'd just refactor the code not to use i
after the loop (or leave it as it is, since it works fine).
What do you think?
Thanks,
Gabriele
[1] - https://github.com/microsoft/pyright/issues/844
>
> Signed-off-by: Wander Lairson Costa <wander@redhat.com>
> ---
> tools/verification/rvgen/rvgen/ltl2k.py | 1 +
> 1 file changed, 1 insertion(+)
>
> diff --git a/tools/verification/rvgen/rvgen/ltl2k.py
> b/tools/verification/rvgen/rvgen/ltl2k.py
> index fa9ea6d597095..94dc64af1716d 100644
> --- a/tools/verification/rvgen/rvgen/ltl2k.py
> +++ b/tools/verification/rvgen/rvgen/ltl2k.py
> @@ -45,6 +45,7 @@ def abbreviate_atoms(atoms: list[str]) -> list[str]:
>
> abbrs = []
> for atom in atoms:
> + i = 0
> for i in range(len(atom), -1, -1):
> if sum(a.startswith(atom[:i]) for a in atoms) > 1:
> break
^ permalink raw reply [flat|nested] 95+ messages in thread* Re: [PATCH 17/26] rv/rvgen: fix possibly unbound variable in ltl2k
2026-01-20 8:59 ` Gabriele Monaco
@ 2026-01-20 11:37 ` Wander Lairson Costa
2026-01-20 12:30 ` Gabriele Monaco
0 siblings, 1 reply; 95+ messages in thread
From: Wander Lairson Costa @ 2026-01-20 11:37 UTC (permalink / raw)
To: Gabriele Monaco
Cc: Steven Rostedt, Nam Cao, open list,
open list:RUNTIME VERIFICATION (RV)
On Tue, Jan 20, 2026 at 09:59:11AM +0100, Gabriele Monaco wrote:
> On Mon, 2026-01-19 at 17:45 -0300, Wander Lairson Costa wrote:
> > Initialize loop variable `i` before the for loop in abbreviate_atoms
> > function to fix pyright static type checker error. The previous code
> > left `i` potentially unbound in edge cases where the range could be
> > empty, though this would not occur in practice since the loop always
> > executes at least once with the given range parameters.
> >
> > The initialization to zero ensures that `i` has a defined value before
> > entering the loop scope, satisfying static analysis requirements
> > while preserving the existing logic. The for loop immediately assigns
> > i to the first value from the range, so the initialization value is
> > never actually used in normal execution paths.
> >
> > This change resolves the pyright reportPossiblyUnbound error without
> > altering the function's behavior or performance characteristics.
>
> So are we just pleasing the tool or is there a real implication of this?
>
> Apparently code like
>
> for i in range(len([]), -1, -1):
> pass
> print(i)
>
> works just fine since range() returns at least 0 (as you mentioned in the commit
> message) and i is not used before assignation in the loop, so I don't really see
> a problem.
>
> Apparently pyright devs don't want ([1]) to implement a logic to sort out the
> /possibly/ unbound error here.
>
> From what I understand, this code is already not pythonic, so rather than
> silence the warning to please this tool I'd just refactor the code not to use i
> after the loop (or leave it as it is, since it works fine).
>
> What do you think?
You're right, I could have done:
for atom in reversed(atoms): ...
I will modify it in v2.
>
> Thanks,
> Gabriele
>
> [1] - https://github.com/microsoft/pyright/issues/844
>
> >
> > Signed-off-by: Wander Lairson Costa <wander@redhat.com>
> > ---
> > tools/verification/rvgen/rvgen/ltl2k.py | 1 +
> > 1 file changed, 1 insertion(+)
> >
> > diff --git a/tools/verification/rvgen/rvgen/ltl2k.py
> > b/tools/verification/rvgen/rvgen/ltl2k.py
> > index fa9ea6d597095..94dc64af1716d 100644
> > --- a/tools/verification/rvgen/rvgen/ltl2k.py
> > +++ b/tools/verification/rvgen/rvgen/ltl2k.py
> > @@ -45,6 +45,7 @@ def abbreviate_atoms(atoms: list[str]) -> list[str]:
> >
> > abbrs = []
> > for atom in atoms:
> > + i = 0
> > for i in range(len(atom), -1, -1):
> > if sum(a.startswith(atom[:i]) for a in atoms) > 1:
> > break
>
^ permalink raw reply [flat|nested] 95+ messages in thread
* Re: [PATCH 17/26] rv/rvgen: fix possibly unbound variable in ltl2k
2026-01-20 11:37 ` Wander Lairson Costa
@ 2026-01-20 12:30 ` Gabriele Monaco
2026-01-20 19:38 ` Wander Lairson Costa
0 siblings, 1 reply; 95+ messages in thread
From: Gabriele Monaco @ 2026-01-20 12:30 UTC (permalink / raw)
To: Wander Lairson Costa
Cc: Steven Rostedt, Nam Cao, open list,
open list:RUNTIME VERIFICATION (RV)
On Tue, 2026-01-20 at 08:37 -0300, Wander Lairson Costa wrote:
> On Tue, Jan 20, 2026 at 09:59:11AM +0100, Gabriele Monaco wrote:
> > On Mon, 2026-01-19 at 17:45 -0300, Wander Lairson Costa wrote:
> > > Initialize loop variable `i` before the for loop in abbreviate_atoms
> > > function to fix pyright static type checker error. The previous code
> > > left `i` potentially unbound in edge cases where the range could be
> > > empty, though this would not occur in practice since the loop always
> > > executes at least once with the given range parameters.
> > >
> > > The initialization to zero ensures that `i` has a defined value before
> > > entering the loop scope, satisfying static analysis requirements
> > > while preserving the existing logic. The for loop immediately assigns
> > > i to the first value from the range, so the initialization value is
> > > never actually used in normal execution paths.
> > >
> > > This change resolves the pyright reportPossiblyUnbound error without
> > > altering the function's behavior or performance characteristics.
> >
> > So are we just pleasing the tool or is there a real implication of this?
> >
> > Apparently code like
> >
> > for i in range(len([]), -1, -1):
> > pass
> > print(i)
> >
> > works just fine since range() returns at least 0 (as you mentioned in the
> > commit
> > message) and i is not used before assignation in the loop, so I don't really
> > see
> > a problem.
> >
> > Apparently pyright devs don't want ([1]) to implement a logic to sort out
> > the
> > /possibly/ unbound error here.
> >
> > From what I understand, this code is already not pythonic, so rather than
> > silence the warning to please this tool I'd just refactor the code not to
> > use i
> > after the loop (or leave it as it is, since it works fine).
> >
> > What do you think?
>
> You're right, I could have done:
>
> for atom in reversed(atoms): ...
>
I'm missing what you mean with this, the range is iterating over the string
representation of atom (in reverse) not the array of atoms.
You basically want i to be the length of the longest prefix common to at least
another atom.
You could assign i to some python trick doing the exact same thing the loop
does, like:
i = next((i for i in range(len(atom), -1, -1)
if sum(a.startswith(atom[:i]) for a in atoms) > 1))
next() is basically doing the break at the first occurrence from the generator,
just now your i doesn't live (only) inside the loop.
So now you save 2 lines and get any C developer scratch their head when they
look at the code, but hey, pyright is happy!
If you do find the trick with next() readable or have any better idea, feel free
to try though.
Thanks,
Gabriele
> I will modify it in v2.
>
> >
> > Thanks,
> > Gabriele
> >
> > [1] - https://github.com/microsoft/pyright/issues/844
> >
> > >
> > > Signed-off-by: Wander Lairson Costa <wander@redhat.com>
> > > ---
> > > tools/verification/rvgen/rvgen/ltl2k.py | 1 +
> > > 1 file changed, 1 insertion(+)
> > >
> > > diff --git a/tools/verification/rvgen/rvgen/ltl2k.py
> > > b/tools/verification/rvgen/rvgen/ltl2k.py
> > > index fa9ea6d597095..94dc64af1716d 100644
> > > --- a/tools/verification/rvgen/rvgen/ltl2k.py
> > > +++ b/tools/verification/rvgen/rvgen/ltl2k.py
> > > @@ -45,6 +45,7 @@ def abbreviate_atoms(atoms: list[str]) -> list[str]:
> > >
> > > abbrs = []
> > > for atom in atoms:
> > > + i = 0
> > > for i in range(len(atom), -1, -1):
> > > if sum(a.startswith(atom[:i]) for a in atoms) > 1:
> > > break
> >
^ permalink raw reply [flat|nested] 95+ messages in thread* Re: [PATCH 17/26] rv/rvgen: fix possibly unbound variable in ltl2k
2026-01-20 12:30 ` Gabriele Monaco
@ 2026-01-20 19:38 ` Wander Lairson Costa
2026-01-21 6:31 ` Gabriele Monaco
0 siblings, 1 reply; 95+ messages in thread
From: Wander Lairson Costa @ 2026-01-20 19:38 UTC (permalink / raw)
To: Gabriele Monaco
Cc: Steven Rostedt, Nam Cao, open list,
open list:RUNTIME VERIFICATION (RV)
On Tue, Jan 20, 2026 at 01:30:35PM +0100, Gabriele Monaco wrote:
> On Tue, 2026-01-20 at 08:37 -0300, Wander Lairson Costa wrote:
> > On Tue, Jan 20, 2026 at 09:59:11AM +0100, Gabriele Monaco wrote:
> > > On Mon, 2026-01-19 at 17:45 -0300, Wander Lairson Costa wrote:
> > > > Initialize loop variable `i` before the for loop in abbreviate_atoms
> > > > function to fix pyright static type checker error. The previous code
> > > > left `i` potentially unbound in edge cases where the range could be
> > > > empty, though this would not occur in practice since the loop always
> > > > executes at least once with the given range parameters.
> > > >
> > > > The initialization to zero ensures that `i` has a defined value before
> > > > entering the loop scope, satisfying static analysis requirements
> > > > while preserving the existing logic. The for loop immediately assigns
> > > > i to the first value from the range, so the initialization value is
> > > > never actually used in normal execution paths.
> > > >
> > > > This change resolves the pyright reportPossiblyUnbound error without
> > > > altering the function's behavior or performance characteristics.
> > >
> > > So are we just pleasing the tool or is there a real implication of this?
> > >
> > > Apparently code like
> > >
> > > for i in range(len([]), -1, -1):
> > > pass
> > > print(i)
> > >
> > > works just fine since range() returns at least 0 (as you mentioned in the
> > > commit
> > > message) and i is not used before assignation in the loop, so I don't really
> > > see
> > > a problem.
> > >
> > > Apparently pyright devs don't want ([1]) to implement a logic to sort out
> > > the
> > > /possibly/ unbound error here.
> > >
> > > From what I understand, this code is already not pythonic, so rather than
> > > silence the warning to please this tool I'd just refactor the code not to
> > > use i
> > > after the loop (or leave it as it is, since it works fine).
> > >
> > > What do you think?
> >
> > You're right, I could have done:
> >
> > for atom in reversed(atoms): ...
> >
>
> I'm missing what you mean with this, the range is iterating over the string
> representation of atom (in reverse) not the array of atoms.
>
Sorry, I misinterpreted you previous comment and picked the wrong piece
of code.
Yes, the basic goal was to make pyright happy.
> You basically want i to be the length of the longest prefix common to at least
> another atom.
>
> You could assign i to some python trick doing the exact same thing the loop
> does, like:
>
> i = next((i for i in range(len(atom), -1, -1)
> if sum(a.startswith(atom[:i]) for a in atoms) > 1))
>
> next() is basically doing the break at the first occurrence from the generator,
> just now your i doesn't live (only) inside the loop.
>
> So now you save 2 lines and get any C developer scratch their head when they
> look at the code, but hey, pyright is happy!
>
Or just leave the assignment.
> If you do find the trick with next() readable or have any better idea, feel free
> to try though.
>
Definitely the next() trick is not worth to make pyright happy.
> Thanks,
> Gabriele
>
> > I will modify it in v2.
> >
> > >
> > > Thanks,
> > > Gabriele
> > >
> > > [1] - https://github.com/microsoft/pyright/issues/844
> > >
> > > >
> > > > Signed-off-by: Wander Lairson Costa <wander@redhat.com>
> > > > ---
> > > > tools/verification/rvgen/rvgen/ltl2k.py | 1 +
> > > > 1 file changed, 1 insertion(+)
> > > >
> > > > diff --git a/tools/verification/rvgen/rvgen/ltl2k.py
> > > > b/tools/verification/rvgen/rvgen/ltl2k.py
> > > > index fa9ea6d597095..94dc64af1716d 100644
> > > > --- a/tools/verification/rvgen/rvgen/ltl2k.py
> > > > +++ b/tools/verification/rvgen/rvgen/ltl2k.py
> > > > @@ -45,6 +45,7 @@ def abbreviate_atoms(atoms: list[str]) -> list[str]:
> > > >
> > > > abbrs = []
> > > > for atom in atoms:
> > > > + i = 0
> > > > for i in range(len(atom), -1, -1):
> > > > if sum(a.startswith(atom[:i]) for a in atoms) > 1:
> > > > break
> > >
>
^ permalink raw reply [flat|nested] 95+ messages in thread
* Re: [PATCH 17/26] rv/rvgen: fix possibly unbound variable in ltl2k
2026-01-20 19:38 ` Wander Lairson Costa
@ 2026-01-21 6:31 ` Gabriele Monaco
0 siblings, 0 replies; 95+ messages in thread
From: Gabriele Monaco @ 2026-01-21 6:31 UTC (permalink / raw)
To: Wander Lairson Costa
Cc: Steven Rostedt, Nam Cao, open list,
open list:RUNTIME VERIFICATION (RV)
On Tue, 2026-01-20 at 16:38 -0300, Wander Lairson Costa wrote:
> On Tue, Jan 20, 2026 at 01:30:35PM +0100, Gabriele Monaco wrote:
>
> > You basically want i to be the length of the longest prefix common to at
> > least
> > another atom.
> >
> > You could assign i to some python trick doing the exact same thing the loop
> > does, like:
> >
> > i = next((i for i in range(len(atom), -1, -1)
> > if sum(a.startswith(atom[:i]) for a in atoms) > 1))
> >
> > next() is basically doing the break at the first occurrence from the
> > generator,
> > just now your i doesn't live (only) inside the loop.
> >
> > So now you save 2 lines and get any C developer scratch their head when they
> > look at the code, but hey, pyright is happy!
> >
>
> Or just leave the assignment.
>
> > If you do find the trick with next() readable or have any better idea, feel
> > free
> > to try though.
> >
>
> Definitely the next() trick is not worth to make pyright happy.
Alright, thinking on this again next() is the python way to do if(...) break ,
it looked a bit odd to me only because I didn't know about it, but if you're
using python iterators, it kinda makes sense.
Anyway I'm fine also with the dull assignment, there's no need to argue on this.
Thanks,
Gabriele
>
> > Thanks,
> > Gabriele
> >
> > > I will modify it in v2.
> > >
> > > >
> > > > Thanks,
> > > > Gabriele
> > > >
> > > > [1] - https://github.com/microsoft/pyright/issues/844
> > > >
> > > > >
> > > > > Signed-off-by: Wander Lairson Costa <wander@redhat.com>
> > > > > ---
> > > > > tools/verification/rvgen/rvgen/ltl2k.py | 1 +
> > > > > 1 file changed, 1 insertion(+)
> > > > >
> > > > > diff --git a/tools/verification/rvgen/rvgen/ltl2k.py
> > > > > b/tools/verification/rvgen/rvgen/ltl2k.py
> > > > > index fa9ea6d597095..94dc64af1716d 100644
> > > > > --- a/tools/verification/rvgen/rvgen/ltl2k.py
> > > > > +++ b/tools/verification/rvgen/rvgen/ltl2k.py
> > > > > @@ -45,6 +45,7 @@ def abbreviate_atoms(atoms: list[str]) -> list[str]:
> > > > >
> > > > > abbrs = []
> > > > > for atom in atoms:
> > > > > + i = 0
> > > > > for i in range(len(atom), -1, -1):
> > > > > if sum(a.startswith(atom[:i]) for a in atoms) > 1:
> > > > > break
> > > >
> >
^ permalink raw reply [flat|nested] 95+ messages in thread
* Re: [PATCH 17/26] rv/rvgen: fix possibly unbound variable in ltl2k
2026-01-19 20:45 ` [PATCH 17/26] rv/rvgen: fix possibly unbound variable in ltl2k Wander Lairson Costa
2026-01-20 8:59 ` Gabriele Monaco
@ 2026-01-22 15:31 ` Nam Cao
1 sibling, 0 replies; 95+ messages in thread
From: Nam Cao @ 2026-01-22 15:31 UTC (permalink / raw)
To: Wander Lairson Costa, Steven Rostedt, Gabriele Monaco,
Wander Lairson Costa, open list,
open list:RUNTIME VERIFICATION (RV)
Wander Lairson Costa <wander@redhat.com> writes:
> Initialize loop variable `i` before the for loop in abbreviate_atoms
> function to fix pyright static type checker error. The previous code
> left `i` potentially unbound in edge cases where the range could be
> empty, though this would not occur in practice since the loop always
> executes at least once with the given range parameters.
>
> The initialization to zero ensures that `i` has a defined value before
> entering the loop scope, satisfying static analysis requirements
> while preserving the existing logic. The for loop immediately assigns
> i to the first value from the range, so the initialization value is
> never actually used in normal execution paths.
>
> This change resolves the pyright reportPossiblyUnbound error without
> altering the function's behavior or performance characteristics.
>
> Signed-off-by: Wander Lairson Costa <wander@redhat.com>
I understand this is just to suppress a false warning, not fixing real
problem.
Reviewed-by: Nam Cao <namcao@linutronix.de>
^ permalink raw reply [flat|nested] 95+ messages in thread
* [PATCH 18/26] rv/rvgen: add fill_tracepoint_args_skel stub to ltl2k
2026-01-19 20:45 [PATCH 00/26] rv/rvgen: Robustness, modernization, and fixes Wander Lairson Costa
` (16 preceding siblings ...)
2026-01-19 20:45 ` [PATCH 17/26] rv/rvgen: fix possibly unbound variable in ltl2k Wander Lairson Costa
@ 2026-01-19 20:45 ` Wander Lairson Costa
2026-01-21 13:57 ` Gabriele Monaco
2026-01-19 20:45 ` [PATCH 19/26] rv/rvgen: add abstract method stubs to Container class Wander Lairson Costa
` (8 subsequent siblings)
26 siblings, 1 reply; 95+ messages in thread
From: Wander Lairson Costa @ 2026-01-19 20:45 UTC (permalink / raw)
To: Steven Rostedt, Gabriele Monaco, Nam Cao, Wander Lairson Costa,
open list, open list:RUNTIME VERIFICATION (RV)
The ltl2k class inherits from Monitor which requires subclasses to
implement fill_tracepoint_args_skel(). However, the ltl2k template
uses hardcoded tracepoint arguments rather than the placeholders that
this method would fill. The base class fill_trace_h() method calls
fill_tracepoint_args_skel() unconditionally, which was exposed when
the @not_implemented decorator was introduced.
Add a stub implementation that returns an empty string. Since the
ltl2k trace.h template does not contain the placeholder strings that
would be replaced, the empty return value has no effect on the
generated output while satisfying the base class interface contract.
Signed-off-by: Wander Lairson Costa <wander@redhat.com>
---
tools/verification/rvgen/rvgen/ltl2k.py | 3 +++
1 file changed, 3 insertions(+)
diff --git a/tools/verification/rvgen/rvgen/ltl2k.py b/tools/verification/rvgen/rvgen/ltl2k.py
index 94dc64af1716d..f1eafc16c754b 100644
--- a/tools/verification/rvgen/rvgen/ltl2k.py
+++ b/tools/verification/rvgen/rvgen/ltl2k.py
@@ -257,6 +257,9 @@ class ltl2k(generator.Monitor):
return '\n'.join(buf)
+ def fill_tracepoint_args_skel(self, tp_type) -> str:
+ return ""
+
def fill_monitor_class_type(self):
return "LTL_MON_EVENTS_ID"
--
2.52.0
^ permalink raw reply related [flat|nested] 95+ messages in thread* Re: [PATCH 18/26] rv/rvgen: add fill_tracepoint_args_skel stub to ltl2k
2026-01-19 20:45 ` [PATCH 18/26] rv/rvgen: add fill_tracepoint_args_skel stub to ltl2k Wander Lairson Costa
@ 2026-01-21 13:57 ` Gabriele Monaco
2026-01-21 17:53 ` Wander Lairson Costa
0 siblings, 1 reply; 95+ messages in thread
From: Gabriele Monaco @ 2026-01-21 13:57 UTC (permalink / raw)
To: Wander Lairson Costa, Steven Rostedt, Nam Cao, open list,
open list:RUNTIME VERIFICATION (RV)
On Mon, 2026-01-19 at 17:45 -0300, Wander Lairson Costa wrote:
> The ltl2k class inherits from Monitor which requires subclasses to
> implement fill_tracepoint_args_skel(). However, the ltl2k template
> uses hardcoded tracepoint arguments rather than the placeholders that
> this method would fill. The base class fill_trace_h() method calls
> fill_tracepoint_args_skel() unconditionally, which was exposed when
> the @not_implemented decorator was introduced.
>
> Add a stub implementation that returns an empty string. Since the
> ltl2k trace.h template does not contain the placeholder strings that
> would be replaced, the empty return value has no effect on the
> generated output while satisfying the base class interface contract.
>
> Signed-off-by: Wander Lairson Costa <wander@redhat.com>
Mmh, this is a bit fishy though.
We the patch using the decorator seems fine, but highlights how this method
isn't meant to be in Monitor if not all monitors use it..
Adding a stub here is just sweeping dust under the carpet.
Here should probably keep the common part of fill_trace_h() in Monitor (e.g.
replacing MODEL_NAME and other common things) and create specific
implementations in dot2k and ltl2k for what is not common while calling the
super() counterpart for the rest.
Does it make sense to you?
Thanks,
Gabriele
> ---
> tools/verification/rvgen/rvgen/ltl2k.py | 3 +++
> 1 file changed, 3 insertions(+)
>
> diff --git a/tools/verification/rvgen/rvgen/ltl2k.py
> b/tools/verification/rvgen/rvgen/ltl2k.py
> index 94dc64af1716d..f1eafc16c754b 100644
> --- a/tools/verification/rvgen/rvgen/ltl2k.py
> +++ b/tools/verification/rvgen/rvgen/ltl2k.py
> @@ -257,6 +257,9 @@ class ltl2k(generator.Monitor):
>
> return '\n'.join(buf)
>
> + def fill_tracepoint_args_skel(self, tp_type) -> str:
> + return ""
> +
> def fill_monitor_class_type(self):
> return "LTL_MON_EVENTS_ID"
>
^ permalink raw reply [flat|nested] 95+ messages in thread
* Re: [PATCH 18/26] rv/rvgen: add fill_tracepoint_args_skel stub to ltl2k
2026-01-21 13:57 ` Gabriele Monaco
@ 2026-01-21 17:53 ` Wander Lairson Costa
2026-01-22 13:10 ` Wander Lairson Costa
0 siblings, 1 reply; 95+ messages in thread
From: Wander Lairson Costa @ 2026-01-21 17:53 UTC (permalink / raw)
To: Gabriele Monaco
Cc: Steven Rostedt, Nam Cao, open list,
open list:RUNTIME VERIFICATION (RV)
On Wed, Jan 21, 2026 at 02:57:02PM +0100, Gabriele Monaco wrote:
> On Mon, 2026-01-19 at 17:45 -0300, Wander Lairson Costa wrote:
> > The ltl2k class inherits from Monitor which requires subclasses to
> > implement fill_tracepoint_args_skel(). However, the ltl2k template
> > uses hardcoded tracepoint arguments rather than the placeholders that
> > this method would fill. The base class fill_trace_h() method calls
> > fill_tracepoint_args_skel() unconditionally, which was exposed when
> > the @not_implemented decorator was introduced.
> >
> > Add a stub implementation that returns an empty string. Since the
> > ltl2k trace.h template does not contain the placeholder strings that
> > would be replaced, the empty return value has no effect on the
> > generated output while satisfying the base class interface contract.
> >
> > Signed-off-by: Wander Lairson Costa <wander@redhat.com>
>
> Mmh, this is a bit fishy though.
> We the patch using the decorator seems fine, but highlights how this method
> isn't meant to be in Monitor if not all monitors use it..
> Adding a stub here is just sweeping dust under the carpet.
>
> Here should probably keep the common part of fill_trace_h() in Monitor (e.g.
> replacing MODEL_NAME and other common things) and create specific
> implementations in dot2k and ltl2k for what is not common while calling the
> super() counterpart for the rest.
>
> Does it make sense to you?
>
Yes, that is exactly my idea. Since the patch series were getting too
long and my brain too rot, I thought would be better addressing this in
a following up patch series. But I can work in the next version if you
are not ok with that approach.
> Thanks,
> Gabriele
>
> > ---
> > tools/verification/rvgen/rvgen/ltl2k.py | 3 +++
> > 1 file changed, 3 insertions(+)
> >
> > diff --git a/tools/verification/rvgen/rvgen/ltl2k.py
> > b/tools/verification/rvgen/rvgen/ltl2k.py
> > index 94dc64af1716d..f1eafc16c754b 100644
> > --- a/tools/verification/rvgen/rvgen/ltl2k.py
> > +++ b/tools/verification/rvgen/rvgen/ltl2k.py
> > @@ -257,6 +257,9 @@ class ltl2k(generator.Monitor):
> >
> > return '\n'.join(buf)
> >
> > + def fill_tracepoint_args_skel(self, tp_type) -> str:
> > + return ""
> > +
> > def fill_monitor_class_type(self):
> > return "LTL_MON_EVENTS_ID"
> >
>
^ permalink raw reply [flat|nested] 95+ messages in thread
* Re: [PATCH 18/26] rv/rvgen: add fill_tracepoint_args_skel stub to ltl2k
2026-01-21 17:53 ` Wander Lairson Costa
@ 2026-01-22 13:10 ` Wander Lairson Costa
2026-01-22 13:49 ` Gabriele Monaco
0 siblings, 1 reply; 95+ messages in thread
From: Wander Lairson Costa @ 2026-01-22 13:10 UTC (permalink / raw)
To: Gabriele Monaco
Cc: Steven Rostedt, Nam Cao, open list,
open list:RUNTIME VERIFICATION (RV)
On Wed, Jan 21, 2026 at 02:53:03PM -0300, Wander Lairson Costa wrote:
> On Wed, Jan 21, 2026 at 02:57:02PM +0100, Gabriele Monaco wrote:
> > On Mon, 2026-01-19 at 17:45 -0300, Wander Lairson Costa wrote:
> > > The ltl2k class inherits from Monitor which requires subclasses to
> > > implement fill_tracepoint_args_skel(). However, the ltl2k template
> > > uses hardcoded tracepoint arguments rather than the placeholders that
> > > this method would fill. The base class fill_trace_h() method calls
> > > fill_tracepoint_args_skel() unconditionally, which was exposed when
> > > the @not_implemented decorator was introduced.
> > >
> > > Add a stub implementation that returns an empty string. Since the
> > > ltl2k trace.h template does not contain the placeholder strings that
> > > would be replaced, the empty return value has no effect on the
> > > generated output while satisfying the base class interface contract.
> > >
> > > Signed-off-by: Wander Lairson Costa <wander@redhat.com>
> >
> > Mmh, this is a bit fishy though.
> > We the patch using the decorator seems fine, but highlights how this method
> > isn't meant to be in Monitor if not all monitors use it..
> > Adding a stub here is just sweeping dust under the carpet.
> >
> > Here should probably keep the common part of fill_trace_h() in Monitor (e.g.
> > replacing MODEL_NAME and other common things) and create specific
> > implementations in dot2k and ltl2k for what is not common while calling the
> > super() counterpart for the rest.
> >
> > Does it make sense to you?
> >
>
> Yes, that is exactly my idea. Since the patch series were getting too
> long and my brain too rot, I thought would be better addressing this in
> a following up patch series. But I can work in the next version if you
> are not ok with that approach.
>
I gave more thought on this matter yesterday before bed. Maybe this
isn't a issue on the design. Some methods on Monitor might just have a
harmless default behavior. I look into it more closely for next the
round.
> > Thanks,
> > Gabriele
> >
> > > ---
> > > tools/verification/rvgen/rvgen/ltl2k.py | 3 +++
> > > 1 file changed, 3 insertions(+)
> > >
> > > diff --git a/tools/verification/rvgen/rvgen/ltl2k.py
> > > b/tools/verification/rvgen/rvgen/ltl2k.py
> > > index 94dc64af1716d..f1eafc16c754b 100644
> > > --- a/tools/verification/rvgen/rvgen/ltl2k.py
> > > +++ b/tools/verification/rvgen/rvgen/ltl2k.py
> > > @@ -257,6 +257,9 @@ class ltl2k(generator.Monitor):
> > >
> > > return '\n'.join(buf)
> > >
> > > + def fill_tracepoint_args_skel(self, tp_type) -> str:
> > > + return ""
> > > +
> > > def fill_monitor_class_type(self):
> > > return "LTL_MON_EVENTS_ID"
> > >
> >
>
^ permalink raw reply [flat|nested] 95+ messages in thread
* Re: [PATCH 18/26] rv/rvgen: add fill_tracepoint_args_skel stub to ltl2k
2026-01-22 13:10 ` Wander Lairson Costa
@ 2026-01-22 13:49 ` Gabriele Monaco
2026-01-23 12:19 ` Wander Lairson Costa
0 siblings, 1 reply; 95+ messages in thread
From: Gabriele Monaco @ 2026-01-22 13:49 UTC (permalink / raw)
To: Wander Lairson Costa
Cc: Steven Rostedt, Nam Cao, open list,
open list:RUNTIME VERIFICATION (RV)
On Thu, 2026-01-22 at 10:10 -0300, Wander Lairson Costa wrote:
> On Wed, Jan 21, 2026 at 02:53:03PM -0300, Wander Lairson Costa wrote:
> > On Wed, Jan 21, 2026 at 02:57:02PM +0100, Gabriele Monaco wrote:
> > > Mmh, this is a bit fishy though.
> > > We the patch using the decorator seems fine, but highlights how this
> > > method
> > > isn't meant to be in Monitor if not all monitors use it..
> > > Adding a stub here is just sweeping dust under the carpet.
> > >
> > > Here should probably keep the common part of fill_trace_h() in Monitor
> > > (e.g.
> > > replacing MODEL_NAME and other common things) and create specific
> > > implementations in dot2k and ltl2k for what is not common while calling
> > > the
> > > super() counterpart for the rest.
> > >
> > > Does it make sense to you?
> >
> > Yes, that is exactly my idea. Since the patch series were getting too
> > long and my brain too rot, I thought would be better addressing this in
> > a following up patch series. But I can work in the next version if you
> > are not ok with that approach.
Good point, that can be a separate series so that we don't mix too many things,
but I'd also separate the initial patch introducing the @not_implemented .
> I gave more thought on this matter yesterday before bed. Maybe this
> isn't a issue on the design. Some methods on Monitor might just have a
> harmless default behavior. I look into it more closely for next the
> round.
Well, I believe that if a bunch of methods from the parent class don't need to
be called and we have to create stubs just to avoid errors, those methods
probably shouldn't be there in the first place.
That's particularly valid for the Container class, that won't ever need to fill
tracepoints and other stuff.
Why fill_tracepoint_args_skel() is not required by LTL is an implementation
detail, so that stub could even stay, in case future monitors are going to need
the entire thing.
Though I still find it cleaner to move that away too until there's a need for it
shared in Monitor.
What do you think?
Thanks,
Gabriele
^ permalink raw reply [flat|nested] 95+ messages in thread
* Re: [PATCH 18/26] rv/rvgen: add fill_tracepoint_args_skel stub to ltl2k
2026-01-22 13:49 ` Gabriele Monaco
@ 2026-01-23 12:19 ` Wander Lairson Costa
2026-01-23 12:26 ` Gabriele Monaco
0 siblings, 1 reply; 95+ messages in thread
From: Wander Lairson Costa @ 2026-01-23 12:19 UTC (permalink / raw)
To: Gabriele Monaco
Cc: Steven Rostedt, Nam Cao, open list,
open list:RUNTIME VERIFICATION (RV)
On Thu, Jan 22, 2026 at 02:49:59PM +0100, Gabriele Monaco wrote:
> On Thu, 2026-01-22 at 10:10 -0300, Wander Lairson Costa wrote:
> > On Wed, Jan 21, 2026 at 02:53:03PM -0300, Wander Lairson Costa wrote:
> > > On Wed, Jan 21, 2026 at 02:57:02PM +0100, Gabriele Monaco wrote:
> > > > Mmh, this is a bit fishy though.
> > > > We the patch using the decorator seems fine, but highlights how this
> > > > method
> > > > isn't meant to be in Monitor if not all monitors use it..
> > > > Adding a stub here is just sweeping dust under the carpet.
> > > >
> > > > Here should probably keep the common part of fill_trace_h() in Monitor
> > > > (e.g.
> > > > replacing MODEL_NAME and other common things) and create specific
> > > > implementations in dot2k and ltl2k for what is not common while calling
> > > > the
> > > > super() counterpart for the rest.
> > > >
> > > > Does it make sense to you?
> > >
> > > Yes, that is exactly my idea. Since the patch series were getting too
> > > long and my brain too rot, I thought would be better addressing this in
> > > a following up patch series. But I can work in the next version if you
> > > are not ok with that approach.
>
> Good point, that can be a separate series so that we don't mix too many things,
> but I'd also separate the initial patch introducing the @not_implemented .
>
> > I gave more thought on this matter yesterday before bed. Maybe this
> > isn't a issue on the design. Some methods on Monitor might just have a
> > harmless default behavior. I look into it more closely for next the
> > round.
>
> Well, I believe that if a bunch of methods from the parent class don't need to
> be called and we have to create stubs just to avoid errors, those methods
> probably shouldn't be there in the first place.
>
> That's particularly valid for the Container class, that won't ever need to fill
> tracepoints and other stuff.
>
> Why fill_tracepoint_args_skel() is not required by LTL is an implementation
> detail, so that stub could even stay, in case future monitors are going to need
> the entire thing.
> Though I still find it cleaner to move that away too until there's a need for it
> shared in Monitor.
>
I didn't catch what is included in "that"...
> What do you think?
>
I agreed. fill_tracepoint_args_skel() makes sense in the Monitor class.
If a derived class doesn't need it, it is an implementation detail.
> Thanks,
> Gabriele
>
^ permalink raw reply [flat|nested] 95+ messages in thread
* Re: [PATCH 18/26] rv/rvgen: add fill_tracepoint_args_skel stub to ltl2k
2026-01-23 12:19 ` Wander Lairson Costa
@ 2026-01-23 12:26 ` Gabriele Monaco
2026-01-23 14:04 ` Wander Lairson Costa
0 siblings, 1 reply; 95+ messages in thread
From: Gabriele Monaco @ 2026-01-23 12:26 UTC (permalink / raw)
To: Wander Lairson Costa
Cc: Steven Rostedt, Nam Cao, open list,
open list:RUNTIME VERIFICATION (RV)
On Fri, 2026-01-23 at 09:19 -0300, Wander Lairson Costa wrote:
> On Thu, Jan 22, 2026 at 02:49:59PM +0100, Gabriele Monaco wrote:
> > Why fill_tracepoint_args_skel() is not required by LTL is an implementation
> > detail, so that stub could even stay, in case future monitors are going to
> > need
> > the entire thing.
> > Though I still find it cleaner to move that away too until there's a need
> > for it
> > shared in Monitor.
>
> I didn't catch what is included in "that"...
Right, it ended up quite cryptic, I meant fill_tracepoint_args_skel() could stay
in Monitor although not all Monitors need it, though I honestly prefer to move
it away and not rely on the stub.
> > What do you think?
>
> I agreed. fill_tracepoint_args_skel() makes sense in the Monitor class.
> If a derived class doesn't need it, it is an implementation detail.
>
But I get your stance and agree with that too, where fill_tracepoint_args_skel()
goes is just nitpicking at this point.
Thanks,
Gabriele
^ permalink raw reply [flat|nested] 95+ messages in thread
* Re: [PATCH 18/26] rv/rvgen: add fill_tracepoint_args_skel stub to ltl2k
2026-01-23 12:26 ` Gabriele Monaco
@ 2026-01-23 14:04 ` Wander Lairson Costa
0 siblings, 0 replies; 95+ messages in thread
From: Wander Lairson Costa @ 2026-01-23 14:04 UTC (permalink / raw)
To: Gabriele Monaco
Cc: Steven Rostedt, Nam Cao, open list,
open list:RUNTIME VERIFICATION (RV)
On Fri, Jan 23, 2026 at 01:26:45PM +0100, Gabriele Monaco wrote:
> On Fri, 2026-01-23 at 09:19 -0300, Wander Lairson Costa wrote:
> > On Thu, Jan 22, 2026 at 02:49:59PM +0100, Gabriele Monaco wrote:
> > > Why fill_tracepoint_args_skel() is not required by LTL is an implementation
> > > detail, so that stub could even stay, in case future monitors are going to
> > > need
> > > the entire thing.
> > > Though I still find it cleaner to move that away too until there's a need
> > > for it
> > > shared in Monitor.
> >
> > I didn't catch what is included in "that"...
>
> Right, it ended up quite cryptic, I meant fill_tracepoint_args_skel() could stay
> in Monitor although not all Monitors need it, though I honestly prefer to move
> it away and not rely on the stub.
>
> > > What do you think?
> >
> > I agreed. fill_tracepoint_args_skel() makes sense in the Monitor class.
> > If a derived class doesn't need it, it is an implementation detail.
> >
>
> But I get your stance and agree with that too, where fill_tracepoint_args_skel()
> goes is just nitpicking at this point.
>
I will go with your early suggestion and drop all this related work in
v2 and submitting a separate patch series addressing these interface
issues. Python has some good tools [1,2] to handle that. I intend to
make use of them.
[1] https://docs.python.org/3/library/abc.html
[2] https://typing.python.org/en/latest/spec/protocol.html
> Thanks,
> Gabriele
>
^ permalink raw reply [flat|nested] 95+ messages in thread
* [PATCH 19/26] rv/rvgen: add abstract method stubs to Container class
2026-01-19 20:45 [PATCH 00/26] rv/rvgen: Robustness, modernization, and fixes Wander Lairson Costa
` (17 preceding siblings ...)
2026-01-19 20:45 ` [PATCH 18/26] rv/rvgen: add fill_tracepoint_args_skel stub to ltl2k Wander Lairson Costa
@ 2026-01-19 20:45 ` Wander Lairson Costa
2026-01-21 13:59 ` Gabriele Monaco
2026-01-19 20:45 ` [PATCH 20/26] rv/rvgen: refactor automata.py to use iterator-based parsing Wander Lairson Costa
` (7 subsequent siblings)
26 siblings, 1 reply; 95+ messages in thread
From: Wander Lairson Costa @ 2026-01-19 20:45 UTC (permalink / raw)
To: Steven Rostedt, Gabriele Monaco, Nam Cao, Wander Lairson Costa,
open list, open list:RUNTIME VERIFICATION (RV)
The Container class extends RVGenerator but was missing implementations
for several abstract methods decorated with @not_implemented in the base
class. This could lead to NotImplementedError exceptions if code paths
attempt to call these methods on Container instances.
Add empty-string returning stub implementations for fill_tracepoint_handlers_skel,
fill_tracepoint_attach_probe, fill_tracepoint_detach_helper, and
fill_monitor_class_type. These empty returns are semantically correct
since Container is a grouping mechanism for organizing monitors, not an
actual monitor that generates tracepoint-specific C code.
Signed-off-by: Wander Lairson Costa <wander@redhat.com>
---
tools/verification/rvgen/rvgen/container.py | 12 ++++++++++++
1 file changed, 12 insertions(+)
diff --git a/tools/verification/rvgen/rvgen/container.py b/tools/verification/rvgen/rvgen/container.py
index 51f188530b4dd..65df21dfd17b2 100644
--- a/tools/verification/rvgen/rvgen/container.py
+++ b/tools/verification/rvgen/rvgen/container.py
@@ -30,3 +30,15 @@ class Container(generator.RVGenerator):
self._kconfig_marker(), container_marker)
return result
return result + container_marker
+
+ def fill_tracepoint_handlers_skel(self) -> str:
+ return ""
+
+ def fill_tracepoint_attach_probe(self) -> str:
+ return ""
+
+ def fill_tracepoint_detach_helper(self) -> str:
+ return ""
+
+ def fill_monitor_class_type(self) -> str:
+ return ""
--
2.52.0
^ permalink raw reply related [flat|nested] 95+ messages in thread* Re: [PATCH 19/26] rv/rvgen: add abstract method stubs to Container class
2026-01-19 20:45 ` [PATCH 19/26] rv/rvgen: add abstract method stubs to Container class Wander Lairson Costa
@ 2026-01-21 13:59 ` Gabriele Monaco
2026-01-21 17:56 ` Wander Lairson Costa
2026-01-22 15:33 ` Nam Cao
0 siblings, 2 replies; 95+ messages in thread
From: Gabriele Monaco @ 2026-01-21 13:59 UTC (permalink / raw)
To: Wander Lairson Costa
Cc: Steven Rostedt, Nam Cao, open list,
open list:RUNTIME VERIFICATION (RV)
On Mon, 2026-01-19 at 17:45 -0300, Wander Lairson Costa wrote:
> The Container class extends RVGenerator but was missing implementations
> for several abstract methods decorated with @not_implemented in the base
> class. This could lead to NotImplementedError exceptions if code paths
> attempt to call these methods on Container instances.
>
> Add empty-string returning stub implementations for
> fill_tracepoint_handlers_skel,
> fill_tracepoint_attach_probe, fill_tracepoint_detach_helper, and
> fill_monitor_class_type. These empty returns are semantically correct
> since Container is a grouping mechanism for organizing monitors, not an
> actual monitor that generates tracepoint-specific C code.
>
> Signed-off-by: Wander Lairson Costa <wander@redhat.com>
> ---
Just like the previous patch, the NotImplementedError here highlights a weakness
in the design we should improve instead of cover.
If all those fillers don't make sense for containers, we should instead move
them to Monitor and leave RVGenerator alone.
Thanks,
Gabriele
> tools/verification/rvgen/rvgen/container.py | 12 ++++++++++++
> 1 file changed, 12 insertions(+)
>
> diff --git a/tools/verification/rvgen/rvgen/container.py
> b/tools/verification/rvgen/rvgen/container.py
> index 51f188530b4dd..65df21dfd17b2 100644
> --- a/tools/verification/rvgen/rvgen/container.py
> +++ b/tools/verification/rvgen/rvgen/container.py
> @@ -30,3 +30,15 @@ class Container(generator.RVGenerator):
> self._kconfig_marker(), container_marker)
> return result
> return result + container_marker
> +
> + def fill_tracepoint_handlers_skel(self) -> str:
> + return ""
> +
> + def fill_tracepoint_attach_probe(self) -> str:
> + return ""
> +
> + def fill_tracepoint_detach_helper(self) -> str:
> + return ""
> +
> + def fill_monitor_class_type(self) -> str:
> + return ""
^ permalink raw reply [flat|nested] 95+ messages in thread
* Re: [PATCH 19/26] rv/rvgen: add abstract method stubs to Container class
2026-01-21 13:59 ` Gabriele Monaco
@ 2026-01-21 17:56 ` Wander Lairson Costa
2026-01-22 15:33 ` Nam Cao
1 sibling, 0 replies; 95+ messages in thread
From: Wander Lairson Costa @ 2026-01-21 17:56 UTC (permalink / raw)
To: Gabriele Monaco
Cc: Steven Rostedt, Nam Cao, open list,
open list:RUNTIME VERIFICATION (RV)
On Wed, Jan 21, 2026 at 02:59:09PM +0100, Gabriele Monaco wrote:
> On Mon, 2026-01-19 at 17:45 -0300, Wander Lairson Costa wrote:
> > The Container class extends RVGenerator but was missing implementations
> > for several abstract methods decorated with @not_implemented in the base
> > class. This could lead to NotImplementedError exceptions if code paths
> > attempt to call these methods on Container instances.
> >
> > Add empty-string returning stub implementations for
> > fill_tracepoint_handlers_skel,
> > fill_tracepoint_attach_probe, fill_tracepoint_detach_helper, and
> > fill_monitor_class_type. These empty returns are semantically correct
> > since Container is a grouping mechanism for organizing monitors, not an
> > actual monitor that generates tracepoint-specific C code.
> >
> > Signed-off-by: Wander Lairson Costa <wander@redhat.com>
> > ---
>
> Just like the previous patch, the NotImplementedError here highlights a weakness
> in the design we should improve instead of cover.
> If all those fillers don't make sense for containers, we should instead move
> them to Monitor and leave RVGenerator alone.
>
Yes, I agree. The design has a separate of concerns problem. The
previous comment apply here as well.
> Thanks,
> Gabriele
>
> > tools/verification/rvgen/rvgen/container.py | 12 ++++++++++++
> > 1 file changed, 12 insertions(+)
> >
> > diff --git a/tools/verification/rvgen/rvgen/container.py
> > b/tools/verification/rvgen/rvgen/container.py
> > index 51f188530b4dd..65df21dfd17b2 100644
> > --- a/tools/verification/rvgen/rvgen/container.py
> > +++ b/tools/verification/rvgen/rvgen/container.py
> > @@ -30,3 +30,15 @@ class Container(generator.RVGenerator):
> > self._kconfig_marker(), container_marker)
> > return result
> > return result + container_marker
> > +
> > + def fill_tracepoint_handlers_skel(self) -> str:
> > + return ""
> > +
> > + def fill_tracepoint_attach_probe(self) -> str:
> > + return ""
> > +
> > + def fill_tracepoint_detach_helper(self) -> str:
> > + return ""
> > +
> > + def fill_monitor_class_type(self) -> str:
> > + return ""
>
^ permalink raw reply [flat|nested] 95+ messages in thread
* Re: [PATCH 19/26] rv/rvgen: add abstract method stubs to Container class
2026-01-21 13:59 ` Gabriele Monaco
2026-01-21 17:56 ` Wander Lairson Costa
@ 2026-01-22 15:33 ` Nam Cao
1 sibling, 0 replies; 95+ messages in thread
From: Nam Cao @ 2026-01-22 15:33 UTC (permalink / raw)
To: Gabriele Monaco, Wander Lairson Costa
Cc: Steven Rostedt, open list, open list:RUNTIME VERIFICATION (RV)
Gabriele Monaco <gmonaco@redhat.com> writes:
> On Mon, 2026-01-19 at 17:45 -0300, Wander Lairson Costa wrote:
>> The Container class extends RVGenerator but was missing implementations
>> for several abstract methods decorated with @not_implemented in the base
>> class. This could lead to NotImplementedError exceptions if code paths
>> attempt to call these methods on Container instances.
>>
>> Add empty-string returning stub implementations for
>> fill_tracepoint_handlers_skel,
>> fill_tracepoint_attach_probe, fill_tracepoint_detach_helper, and
>> fill_monitor_class_type. These empty returns are semantically correct
>> since Container is a grouping mechanism for organizing monitors, not an
>> actual monitor that generates tracepoint-specific C code.
>>
>> Signed-off-by: Wander Lairson Costa <wander@redhat.com>
>> ---
>
> Just like the previous patch, the NotImplementedError here highlights a weakness
> in the design we should improve instead of cover.
> If all those fillers don't make sense for containers, we should instead move
> them to Monitor and leave RVGenerator alone.
Agree.
Nam
^ permalink raw reply [flat|nested] 95+ messages in thread
* [PATCH 20/26] rv/rvgen: refactor automata.py to use iterator-based parsing
2026-01-19 20:45 [PATCH 00/26] rv/rvgen: Robustness, modernization, and fixes Wander Lairson Costa
` (18 preceding siblings ...)
2026-01-19 20:45 ` [PATCH 19/26] rv/rvgen: add abstract method stubs to Container class Wander Lairson Costa
@ 2026-01-19 20:45 ` Wander Lairson Costa
2026-01-20 9:43 ` Gabriele Monaco
2026-01-19 20:45 ` [PATCH 21/26] rv/rvgen: remove unused sys import from dot2c Wander Lairson Costa
` (6 subsequent siblings)
26 siblings, 1 reply; 95+ messages in thread
From: Wander Lairson Costa @ 2026-01-19 20:45 UTC (permalink / raw)
To: Steven Rostedt, Gabriele Monaco, Nam Cao, Wander Lairson Costa,
open list, open list:RUNTIME VERIFICATION (RV)
Refactor the DOT file parsing logic in automata.py to use Python's
iterator-based patterns instead of manual cursor indexing. The previous
implementation relied on while loops with explicit cursor management,
which made the code prone to off-by-one errors and would crash on
malformed input files containing empty lines.
The new implementation uses enumerate and itertools.islice to iterate
over lines, eliminating manual cursor tracking. Functions that search
for specific markers now use for loops with early returns and explicit
AutomataError exceptions for missing markers, rather than assuming the
markers exist. Additional bounds checking ensures that split line
arrays have sufficient elements before accessing specific indices,
preventing IndexError exceptions on malformed DOT files.
The matrix creation and event variable extraction methods now use
functional patterns with map combined with itertools.islice,
making the intent clearer while maintaining the same behavior. Minor
improvements include using extend instead of append in a loop, adding
empty file validation, and replacing enumerate with range where the
enumerated value was unused.
Signed-off-by: Wander Lairson Costa <wander@redhat.com>
---
tools/verification/rvgen/rvgen/automata.py | 109 +++++++++++++--------
1 file changed, 67 insertions(+), 42 deletions(-)
diff --git a/tools/verification/rvgen/rvgen/automata.py b/tools/verification/rvgen/rvgen/automata.py
index 083d0f5cfb773..a6889d0c26c3f 100644
--- a/tools/verification/rvgen/rvgen/automata.py
+++ b/tools/verification/rvgen/rvgen/automata.py
@@ -9,6 +9,7 @@
# Documentation/trace/rv/deterministic_automata.rst
import ntpath
+from itertools import islice
class AutomataError(OSError):
@@ -53,37 +54,54 @@ class Automata:
return model_name
def __open_dot(self):
- cursor = 0
dot_lines = []
try:
with open(self.__dot_path) as dot_file:
- dot_lines = dot_file.read().splitlines()
+ dot_lines = dot_file.readlines()
except OSError as exc:
raise AutomataError(f"Cannot open the file: {self.__dot_path}") from exc
+ if not dot_lines:
+ raise AutomataError(f"{self.__dot_path} is empty")
+
# checking the first line:
- line = dot_lines[cursor].split()
+ line = dot_lines[0].split()
- if (line[0] != "digraph") or (line[1] != "state_automaton"):
+ if len(line) < 2 or line[0] != "digraph" or line[1] != "state_automaton":
raise AutomataError(f"Not a valid .dot format: {self.__dot_path}")
- else:
- cursor += 1
+
return dot_lines
def __get_cursor_begin_states(self):
- cursor = 0
- while self.__dot_lines[cursor].split()[0] != "{node":
- cursor += 1
- return cursor
+ for cursor, line in enumerate(self.__dot_lines):
+ split_line = line.split()
+
+ if len(split_line) and split_line[0] == "{node":
+ return cursor
+
+ raise AutomataError("Could not find a beginning state")
def __get_cursor_begin_events(self):
- cursor = 0
- while self.__dot_lines[cursor].split()[0] != "{node":
- cursor += 1
- while self.__dot_lines[cursor].split()[0] == "{node":
- cursor += 1
- # skip initial state transition
- cursor += 1
+ state = 0
+ cursor = 0 # make pyright happy
+
+ for cursor, line in enumerate(self.__dot_lines):
+ line = line.split()
+ if not line:
+ continue
+
+ if state == 0:
+ if line[0] == "{node":
+ state = 1
+ elif line[0] != "{node":
+ break
+ else:
+ raise AutomataError("Could not find beginning event")
+
+ cursor += 1 # skip initial state transition
+ if cursor == len(self.__dot_lines):
+ raise AutomataError("Dot file ended after event beginning")
+
return cursor
def __get_state_variables(self):
@@ -96,9 +114,12 @@ class Automata:
cursor = self.__get_cursor_begin_states()
# process nodes
- while self.__dot_lines[cursor].split()[0] == "{node":
- line = self.__dot_lines[cursor].split()
- raw_state = line[-1]
+ for line in islice(self.__dot_lines, cursor, None):
+ split_line = line.split()
+ if not split_line or split_line[0] != "{node":
+ break
+
+ raw_state = split_line[-1]
# "enabled_fired"}; -> enabled_fired
state = raw_state.replace('"', "").replace("};", "").replace(",", "_")
@@ -106,16 +127,14 @@ class Automata:
initial_state = state[len(self.init_marker) :]
else:
states.append(state)
- if "doublecircle" in self.__dot_lines[cursor]:
+ if "doublecircle" in line:
final_states.append(state)
has_final_states = True
- if "ellipse" in self.__dot_lines[cursor]:
+ if "ellipse" in line:
final_states.append(state)
has_final_states = True
- cursor += 1
-
if initial_state is None:
raise AutomataError("The automaton doesn't have a initial state")
@@ -130,26 +149,27 @@ class Automata:
return states, initial_state, final_states
def __get_event_variables(self):
+ events: list[str] = []
# here we are at the begin of transitions, take a note, we will return later.
cursor = self.__get_cursor_begin_events()
- events = []
- while self.__dot_lines[cursor].lstrip()[0] == '"':
+ for line in map(str.lstrip, islice(self.__dot_lines, cursor, None)):
+ if not line.startswith('"'):
+ break
+
# transitions have the format:
# "all_fired" -> "both_fired" [ label = "disable_irq" ];
# ------------ event is here ------------^^^^^
- if self.__dot_lines[cursor].split()[1] == "->":
- line = self.__dot_lines[cursor].split()
- event = line[-2].replace('"', "")
+ split_line = line.split()
+ if len(split_line) > 1 and split_line[1] == "->":
+ event = split_line[-2].replace('"', "")
# when a transition has more than one labels, they are like this
# "local_irq_enable\nhw_local_irq_enable_n"
# so split them.
event = event.replace("\\n", " ")
- for i in event.split():
- events.append(i)
- cursor += 1
+ events.extend(event.split())
return sorted(set(events))
@@ -171,32 +191,37 @@ class Automata:
# declare the matrix....
matrix = [
- [self.invalid_state_str for x in range(nr_event)] for y in range(nr_state)
+ [self.invalid_state_str for _ in range(nr_event)] for _ in range(nr_state)
]
# and we are back! Let's fill the matrix
cursor = self.__get_cursor_begin_events()
- while self.__dot_lines[cursor].lstrip()[0] == '"':
- if self.__dot_lines[cursor].split()[1] == "->":
- line = self.__dot_lines[cursor].split()
- origin_state = line[0].replace('"', "").replace(",", "_")
- dest_state = line[2].replace('"', "").replace(",", "_")
- possible_events = line[-2].replace('"', "").replace("\\n", " ")
+ for line in map(str.lstrip,
+ islice(self.__dot_lines, cursor, None)):
+
+ if not line or line[0] != '"':
+ break
+
+ split_line = line.split()
+
+ if len(split_line) > 2 and split_line[1] == "->":
+ origin_state = split_line[0].replace('"', "").replace(",", "_")
+ dest_state = split_line[2].replace('"', "").replace(",", "_")
+ possible_events = split_line[-2].replace('"', "").replace("\\n", " ")
for event in possible_events.split():
matrix[states_dict[origin_state]][events_dict[event]] = dest_state
- cursor += 1
return matrix
def __store_init_events(self):
events_start = [False] * len(self.events)
events_start_run = [False] * len(self.events)
- for i, _ in enumerate(self.events):
+ for i in range(len(self.events)):
curr_event_will_init = 0
curr_event_from_init = False
curr_event_used = 0
- for j, _ in enumerate(self.states):
+ for j in range(len(self.states)):
if self.function[j][i] != self.invalid_state_str:
curr_event_used += 1
if self.function[j][i] == self.initial_state:
--
2.52.0
^ permalink raw reply related [flat|nested] 95+ messages in thread* Re: [PATCH 20/26] rv/rvgen: refactor automata.py to use iterator-based parsing
2026-01-19 20:45 ` [PATCH 20/26] rv/rvgen: refactor automata.py to use iterator-based parsing Wander Lairson Costa
@ 2026-01-20 9:43 ` Gabriele Monaco
2026-01-22 15:35 ` Nam Cao
0 siblings, 1 reply; 95+ messages in thread
From: Gabriele Monaco @ 2026-01-20 9:43 UTC (permalink / raw)
To: Wander Lairson Costa
Cc: Steven Rostedt, Nam Cao, open list,
open list:RUNTIME VERIFICATION (RV)
On Mon, 2026-01-19 at 17:45 -0300, Wander Lairson Costa wrote:
> Refactor the DOT file parsing logic in automata.py to use Python's
> iterator-based patterns instead of manual cursor indexing. The previous
> implementation relied on while loops with explicit cursor management,
> which made the code prone to off-by-one errors and would crash on
> malformed input files containing empty lines.
>
> The new implementation uses enumerate and itertools.islice to iterate
> over lines, eliminating manual cursor tracking. Functions that search
> for specific markers now use for loops with early returns and explicit
> AutomataError exceptions for missing markers, rather than assuming the
> markers exist. Additional bounds checking ensures that split line
> arrays have sufficient elements before accessing specific indices,
> preventing IndexError exceptions on malformed DOT files.
>
> The matrix creation and event variable extraction methods now use
> functional patterns with map combined with itertools.islice,
> making the intent clearer while maintaining the same behavior. Minor
> improvements include using extend instead of append in a loop, adding
> empty file validation, and replacing enumerate with range where the
> enumerated value was unused.
>
> Signed-off-by: Wander Lairson Costa <wander@redhat.com>
The changes look sensible, thanks.
Just know that this parser is already quite fragile and we are planning a major
refactor using ply with a well-defined grammar and tokenizer, like how the LTL
parser is implemented.
So I wouldn't spend too much time on this implementation.
Reviewed-by: Gabriele Monaco <gmonaco@redhat.com>
> ---
> tools/verification/rvgen/rvgen/automata.py | 109 +++++++++++++--------
> 1 file changed, 67 insertions(+), 42 deletions(-)
>
> diff --git a/tools/verification/rvgen/rvgen/automata.py
> b/tools/verification/rvgen/rvgen/automata.py
> index 083d0f5cfb773..a6889d0c26c3f 100644
> --- a/tools/verification/rvgen/rvgen/automata.py
> +++ b/tools/verification/rvgen/rvgen/automata.py
> @@ -9,6 +9,7 @@
> # Documentation/trace/rv/deterministic_automata.rst
>
> import ntpath
> +from itertools import islice
>
>
> class AutomataError(OSError):
> @@ -53,37 +54,54 @@ class Automata:
> return model_name
>
> def __open_dot(self):
> - cursor = 0
> dot_lines = []
> try:
> with open(self.__dot_path) as dot_file:
> - dot_lines = dot_file.read().splitlines()
> + dot_lines = dot_file.readlines()
> except OSError as exc:
> raise AutomataError(f"Cannot open the file: {self.__dot_path}")
> from exc
>
> + if not dot_lines:
> + raise AutomataError(f"{self.__dot_path} is empty")
> +
> # checking the first line:
> - line = dot_lines[cursor].split()
> + line = dot_lines[0].split()
>
> - if (line[0] != "digraph") or (line[1] != "state_automaton"):
> + if len(line) < 2 or line[0] != "digraph" or line[1] !=
> "state_automaton":
> raise AutomataError(f"Not a valid .dot format:
> {self.__dot_path}")
> - else:
> - cursor += 1
> +
> return dot_lines
>
> def __get_cursor_begin_states(self):
> - cursor = 0
> - while self.__dot_lines[cursor].split()[0] != "{node":
> - cursor += 1
> - return cursor
> + for cursor, line in enumerate(self.__dot_lines):
> + split_line = line.split()
> +
> + if len(split_line) and split_line[0] == "{node":
> + return cursor
> +
> + raise AutomataError("Could not find a beginning state")
>
> def __get_cursor_begin_events(self):
> - cursor = 0
> - while self.__dot_lines[cursor].split()[0] != "{node":
> - cursor += 1
> - while self.__dot_lines[cursor].split()[0] == "{node":
> - cursor += 1
> - # skip initial state transition
> - cursor += 1
> + state = 0
> + cursor = 0 # make pyright happy
> +
> + for cursor, line in enumerate(self.__dot_lines):
> + line = line.split()
> + if not line:
> + continue
> +
> + if state == 0:
> + if line[0] == "{node":
> + state = 1
> + elif line[0] != "{node":
> + break
> + else:
> + raise AutomataError("Could not find beginning event")
> +
> + cursor += 1 # skip initial state transition
> + if cursor == len(self.__dot_lines):
> + raise AutomataError("Dot file ended after event beginning")
> +
> return cursor
>
> def __get_state_variables(self):
> @@ -96,9 +114,12 @@ class Automata:
> cursor = self.__get_cursor_begin_states()
>
> # process nodes
> - while self.__dot_lines[cursor].split()[0] == "{node":
> - line = self.__dot_lines[cursor].split()
> - raw_state = line[-1]
> + for line in islice(self.__dot_lines, cursor, None):
> + split_line = line.split()
> + if not split_line or split_line[0] != "{node":
> + break
> +
> + raw_state = split_line[-1]
>
> # "enabled_fired"}; -> enabled_fired
> state = raw_state.replace('"', "").replace("};", "").replace(",",
> "_")
> @@ -106,16 +127,14 @@ class Automata:
> initial_state = state[len(self.init_marker) :]
> else:
> states.append(state)
> - if "doublecircle" in self.__dot_lines[cursor]:
> + if "doublecircle" in line:
> final_states.append(state)
> has_final_states = True
>
> - if "ellipse" in self.__dot_lines[cursor]:
> + if "ellipse" in line:
> final_states.append(state)
> has_final_states = True
>
> - cursor += 1
> -
> if initial_state is None:
> raise AutomataError("The automaton doesn't have a initial state")
>
> @@ -130,26 +149,27 @@ class Automata:
> return states, initial_state, final_states
>
> def __get_event_variables(self):
> + events: list[str] = []
> # here we are at the begin of transitions, take a note, we will
> return later.
> cursor = self.__get_cursor_begin_events()
>
> - events = []
> - while self.__dot_lines[cursor].lstrip()[0] == '"':
> + for line in map(str.lstrip, islice(self.__dot_lines, cursor, None)):
> + if not line.startswith('"'):
> + break
> +
> # transitions have the format:
> # "all_fired" -> "both_fired" [ label = "disable_irq" ];
> # ------------ event is here ------------^^^^^
> - if self.__dot_lines[cursor].split()[1] == "->":
> - line = self.__dot_lines[cursor].split()
> - event = line[-2].replace('"', "")
> + split_line = line.split()
> + if len(split_line) > 1 and split_line[1] == "->":
> + event = split_line[-2].replace('"', "")
>
> # when a transition has more than one labels, they are like
> this
> # "local_irq_enable\nhw_local_irq_enable_n"
> # so split them.
>
> event = event.replace("\\n", " ")
> - for i in event.split():
> - events.append(i)
> - cursor += 1
> + events.extend(event.split())
>
> return sorted(set(events))
>
> @@ -171,32 +191,37 @@ class Automata:
>
> # declare the matrix....
> matrix = [
> - [self.invalid_state_str for x in range(nr_event)] for y in
> range(nr_state)
> + [self.invalid_state_str for _ in range(nr_event)] for _ in
> range(nr_state)
> ]
>
> # and we are back! Let's fill the matrix
> cursor = self.__get_cursor_begin_events()
>
> - while self.__dot_lines[cursor].lstrip()[0] == '"':
> - if self.__dot_lines[cursor].split()[1] == "->":
> - line = self.__dot_lines[cursor].split()
> - origin_state = line[0].replace('"', "").replace(",", "_")
> - dest_state = line[2].replace('"', "").replace(",", "_")
> - possible_events = line[-2].replace('"', "").replace("\\n", "
> ")
> + for line in map(str.lstrip,
> + islice(self.__dot_lines, cursor, None)):
> +
> + if not line or line[0] != '"':
> + break
> +
> + split_line = line.split()
> +
> + if len(split_line) > 2 and split_line[1] == "->":
> + origin_state = split_line[0].replace('"', "").replace(",",
> "_")
> + dest_state = split_line[2].replace('"', "").replace(",", "_")
> + possible_events = split_line[-2].replace('"',
> "").replace("\\n", " ")
> for event in possible_events.split():
> matrix[states_dict[origin_state]][events_dict[event]] =
> dest_state
> - cursor += 1
>
> return matrix
>
> def __store_init_events(self):
> events_start = [False] * len(self.events)
> events_start_run = [False] * len(self.events)
> - for i, _ in enumerate(self.events):
> + for i in range(len(self.events)):
> curr_event_will_init = 0
> curr_event_from_init = False
> curr_event_used = 0
> - for j, _ in enumerate(self.states):
> + for j in range(len(self.states)):
> if self.function[j][i] != self.invalid_state_str:
> curr_event_used += 1
> if self.function[j][i] == self.initial_state:
^ permalink raw reply [flat|nested] 95+ messages in thread* Re: [PATCH 20/26] rv/rvgen: refactor automata.py to use iterator-based parsing
2026-01-20 9:43 ` Gabriele Monaco
@ 2026-01-22 15:35 ` Nam Cao
2026-01-22 15:40 ` Gabriele Monaco
0 siblings, 1 reply; 95+ messages in thread
From: Nam Cao @ 2026-01-22 15:35 UTC (permalink / raw)
To: Gabriele Monaco, Wander Lairson Costa
Cc: Steven Rostedt, open list, open list:RUNTIME VERIFICATION (RV)
Gabriele Monaco <gmonaco@redhat.com> writes:
> Just know that this parser is already quite fragile and we are planning a major
> refactor using ply with a well-defined grammar and tokenizer, like how the LTL
> parser is implemented.
I will get to it after your hybrid automaton stuff is merged, I don't
want to deal with conflict.
Nam
^ permalink raw reply [flat|nested] 95+ messages in thread
* Re: [PATCH 20/26] rv/rvgen: refactor automata.py to use iterator-based parsing
2026-01-22 15:35 ` Nam Cao
@ 2026-01-22 15:40 ` Gabriele Monaco
2026-01-22 16:01 ` Nam Cao
0 siblings, 1 reply; 95+ messages in thread
From: Gabriele Monaco @ 2026-01-22 15:40 UTC (permalink / raw)
To: Nam Cao, Wander Lairson Costa
Cc: Steven Rostedt, open list, open list:RUNTIME VERIFICATION (RV)
On Thu, 2026-01-22 at 16:35 +0100, Nam Cao wrote:
> Gabriele Monaco <gmonaco@redhat.com> writes:
> > Just know that this parser is already quite fragile and we are planning a
> > major
> > refactor using ply with a well-defined grammar and tokenizer, like how the
> > LTL
> > parser is implemented.
>
> I will get to it after your hybrid automaton stuff is merged, I don't
> want to deal with conflict.
>
> Nam
Definitely, that isn't a priority.
By the way, I just noticed the ply repo got archived on Github [1], I wonder
this endeavour is wise, although ply seems quite ubiquitous so someone may step
up and fork the project.
[1] - https://github.com/dabeaz/ply#important-notice---december-21-2025
^ permalink raw reply [flat|nested] 95+ messages in thread
* Re: [PATCH 20/26] rv/rvgen: refactor automata.py to use iterator-based parsing
2026-01-22 15:40 ` Gabriele Monaco
@ 2026-01-22 16:01 ` Nam Cao
0 siblings, 0 replies; 95+ messages in thread
From: Nam Cao @ 2026-01-22 16:01 UTC (permalink / raw)
To: Gabriele Monaco, Wander Lairson Costa
Cc: Steven Rostedt, open list, open list:RUNTIME VERIFICATION (RV)
Gabriele Monaco <gmonaco@redhat.com> writes:
> By the way, I just noticed the ply repo got archived on Github [1], I wonder
> this endeavour is wise, although ply seems quite ubiquitous so someone may step
> up and fork the project.
Nooo :(
Let me figure out why he means by "there are many high-quality parsing
libraries that you might consider using instead".
Nam
^ permalink raw reply [flat|nested] 95+ messages in thread
* [PATCH 21/26] rv/rvgen: remove unused sys import from dot2c
2026-01-19 20:45 [PATCH 00/26] rv/rvgen: Robustness, modernization, and fixes Wander Lairson Costa
` (19 preceding siblings ...)
2026-01-19 20:45 ` [PATCH 20/26] rv/rvgen: refactor automata.py to use iterator-based parsing Wander Lairson Costa
@ 2026-01-19 20:45 ` Wander Lairson Costa
2026-01-20 9:16 ` Gabriele Monaco
2026-01-19 20:45 ` [PATCH 22/26] rv/rvgen: remove unused __get_main_name method Wander Lairson Costa
` (5 subsequent siblings)
26 siblings, 1 reply; 95+ messages in thread
From: Wander Lairson Costa @ 2026-01-19 20:45 UTC (permalink / raw)
To: Steven Rostedt, Gabriele Monaco, Nam Cao, Wander Lairson Costa,
open list, open list:RUNTIME VERIFICATION (RV)
The sys module was imported in the dot2c frontend script but never
used. This import was likely left over from earlier development or
copied from a template that required sys for exit handling.
Remove the unused import to clean up the code and satisfy linters
that flag unused imports as errors.
Signed-off-by: Wander Lairson Costa <wander@redhat.com>
---
tools/verification/rvgen/dot2c | 1 -
1 file changed, 1 deletion(-)
diff --git a/tools/verification/rvgen/dot2c b/tools/verification/rvgen/dot2c
index bf0c67c5b66c8..1012becc7fab6 100644
--- a/tools/verification/rvgen/dot2c
+++ b/tools/verification/rvgen/dot2c
@@ -16,7 +16,6 @@
if __name__ == '__main__':
from rvgen import dot2c
import argparse
- import sys
parser = argparse.ArgumentParser(description='dot2c: converts a .dot file into a C structure')
parser.add_argument('dot_file', help='The dot file to be converted')
--
2.52.0
^ permalink raw reply related [flat|nested] 95+ messages in thread* Re: [PATCH 21/26] rv/rvgen: remove unused sys import from dot2c
2026-01-19 20:45 ` [PATCH 21/26] rv/rvgen: remove unused sys import from dot2c Wander Lairson Costa
@ 2026-01-20 9:16 ` Gabriele Monaco
0 siblings, 0 replies; 95+ messages in thread
From: Gabriele Monaco @ 2026-01-20 9:16 UTC (permalink / raw)
To: Wander Lairson Costa
Cc: Steven Rostedt, Nam Cao, open list,
open list:RUNTIME VERIFICATION (RV)
On Mon, 2026-01-19 at 17:45 -0300, Wander Lairson Costa wrote:
> The sys module was imported in the dot2c frontend script but never
> used. This import was likely left over from earlier development or
> copied from a template that required sys for exit handling.
>
> Remove the unused import to clean up the code and satisfy linters
> that flag unused imports as errors.
>
> Signed-off-by: Wander Lairson Costa <wander@redhat.com>
Good catch, thanks!
Reviewed-by: Gabriele Monaco <gmonaco@redhat.com>
> ---
> tools/verification/rvgen/dot2c | 1 -
> 1 file changed, 1 deletion(-)
>
> diff --git a/tools/verification/rvgen/dot2c b/tools/verification/rvgen/dot2c
> index bf0c67c5b66c8..1012becc7fab6 100644
> --- a/tools/verification/rvgen/dot2c
> +++ b/tools/verification/rvgen/dot2c
> @@ -16,7 +16,6 @@
> if __name__ == '__main__':
> from rvgen import dot2c
> import argparse
> - import sys
>
> parser = argparse.ArgumentParser(description='dot2c: converts a .dot file
> into a C structure')
> parser.add_argument('dot_file', help='The dot file to be converted')
^ permalink raw reply [flat|nested] 95+ messages in thread
* [PATCH 22/26] rv/rvgen: remove unused __get_main_name method
2026-01-19 20:45 [PATCH 00/26] rv/rvgen: Robustness, modernization, and fixes Wander Lairson Costa
` (20 preceding siblings ...)
2026-01-19 20:45 ` [PATCH 21/26] rv/rvgen: remove unused sys import from dot2c Wander Lairson Costa
@ 2026-01-19 20:45 ` Wander Lairson Costa
2026-01-20 9:08 ` Gabriele Monaco
2026-01-19 20:45 ` [PATCH 23/26] rv/rvgen: add type annotations to fix pyright errors Wander Lairson Costa
` (4 subsequent siblings)
26 siblings, 1 reply; 95+ messages in thread
From: Wander Lairson Costa @ 2026-01-19 20:45 UTC (permalink / raw)
To: Steven Rostedt, Gabriele Monaco, Nam Cao, Wander Lairson Costa,
open list, open list:RUNTIME VERIFICATION (RV)
The __get_main_name() method in the generator module is never called
from anywhere in the codebase. Remove this dead code to improve
maintainability.
Signed-off-by: Wander Lairson Costa <wander@redhat.com>
---
tools/verification/rvgen/rvgen/generator.py | 6 ------
1 file changed, 6 deletions(-)
diff --git a/tools/verification/rvgen/rvgen/generator.py b/tools/verification/rvgen/rvgen/generator.py
index 0491f8c9cb0b9..d99a980850d64 100644
--- a/tools/verification/rvgen/rvgen/generator.py
+++ b/tools/verification/rvgen/rvgen/generator.py
@@ -206,12 +206,6 @@ obj-$(CONFIG_RV_MON_{name_up}) += monitors/{name}/{name}.o
path = os.path.join(self.rv_dir, "monitors", path)
self.__write_file(path, content)
- def __get_main_name(self):
- path = f"{self.name}/main.c"
- if not os.path.exists(path):
- return "main.c"
- return "__main.c"
-
def print_files(self):
main_c = self.fill_main_c()
--
2.52.0
^ permalink raw reply related [flat|nested] 95+ messages in thread* Re: [PATCH 22/26] rv/rvgen: remove unused __get_main_name method
2026-01-19 20:45 ` [PATCH 22/26] rv/rvgen: remove unused __get_main_name method Wander Lairson Costa
@ 2026-01-20 9:08 ` Gabriele Monaco
0 siblings, 0 replies; 95+ messages in thread
From: Gabriele Monaco @ 2026-01-20 9:08 UTC (permalink / raw)
To: Wander Lairson Costa
Cc: Steven Rostedt, Nam Cao, open list,
open list:RUNTIME VERIFICATION (RV)
On Mon, 2026-01-19 at 17:45 -0300, Wander Lairson Costa wrote:
> The __get_main_name() method in the generator module is never called
> from anywhere in the codebase. Remove this dead code to improve
> maintainability.
>
> Signed-off-by: Wander Lairson Costa <wander@redhat.com>
Good catch, thanks!
Reviewed-by: Gabriele Monaco <gmonaco@redhat.com>
> ---
> tools/verification/rvgen/rvgen/generator.py | 6 ------
> 1 file changed, 6 deletions(-)
>
> diff --git a/tools/verification/rvgen/rvgen/generator.py
> b/tools/verification/rvgen/rvgen/generator.py
> index 0491f8c9cb0b9..d99a980850d64 100644
> --- a/tools/verification/rvgen/rvgen/generator.py
> +++ b/tools/verification/rvgen/rvgen/generator.py
> @@ -206,12 +206,6 @@ obj-$(CONFIG_RV_MON_{name_up}) +=
> monitors/{name}/{name}.o
> path = os.path.join(self.rv_dir, "monitors", path)
> self.__write_file(path, content)
>
> - def __get_main_name(self):
> - path = f"{self.name}/main.c"
> - if not os.path.exists(path):
> - return "main.c"
> - return "__main.c"
> -
> def print_files(self):
> main_c = self.fill_main_c()
>
^ permalink raw reply [flat|nested] 95+ messages in thread
* [PATCH 23/26] rv/rvgen: add type annotations to fix pyright errors
2026-01-19 20:45 [PATCH 00/26] rv/rvgen: Robustness, modernization, and fixes Wander Lairson Costa
` (21 preceding siblings ...)
2026-01-19 20:45 ` [PATCH 22/26] rv/rvgen: remove unused __get_main_name method Wander Lairson Costa
@ 2026-01-19 20:45 ` Wander Lairson Costa
2026-01-22 15:43 ` Nam Cao
2026-01-19 20:46 ` [PATCH 24/26] rv/rvgen: make monitor arguments required in rvgen Wander Lairson Costa
` (3 subsequent siblings)
26 siblings, 1 reply; 95+ messages in thread
From: Wander Lairson Costa @ 2026-01-19 20:45 UTC (permalink / raw)
To: Steven Rostedt, Gabriele Monaco, Nam Cao, Wander Lairson Costa,
open list, open list:RUNTIME VERIFICATION (RV)
Add return type annotations to RVGenerator base class methods and
LTL operator classes to resolve pyright reportIncompatibleMethodOverride
errors.
In generator.py, add string return type annotations to all template
filling methods and annotate the template_dir class attribute to enable
proper type checking during initialization.
In ltl2ba.py, introduce a LTLNode type alias as a Union of all AST node
types (BinaryOp, UnaryOp, Variable, Literal) to properly type operator
transformations. The operator base classes BinaryOp and UnaryOp receive
return type annotations using this type alias for their normalize and
negate methods, since these transformations can return different node
types depending on the expression. The Variable and Literal classes gain
return type annotations for their manipulation methods, and all temporal
checking methods are annotated to return bool.
The LTLNode type alias is necessary because operator transformations are
polymorphic: NotOp.negate() can return BinaryOp, UnaryOp, Variable, or
Literal depending on what expression is being negated.
In ltl2k.py, fix the _fill_states return type from str to list[str] to
match the actual implementation.
Signed-off-by: Wander Lairson Costa <wander@redhat.com>
---
tools/verification/rvgen/rvgen/generator.py | 35 +++++++++++----------
tools/verification/rvgen/rvgen/ltl2ba.py | 33 ++++++++++---------
tools/verification/rvgen/rvgen/ltl2k.py | 2 +-
3 files changed, 38 insertions(+), 32 deletions(-)
diff --git a/tools/verification/rvgen/rvgen/generator.py b/tools/verification/rvgen/rvgen/generator.py
index d99a980850d64..c58a81a775681 100644
--- a/tools/verification/rvgen/rvgen/generator.py
+++ b/tools/verification/rvgen/rvgen/generator.py
@@ -12,6 +12,7 @@ from .utils import not_implemented
class RVGenerator:
rv_dir = "kernel/trace/rv"
+ template_dir: str
def __init__(self, extra_params={}):
self.name = extra_params.get("model_name")
@@ -66,24 +67,24 @@ class RVGenerator:
path = os.path.join(self.abs_template_dir, "..", file)
return self._read_file(path)
- def fill_parent(self):
+ def fill_parent(self) -> str:
return f"&rv_{self.parent}" if self.parent else "NULL"
- def fill_include_parent(self):
+ def fill_include_parent(self) -> str:
if self.parent:
return f"#include <monitors/{self.parent}/{self.parent}.h>\n"
return ""
@not_implemented
- def fill_tracepoint_handlers_skel(self): ...
+ def fill_tracepoint_handlers_skel(self) -> str: ...
@not_implemented
- def fill_tracepoint_attach_probe(self): ...
+ def fill_tracepoint_attach_probe(self) -> str: ...
@not_implemented
- def fill_tracepoint_detach_helper(self): ...
+ def fill_tracepoint_detach_helper(self) -> str: ...
- def fill_main_c(self):
+ def fill_main_c(self) -> str:
main_c = self.main_c
tracepoint_handlers = self.fill_tracepoint_handlers_skel()
tracepoint_attach = self.fill_tracepoint_attach_probe()
@@ -102,18 +103,18 @@ class RVGenerator:
return main_c
@not_implemented
- def fill_model_h(self): ...
+ def fill_model_h(self) -> str: ...
@not_implemented
- def fill_monitor_class_type(self): ...
+ def fill_monitor_class_type(self) -> str: ...
@not_implemented
- def fill_monitor_class(self): ...
+ def fill_monitor_class(self) -> str: ...
@not_implemented
- def fill_tracepoint_args_skel(self, tp_type): ...
+ def fill_tracepoint_args_skel(self, tp_type) -> str: ...
- def fill_monitor_deps(self):
+ def fill_monitor_deps(self) -> str:
buff = []
buff.append(" # XXX: add dependencies if there")
if self.parent:
@@ -121,7 +122,7 @@ class RVGenerator:
buff.append(" default y")
return '\n'.join(buff)
- def fill_kconfig(self):
+ def fill_kconfig(self) -> str:
kconfig = self.kconfig
monitor_class_type = self.fill_monitor_class_type()
monitor_deps = self.fill_monitor_deps()
@@ -139,7 +140,7 @@ class RVGenerator:
content = content.replace(marker, line + "\n" + marker)
self.__write_file(file_to_patch, content)
- def fill_tracepoint_tooltip(self):
+ def fill_tracepoint_tooltip(self) -> str:
monitor_class_type = self.fill_monitor_class_type()
if self.auto_patch:
self._patch_file("rv_trace.h",
@@ -155,7 +156,7 @@ Add this line where other tracepoints are included and {monitor_class_type} is d
def _kconfig_marker(self, container=None) -> str:
return f"# Add new {container + ' ' if container else ''}monitors here"
- def fill_kconfig_tooltip(self):
+ def fill_kconfig_tooltip(self) -> str:
if self.auto_patch:
# monitors with a container should stay together in the Kconfig
self._patch_file("Kconfig",
@@ -168,7 +169,7 @@ Add this line where other monitors are included:
source \"kernel/trace/rv/monitors/{self.name}/Kconfig\"
"""
- def fill_makefile_tooltip(self):
+ def fill_makefile_tooltip(self) -> str:
name = self.name
name_up = name.upper()
if self.auto_patch:
@@ -182,7 +183,7 @@ Add this line where other monitors are included:
obj-$(CONFIG_RV_MON_{name_up}) += monitors/{name}/{name}.o
"""
- def fill_monitor_tooltip(self):
+ def fill_monitor_tooltip(self) -> str:
if self.auto_patch:
return f" - Monitor created in {self.rv_dir}/monitors/{self.name}"
return f" - Move {self.name}/ to the kernel's monitor directory ({self.rv_dir}/monitors)"
@@ -229,7 +230,7 @@ class Monitor(RVGenerator):
super().__init__(extra_params)
self.trace_h = self._read_template_file("trace.h")
- def fill_trace_h(self):
+ def fill_trace_h(self) -> str:
trace_h = self.trace_h
monitor_class = self.fill_monitor_class()
monitor_class_type = self.fill_monitor_class_type()
diff --git a/tools/verification/rvgen/rvgen/ltl2ba.py b/tools/verification/rvgen/rvgen/ltl2ba.py
index 9a3fb7c5f4f65..49f6b9200ff0a 100644
--- a/tools/verification/rvgen/rvgen/ltl2ba.py
+++ b/tools/verification/rvgen/rvgen/ltl2ba.py
@@ -7,10 +7,15 @@
# https://doi.org/10.1007/978-0-387-34892-6_1
# With extra optimizations
+from __future__ import annotations
+from typing import Union
from ply.lex import lex
from ply.yacc import yacc
from .utils import not_implemented
+# Type alias for all LTL node types in the AST
+LTLNode = Union['BinaryOp', 'UnaryOp', 'Variable', 'Literal']
+
# Grammar:
# ltl ::= opd | ( ltl ) | ltl binop ltl | unop ltl
#
@@ -152,15 +157,15 @@ class BinaryOp:
yield from self.right
@not_implemented
- def normalize(self): ...
+ def normalize(self) -> BinaryOp: ...
@not_implemented
- def negate(self): ...
+ def negate(self) -> BinaryOp: ...
@not_implemented
- def _is_temporal(self): ...
+ def _is_temporal(self) -> bool: ...
- def is_temporal(self):
+ def is_temporal(self) -> bool:
if self.left.op.is_temporal():
return True
if self.right.op.is_temporal():
@@ -291,20 +296,20 @@ class UnaryOp:
return hash(self.child)
@not_implemented
- def normalize(self):
+ def normalize(self) -> LTLNode:
...
@not_implemented
- def _is_temporal(self):
+ def _is_temporal(self) -> bool:
...
- def is_temporal(self):
+ def is_temporal(self) -> bool:
if self.child.op.is_temporal():
return True
return self._is_temporal()
@not_implemented
- def negate(self):
+ def negate(self) -> LTLNode:
...
class EventuallyOp(UnaryOp):
@@ -386,14 +391,14 @@ class Variable:
def __iter__(self):
yield from ()
- def negate(self):
+ def negate(self) -> NotOp:
new = ASTNode(self)
return NotOp(new)
- def normalize(self):
+ def normalize(self) -> Variable:
return self
- def is_temporal(self):
+ def is_temporal(self) -> bool:
return False
@staticmethod
@@ -419,14 +424,14 @@ class Literal:
return "true"
return "false"
- def negate(self):
+ def negate(self) -> Literal:
self.value = not self.value
return self
- def normalize(self):
+ def normalize(self) -> Literal:
return self
- def is_temporal(self):
+ def is_temporal(self) -> bool:
return False
@staticmethod
diff --git a/tools/verification/rvgen/rvgen/ltl2k.py b/tools/verification/rvgen/rvgen/ltl2k.py
index f1eafc16c754b..44231aadb257c 100644
--- a/tools/verification/rvgen/rvgen/ltl2k.py
+++ b/tools/verification/rvgen/rvgen/ltl2k.py
@@ -68,7 +68,7 @@ class ltl2k(generator.Monitor):
if not self.name:
self.name = Path(file_path).stem
- def _fill_states(self) -> str:
+ def _fill_states(self) -> list[str]:
buf = [
"enum ltl_buchi_state {",
]
--
2.52.0
^ permalink raw reply related [flat|nested] 95+ messages in thread* Re: [PATCH 23/26] rv/rvgen: add type annotations to fix pyright errors
2026-01-19 20:45 ` [PATCH 23/26] rv/rvgen: add type annotations to fix pyright errors Wander Lairson Costa
@ 2026-01-22 15:43 ` Nam Cao
0 siblings, 0 replies; 95+ messages in thread
From: Nam Cao @ 2026-01-22 15:43 UTC (permalink / raw)
To: Wander Lairson Costa, Steven Rostedt, Gabriele Monaco,
Wander Lairson Costa, open list,
open list:RUNTIME VERIFICATION (RV)
Wander Lairson Costa <wander@redhat.com> writes:
> Add return type annotations to RVGenerator base class methods and
> LTL operator classes to resolve pyright reportIncompatibleMethodOverride
> errors.
>
> In generator.py, add string return type annotations to all template
> filling methods and annotate the template_dir class attribute to enable
> proper type checking during initialization.
>
> In ltl2ba.py, introduce a LTLNode type alias as a Union of all AST node
> types (BinaryOp, UnaryOp, Variable, Literal) to properly type operator
> transformations. The operator base classes BinaryOp and UnaryOp receive
> return type annotations using this type alias for their normalize and
> negate methods, since these transformations can return different node
> types depending on the expression. The Variable and Literal classes gain
> return type annotations for their manipulation methods, and all temporal
> checking methods are annotated to return bool.
>
> The LTLNode type alias is necessary because operator transformations are
> polymorphic: NotOp.negate() can return BinaryOp, UnaryOp, Variable, or
> Literal depending on what expression is being negated.
>
> In ltl2k.py, fix the _fill_states return type from str to list[str] to
> match the actual implementation.
>
> Signed-off-by: Wander Lairson Costa <wander@redhat.com>
Reviewed-by: Nam Cao <namcao@linutronix.de>
^ permalink raw reply [flat|nested] 95+ messages in thread
* [PATCH 24/26] rv/rvgen: make monitor arguments required in rvgen
2026-01-19 20:45 [PATCH 00/26] rv/rvgen: Robustness, modernization, and fixes Wander Lairson Costa
` (22 preceding siblings ...)
2026-01-19 20:45 ` [PATCH 23/26] rv/rvgen: add type annotations to fix pyright errors Wander Lairson Costa
@ 2026-01-19 20:46 ` Wander Lairson Costa
2026-01-20 9:07 ` Gabriele Monaco
2026-01-22 15:44 ` Nam Cao
2026-01-19 20:46 ` [PATCH 25/26] rv/rvgen: fix isinstance check in Variable.expand() Wander Lairson Costa
` (2 subsequent siblings)
26 siblings, 2 replies; 95+ messages in thread
From: Wander Lairson Costa @ 2026-01-19 20:46 UTC (permalink / raw)
To: Steven Rostedt, Gabriele Monaco, Nam Cao, Wander Lairson Costa,
open list, open list:RUNTIME VERIFICATION (RV)
Add required=True to the monitor subcommand arguments for class, spec,
and monitor_type in rvgen. These arguments are essential for monitor
generation and attempting to run without them would cause AttributeError
exceptions later in the code when the script tries to access them.
Making these arguments explicitly required provides clearer error
messages to users at parse time rather than cryptic exceptions during
execution. This improves the user experience by catching missing
arguments early with helpful usage information.
Signed-off-by: Wander Lairson Costa <wander@redhat.com>
---
tools/verification/rvgen/__main__.py | 7 ++++---
1 file changed, 4 insertions(+), 3 deletions(-)
diff --git a/tools/verification/rvgen/__main__.py b/tools/verification/rvgen/__main__.py
index eeeccf81d4b90..f3e79b14c5d5d 100644
--- a/tools/verification/rvgen/__main__.py
+++ b/tools/verification/rvgen/__main__.py
@@ -28,10 +28,11 @@ if __name__ == '__main__':
monitor_parser.add_argument('-n', "--model_name", dest="model_name")
monitor_parser.add_argument("-p", "--parent", dest="parent",
required=False, help="Create a monitor nested to parent")
- monitor_parser.add_argument('-c', "--class", dest="monitor_class",
+ monitor_parser.add_argument('-c', "--class", dest="monitor_class", required=True,
help="Monitor class, either \"da\" or \"ltl\"")
- monitor_parser.add_argument('-s', "--spec", dest="spec", help="Monitor specification file")
- monitor_parser.add_argument('-t', "--monitor_type", dest="monitor_type",
+ monitor_parser.add_argument('-s', "--spec", dest="spec", required=True,
+ help="Monitor specification file")
+ monitor_parser.add_argument('-t', "--monitor_type", dest="monitor_type", required=True,
help=f"Available options: {', '.join(Monitor.monitor_types.keys())}")
container_parser = subparsers.add_parser("container")
--
2.52.0
^ permalink raw reply related [flat|nested] 95+ messages in thread* Re: [PATCH 24/26] rv/rvgen: make monitor arguments required in rvgen
2026-01-19 20:46 ` [PATCH 24/26] rv/rvgen: make monitor arguments required in rvgen Wander Lairson Costa
@ 2026-01-20 9:07 ` Gabriele Monaco
2026-01-22 15:44 ` Nam Cao
1 sibling, 0 replies; 95+ messages in thread
From: Gabriele Monaco @ 2026-01-20 9:07 UTC (permalink / raw)
To: Wander Lairson Costa
Cc: Steven Rostedt, Nam Cao, open list,
open list:RUNTIME VERIFICATION (RV)
On Mon, 2026-01-19 at 17:46 -0300, Wander Lairson Costa wrote:
> Add required=True to the monitor subcommand arguments for class, spec,
> and monitor_type in rvgen. These arguments are essential for monitor
> generation and attempting to run without them would cause AttributeError
> exceptions later in the code when the script tries to access them.
>
> Making these arguments explicitly required provides clearer error
> messages to users at parse time rather than cryptic exceptions during
> execution. This improves the user experience by catching missing
> arguments early with helpful usage information.
>
> Signed-off-by: Wander Lairson Costa <wander@redhat.com>
Good catch, thanks!
Reviewed-by: Gabriele Monaco <gmonaco@redhat.com>
> ---
> tools/verification/rvgen/__main__.py | 7 ++++---
> 1 file changed, 4 insertions(+), 3 deletions(-)
>
> diff --git a/tools/verification/rvgen/__main__.py
> b/tools/verification/rvgen/__main__.py
> index eeeccf81d4b90..f3e79b14c5d5d 100644
> --- a/tools/verification/rvgen/__main__.py
> +++ b/tools/verification/rvgen/__main__.py
> @@ -28,10 +28,11 @@ if __name__ == '__main__':
> monitor_parser.add_argument('-n', "--model_name", dest="model_name")
> monitor_parser.add_argument("-p", "--parent", dest="parent",
> required=False, help="Create a monitor nested
> to parent")
> - monitor_parser.add_argument('-c', "--class", dest="monitor_class",
> + monitor_parser.add_argument('-c', "--class", dest="monitor_class",
> required=True,
> help="Monitor class, either \"da\" or
> \"ltl\"")
> - monitor_parser.add_argument('-s', "--spec", dest="spec", help="Monitor
> specification file")
> - monitor_parser.add_argument('-t', "--monitor_type", dest="monitor_type",
> + monitor_parser.add_argument('-s', "--spec", dest="spec", required=True,
> + help="Monitor specification file")
> + monitor_parser.add_argument('-t', "--monitor_type", dest="monitor_type",
> required=True,
> help=f"Available options: {',
> '.join(Monitor.monitor_types.keys())}")
>
> container_parser = subparsers.add_parser("container")
^ permalink raw reply [flat|nested] 95+ messages in thread* Re: [PATCH 24/26] rv/rvgen: make monitor arguments required in rvgen
2026-01-19 20:46 ` [PATCH 24/26] rv/rvgen: make monitor arguments required in rvgen Wander Lairson Costa
2026-01-20 9:07 ` Gabriele Monaco
@ 2026-01-22 15:44 ` Nam Cao
1 sibling, 0 replies; 95+ messages in thread
From: Nam Cao @ 2026-01-22 15:44 UTC (permalink / raw)
To: Wander Lairson Costa, Steven Rostedt, Gabriele Monaco,
Wander Lairson Costa, open list,
open list:RUNTIME VERIFICATION (RV)
Wander Lairson Costa <wander@redhat.com> writes:
> Add required=True to the monitor subcommand arguments for class, spec,
> and monitor_type in rvgen. These arguments are essential for monitor
> generation and attempting to run without them would cause AttributeError
> exceptions later in the code when the script tries to access them.
>
> Making these arguments explicitly required provides clearer error
> messages to users at parse time rather than cryptic exceptions during
> execution. This improves the user experience by catching missing
> arguments early with helpful usage information.
>
> Signed-off-by: Wander Lairson Costa <wander@redhat.com>
Reviewed-by: Nam Cao <namcao@linutronix.de>
^ permalink raw reply [flat|nested] 95+ messages in thread
* [PATCH 25/26] rv/rvgen: fix isinstance check in Variable.expand()
2026-01-19 20:45 [PATCH 00/26] rv/rvgen: Robustness, modernization, and fixes Wander Lairson Costa
` (23 preceding siblings ...)
2026-01-19 20:46 ` [PATCH 24/26] rv/rvgen: make monitor arguments required in rvgen Wander Lairson Costa
@ 2026-01-19 20:46 ` Wander Lairson Costa
2026-01-22 15:53 ` Nam Cao
2026-01-19 20:46 ` [PATCH 26/26] rv/rvgen: extract node marker string to class constant Wander Lairson Costa
2026-01-20 7:20 ` [PATCH 00/26] rv/rvgen: Robustness, modernization, and fixes Nam Cao
26 siblings, 1 reply; 95+ messages in thread
From: Wander Lairson Costa @ 2026-01-19 20:46 UTC (permalink / raw)
To: Steven Rostedt, Gabriele Monaco, Nam Cao, Wander Lairson Costa,
open list, open list:RUNTIME VERIFICATION (RV)
The Variable.expand() method in ltl2ba.py performs contradiction
detection by checking if a negated variable already exists in the
graph node's old set. However, the isinstance check was incorrectly
testing the ASTNode wrapper instead of the wrapped operator, causing
the check to always return False.
The old set contains ASTNode instances which wrap LTL operators via
their .op attribute. The fix changes isinstance(f, NotOp) to
isinstance(f.op, NotOp) to correctly examine the wrapped operator
type. This follows the established pattern used elsewhere in the
file, such as the iteration at lines 572-574 which accesses
o.op.is_temporal() on items from node.old.
Signed-off-by: Wander Lairson Costa <wander@redhat.com>
---
tools/verification/rvgen/rvgen/ltl2ba.py | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/tools/verification/rvgen/rvgen/ltl2ba.py b/tools/verification/rvgen/rvgen/ltl2ba.py
index 49f6b9200ff0a..79b45a1d61130 100644
--- a/tools/verification/rvgen/rvgen/ltl2ba.py
+++ b/tools/verification/rvgen/rvgen/ltl2ba.py
@@ -404,7 +404,7 @@ class Variable:
@staticmethod
def expand(n: ASTNode, node: GraphNode, node_set) -> set[GraphNode]:
for f in node.old:
- if isinstance(f, NotOp) and f.op.child is n:
+ if isinstance(f.op, NotOp) and f.op.child is n:
return node_set
node.old |= {n}
return node.expand(node_set)
--
2.52.0
^ permalink raw reply related [flat|nested] 95+ messages in thread* Re: [PATCH 25/26] rv/rvgen: fix isinstance check in Variable.expand()
2026-01-19 20:46 ` [PATCH 25/26] rv/rvgen: fix isinstance check in Variable.expand() Wander Lairson Costa
@ 2026-01-22 15:53 ` Nam Cao
0 siblings, 0 replies; 95+ messages in thread
From: Nam Cao @ 2026-01-22 15:53 UTC (permalink / raw)
To: Wander Lairson Costa, Steven Rostedt, Gabriele Monaco,
Wander Lairson Costa, open list,
open list:RUNTIME VERIFICATION (RV)
Wander Lairson Costa <wander@redhat.com> writes:
> The Variable.expand() method in ltl2ba.py performs contradiction
> detection by checking if a negated variable already exists in the
> graph node's old set. However, the isinstance check was incorrectly
> testing the ASTNode wrapper instead of the wrapped operator, causing
> the check to always return False.
>
> The old set contains ASTNode instances which wrap LTL operators via
> their .op attribute. The fix changes isinstance(f, NotOp) to
> isinstance(f.op, NotOp) to correctly examine the wrapped operator
> type. This follows the established pattern used elsewhere in the
> file, such as the iteration at lines 572-574 which accesses
> o.op.is_temporal() on items from node.old.
>
> Signed-off-by: Wander Lairson Costa <wander@redhat.com>
These isinstance() usages deserve to be buried. But I'm not sure yet how
to replace them. So, for now:
Reviewed-by: Nam Cao <namcao@linutronix.de>
^ permalink raw reply [flat|nested] 95+ messages in thread
* [PATCH 26/26] rv/rvgen: extract node marker string to class constant
2026-01-19 20:45 [PATCH 00/26] rv/rvgen: Robustness, modernization, and fixes Wander Lairson Costa
` (24 preceding siblings ...)
2026-01-19 20:46 ` [PATCH 25/26] rv/rvgen: fix isinstance check in Variable.expand() Wander Lairson Costa
@ 2026-01-19 20:46 ` Wander Lairson Costa
2026-01-20 9:03 ` Gabriele Monaco
2026-01-20 7:20 ` [PATCH 00/26] rv/rvgen: Robustness, modernization, and fixes Nam Cao
26 siblings, 1 reply; 95+ messages in thread
From: Wander Lairson Costa @ 2026-01-19 20:46 UTC (permalink / raw)
To: Steven Rostedt, Gabriele Monaco, Nam Cao, Wander Lairson Costa,
open list, open list:RUNTIME VERIFICATION (RV)
Add a node_marker class constant to the Automata class to replace the
hardcoded "{node" string literal used throughout the DOT file parsing
logic. This follows the existing pattern established by the init_marker
and invalid_state_str class constants in the same class.
The "{node" string is used as a marker to identify node declaration
lines in DOT files during state variable extraction and cursor
positioning. Extracting it to a named constant improves code
maintainability and makes the marker's purpose explicit.
Signed-off-by: Wander Lairson Costa <wander@redhat.com>
---
tools/verification/rvgen/rvgen/automata.py | 9 +++++----
1 file changed, 5 insertions(+), 4 deletions(-)
diff --git a/tools/verification/rvgen/rvgen/automata.py b/tools/verification/rvgen/rvgen/automata.py
index a6889d0c26c3f..5f23db1855cd3 100644
--- a/tools/verification/rvgen/rvgen/automata.py
+++ b/tools/verification/rvgen/rvgen/automata.py
@@ -29,6 +29,7 @@ class Automata:
invalid_state_str = "INVALID_STATE"
init_marker = "__init_"
+ node_marker = "{node"
def __init__(self, file_path, model_name=None):
self.__dot_path = file_path
@@ -76,7 +77,7 @@ class Automata:
for cursor, line in enumerate(self.__dot_lines):
split_line = line.split()
- if len(split_line) and split_line[0] == "{node":
+ if len(split_line) and split_line[0] == self.node_marker:
return cursor
raise AutomataError("Could not find a beginning state")
@@ -91,9 +92,9 @@ class Automata:
continue
if state == 0:
- if line[0] == "{node":
+ if line[0] == self.node_marker:
state = 1
- elif line[0] != "{node":
+ elif line[0] != self.node_marker:
break
else:
raise AutomataError("Could not find beginning event")
@@ -116,7 +117,7 @@ class Automata:
# process nodes
for line in islice(self.__dot_lines, cursor, None):
split_line = line.split()
- if not split_line or split_line[0] != "{node":
+ if not split_line or split_line[0] != self.node_marker:
break
raw_state = split_line[-1]
--
2.52.0
^ permalink raw reply related [flat|nested] 95+ messages in thread* Re: [PATCH 26/26] rv/rvgen: extract node marker string to class constant
2026-01-19 20:46 ` [PATCH 26/26] rv/rvgen: extract node marker string to class constant Wander Lairson Costa
@ 2026-01-20 9:03 ` Gabriele Monaco
2026-01-20 11:34 ` Wander Lairson Costa
0 siblings, 1 reply; 95+ messages in thread
From: Gabriele Monaco @ 2026-01-20 9:03 UTC (permalink / raw)
To: Wander Lairson Costa
Cc: Steven Rostedt, Nam Cao, open list,
open list:RUNTIME VERIFICATION (RV)
On Mon, 2026-01-19 at 17:46 -0300, Wander Lairson Costa wrote:
> Add a node_marker class constant to the Automata class to replace the
> hardcoded "{node" string literal used throughout the DOT file parsing
> logic. This follows the existing pattern established by the init_marker
> and invalid_state_str class constants in the same class.
>
> The "{node" string is used as a marker to identify node declaration
> lines in DOT files during state variable extraction and cursor
> positioning. Extracting it to a named constant improves code
> maintainability and makes the marker's purpose explicit.
>
> Signed-off-by: Wander Lairson Costa <wander@redhat.com>
Looks fine for me, thanks!
I wonder if we could merge this patch with 15/26 that is introducing a very
similar change on init_marker.
Anyway:
Reviewed-by: Gabriele Monaco <gmonaco@redhat.com>
> ---
> tools/verification/rvgen/rvgen/automata.py | 9 +++++----
> 1 file changed, 5 insertions(+), 4 deletions(-)
>
> diff --git a/tools/verification/rvgen/rvgen/automata.py
> b/tools/verification/rvgen/rvgen/automata.py
> index a6889d0c26c3f..5f23db1855cd3 100644
> --- a/tools/verification/rvgen/rvgen/automata.py
> +++ b/tools/verification/rvgen/rvgen/automata.py
> @@ -29,6 +29,7 @@ class Automata:
>
> invalid_state_str = "INVALID_STATE"
> init_marker = "__init_"
> + node_marker = "{node"
>
> def __init__(self, file_path, model_name=None):
> self.__dot_path = file_path
> @@ -76,7 +77,7 @@ class Automata:
> for cursor, line in enumerate(self.__dot_lines):
> split_line = line.split()
>
> - if len(split_line) and split_line[0] == "{node":
> + if len(split_line) and split_line[0] == self.node_marker:
> return cursor
>
> raise AutomataError("Could not find a beginning state")
> @@ -91,9 +92,9 @@ class Automata:
> continue
>
> if state == 0:
> - if line[0] == "{node":
> + if line[0] == self.node_marker:
> state = 1
> - elif line[0] != "{node":
> + elif line[0] != self.node_marker:
> break
> else:
> raise AutomataError("Could not find beginning event")
> @@ -116,7 +117,7 @@ class Automata:
> # process nodes
> for line in islice(self.__dot_lines, cursor, None):
> split_line = line.split()
> - if not split_line or split_line[0] != "{node":
> + if not split_line or split_line[0] != self.node_marker:
> break
>
> raw_state = split_line[-1]
^ permalink raw reply [flat|nested] 95+ messages in thread* Re: [PATCH 26/26] rv/rvgen: extract node marker string to class constant
2026-01-20 9:03 ` Gabriele Monaco
@ 2026-01-20 11:34 ` Wander Lairson Costa
2026-01-20 12:36 ` Gabriele Monaco
0 siblings, 1 reply; 95+ messages in thread
From: Wander Lairson Costa @ 2026-01-20 11:34 UTC (permalink / raw)
To: Gabriele Monaco
Cc: Steven Rostedt, Nam Cao, open list,
open list:RUNTIME VERIFICATION (RV)
On Tue, Jan 20, 2026 at 10:03:20AM +0100, Gabriele Monaco wrote:
> On Mon, 2026-01-19 at 17:46 -0300, Wander Lairson Costa wrote:
> > Add a node_marker class constant to the Automata class to replace the
> > hardcoded "{node" string literal used throughout the DOT file parsing
> > logic. This follows the existing pattern established by the init_marker
> > and invalid_state_str class constants in the same class.
> >
> > The "{node" string is used as a marker to identify node declaration
> > lines in DOT files during state variable extraction and cursor
> > positioning. Extracting it to a named constant improves code
> > maintainability and makes the marker's purpose explicit.
> >
> > Signed-off-by: Wander Lairson Costa <wander@redhat.com>
>
> Looks fine for me, thanks!
>
> I wonder if we could merge this patch with 15/26 that is introducing a very
> similar change on init_marker.
The idea was to make each patch doing one thing to make the reviewer's
life easier (I think I broke my own rule in a couple of patch). But if
there is a strong feeling about the merge, I could merged them in a
possible v2 patch series.
>
> Anyway:
>
> Reviewed-by: Gabriele Monaco <gmonaco@redhat.com>
>
> > ---
> > tools/verification/rvgen/rvgen/automata.py | 9 +++++----
> > 1 file changed, 5 insertions(+), 4 deletions(-)
> >
> > diff --git a/tools/verification/rvgen/rvgen/automata.py
> > b/tools/verification/rvgen/rvgen/automata.py
> > index a6889d0c26c3f..5f23db1855cd3 100644
> > --- a/tools/verification/rvgen/rvgen/automata.py
> > +++ b/tools/verification/rvgen/rvgen/automata.py
> > @@ -29,6 +29,7 @@ class Automata:
> >
> > invalid_state_str = "INVALID_STATE"
> > init_marker = "__init_"
> > + node_marker = "{node"
> >
> > def __init__(self, file_path, model_name=None):
> > self.__dot_path = file_path
> > @@ -76,7 +77,7 @@ class Automata:
> > for cursor, line in enumerate(self.__dot_lines):
> > split_line = line.split()
> >
> > - if len(split_line) and split_line[0] == "{node":
> > + if len(split_line) and split_line[0] == self.node_marker:
> > return cursor
> >
> > raise AutomataError("Could not find a beginning state")
> > @@ -91,9 +92,9 @@ class Automata:
> > continue
> >
> > if state == 0:
> > - if line[0] == "{node":
> > + if line[0] == self.node_marker:
> > state = 1
> > - elif line[0] != "{node":
> > + elif line[0] != self.node_marker:
> > break
> > else:
> > raise AutomataError("Could not find beginning event")
> > @@ -116,7 +117,7 @@ class Automata:
> > # process nodes
> > for line in islice(self.__dot_lines, cursor, None):
> > split_line = line.split()
> > - if not split_line or split_line[0] != "{node":
> > + if not split_line or split_line[0] != self.node_marker:
> > break
> >
> > raw_state = split_line[-1]
^ permalink raw reply [flat|nested] 95+ messages in thread* Re: [PATCH 26/26] rv/rvgen: extract node marker string to class constant
2026-01-20 11:34 ` Wander Lairson Costa
@ 2026-01-20 12:36 ` Gabriele Monaco
2026-01-20 13:11 ` Gabriele Monaco
0 siblings, 1 reply; 95+ messages in thread
From: Gabriele Monaco @ 2026-01-20 12:36 UTC (permalink / raw)
To: Wander Lairson Costa
Cc: Steven Rostedt, Nam Cao, open list,
open list:RUNTIME VERIFICATION (RV)
On Tue, 2026-01-20 at 08:34 -0300, Wander Lairson Costa wrote:
> On Tue, Jan 20, 2026 at 10:03:20AM +0100, Gabriele Monaco wrote:
> > On Mon, 2026-01-19 at 17:46 -0300, Wander Lairson Costa wrote:
> > > Add a node_marker class constant to the Automata class to replace the
> > > hardcoded "{node" string literal used throughout the DOT file parsing
> > > logic. This follows the existing pattern established by the init_marker
> > > and invalid_state_str class constants in the same class.
> > >
> > > The "{node" string is used as a marker to identify node declaration
> > > lines in DOT files during state variable extraction and cursor
> > > positioning. Extracting it to a named constant improves code
> > > maintainability and makes the marker's purpose explicit.
> > >
> > > Signed-off-by: Wander Lairson Costa <wander@redhat.com>
> >
> > Looks fine for me, thanks!
> >
> > I wonder if we could merge this patch with 15/26 that is introducing a very
> > similar change on init_marker.
>
> The idea was to make each patch doing one thing to make the reviewer's
> life easier (I think I broke my own rule in a couple of patch). But if
> there is a strong feeling about the merge, I could merged them in a
> possible v2 patch series.
>
Yeah I get the idea, I guess I could just pick the most obvious patches and send
a PR to Steve before the merge window, so I can see directly if it makes sense
to squash them and you don't need to send them all in the v2.
I'm leaving the longer or trickier ones for the next cycle so that I can test
them a bit better and perhaps get some rvgen selftest help with that. Also for
some it's better to wait for Nam's comments.
Will let you know the ones I pick. Thanks again for the extensive work!
Gabriele
> >
> > Anyway:
> >
> > Reviewed-by: Gabriele Monaco <gmonaco@redhat.com>
> >
> > > ---
> > > tools/verification/rvgen/rvgen/automata.py | 9 +++++----
> > > 1 file changed, 5 insertions(+), 4 deletions(-)
> > >
> > > diff --git a/tools/verification/rvgen/rvgen/automata.py
> > > b/tools/verification/rvgen/rvgen/automata.py
> > > index a6889d0c26c3f..5f23db1855cd3 100644
> > > --- a/tools/verification/rvgen/rvgen/automata.py
> > > +++ b/tools/verification/rvgen/rvgen/automata.py
> > > @@ -29,6 +29,7 @@ class Automata:
> > >
> > > invalid_state_str = "INVALID_STATE"
> > > init_marker = "__init_"
> > > + node_marker = "{node"
> > >
> > > def __init__(self, file_path, model_name=None):
> > > self.__dot_path = file_path
> > > @@ -76,7 +77,7 @@ class Automata:
> > > for cursor, line in enumerate(self.__dot_lines):
> > > split_line = line.split()
> > >
> > > - if len(split_line) and split_line[0] == "{node":
> > > + if len(split_line) and split_line[0] == self.node_marker:
> > > return cursor
> > >
> > > raise AutomataError("Could not find a beginning state")
> > > @@ -91,9 +92,9 @@ class Automata:
> > > continue
> > >
> > > if state == 0:
> > > - if line[0] == "{node":
> > > + if line[0] == self.node_marker:
> > > state = 1
> > > - elif line[0] != "{node":
> > > + elif line[0] != self.node_marker:
> > > break
> > > else:
> > > raise AutomataError("Could not find beginning event")
> > > @@ -116,7 +117,7 @@ class Automata:
> > > # process nodes
> > > for line in islice(self.__dot_lines, cursor, None):
> > > split_line = line.split()
> > > - if not split_line or split_line[0] != "{node":
> > > + if not split_line or split_line[0] != self.node_marker:
> > > break
> > >
> > > raw_state = split_line[-1]
^ permalink raw reply [flat|nested] 95+ messages in thread* Re: [PATCH 26/26] rv/rvgen: extract node marker string to class constant
2026-01-20 12:36 ` Gabriele Monaco
@ 2026-01-20 13:11 ` Gabriele Monaco
2026-01-20 18:56 ` Wander Lairson Costa
0 siblings, 1 reply; 95+ messages in thread
From: Gabriele Monaco @ 2026-01-20 13:11 UTC (permalink / raw)
To: Wander Lairson Costa
Cc: Steven Rostedt, Nam Cao, open list,
open list:RUNTIME VERIFICATION (RV)
On Tue, 2026-01-20 at 13:36 +0100, Gabriele Monaco wrote:
> On Tue, 2026-01-20 at 08:34 -0300, Wander Lairson Costa wrote:
> > On Tue, Jan 20, 2026 at 10:03:20AM +0100, Gabriele Monaco wrote:
> > > On Mon, 2026-01-19 at 17:46 -0300, Wander Lairson Costa wrote:
> > > > Add a node_marker class constant to the Automata class to replace the
> > > > hardcoded "{node" string literal used throughout the DOT file parsing
> > > > logic. This follows the existing pattern established by the init_marker
> > > > and invalid_state_str class constants in the same class.
> > > >
> > > > The "{node" string is used as a marker to identify node declaration
> > > > lines in DOT files during state variable extraction and cursor
> > > > positioning. Extracting it to a named constant improves code
> > > > maintainability and makes the marker's purpose explicit.
> > > >
> > > > Signed-off-by: Wander Lairson Costa <wander@redhat.com>
> > >
> > > Looks fine for me, thanks!
> > >
> > > I wonder if we could merge this patch with 15/26 that is introducing a
> > > very
> > > similar change on init_marker.
> >
> > The idea was to make each patch doing one thing to make the reviewer's
> > life easier (I think I broke my own rule in a couple of patch). But if
> > there is a strong feeling about the merge, I could merged them in a
> > possible v2 patch series.
> >
>
> Yeah I get the idea, I guess I could just pick the most obvious patches and
> send
> a PR to Steve before the merge window, so I can see directly if it makes sense
> to squash them and you don't need to send them all in the v2.
Screamed victory too fast.. I tried the patches on the latest version of the
tree (which reached already linux-next) and they're have several conflicts.
I don't have time to rebase them one by one right now, let's continue with this
series as a whole.
As a rule of thumb, considering these patches get first reviewed, then PR-ed to
Steve and then to Linus, I'd favour to lower the number if possible, but feel
free to choose where it makes sense for them to stay separate.
Thanks,
Gabriele
>
> I'm leaving the longer or trickier ones for the next cycle so that I can test
> them a bit better and perhaps get some rvgen selftest help with that. Also for
> some it's better to wait for Nam's comments.
>
> Will let you know the ones I pick. Thanks again for the extensive work!
>
> Gabriele
>
> > >
> > > Anyway:
> > >
> > > Reviewed-by: Gabriele Monaco <gmonaco@redhat.com>
> > >
> > > > ---
> > > > tools/verification/rvgen/rvgen/automata.py | 9 +++++----
> > > > 1 file changed, 5 insertions(+), 4 deletions(-)
> > > >
> > > > diff --git a/tools/verification/rvgen/rvgen/automata.py
> > > > b/tools/verification/rvgen/rvgen/automata.py
> > > > index a6889d0c26c3f..5f23db1855cd3 100644
> > > > --- a/tools/verification/rvgen/rvgen/automata.py
> > > > +++ b/tools/verification/rvgen/rvgen/automata.py
> > > > @@ -29,6 +29,7 @@ class Automata:
> > > >
> > > > invalid_state_str = "INVALID_STATE"
> > > > init_marker = "__init_"
> > > > + node_marker = "{node"
> > > >
> > > > def __init__(self, file_path, model_name=None):
> > > > self.__dot_path = file_path
> > > > @@ -76,7 +77,7 @@ class Automata:
> > > > for cursor, line in enumerate(self.__dot_lines):
> > > > split_line = line.split()
> > > >
> > > > - if len(split_line) and split_line[0] == "{node":
> > > > + if len(split_line) and split_line[0] == self.node_marker:
> > > > return cursor
> > > >
> > > > raise AutomataError("Could not find a beginning state")
> > > > @@ -91,9 +92,9 @@ class Automata:
> > > > continue
> > > >
> > > > if state == 0:
> > > > - if line[0] == "{node":
> > > > + if line[0] == self.node_marker:
> > > > state = 1
> > > > - elif line[0] != "{node":
> > > > + elif line[0] != self.node_marker:
> > > > break
> > > > else:
> > > > raise AutomataError("Could not find beginning event")
> > > > @@ -116,7 +117,7 @@ class Automata:
> > > > # process nodes
> > > > for line in islice(self.__dot_lines, cursor, None):
> > > > split_line = line.split()
> > > > - if not split_line or split_line[0] != "{node":
> > > > + if not split_line or split_line[0] != self.node_marker:
> > > > break
> > > >
> > > > raw_state = split_line[-1]
^ permalink raw reply [flat|nested] 95+ messages in thread* Re: [PATCH 26/26] rv/rvgen: extract node marker string to class constant
2026-01-20 13:11 ` Gabriele Monaco
@ 2026-01-20 18:56 ` Wander Lairson Costa
2026-01-21 6:16 ` Gabriele Monaco
0 siblings, 1 reply; 95+ messages in thread
From: Wander Lairson Costa @ 2026-01-20 18:56 UTC (permalink / raw)
To: Gabriele Monaco
Cc: Steven Rostedt, Nam Cao, open list,
open list:RUNTIME VERIFICATION (RV)
On Tue, Jan 20, 2026 at 02:11:46PM +0100, Gabriele Monaco wrote:
> On Tue, 2026-01-20 at 13:36 +0100, Gabriele Monaco wrote:
> > On Tue, 2026-01-20 at 08:34 -0300, Wander Lairson Costa wrote:
> > > On Tue, Jan 20, 2026 at 10:03:20AM +0100, Gabriele Monaco wrote:
> > > > On Mon, 2026-01-19 at 17:46 -0300, Wander Lairson Costa wrote:
> > > > > Add a node_marker class constant to the Automata class to replace the
> > > > > hardcoded "{node" string literal used throughout the DOT file parsing
> > > > > logic. This follows the existing pattern established by the init_marker
> > > > > and invalid_state_str class constants in the same class.
> > > > >
> > > > > The "{node" string is used as a marker to identify node declaration
> > > > > lines in DOT files during state variable extraction and cursor
> > > > > positioning. Extracting it to a named constant improves code
> > > > > maintainability and makes the marker's purpose explicit.
> > > > >
> > > > > Signed-off-by: Wander Lairson Costa <wander@redhat.com>
> > > >
> > > > Looks fine for me, thanks!
> > > >
> > > > I wonder if we could merge this patch with 15/26 that is introducing a
> > > > very
> > > > similar change on init_marker.
> > >
> > > The idea was to make each patch doing one thing to make the reviewer's
> > > life easier (I think I broke my own rule in a couple of patch). But if
> > > there is a strong feeling about the merge, I could merged them in a
> > > possible v2 patch series.
> > >
> >
> > Yeah I get the idea, I guess I could just pick the most obvious patches and
> > send
> > a PR to Steve before the merge window, so I can see directly if it makes sense
> > to squash them and you don't need to send them all in the v2.
>
> Screamed victory too fast.. I tried the patches on the latest version of the
> tree (which reached already linux-next) and they're have several conflicts.
>
> I don't have time to rebase them one by one right now, let's continue with this
> series as a whole.
> As a rule of thumb, considering these patches get first reviewed, then PR-ed to
> Steve and then to Linus, I'd favour to lower the number if possible, but feel
> free to choose where it makes sense for them to stay separate.
I created the patches on top of linux-trace/tools/for-next. Is this the
wrong branch?
>
> Thanks,
> Gabriele
>
^ permalink raw reply [flat|nested] 95+ messages in thread* Re: [PATCH 26/26] rv/rvgen: extract node marker string to class constant
2026-01-20 18:56 ` Wander Lairson Costa
@ 2026-01-21 6:16 ` Gabriele Monaco
0 siblings, 0 replies; 95+ messages in thread
From: Gabriele Monaco @ 2026-01-21 6:16 UTC (permalink / raw)
To: Wander Lairson Costa
Cc: Steven Rostedt, Nam Cao, open list,
open list:RUNTIME VERIFICATION (RV)
On Tue, 2026-01-20 at 15:56 -0300, Wander Lairson Costa wrote:
> I created the patches on top of linux-trace/tools/for-next. Is this the
> wrong branch?
>
Oh that tree is tricky, usually RV pull requests go to latency/for-next , that's
where you can find it this time (Steve created the specific rv/fixes and rv/for-
next but hasn't used them recently).
Anyway they're all linked to linux-next, so that's usually a safe bet.
Thanks,
Gabriele
^ permalink raw reply [flat|nested] 95+ messages in thread
* Re: [PATCH 00/26] rv/rvgen: Robustness, modernization, and fixes
2026-01-19 20:45 [PATCH 00/26] rv/rvgen: Robustness, modernization, and fixes Wander Lairson Costa
` (25 preceding siblings ...)
2026-01-19 20:46 ` [PATCH 26/26] rv/rvgen: extract node marker string to class constant Wander Lairson Costa
@ 2026-01-20 7:20 ` Nam Cao
26 siblings, 0 replies; 95+ messages in thread
From: Nam Cao @ 2026-01-20 7:20 UTC (permalink / raw)
To: Wander Lairson Costa, Steven Rostedt, Gabriele Monaco,
Wander Lairson Costa, open list,
open list:RUNTIME VERIFICATION (RV)
Wander Lairson Costa <wander@redhat.com> writes:
> This patch series introduces a number of fixes and improvements to the
> RV Generator (rvgen) tool in tools/verification. The primary goal is to
> enhance the tool's robustness, maintainability, and correctness by
> addressing several latent bugs, modernizing the Python codebase, and
> improving its overall structure and error handling.
Great, someone who knows python is fixing our mess.
I had a brief look and they look reasonable. I will do an actual review
when I have time for it. Thanks so much for this work.
Nam
^ permalink raw reply [flat|nested] 95+ messages in thread