From 7a3aaaa9fce710938c3557e5708ba5b00dd38226 Mon Sep 17 00:00:00 2001 From: "Matthieu Baerts (NGI0)" Date: Tue, 9 Sep 2025 23:07:47 +0200 Subject: [PATCH 1/8] tools: ynl: fix undefined variable name MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This variable used in the error path was not defined according to Ruff. msg_format.attr_set is used instead, presumably the one that was supposed to be used originally. This is linked to Ruff error F821 [1]: An undefined name is likely to raise NameError at runtime. Fixes: 1769e2be4baa ("tools/net/ynl: Add 'sub-message' attribute decoding to ynl") Link: https://docs.astral.sh/ruff/rules/undefined-name/ [1] Signed-off-by: Matthieu Baerts (NGI0) Reviewed-by: Donald Hunter Reviewed-by: Asbjørn Sloth Tønnesen Link: https://patch.msgid.link/20250909-net-next-ynl-ruff-v1-1-238c2bccdd99@kernel.org Signed-off-by: Jakub Kicinski --- tools/net/ynl/pyynl/lib/ynl.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/net/ynl/pyynl/lib/ynl.py b/tools/net/ynl/pyynl/lib/ynl.py index 8244a5f440b2..15ddb0b1adb6 100644 --- a/tools/net/ynl/pyynl/lib/ynl.py +++ b/tools/net/ynl/pyynl/lib/ynl.py @@ -746,7 +746,7 @@ class YnlFamily(SpecFamily): subdict = self._decode(NlAttrs(attr.raw, offset), msg_format.attr_set) decoded.update(subdict) else: - raise Exception(f"Unknown attribute-set '{attr_space}' when decoding '{attr_spec.name}'") + raise Exception(f"Unknown attribute-set '{msg_format.attr_set}' when decoding '{attr_spec.name}'") return decoded def _decode(self, attrs, space, outer_attrs = None): From 287bc89bb41fdb4c9433cbd9bedc240d53ce50ac Mon Sep 17 00:00:00 2001 From: "Matthieu Baerts (NGI0)" Date: Tue, 9 Sep 2025 23:07:48 +0200 Subject: [PATCH 2/8] tools: ynl: avoid bare except MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This 'except' was used without specifying the exception class according to Ruff. Here, only the ValueError class is expected and handled. This is linked to Ruff error E722 [1]: A bare except catches BaseException which includes KeyboardInterrupt, SystemExit, Exception, and others. Catching BaseException can make it hard to interrupt the program (e.g., with Ctrl-C) and can disguise other problems. Link: https://docs.astral.sh/ruff/rules/bare-except/ [1] Signed-off-by: Matthieu Baerts (NGI0) Reviewed-by: Donald Hunter Reviewed-by: Asbjørn Sloth Tønnesen Link: https://patch.msgid.link/20250909-net-next-ynl-ruff-v1-2-238c2bccdd99@kernel.org Signed-off-by: Jakub Kicinski --- tools/net/ynl/pyynl/ethtool.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/net/ynl/pyynl/ethtool.py b/tools/net/ynl/pyynl/ethtool.py index cab6b576c876..44440beab62f 100755 --- a/tools/net/ynl/pyynl/ethtool.py +++ b/tools/net/ynl/pyynl/ethtool.py @@ -51,7 +51,7 @@ def print_field(reply, *desc): for spec in desc: try: field, name, tp = spec - except: + except ValueError: field, name = spec tp = 'int' From 02962ddb3936f91780c2e05662e4b20c7b35a2df Mon Sep 17 00:00:00 2001 From: "Matthieu Baerts (NGI0)" Date: Tue, 9 Sep 2025 23:07:49 +0200 Subject: [PATCH 3/8] tools: ynl: remove assigned but never used variable MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit These variables are assigned but never used according to Ruff. They can then be safely removed. This is linked to Ruff error F841 [1]: A variable that is defined but not used is likely a mistake, and should be removed to avoid confusion. Link: https://docs.astral.sh/ruff/rules/unused-variable/ [1] Signed-off-by: Matthieu Baerts (NGI0) Reviewed-by: Donald Hunter Reviewed-by: Asbjørn Sloth Tønnesen Link: https://patch.msgid.link/20250909-net-next-ynl-ruff-v1-3-238c2bccdd99@kernel.org Signed-off-by: Jakub Kicinski --- tools/net/ynl/pyynl/ethtool.py | 1 - tools/net/ynl/pyynl/ynl_gen_c.py | 2 -- 2 files changed, 3 deletions(-) diff --git a/tools/net/ynl/pyynl/ethtool.py b/tools/net/ynl/pyynl/ethtool.py index 44440beab62f..ef2cbad41f9b 100755 --- a/tools/net/ynl/pyynl/ethtool.py +++ b/tools/net/ynl/pyynl/ethtool.py @@ -156,7 +156,6 @@ def main(): global args args = parser.parse_args() - script_abs_dir = os.path.dirname(os.path.abspath(sys.argv[0])) spec = os.path.join(spec_dir(), 'ethtool.yaml') schema = os.path.join(schema_dir(), 'genetlink-legacy.yaml') diff --git a/tools/net/ynl/pyynl/ynl_gen_c.py b/tools/net/ynl/pyynl/ynl_gen_c.py index fb7e03805a11..957fae8e27ed 100755 --- a/tools/net/ynl/pyynl/ynl_gen_c.py +++ b/tools/net/ynl/pyynl/ynl_gen_c.py @@ -2803,8 +2803,6 @@ def print_kernel_policy_sparse_enum_validates(family, cw): cw.p('/* Sparse enums validation callbacks */') first = False - sign = '' if attr.type[0] == 'u' else '_signed' - suffix = 'ULL' if attr.type[0] == 'u' else 'LL' cw.write_func_prot('static int', f'{c_lower(attr.enum_name)}_validate', ['const struct nlattr *attr', 'struct netlink_ext_ack *extack']) cw.block_start() From d8e0e25406a1208a836b476418c7a85903d047ac Mon Sep 17 00:00:00 2001 From: "Matthieu Baerts (NGI0)" Date: Tue, 9 Sep 2025 23:07:50 +0200 Subject: [PATCH 4/8] tools: ynl: remove f-string without any placeholders MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 'f-strings' without any placeholders don't need to be marked as such according to Ruff. This 'f' can be safely removed. This is linked to Ruff error F541 [1]: f-strings are a convenient way to format strings, but they are not necessary if there are no placeholder expressions to format. In this case, a regular string should be used instead, as an f-string without placeholders can be confusing for readers, who may expect such a placeholder to be present. Link: https://docs.astral.sh/ruff/rules/f-string-missing-placeholders/ [1] Signed-off-by: Matthieu Baerts (NGI0) Reviewed-by: Donald Hunter Reviewed-by: Asbjørn Sloth Tønnesen Link: https://patch.msgid.link/20250909-net-next-ynl-ruff-v1-4-238c2bccdd99@kernel.org Signed-off-by: Jakub Kicinski --- tools/net/ynl/pyynl/ethtool.py | 10 +++++----- tools/net/ynl/pyynl/ynl_gen_c.py | 22 +++++++++++----------- 2 files changed, 16 insertions(+), 16 deletions(-) diff --git a/tools/net/ynl/pyynl/ethtool.py b/tools/net/ynl/pyynl/ethtool.py index ef2cbad41f9b..c1cd088c050c 100755 --- a/tools/net/ynl/pyynl/ethtool.py +++ b/tools/net/ynl/pyynl/ethtool.py @@ -254,14 +254,14 @@ def main(): reply = dumpit(ynl, args, 'channels-get') print(f'Channel parameters for {args.device}:') - print(f'Pre-set maximums:') + print('Pre-set maximums:') print_field(reply, ('rx-max', 'RX'), ('tx-max', 'TX'), ('other-max', 'Other'), ('combined-max', 'Combined')) - print(f'Current hardware settings:') + print('Current hardware settings:') print_field(reply, ('rx-count', 'RX'), ('tx-count', 'TX'), @@ -275,14 +275,14 @@ def main(): print(f'Ring parameters for {args.device}:') - print(f'Pre-set maximums:') + print('Pre-set maximums:') print_field(reply, ('rx-max', 'RX'), ('rx-mini-max', 'RX Mini'), ('rx-jumbo-max', 'RX Jumbo'), ('tx-max', 'TX')) - print(f'Current hardware settings:') + print('Current hardware settings:') print_field(reply, ('rx', 'RX'), ('rx-mini', 'RX Mini'), @@ -297,7 +297,7 @@ def main(): return if args.statistics: - print(f'NIC statistics:') + print('NIC statistics:') # TODO: pass id? strset = dumpit(ynl, args, 'strset-get') diff --git a/tools/net/ynl/pyynl/ynl_gen_c.py b/tools/net/ynl/pyynl/ynl_gen_c.py index 957fae8e27ed..8e95c5bb1399 100755 --- a/tools/net/ynl/pyynl/ynl_gen_c.py +++ b/tools/net/ynl/pyynl/ynl_gen_c.py @@ -485,7 +485,7 @@ class TypeString(Type): ri.cw.p(f"char *{self.c_name};") def _attr_typol(self): - typol = f'.type = YNL_PT_NUL_STR, ' + typol = '.type = YNL_PT_NUL_STR, ' if self.is_selector: typol += '.is_selector = 1, ' return typol @@ -539,7 +539,7 @@ class TypeBinary(Type): ri.cw.p(f"void *{self.c_name};") def _attr_typol(self): - return f'.type = YNL_PT_BINARY,' + return '.type = YNL_PT_BINARY,' def _attr_policy(self, policy): if len(self.checks) == 0: @@ -636,7 +636,7 @@ class TypeBitfield32(Type): return "struct nla_bitfield32" def _attr_typol(self): - return f'.type = YNL_PT_BITFIELD32, ' + return '.type = YNL_PT_BITFIELD32, ' def _attr_policy(self, policy): if not 'enum' in self.attr: @@ -909,7 +909,7 @@ class TypeSubMessage(TypeNest): else: sel_var = f"{var}->{sel}" get_lines = [f'if (!{sel_var})', - f'return ynl_submsg_failed(yarg, "%s", "%s");' % + 'return ynl_submsg_failed(yarg, "%s", "%s");' % (self.name, self['selector']), f"if ({self.nested_render_name}_parse(&parg, {sel_var}, attr))", "return YNL_PARSE_CB_ERROR;"] @@ -1563,7 +1563,7 @@ class RenderInfo: if family.is_classic(): self.fixed_hdr_len = f"sizeof(struct {c_lower(fixed_hdr)})" else: - raise Exception(f"Per-op fixed header not supported, yet") + raise Exception("Per-op fixed header not supported, yet") # 'do' and 'dump' response parsing is identical @@ -2099,7 +2099,7 @@ def _multi_parse(ri, struct, init_lines, local_vars): if ri.family.is_classic(): iter_line = f"ynl_attr_for_each(attr, nlh, sizeof({struct.fixed_header}))" else: - raise Exception(f"Per-op fixed header not supported, yet") + raise Exception("Per-op fixed header not supported, yet") array_nests = set() multi_attrs = set() @@ -2502,7 +2502,7 @@ def print_free_prototype(ri, direction, suffix=';'): def print_nlflags_set(ri, direction): name = op_prefix(ri, direction) - ri.cw.write_func_prot(f'static inline void', f"{name}_set_nlflags", + ri.cw.write_func_prot('static inline void', f"{name}_set_nlflags", [f"struct {name} *req", "__u16 nl_flags"]) ri.cw.block_start() ri.cw.p('req->_nlmsg_flags = nl_flags;') @@ -2533,7 +2533,7 @@ def _print_type(ri, direction, struct): line = attr.presence_member(ri.ku_space, type_filter) if line: if not meta_started: - ri.cw.block_start(line=f"struct") + ri.cw.block_start(line="struct") meta_started = True ri.cw.p(line) if meta_started: @@ -2697,7 +2697,7 @@ def print_dump_type_free(ri): ri.cw.nl() _free_type_members(ri, 'rsp', ri.struct['reply'], ref='obj.') - ri.cw.p(f'free(rsp);') + ri.cw.p('free(rsp);') ri.cw.block_end() ri.cw.block_end() ri.cw.nl() @@ -2708,7 +2708,7 @@ def print_ntf_type_free(ri): ri.cw.block_start() _free_type_members_iter(ri, ri.struct['reply']) _free_type_members(ri, 'rsp', ri.struct['reply'], ref='obj.') - ri.cw.p(f'free(rsp);') + ri.cw.p('free(rsp);') ri.cw.block_end() ri.cw.nl() @@ -3322,7 +3322,7 @@ def render_user_family(family, cw, prototype): cw.block_start(f'{symbol} = ') cw.p(f'.name\t\t= "{family.c_name}",') if family.is_classic(): - cw.p(f'.is_classic\t= true,') + cw.p('.is_classic\t= true,') cw.p(f'.classic_id\t= {family.get("protonum")},') if family.is_classic(): if family.fixed_header: From 389712b0da1f0af9ef28b3d8f9b18e41f92ade28 Mon Sep 17 00:00:00 2001 From: "Matthieu Baerts (NGI0)" Date: Tue, 9 Sep 2025 23:07:51 +0200 Subject: [PATCH 5/8] tools: ynl: remove unused imports MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit These imports are not used according to Ruff, and can be safely removed. This is linked to Ruff error F401 [1]: Unused imports add a performance overhead at runtime, and risk creating import cycles. They also increase the cognitive load of reading the code. There is one exception with 'YnlDocGenerator' which is added in __all__: it is used by ynl_gen_rst.py. Link: https://docs.astral.sh/ruff/rules/unused-import/ [1] Signed-off-by: Matthieu Baerts (NGI0) Reviewed-by: Donald Hunter Reviewed-by: Asbjørn Sloth Tønnesen Link: https://patch.msgid.link/20250909-net-next-ynl-ruff-v1-5-238c2bccdd99@kernel.org Signed-off-by: Jakub Kicinski --- tools/net/ynl/pyynl/ethtool.py | 1 - tools/net/ynl/pyynl/lib/__init__.py | 2 +- tools/net/ynl/pyynl/lib/ynl.py | 1 - tools/net/ynl/pyynl/ynl_gen_c.py | 3 +-- 4 files changed, 2 insertions(+), 5 deletions(-) diff --git a/tools/net/ynl/pyynl/ethtool.py b/tools/net/ynl/pyynl/ethtool.py index c1cd088c050c..9b523cbb3568 100755 --- a/tools/net/ynl/pyynl/ethtool.py +++ b/tools/net/ynl/pyynl/ethtool.py @@ -2,7 +2,6 @@ # SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause import argparse -import json import pathlib import pprint import sys diff --git a/tools/net/ynl/pyynl/lib/__init__.py b/tools/net/ynl/pyynl/lib/__init__.py index 5f266ebe4526..ec9ea00071be 100644 --- a/tools/net/ynl/pyynl/lib/__init__.py +++ b/tools/net/ynl/pyynl/lib/__init__.py @@ -8,4 +8,4 @@ from .doc_generator import YnlDocGenerator __all__ = ["SpecAttr", "SpecAttrSet", "SpecEnumEntry", "SpecEnumSet", "SpecFamily", "SpecOperation", "SpecSubMessage", "SpecSubMessageFormat", - "YnlFamily", "Netlink", "NlError"] + "YnlFamily", "Netlink", "NlError", "YnlDocGenerator"] diff --git a/tools/net/ynl/pyynl/lib/ynl.py b/tools/net/ynl/pyynl/lib/ynl.py index 15ddb0b1adb6..da307fd1e9b0 100644 --- a/tools/net/ynl/pyynl/lib/ynl.py +++ b/tools/net/ynl/pyynl/lib/ynl.py @@ -9,7 +9,6 @@ import socket import struct from struct import Struct import sys -import yaml import ipaddress import uuid import queue diff --git a/tools/net/ynl/pyynl/ynl_gen_c.py b/tools/net/ynl/pyynl/ynl_gen_c.py index 8e95c5bb1399..5113cf1787f6 100755 --- a/tools/net/ynl/pyynl/ynl_gen_c.py +++ b/tools/net/ynl/pyynl/ynl_gen_c.py @@ -2,7 +2,6 @@ # SPDX-License-Identifier: ((GPL-2.0 WITH Linux-syscall-note) OR BSD-3-Clause) import argparse -import collections import filecmp import pathlib import os @@ -14,7 +13,7 @@ import yaml sys.path.append(pathlib.Path(__file__).resolve().parent.as_posix()) from lib import SpecFamily, SpecAttrSet, SpecAttr, SpecOperation, SpecEnumSet, SpecEnumEntry -from lib import SpecSubMessage, SpecSubMessageFormat +from lib import SpecSubMessage def c_upper(name): From 616129d6b421e3603a1c66bf494b6a95f0128602 Mon Sep 17 00:00:00 2001 From: "Matthieu Baerts (NGI0)" Date: Tue, 9 Sep 2025 23:07:52 +0200 Subject: [PATCH 6/8] tools: ynl: remove unnecessary semicolons MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit These semicolons are not required according to Ruff. Simply remove them. This is linked to Ruff error E703 [1]: A trailing semicolon is unnecessary and should be removed. Link: https://docs.astral.sh/ruff/rules/useless-semicolon/ [1] Signed-off-by: Matthieu Baerts (NGI0) Reviewed-by: Donald Hunter Reviewed-by: Asbjørn Sloth Tønnesen Link: https://patch.msgid.link/20250909-net-next-ynl-ruff-v1-6-238c2bccdd99@kernel.org Signed-off-by: Jakub Kicinski --- tools/net/ynl/pyynl/lib/nlspec.py | 2 +- tools/net/ynl/pyynl/lib/ynl.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/tools/net/ynl/pyynl/lib/nlspec.py b/tools/net/ynl/pyynl/lib/nlspec.py index 314ec8007496..85c17fe01e35 100644 --- a/tools/net/ynl/pyynl/lib/nlspec.py +++ b/tools/net/ynl/pyynl/lib/nlspec.py @@ -501,7 +501,7 @@ class SpecFamily(SpecElement): return SpecStruct(self, elem) def new_sub_message(self, elem): - return SpecSubMessage(self, elem); + return SpecSubMessage(self, elem) def new_operation(self, elem, req_val, rsp_val): return SpecOperation(self, elem, req_val, rsp_val) diff --git a/tools/net/ynl/pyynl/lib/ynl.py b/tools/net/ynl/pyynl/lib/ynl.py index da307fd1e9b0..1e06f79beb57 100644 --- a/tools/net/ynl/pyynl/lib/ynl.py +++ b/tools/net/ynl/pyynl/lib/ynl.py @@ -738,7 +738,7 @@ class YnlFamily(SpecFamily): decoded = {} offset = 0 if msg_format.fixed_header: - decoded.update(self._decode_struct(attr.raw, msg_format.fixed_header)); + decoded.update(self._decode_struct(attr.raw, msg_format.fixed_header)) offset = self._struct_size(msg_format.fixed_header) if msg_format.attr_set: if msg_format.attr_set in self.attr_sets: From 10d32b0ddcc142749f6759c0b052a3780903b4df Mon Sep 17 00:00:00 2001 From: "Matthieu Baerts (NGI0)" Date: Tue, 9 Sep 2025 23:07:53 +0200 Subject: [PATCH 7/8] tools: ynl: use 'cond is None' MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit It is better to use the 'is' keyword instead of comparing to None according to Ruff. This is linked to Ruff error E711 [1]: According to PEP 8, "Comparisons to singletons like None should always be done with is or is not, never the equality operators." Link: https://docs.astral.sh/ruff/rules/none-comparison/ [1] Signed-off-by: Matthieu Baerts (NGI0) Reviewed-by: Donald Hunter Reviewed-by: Asbjørn Sloth Tønnesen Link: https://patch.msgid.link/20250909-net-next-ynl-ruff-v1-7-238c2bccdd99@kernel.org Signed-off-by: Jakub Kicinski --- tools/net/ynl/pyynl/lib/ynl.py | 2 +- tools/net/ynl/pyynl/ynl_gen_c.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/tools/net/ynl/pyynl/lib/ynl.py b/tools/net/ynl/pyynl/lib/ynl.py index 1e06f79beb57..50805e05020a 100644 --- a/tools/net/ynl/pyynl/lib/ynl.py +++ b/tools/net/ynl/pyynl/lib/ynl.py @@ -705,7 +705,7 @@ class YnlFamily(SpecFamily): return attr.as_bin() def _rsp_add(self, rsp, name, is_multi, decoded): - if is_multi == None: + if is_multi is None: if name in rsp and type(rsp[name]) is not list: rsp[name] = [rsp[name]] is_multi = True diff --git a/tools/net/ynl/pyynl/ynl_gen_c.py b/tools/net/ynl/pyynl/ynl_gen_c.py index 5113cf1787f6..c7fb8abfd65e 100755 --- a/tools/net/ynl/pyynl/ynl_gen_c.py +++ b/tools/net/ynl/pyynl/ynl_gen_c.py @@ -397,7 +397,7 @@ class TypeScalar(Type): if 'enum' in self.attr: enum = self.family.consts[self.attr['enum']] low, high = enum.value_range() - if low == None and high == None: + if low is None and high is None: self.checks['sparse'] = True else: if 'min' not in self.checks: From f6259ba70e7e056ae626b393c908500a5d6e8755 Mon Sep 17 00:00:00 2001 From: "Matthieu Baerts (NGI0)" Date: Tue, 9 Sep 2025 23:07:54 +0200 Subject: [PATCH 8/8] tools: ynl: check for membership with 'not in' MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit It is better to use 'not in' instead of 'not {element} in {collection}' according to Ruff. This is linked to Ruff error E713 [1]: Testing membership with {element} not in {collection} is more readable. Link: https://docs.astral.sh/ruff/rules/not-in-test/ [1] Signed-off-by: Matthieu Baerts (NGI0) Reviewed-by: Donald Hunter Reviewed-by: Asbjørn Sloth Tønnesen Link: https://patch.msgid.link/20250909-net-next-ynl-ruff-v1-8-238c2bccdd99@kernel.org Signed-off-by: Jakub Kicinski --- tools/net/ynl/pyynl/ynl_gen_c.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/net/ynl/pyynl/ynl_gen_c.py b/tools/net/ynl/pyynl/ynl_gen_c.py index c7fb8abfd65e..101d8ba9626f 100755 --- a/tools/net/ynl/pyynl/ynl_gen_c.py +++ b/tools/net/ynl/pyynl/ynl_gen_c.py @@ -638,7 +638,7 @@ class TypeBitfield32(Type): return '.type = YNL_PT_BITFIELD32, ' def _attr_policy(self, policy): - if not 'enum' in self.attr: + if 'enum' not in self.attr: raise Exception('Enum required for bitfield32 attr') enum = self.family.consts[self.attr['enum']] mask = enum.get_mask(as_flags=True)