Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

Merge branch 'tools-ynl-clean-up-pylint-issues'

Donald Hunter says:

====================
tools: ynl: clean up pylint issues

pylint tools/net/ynl/pyynl reports >850 issues, with a rating of
8.59/10. It's hard to spot new issues or genuine code smells in
all that noise.

Fix the easily fixable issues and suppress the noisy warnings.

pylint tools/net/ynl/pyynl
************* Module pyynl.ethtool
tools/net/ynl/pyynl/ethtool.py:159:5: W0511: TODO: --show-tunnels tunnel-info-get (fixme)
tools/net/ynl/pyynl/ethtool.py:160:5: W0511: TODO: --show-module module-get (fixme)
tools/net/ynl/pyynl/ethtool.py:161:5: W0511: TODO: --get-plca-cfg plca-get (fixme)
tools/net/ynl/pyynl/ethtool.py:162:5: W0511: TODO: --get-plca-status plca-get-status (fixme)
tools/net/ynl/pyynl/ethtool.py:163:5: W0511: TODO: --show-mm mm-get (fixme)
tools/net/ynl/pyynl/ethtool.py:164:5: W0511: TODO: --show-fec fec-get (fixme)
tools/net/ynl/pyynl/ethtool.py:165:5: W0511: TODO: --dump-module-eerpom module-eeprom-get (fixme)
tools/net/ynl/pyynl/ethtool.py:166:5: W0511: TODO: pse-get (fixme)
tools/net/ynl/pyynl/ethtool.py:167:5: W0511: TODO: rss-get (fixme)
tools/net/ynl/pyynl/ethtool.py:179:9: W0511: TODO: parse the bitmask (fixme)
tools/net/ynl/pyynl/ethtool.py:196:9: W0511: TODO: parse the bitmask (fixme)
tools/net/ynl/pyynl/ethtool.py:321:9: W0511: TODO: pass id? (fixme)
tools/net/ynl/pyynl/ethtool.py:330:17: W0511: TODO: support passing the bitmask (fixme)
tools/net/ynl/pyynl/ethtool.py:459:5: W0511: TODO: wol-get (fixme)

------------------------------------------------------------------
Your code has been rated at 9.97/10 (previous run: 8.59/10, +1.38)
====================

Link: https://patch.msgid.link/20260108161339.29166-1-donald.hunter@gmail.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>

+343 -249
+42 -25
tools/net/ynl/pyynl/cli.py
··· 1 1 #!/usr/bin/env python3 2 2 # SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause 3 3 4 + """ 5 + YNL cli tool 6 + """ 7 + 4 8 import argparse 5 9 import json 6 10 import os ··· 13 9 import sys 14 10 import textwrap 15 11 12 + # pylint: disable=no-name-in-module,wrong-import-position 16 13 sys.path.append(pathlib.Path(__file__).resolve().parent.as_posix()) 17 - from lib import YnlFamily, Netlink, NlError, SpecFamily 14 + from lib import YnlFamily, Netlink, NlError, SpecFamily, SpecException, YnlException 18 15 19 - sys_schema_dir='/usr/share/ynl' 20 - relative_schema_dir='../../../../Documentation/netlink' 16 + SYS_SCHEMA_DIR='/usr/share/ynl' 17 + RELATIVE_SCHEMA_DIR='../../../../Documentation/netlink' 21 18 22 19 def schema_dir(): 20 + """ 21 + Return the effective schema directory, preferring in-tree before 22 + system schema directory. 23 + """ 23 24 script_dir = os.path.dirname(os.path.abspath(__file__)) 24 - schema_dir = os.path.abspath(f"{script_dir}/{relative_schema_dir}") 25 - if not os.path.isdir(schema_dir): 26 - schema_dir = sys_schema_dir 27 - if not os.path.isdir(schema_dir): 28 - raise Exception(f"Schema directory {schema_dir} does not exist") 29 - return schema_dir 25 + schema_dir_ = os.path.abspath(f"{script_dir}/{RELATIVE_SCHEMA_DIR}") 26 + if not os.path.isdir(schema_dir_): 27 + schema_dir_ = SYS_SCHEMA_DIR 28 + if not os.path.isdir(schema_dir_): 29 + raise YnlException(f"Schema directory {schema_dir_} does not exist") 30 + return schema_dir_ 30 31 31 32 def spec_dir(): 32 - spec_dir = schema_dir() + '/specs' 33 - if not os.path.isdir(spec_dir): 34 - raise Exception(f"Spec directory {spec_dir} does not exist") 35 - return spec_dir 33 + """ 34 + Return the effective spec directory, relative to the effective 35 + schema directory. 36 + """ 37 + spec_dir_ = schema_dir() + '/specs' 38 + if not os.path.isdir(spec_dir_): 39 + raise YnlException(f"Spec directory {spec_dir_} does not exist") 40 + return spec_dir_ 36 41 37 42 38 43 class YnlEncoder(json.JSONEncoder): 39 - def default(self, obj): 40 - if isinstance(obj, bytes): 41 - return bytes.hex(obj) 42 - if isinstance(obj, set): 43 - return list(obj) 44 - return json.JSONEncoder.default(self, obj) 44 + """A custom encoder for emitting JSON with ynl-specific instance types""" 45 + def default(self, o): 46 + if isinstance(o, bytes): 47 + return bytes.hex(o) 48 + if isinstance(o, set): 49 + return list(o) 50 + return json.JSONEncoder.default(self, o) 45 51 46 52 47 53 def print_attr_list(ynl, attr_names, attr_set, indent=2): ··· 108 94 print_attr_list(ynl, mode_spec['attributes'], attr_set) 109 95 110 96 97 + # pylint: disable=too-many-locals,too-many-branches,too-many-statements 111 98 def main(): 99 + """YNL cli tool""" 100 + 112 101 description = """ 113 102 YNL CLI utility - a general purpose netlink utility that uses YAML 114 103 specs to drive protocol encoding and decoding. ··· 189 172 else: 190 173 spec = args.spec 191 174 if not os.path.isfile(spec): 192 - raise Exception(f"Spec file {spec} does not exist") 175 + raise YnlException(f"Spec file {spec} does not exist") 193 176 194 177 if args.validate: 195 178 try: 196 179 SpecFamily(spec, args.schema) 197 - except Exception as error: 180 + except SpecException as error: 198 181 print(error) 199 - exit(1) 182 + sys.exit(1) 200 183 return 201 184 202 185 if args.family: # set behaviour when using installed specs 203 - if args.schema is None and spec.startswith(sys_schema_dir): 186 + if args.schema is None and spec.startswith(SYS_SCHEMA_DIR): 204 187 args.schema = '' # disable schema validation when installed 205 188 if args.process_unknown is None: 206 189 args.process_unknown = True ··· 224 207 op = ynl.msgs.get(args.list_attrs) 225 208 if not op: 226 209 print(f'Operation {args.list_attrs} not found') 227 - exit(1) 210 + sys.exit(1) 228 211 229 212 print(f'Operation: {op.name}') 230 213 print(op.yaml['doc']) ··· 259 242 output(msg) 260 243 except NlError as e: 261 244 print(e) 262 - exit(1) 245 + sys.exit(1) 263 246 except KeyboardInterrupt: 264 247 pass 265 248 except BrokenPipeError:
+32 -15
tools/net/ynl/pyynl/ethtool.py
··· 1 1 #!/usr/bin/env python3 2 2 # SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause 3 + # 4 + # pylint: disable=too-many-locals, too-many-branches, too-many-statements 5 + # pylint: disable=too-many-return-statements 6 + 7 + """ YNL ethtool utility """ 3 8 4 9 import argparse 5 10 import pathlib ··· 13 8 import re 14 9 import os 15 10 11 + # pylint: disable=no-name-in-module,wrong-import-position 16 12 sys.path.append(pathlib.Path(__file__).resolve().parent.as_posix()) 17 - from lib import YnlFamily 13 + # pylint: disable=import-error 18 14 from cli import schema_dir, spec_dir 15 + from lib import YnlFamily 16 + 19 17 20 18 def args_to_req(ynl, op_name, args, req): 21 19 """ ··· 56 48 return 57 49 58 50 if len(desc) == 0: 59 - return print_field(reply, *zip(reply.keys(), reply.keys())) 51 + print_field(reply, *zip(reply.keys(), reply.keys())) 52 + return 60 53 61 54 for spec in desc: 62 55 try: ··· 97 88 args_to_req(ynl, op_name, args.args, req) 98 89 ynl.do(op_name, req) 99 90 100 - def dumpit(ynl, args, op_name, extra = {}): 91 + def dumpit(ynl, args, op_name, extra=None): 101 92 """ 102 93 Prepare request header, parse arguments and dumpit (filtering out the 103 94 devices we're not interested in). 104 95 """ 96 + extra = extra or {} 105 97 reply = ynl.dump(op_name, { 'header': {} } | extra) 106 98 if not reply: 107 99 return {} ··· 124 114 """ 125 115 ret = {} 126 116 if 'bits' not in attr: 127 - return dict() 117 + return {} 128 118 if 'bit' not in attr['bits']: 129 - return dict() 119 + return {} 130 120 for bit in attr['bits']['bit']: 131 121 if bit['name'] == '': 132 122 continue ··· 136 126 return ret 137 127 138 128 def main(): 129 + """ YNL ethtool utility """ 130 + 139 131 parser = argparse.ArgumentParser(description='ethtool wannabe') 140 132 parser.add_argument('--json', action=argparse.BooleanOptionalAction) 141 133 parser.add_argument('--show-priv-flags', action=argparse.BooleanOptionalAction) ··· 167 155 # TODO: rss-get 168 156 parser.add_argument('device', metavar='device', type=str) 169 157 parser.add_argument('args', metavar='args', type=str, nargs='*') 170 - global args 158 + 171 159 args = parser.parse_args() 172 160 173 161 spec = os.path.join(spec_dir(), 'ethtool.yaml') ··· 181 169 return 182 170 183 171 if args.set_eee: 184 - return doit(ynl, args, 'eee-set') 172 + doit(ynl, args, 'eee-set') 173 + return 185 174 186 175 if args.set_pause: 187 - return doit(ynl, args, 'pause-set') 176 + doit(ynl, args, 'pause-set') 177 + return 188 178 189 179 if args.set_coalesce: 190 - return doit(ynl, args, 'coalesce-set') 180 + doit(ynl, args, 'coalesce-set') 181 + return 191 182 192 183 if args.set_features: 193 184 # TODO: parse the bitmask ··· 198 183 return 199 184 200 185 if args.set_channels: 201 - return doit(ynl, args, 'channels-set') 186 + doit(ynl, args, 'channels-set') 187 + return 202 188 203 189 if args.set_ring: 204 - return doit(ynl, args, 'rings-set') 190 + doit(ynl, args, 'rings-set') 191 + return 205 192 206 193 if args.show_priv_flags: 207 194 flags = bits_to_dict(dumpit(ynl, args, 'privflags-get')['flags']) ··· 354 337 print(f'Time stamping parameters for {args.device}:') 355 338 356 339 print('Capabilities:') 357 - [print(f'\t{v}') for v in bits_to_dict(tsinfo['timestamping'])] 340 + _ = [print(f'\t{v}') for v in bits_to_dict(tsinfo['timestamping'])] 358 341 359 342 print(f'PTP Hardware Clock: {tsinfo.get("phc-index", "none")}') 360 343 361 344 if 'tx-types' in tsinfo: 362 345 print('Hardware Transmit Timestamp Modes:') 363 - [print(f'\t{v}') for v in bits_to_dict(tsinfo['tx-types'])] 346 + _ = [print(f'\t{v}') for v in bits_to_dict(tsinfo['tx-types'])] 364 347 else: 365 348 print('Hardware Transmit Timestamp Modes: none') 366 349 367 350 if 'rx-filters' in tsinfo: 368 351 print('Hardware Receive Filter Modes:') 369 - [print(f'\t{v}') for v in bits_to_dict(tsinfo['rx-filters'])] 352 + _ = [print(f'\t{v}') for v in bits_to_dict(tsinfo['rx-filters'])] 370 353 else: 371 354 print('Hardware Receive Filter Modes: none') 372 355 373 356 if 'stats' in tsinfo and tsinfo['stats']: 374 357 print('Statistics:') 375 - [print(f'\t{k}: {v}') for k, v in tsinfo['stats'].items()] 358 + _ = [print(f'\t{k}: {v}') for k, v in tsinfo['stats'].items()] 376 359 377 360 return 378 361
+7 -3
tools/net/ynl/pyynl/lib/__init__.py
··· 1 1 # SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause 2 2 3 + """ YNL library """ 4 + 3 5 from .nlspec import SpecAttr, SpecAttrSet, SpecEnumEntry, SpecEnumSet, \ 4 - SpecFamily, SpecOperation, SpecSubMessage, SpecSubMessageFormat 5 - from .ynl import YnlFamily, Netlink, NlError 6 + SpecFamily, SpecOperation, SpecSubMessage, SpecSubMessageFormat, \ 7 + SpecException 8 + from .ynl import YnlFamily, Netlink, NlError, YnlException 6 9 7 10 from .doc_generator import YnlDocGenerator 8 11 9 12 __all__ = ["SpecAttr", "SpecAttrSet", "SpecEnumEntry", "SpecEnumSet", 10 13 "SpecFamily", "SpecOperation", "SpecSubMessage", "SpecSubMessageFormat", 11 - "YnlFamily", "Netlink", "NlError", "YnlDocGenerator"] 14 + "SpecException", 15 + "YnlFamily", "Netlink", "NlError", "YnlDocGenerator", "YnlException"]
+1 -2
tools/net/ynl/pyynl/lib/doc_generator.py
··· 109 109 'fixed-header': 'definition', 110 110 'nested-attributes': 'attribute-set', 111 111 'struct': 'definition'} 112 - if prefix in mappings: 113 - prefix = mappings[prefix] 112 + prefix = mappings.get(prefix, prefix) 114 113 return f":ref:`{namespace}-{prefix}-{name}`" 115 114 116 115 def rst_header(self) -> str:
+43 -34
tools/net/ynl/pyynl/lib/nlspec.py
··· 1 1 # SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause 2 + # 3 + # pylint: disable=missing-function-docstring, too-many-instance-attributes, too-many-branches 4 + 5 + """ 6 + The nlspec is a python library for parsing and using YNL netlink 7 + specifications. 8 + """ 2 9 3 10 import collections 4 11 import importlib 5 12 import os 6 - import yaml 13 + import yaml as pyyaml 7 14 8 15 9 - # To be loaded dynamically as needed 10 - jsonschema = None 16 + class SpecException(Exception): 17 + """Netlink spec exception. 18 + """ 11 19 12 20 13 21 class SpecElement: ··· 101 93 def user_value(self, as_flags=None): 102 94 if self.enum_set['type'] == 'flags' or as_flags: 103 95 return 1 << self.value 104 - else: 105 - return self.value 96 + return self.value 106 97 107 98 108 99 class SpecEnumSet(SpecElement): ··· 124 117 125 118 prev_entry = None 126 119 value_start = self.yaml.get('value-start', 0) 127 - self.entries = dict() 128 - self.entries_by_val = dict() 120 + self.entries = {} 121 + self.entries_by_val = {} 129 122 for entry in self.yaml['entries']: 130 123 e = self.new_entry(entry, prev_entry, value_start) 131 124 self.entries[e.name] = e ··· 189 182 self.sub_message = yaml.get('sub-message') 190 183 self.selector = yaml.get('selector') 191 184 192 - self.is_auto_scalar = self.type == "sint" or self.type == "uint" 185 + self.is_auto_scalar = self.type in ("sint", "uint") 193 186 194 187 195 188 class SpecAttrSet(SpecElement): ··· 295 288 yield from self.members 296 289 297 290 def items(self): 298 - return self.members.items() 291 + return self.members 299 292 300 293 301 294 class SpecSubMessage(SpecElement): ··· 313 306 314 307 self.formats = collections.OrderedDict() 315 308 for elem in self.yaml['formats']: 316 - format = self.new_format(family, elem) 317 - self.formats[format.value] = format 309 + msg_format = self.new_format(family, elem) 310 + self.formats[msg_format.value] = msg_format 318 311 319 - def new_format(self, family, format): 320 - return SpecSubMessageFormat(family, format) 312 + def new_format(self, family, msg_format): 313 + return SpecSubMessageFormat(family, msg_format) 321 314 322 315 323 316 class SpecSubMessageFormat(SpecElement): ··· 385 378 elif self.is_resv: 386 379 attr_set_name = '' 387 380 else: 388 - raise Exception(f"Can't resolve attribute set for op '{self.name}'") 381 + raise SpecException(f"Can't resolve attribute set for op '{self.name}'") 389 382 if attr_set_name: 390 383 self.attr_set = self.family.attr_sets[attr_set_name] 391 384 ··· 435 428 mcast_groups dict of all multicast groups (index by name) 436 429 kernel_family dict of kernel family attributes 437 430 """ 431 + 432 + # To be loaded dynamically as needed 433 + jsonschema = None 434 + 438 435 def __init__(self, spec_path, schema_path=None, exclude_ops=None): 439 - with open(spec_path, "r") as stream: 436 + with open(spec_path, "r", encoding='utf-8') as stream: 440 437 prefix = '# SPDX-License-Identifier: ' 441 438 first = stream.readline().strip() 442 439 if not first.startswith(prefix): 443 - raise Exception('SPDX license tag required in the spec') 440 + raise SpecException('SPDX license tag required in the spec') 444 441 self.license = first[len(prefix):] 445 442 446 443 stream.seek(0) 447 - spec = yaml.safe_load(stream) 444 + spec = pyyaml.safe_load(stream) 448 445 446 + self.fixed_header = None 449 447 self._resolution_list = [] 450 448 451 449 super().__init__(self, spec) ··· 463 451 if schema_path is None: 464 452 schema_path = os.path.dirname(os.path.dirname(spec_path)) + f'/{self.proto}.yaml' 465 453 if schema_path: 466 - global jsonschema 454 + with open(schema_path, "r", encoding='utf-8') as stream: 455 + schema = pyyaml.safe_load(stream) 467 456 468 - with open(schema_path, "r") as stream: 469 - schema = yaml.safe_load(stream) 457 + if SpecFamily.jsonschema is None: 458 + SpecFamily.jsonschema = importlib.import_module("jsonschema") 470 459 471 - if jsonschema is None: 472 - jsonschema = importlib.import_module("jsonschema") 473 - 474 - jsonschema.validate(self.yaml, schema) 460 + SpecFamily.jsonschema.validate(self.yaml, schema) 475 461 476 462 self.attr_sets = collections.OrderedDict() 477 463 self.sub_msgs = collections.OrderedDict() ··· 558 548 req_val_next = req_val + 1 559 549 rsp_val_next = rsp_val + rsp_inc 560 550 else: 561 - raise Exception("Can't parse directional ops") 551 + raise SpecException("Can't parse directional ops") 562 552 563 553 if req_val == req_val_next: 564 554 req_val = None ··· 570 560 skip |= bool(exclude.match(elem['name'])) 571 561 if not skip: 572 562 op = self.new_operation(elem, req_val, rsp_val) 563 + self.msgs[op.name] = op 573 564 574 565 req_val = req_val_next 575 566 rsp_val = rsp_val_next 576 567 577 - self.msgs[op.name] = op 578 - 579 568 def find_operation(self, name): 580 - """ 581 - For a given operation name, find and return operation spec. 582 - """ 583 - for op in self.yaml['operations']['list']: 584 - if name == op['name']: 585 - return op 586 - return None 569 + """ 570 + For a given operation name, find and return operation spec. 571 + """ 572 + for op in self.yaml['operations']['list']: 573 + if name == op['name']: 574 + return op 575 + return None 587 576 588 577 def resolve(self): 589 578 self.resolve_up(super())
+116 -92
tools/net/ynl/pyynl/lib/ynl.py
··· 1 1 # SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause 2 + # 3 + # pylint: disable=missing-class-docstring, missing-function-docstring 4 + # pylint: disable=too-many-branches, too-many-locals, too-many-instance-attributes 5 + # pylint: disable=too-many-lines 6 + 7 + """ 8 + YAML Netlink Library 9 + 10 + An implementation of the genetlink and raw netlink protocols. 11 + """ 2 12 3 13 from collections import namedtuple 4 14 from enum import Enum ··· 32 22 # 33 23 34 24 25 + class YnlException(Exception): 26 + pass 27 + 28 + 29 + # pylint: disable=too-few-public-methods 35 30 class Netlink: 36 31 # Netlink socket 37 32 SOL_NETLINK = 270 ··· 159 144 160 145 @classmethod 161 146 def get_format(cls, attr_type, byte_order=None): 162 - format = cls.type_formats[attr_type] 147 + format_ = cls.type_formats[attr_type] 163 148 if byte_order: 164 - return format.big if byte_order == "big-endian" \ 165 - else format.little 166 - return format.native 149 + return format_.big if byte_order == "big-endian" \ 150 + else format_.little 151 + return format_.native 167 152 168 153 def as_scalar(self, attr_type, byte_order=None): 169 - format = self.get_format(attr_type, byte_order) 170 - return format.unpack(self.raw)[0] 154 + format_ = self.get_format(attr_type, byte_order) 155 + return format_.unpack(self.raw)[0] 171 156 172 157 def as_auto_scalar(self, attr_type, byte_order=None): 173 158 if len(self.raw) != 4 and len(self.raw) != 8: 174 - raise Exception(f"Auto-scalar len payload be 4 or 8 bytes, got {len(self.raw)}") 159 + raise YnlException(f"Auto-scalar len payload be 4 or 8 bytes, got {len(self.raw)}") 175 160 real_type = attr_type[0] + str(len(self.raw) * 8) 176 - format = self.get_format(real_type, byte_order) 177 - return format.unpack(self.raw)[0] 161 + format_ = self.get_format(real_type, byte_order) 162 + return format_.unpack(self.raw)[0] 178 163 179 164 def as_strz(self): 180 165 return self.raw.decode('ascii')[:-1] ··· 182 167 def as_bin(self): 183 168 return self.raw 184 169 185 - def as_c_array(self, type): 186 - format = self.get_format(type) 187 - return [ x[0] for x in format.iter_unpack(self.raw) ] 170 + def as_c_array(self, c_type): 171 + format_ = self.get_format(c_type) 172 + return [ x[0] for x in format_.iter_unpack(self.raw) ] 188 173 189 174 def __repr__(self): 190 175 return f"[type:{self.type} len:{self._len}] {self.raw}" ··· 235 220 236 221 self.extack = None 237 222 if self.nl_flags & Netlink.NLM_F_ACK_TLVS and extack_off: 238 - self.extack = dict() 223 + self.extack = {} 239 224 extack_attrs = NlAttrs(self.raw[extack_off:]) 240 225 for extack in extack_attrs: 241 226 if extack.type == Netlink.NLMSGERR_ATTR_MSG: ··· 260 245 policy = {} 261 246 for attr in NlAttrs(raw): 262 247 if attr.type == Netlink.NL_POLICY_TYPE_ATTR_TYPE: 263 - type = attr.as_scalar('u32') 264 - policy['type'] = Netlink.AttrType(type).name 248 + type_ = attr.as_scalar('u32') 249 + policy['type'] = Netlink.AttrType(type_).name 265 250 elif attr.type == Netlink.NL_POLICY_TYPE_ATTR_MIN_VALUE_S: 266 251 policy['min-value'] = attr.as_scalar('s64') 267 252 elif attr.type == Netlink.NL_POLICY_TYPE_ATTR_MAX_VALUE_S: ··· 296 281 return self.nl_type 297 282 298 283 def __repr__(self): 299 - msg = f"nl_len = {self.nl_len} ({len(self.raw)}) nl_flags = 0x{self.nl_flags:x} nl_type = {self.nl_type}" 284 + msg = (f"nl_len = {self.nl_len} ({len(self.raw)}) " 285 + f"nl_flags = 0x{self.nl_flags:x} nl_type = {self.nl_type}") 300 286 if self.error: 301 287 msg += '\n\terror: ' + str(self.error) 302 288 if self.extack: ··· 305 289 return msg 306 290 307 291 292 + # pylint: disable=too-few-public-methods 308 293 class NlMsgs: 309 294 def __init__(self, data): 310 295 self.msgs = [] ··· 318 301 319 302 def __iter__(self): 320 303 yield from self.msgs 321 - 322 - 323 - genl_family_name_to_id = None 324 304 325 305 326 306 def _genl_msg(nl_type, nl_flags, genl_cmd, genl_version, seq=None): ··· 333 319 return struct.pack("I", len(msg) + 4) + msg 334 320 335 321 322 + # pylint: disable=too-many-nested-blocks 336 323 def _genl_load_families(): 324 + genl_family_name_to_id = {} 325 + 337 326 with socket.socket(socket.AF_NETLINK, socket.SOCK_RAW, Netlink.NETLINK_GENERIC) as sock: 338 327 sock.setsockopt(Netlink.SOL_NETLINK, Netlink.NETLINK_CAP_ACK, 1) 339 328 ··· 347 330 348 331 sock.send(msg, 0) 349 332 350 - global genl_family_name_to_id 351 - genl_family_name_to_id = dict() 352 - 353 333 while True: 354 334 reply = sock.recv(128 * 1024) 355 335 nms = NlMsgs(reply) 356 336 for nl_msg in nms: 357 337 if nl_msg.error: 358 - print("Netlink error:", nl_msg.error) 359 - return 338 + raise YnlException(f"Netlink error: {nl_msg.error}") 360 339 if nl_msg.done: 361 - return 340 + return genl_family_name_to_id 362 341 363 342 gm = GenlMsg(nl_msg) 364 - fam = dict() 343 + fam = {} 365 344 for attr in NlAttrs(gm.raw): 366 345 if attr.type == Netlink.CTRL_ATTR_FAMILY_ID: 367 346 fam['id'] = attr.as_scalar('u16') ··· 366 353 elif attr.type == Netlink.CTRL_ATTR_MAXATTR: 367 354 fam['maxattr'] = attr.as_scalar('u32') 368 355 elif attr.type == Netlink.CTRL_ATTR_MCAST_GROUPS: 369 - fam['mcast'] = dict() 356 + fam['mcast'] = {} 370 357 for entry in NlAttrs(attr.raw): 371 358 mcast_name = None 372 359 mcast_id = None ··· 386 373 self.nl = nl_msg 387 374 self.genl_cmd, self.genl_version, _ = struct.unpack_from("BBH", nl_msg.raw, 0) 388 375 self.raw = nl_msg.raw[4:] 376 + self.raw_attrs = [] 389 377 390 378 def cmd(self): 391 379 return self.genl_cmd ··· 410 396 nlmsg = struct.pack("HHII", nl_type, nl_flags, seq, 0) 411 397 return nlmsg 412 398 413 - def message(self, flags, command, version, seq=None): 399 + def message(self, flags, command, _version, seq=None): 414 400 return self._message(command, flags, seq) 415 401 416 402 def _decode(self, nl_msg): ··· 420 406 msg = self._decode(nl_msg) 421 407 if op is None: 422 408 op = ynl.rsp_by_value[msg.cmd()] 423 - fixed_header_size = ynl._struct_size(op.fixed_header) 409 + fixed_header_size = ynl.struct_size(op.fixed_header) 424 410 msg.raw_attrs = NlAttrs(msg.raw, fixed_header_size) 425 411 return msg 426 412 427 413 def get_mcast_id(self, mcast_name, mcast_groups): 428 414 if mcast_name not in mcast_groups: 429 - raise Exception(f'Multicast group "{mcast_name}" not present in the spec') 415 + raise YnlException(f'Multicast group "{mcast_name}" not present in the spec') 430 416 return mcast_groups[mcast_name].value 431 417 432 418 def msghdr_size(self): ··· 434 420 435 421 436 422 class GenlProtocol(NetlinkProtocol): 423 + genl_family_name_to_id = {} 424 + 437 425 def __init__(self, family_name): 438 426 super().__init__(family_name, Netlink.NETLINK_GENERIC) 439 427 440 - global genl_family_name_to_id 441 - if genl_family_name_to_id is None: 442 - _genl_load_families() 428 + if not GenlProtocol.genl_family_name_to_id: 429 + GenlProtocol.genl_family_name_to_id = _genl_load_families() 443 430 444 - self.genl_family = genl_family_name_to_id[family_name] 445 - self.family_id = genl_family_name_to_id[family_name]['id'] 431 + self.genl_family = GenlProtocol.genl_family_name_to_id[family_name] 432 + self.family_id = GenlProtocol.genl_family_name_to_id[family_name]['id'] 446 433 447 434 def message(self, flags, command, version, seq=None): 448 435 nlmsg = self._message(self.family_id, flags, seq) ··· 455 440 456 441 def get_mcast_id(self, mcast_name, mcast_groups): 457 442 if mcast_name not in self.genl_family['mcast']: 458 - raise Exception(f'Multicast group "{mcast_name}" not present in the family') 443 + raise YnlException(f'Multicast group "{mcast_name}" not present in the family') 459 444 return self.genl_family['mcast'][mcast_name] 460 445 461 446 def msghdr_size(self): 462 447 return super().msghdr_size() + 4 463 448 464 449 450 + # pylint: disable=too-few-public-methods 465 451 class SpaceAttrs: 466 452 SpecValuesPair = namedtuple('SpecValuesPair', ['spec', 'values']) 467 453 ··· 477 461 if name in scope.values: 478 462 return scope.values[name] 479 463 spec_name = scope.spec.yaml['name'] 480 - raise Exception( 464 + raise YnlException( 481 465 f"No value for '{name}' in attribute space '{spec_name}'") 482 - raise Exception(f"Attribute '{name}' not defined in any attribute-set") 466 + raise YnlException(f"Attribute '{name}' not defined in any attribute-set") 483 467 484 468 485 469 # ··· 501 485 self.yaml['protonum']) 502 486 else: 503 487 self.nlproto = GenlProtocol(self.yaml['name']) 504 - except KeyError: 505 - raise Exception(f"Family '{self.yaml['name']}' not supported by the kernel") 488 + except KeyError as err: 489 + raise YnlException(f"Family '{self.yaml['name']}' not supported by the kernel") from err 506 490 507 491 self._recv_dbg = False 508 492 # Note that netlink will use conservative (min) message size for ··· 558 542 for single_value in value: 559 543 scalar += enum.entries[single_value].user_value(as_flags = True) 560 544 return scalar 561 - else: 562 - return enum.entries[value].user_value() 545 + return enum.entries[value].user_value() 563 546 564 547 def _get_scalar(self, attr_spec, value): 565 548 try: ··· 570 555 return self._from_string(value, attr_spec) 571 556 raise e 572 557 558 + # pylint: disable=too-many-statements 573 559 def _add_attr(self, space, name, value, search_attrs): 574 560 try: 575 561 attr = self.attr_sets[space][name] 576 - except KeyError: 577 - raise Exception(f"Space '{space}' has no attribute '{name}'") 562 + except KeyError as err: 563 + raise YnlException(f"Space '{space}' has no attribute '{name}'") from err 578 564 nl_type = attr.value 579 565 580 566 if attr.is_multi and isinstance(value, list): ··· 613 597 elif isinstance(value, dict) and attr.struct_name: 614 598 attr_payload = self._encode_struct(attr.struct_name, value) 615 599 elif isinstance(value, list) and attr.sub_type in NlAttr.type_formats: 616 - format = NlAttr.get_format(attr.sub_type) 617 - attr_payload = b''.join([format.pack(x) for x in value]) 600 + format_ = NlAttr.get_format(attr.sub_type) 601 + attr_payload = b''.join([format_.pack(x) for x in value]) 618 602 else: 619 - raise Exception(f'Unknown type for binary attribute, value: {value}') 603 + raise YnlException(f'Unknown type for binary attribute, value: {value}') 620 604 elif attr['type'] in NlAttr.type_formats or attr.is_auto_scalar: 621 605 scalar = self._get_scalar(attr, value) 622 606 if attr.is_auto_scalar: 623 607 attr_type = attr["type"][0] + ('32' if scalar.bit_length() <= 32 else '64') 624 608 else: 625 609 attr_type = attr["type"] 626 - format = NlAttr.get_format(attr_type, attr.byte_order) 627 - attr_payload = format.pack(scalar) 610 + format_ = NlAttr.get_format(attr_type, attr.byte_order) 611 + attr_payload = format_.pack(scalar) 628 612 elif attr['type'] in "bitfield32": 629 613 scalar_value = self._get_scalar(attr, value["value"]) 630 614 scalar_selector = self._get_scalar(attr, value["selector"]) ··· 642 626 attr_payload += self._add_attr(msg_format.attr_set, 643 627 subname, subvalue, sub_attrs) 644 628 else: 645 - raise Exception(f"Unknown attribute-set '{msg_format.attr_set}'") 629 + raise YnlException(f"Unknown attribute-set '{msg_format.attr_set}'") 646 630 else: 647 - raise Exception(f'Unknown type at {space} {name} {value} {attr["type"]}') 631 + raise YnlException(f'Unknown type at {space} {name} {value} {attr["type"]}') 648 632 649 633 return self._add_attr_raw(nl_type, attr_payload) 650 634 ··· 731 715 subattr = self._formatted_string(subattr, attr_spec.display_hint) 732 716 decoded.append(subattr) 733 717 else: 734 - raise Exception(f'Unknown {attr_spec["sub-type"]} with name {attr_spec["name"]}') 718 + raise YnlException(f'Unknown {attr_spec["sub-type"]} with name {attr_spec["name"]}') 735 719 return decoded 736 720 737 721 def _decode_nest_type_value(self, attr, attr_spec): ··· 747 731 def _decode_unknown(self, attr): 748 732 if attr.is_nest: 749 733 return self._decode(NlAttrs(attr.raw), None) 750 - else: 751 - return attr.as_bin() 734 + return attr.as_bin() 752 735 753 736 def _rsp_add(self, rsp, name, is_multi, decoded): 754 737 if is_multi is None: 755 - if name in rsp and type(rsp[name]) is not list: 738 + if name in rsp and not isinstance(rsp[name], list): 756 739 rsp[name] = [rsp[name]] 757 740 is_multi = True 758 741 else: ··· 767 752 def _resolve_selector(self, attr_spec, search_attrs): 768 753 sub_msg = attr_spec.sub_message 769 754 if sub_msg not in self.sub_msgs: 770 - raise Exception(f"No sub-message spec named {sub_msg} for {attr_spec.name}") 755 + raise YnlException(f"No sub-message spec named {sub_msg} for {attr_spec.name}") 771 756 sub_msg_spec = self.sub_msgs[sub_msg] 772 757 773 758 selector = attr_spec.selector 774 759 value = search_attrs.lookup(selector) 775 760 if value not in sub_msg_spec.formats: 776 - raise Exception(f"No message format for '{value}' in sub-message spec '{sub_msg}'") 761 + raise YnlException(f"No message format for '{value}' in sub-message spec '{sub_msg}'") 777 762 778 763 spec = sub_msg_spec.formats[value] 779 764 return spec, value ··· 784 769 offset = 0 785 770 if msg_format.fixed_header: 786 771 decoded.update(self._decode_struct(attr.raw, msg_format.fixed_header)) 787 - offset = self._struct_size(msg_format.fixed_header) 772 + offset = self.struct_size(msg_format.fixed_header) 788 773 if msg_format.attr_set: 789 774 if msg_format.attr_set in self.attr_sets: 790 775 subdict = self._decode(NlAttrs(attr.raw, offset), msg_format.attr_set) 791 776 decoded.update(subdict) 792 777 else: 793 - raise Exception(f"Unknown attribute-set '{msg_format.attr_set}' when decoding '{attr_spec.name}'") 778 + raise YnlException(f"Unknown attribute-set '{msg_format.attr_set}' " 779 + f"when decoding '{attr_spec.name}'") 794 780 return decoded 795 781 782 + # pylint: disable=too-many-statements 796 783 def _decode(self, attrs, space, outer_attrs = None): 797 - rsp = dict() 784 + rsp = {} 785 + search_attrs = {} 798 786 if space: 799 787 attr_space = self.attr_sets[space] 800 788 search_attrs = SpaceAttrs(attr_space, rsp, outer_attrs) ··· 805 787 for attr in attrs: 806 788 try: 807 789 attr_spec = attr_space.attrs_by_val[attr.type] 808 - except (KeyError, UnboundLocalError): 790 + except (KeyError, UnboundLocalError) as err: 809 791 if not self.process_unknown: 810 - raise Exception(f"Space '{space}' has no attribute with value '{attr.type}'") 792 + raise YnlException(f"Space '{space}' has no attribute " 793 + f"with value '{attr.type}'") from err 811 794 attr_name = f"UnknownAttr({attr.type})" 812 795 self._rsp_add(rsp, attr_name, None, self._decode_unknown(attr)) 813 796 continue 814 797 815 798 try: 816 799 if attr_spec["type"] == 'nest': 817 - subdict = self._decode(NlAttrs(attr.raw), attr_spec['nested-attributes'], search_attrs) 800 + subdict = self._decode(NlAttrs(attr.raw), 801 + attr_spec['nested-attributes'], 802 + search_attrs) 818 803 decoded = subdict 819 804 elif attr_spec["type"] == 'string': 820 805 decoded = attr.as_strz() ··· 849 828 decoded = self._decode_nest_type_value(attr, attr_spec) 850 829 else: 851 830 if not self.process_unknown: 852 - raise Exception(f'Unknown {attr_spec["type"]} with name {attr_spec["name"]}') 831 + raise YnlException(f'Unknown {attr_spec["type"]} ' 832 + f'with name {attr_spec["name"]}') 853 833 decoded = self._decode_unknown(attr) 854 834 855 835 self._rsp_add(rsp, attr_spec["name"], attr_spec.is_multi, decoded) ··· 860 838 861 839 return rsp 862 840 841 + # pylint: disable=too-many-arguments, too-many-positional-arguments 863 842 def _decode_extack_path(self, attrs, attr_set, offset, target, search_attrs): 864 843 for attr in attrs: 865 844 try: 866 845 attr_spec = attr_set.attrs_by_val[attr.type] 867 - except KeyError: 868 - raise Exception(f"Space '{attr_set.name}' has no attribute with value '{attr.type}'") 846 + except KeyError as err: 847 + raise YnlException( 848 + f"Space '{attr_set.name}' has no attribute with value '{attr.type}'") from err 869 849 if offset > target: 870 850 break 871 851 if offset == target: ··· 884 860 elif attr_spec['type'] == 'sub-message': 885 861 msg_format, value = self._resolve_selector(attr_spec, search_attrs) 886 862 if msg_format is None: 887 - raise Exception(f"Can't resolve sub-message of {attr_spec['name']} for extack") 863 + raise YnlException(f"Can't resolve sub-message of " 864 + f"{attr_spec['name']} for extack") 888 865 sub_attrs = self.attr_sets[msg_format.attr_set] 889 866 pathname += f"({value})" 890 867 else: 891 - raise Exception(f"Can't dive into {attr.type} ({attr_spec['name']}) for extack") 868 + raise YnlException(f"Can't dive into {attr.type} ({attr_spec['name']}) for extack") 892 869 offset += 4 893 870 subpath = self._decode_extack_path(NlAttrs(attr.raw), sub_attrs, 894 871 offset, target, search_attrs) ··· 904 879 return 905 880 906 881 msg = self.nlproto.decode(self, NlMsg(request, 0, op.attr_set), op) 907 - offset = self.nlproto.msghdr_size() + self._struct_size(op.fixed_header) 882 + offset = self.nlproto.msghdr_size() + self.struct_size(op.fixed_header) 908 883 search_attrs = SpaceAttrs(op.attr_set, vals) 909 884 path = self._decode_extack_path(msg.raw_attrs, op.attr_set, offset, 910 885 extack['bad-attr-offs'], search_attrs) ··· 912 887 del extack['bad-attr-offs'] 913 888 extack['bad-attr'] = path 914 889 915 - def _struct_size(self, name): 890 + def struct_size(self, name): 916 891 if name: 917 892 members = self.consts[name].members 918 893 size = 0 919 894 for m in members: 920 895 if m.type in ['pad', 'binary']: 921 896 if m.struct: 922 - size += self._struct_size(m.struct) 897 + size += self.struct_size(m.struct) 923 898 else: 924 899 size += m.len 925 900 else: 926 - format = NlAttr.get_format(m.type, m.byte_order) 927 - size += format.size 901 + format_ = NlAttr.get_format(m.type, m.byte_order) 902 + size += format_.size 928 903 return size 929 - else: 930 - return 0 904 + return 0 931 905 932 906 def _decode_struct(self, data, name): 933 907 members = self.consts[name].members 934 - attrs = dict() 908 + attrs = {} 935 909 offset = 0 936 910 for m in members: 937 911 value = None ··· 938 914 offset += m.len 939 915 elif m.type == 'binary': 940 916 if m.struct: 941 - len = self._struct_size(m.struct) 942 - value = self._decode_struct(data[offset : offset + len], 917 + len_ = self.struct_size(m.struct) 918 + value = self._decode_struct(data[offset : offset + len_], 943 919 m.struct) 944 - offset += len 920 + offset += len_ 945 921 else: 946 922 value = data[offset : offset + m.len] 947 923 offset += m.len 948 924 else: 949 - format = NlAttr.get_format(m.type, m.byte_order) 950 - [ value ] = format.unpack_from(data, offset) 951 - offset += format.size 925 + format_ = NlAttr.get_format(m.type, m.byte_order) 926 + [ value ] = format_.unpack_from(data, offset) 927 + offset += format_.size 952 928 if value is not None: 953 929 if m.enum: 954 930 value = self._decode_enum(value, m) ··· 967 943 elif m.type == 'binary': 968 944 if m.struct: 969 945 if value is None: 970 - value = dict() 946 + value = {} 971 947 attr_payload += self._encode_struct(m.struct, value) 972 948 else: 973 949 if value is None: ··· 977 953 else: 978 954 if value is None: 979 955 value = 0 980 - format = NlAttr.get_format(m.type, m.byte_order) 981 - attr_payload += format.pack(value) 956 + format_ = NlAttr.get_format(m.type, m.byte_order) 957 + attr_payload += format_.pack(value) 982 958 return attr_payload 983 959 984 960 def _formatted_string(self, raw, display_hint): 985 961 if display_hint == 'mac': 986 - formatted = ':'.join('%02x' % b for b in raw) 962 + formatted = ':'.join(f'{b:02x}' for b in raw) 987 963 elif display_hint == 'hex': 988 964 if isinstance(raw, int): 989 965 formatted = hex(raw) ··· 1015 991 mac_bytes = [int(x, 16) for x in string.split(':')] 1016 992 else: 1017 993 if len(string) % 2 != 0: 1018 - raise Exception(f"Invalid MAC address format: {string}") 994 + raise YnlException(f"Invalid MAC address format: {string}") 1019 995 mac_bytes = [int(string[i:i+2], 16) for i in range(0, len(string), 2)] 1020 996 raw = bytes(mac_bytes) 1021 997 else: 1022 - raise Exception(f"Display hint '{attr_spec.display_hint}' not implemented" 998 + raise YnlException(f"Display hint '{attr_spec.display_hint}' not implemented" 1023 999 f" when parsing '{attr_spec['name']}'") 1024 1000 return raw 1025 1001 1026 1002 def handle_ntf(self, decoded): 1027 - msg = dict() 1003 + msg = {} 1028 1004 if self.include_raw: 1029 1005 msg['raw'] = decoded 1030 1006 op = self.rsp_by_value[decoded.cmd()] ··· 1105 1081 msg = _genl_msg_finalize(msg) 1106 1082 return msg 1107 1083 1084 + # pylint: disable=too-many-statements 1108 1085 def _ops(self, ops): 1109 1086 reqs_by_seq = {} 1110 1087 req_seq = random.randint(1024, 65535) ··· 1164 1139 if decoded.cmd() in self.async_msg_ids: 1165 1140 self.handle_ntf(decoded) 1166 1141 continue 1167 - else: 1168 - print('Unexpected message: ' + repr(decoded)) 1169 - continue 1142 + print('Unexpected message: ' + repr(decoded)) 1143 + continue 1170 1144 1171 1145 rsp_msg = self._decode(decoded.raw_attrs, op.attr_set.name) 1172 1146 if op.fixed_header:
+100 -78
tools/net/ynl/pyynl/ynl_gen_c.py
··· 1 1 #!/usr/bin/env python3 2 2 # SPDX-License-Identifier: ((GPL-2.0 WITH Linux-syscall-note) OR BSD-3-Clause) 3 + # 4 + # pylint: disable=line-too-long, missing-class-docstring, missing-function-docstring 5 + # pylint: disable=too-many-positional-arguments, too-many-arguments, too-many-statements 6 + # pylint: disable=too-many-branches, too-many-locals, too-many-instance-attributes 7 + # pylint: disable=too-many-nested-blocks, too-many-lines, too-few-public-methods 8 + # pylint: disable=broad-exception-raised, broad-exception-caught, protected-access 9 + 10 + """ 11 + ynl_gen_c 12 + 13 + A YNL to C code generator for both kernel and userspace protocol stubs. 14 + """ 3 15 4 16 import argparse 5 17 import filecmp ··· 21 9 import shutil 22 10 import sys 23 11 import tempfile 24 - import yaml 12 + import yaml as pyyaml 25 13 14 + # pylint: disable=no-name-in-module,wrong-import-position 26 15 sys.path.append(pathlib.Path(__file__).resolve().parent.as_posix()) 27 16 from lib import SpecFamily, SpecAttrSet, SpecAttr, SpecOperation, SpecEnumSet, SpecEnumEntry 28 17 from lib import SpecSubMessage ··· 170 157 171 158 def presence_member(self, space, type_filter): 172 159 if self.presence_type() != type_filter: 173 - return 160 + return '' 174 161 175 162 if self.presence_type() == 'present': 176 163 pfx = '__' if space == 'user' else '' ··· 179 166 if self.presence_type() in {'len', 'count'}: 180 167 pfx = '__' if space == 'user' else '' 181 168 return f"{pfx}u32 {self.c_name};" 169 + return '' 182 170 183 - def _complex_member_type(self, ri): 171 + def _complex_member_type(self, _ri): 184 172 return None 185 173 186 174 def free_needs_iter(self): 187 175 return False 188 176 189 - def _free_lines(self, ri, var, ref): 177 + def _free_lines(self, _ri, var, ref): 190 178 if self.is_multi_val() or self.presence_type() in {'count', 'len'}: 191 179 return [f'free({var}->{ref}{self.c_name});'] 192 180 return [] ··· 197 183 for line in lines: 198 184 ri.cw.p(line) 199 185 186 + # pylint: disable=assignment-from-none 200 187 def arg_member(self, ri): 201 188 member = self._complex_member_type(ri) 202 - if member: 189 + if member is not None: 203 190 spc = ' ' if member[-1] != '*' else '' 204 191 arg = [member + spc + '*' + self.c_name] 205 192 if self.presence_type() == 'count': ··· 210 195 211 196 def struct_member(self, ri): 212 197 member = self._complex_member_type(ri) 213 - if member: 198 + if member is not None: 214 199 ptr = '*' if self.is_multi_val() else '' 215 200 if self.is_recursive_for_op(ri): 216 201 ptr = '*' ··· 258 243 259 244 def attr_get(self, ri, var, first): 260 245 lines, init_lines, _ = self._attr_get(ri, var) 261 - if type(lines) is str: 246 + if isinstance(lines, str): 262 247 lines = [lines] 263 - if type(init_lines) is str: 248 + if isinstance(init_lines, str): 264 249 init_lines = [init_lines] 265 250 266 251 kw = 'if' if first else 'else if' ··· 285 270 def _setter_lines(self, ri, member, presence): 286 271 raise Exception(f"Setter not implemented for class type {self.type}") 287 272 288 - def setter(self, ri, space, direction, deref=False, ref=None, var="req"): 273 + def setter(self, ri, _space, direction, deref=False, ref=None, var="req"): 289 274 ref = (ref if ref else []) + [self.c_name] 290 275 member = f"{var}->{'.'.join(ref)}" 291 276 ··· 295 280 296 281 code = [] 297 282 presence = '' 283 + # pylint: disable=consider-using-enumerate 298 284 for i in range(0, len(ref)): 299 285 presence = f"{var}->{'.'.join(ref[:i] + [''])}_present.{ref[i]}" 300 286 # Every layer below last is a nest, so we know it uses bit presence ··· 430 414 if low < -32768 or high > 32767: 431 415 self.checks['full-range'] = True 432 416 417 + # pylint: disable=too-many-return-statements 433 418 def _attr_policy(self, policy): 434 419 if 'flags-mask' in self.checks or self.is_bitfield: 435 420 if self.is_bitfield: ··· 441 424 flag_cnt = len(flags['entries']) 442 425 mask = (1 << flag_cnt) - 1 443 426 return f"NLA_POLICY_MASK({policy}, 0x{mask:x})" 444 - elif 'full-range' in self.checks: 427 + if 'full-range' in self.checks: 445 428 return f"NLA_POLICY_FULL_RANGE({policy}, &{c_lower(self.enum_name)}_range)" 446 - elif 'range' in self.checks: 429 + if 'range' in self.checks: 447 430 return f"NLA_POLICY_RANGE({policy}, {self.get_limit_str('min')}, {self.get_limit_str('max')})" 448 - elif 'min' in self.checks: 431 + if 'min' in self.checks: 449 432 return f"NLA_POLICY_MIN({policy}, {self.get_limit_str('min')})" 450 - elif 'max' in self.checks: 433 + if 'max' in self.checks: 451 434 return f"NLA_POLICY_MAX({policy}, {self.get_limit_str('max')})" 452 - elif 'sparse' in self.checks: 435 + if 'sparse' in self.checks: 453 436 return f"NLA_POLICY_VALIDATE_FN({policy}, &{c_lower(self.enum_name)}_validate)" 454 437 return super()._attr_policy(policy) 455 438 ··· 571 554 mem = 'NLA_POLICY_MIN_LEN(' + self.get_limit_str('min-len') + ')' 572 555 elif 'max-len' in self.checks: 573 556 mem = 'NLA_POLICY_MAX_LEN(' + self.get_limit_str('max-len') + ')' 557 + else: 558 + raise Exception('Failed to process policy check for binary type') 574 559 575 560 return mem 576 561 ··· 646 627 647 628 648 629 class TypeBitfield32(Type): 649 - def _complex_member_type(self, ri): 630 + def _complex_member_type(self, _ri): 650 631 return "struct nla_bitfield32" 651 632 652 633 def _attr_typol(self): ··· 674 655 def is_recursive(self): 675 656 return self.family.pure_nested_structs[self.nested_attrs].recursive 676 657 677 - def _complex_member_type(self, ri): 658 + def _complex_member_type(self, _ri): 678 659 return self.nested_struct_type 679 660 680 661 def _free_lines(self, ri, var, ref): ··· 708 689 f"parg.data = &{var}->{self.c_name};"] 709 690 return get_lines, init_lines, None 710 691 711 - def setter(self, ri, space, direction, deref=False, ref=None, var="req"): 692 + def setter(self, ri, _space, direction, deref=False, ref=None, var="req"): 712 693 ref = (ref if ref else []) + [self.c_name] 713 694 714 695 for _, attr in ri.family.pure_nested_structs[self.nested_attrs].member_list(): ··· 733 714 def _complex_member_type(self, ri): 734 715 if 'type' not in self.attr or self.attr['type'] == 'nest': 735 716 return self.nested_struct_type 736 - elif self.attr['type'] == 'binary' and 'struct' in self.attr: 717 + if self.attr['type'] == 'binary' and 'struct' in self.attr: 737 718 return None # use arg_member() 738 - elif self.attr['type'] == 'string': 719 + if self.attr['type'] == 'string': 739 720 return 'struct ynl_string *' 740 - elif self.attr['type'] in scalars: 721 + if self.attr['type'] in scalars: 741 722 scalar_pfx = '__' if ri.ku_space == 'user' else '' 742 723 if self.is_auto_scalar: 743 724 name = self.type[0] + '64' 744 725 else: 745 726 name = self.attr['type'] 746 727 return scalar_pfx + name 747 - else: 748 - raise Exception(f"Sub-type {self.attr['type']} not supported yet") 728 + raise Exception(f"Sub-type {self.attr['type']} not supported yet") 749 729 750 730 def arg_member(self, ri): 751 731 if self.type == 'binary' and 'struct' in self.attr: ··· 755 737 def free_needs_iter(self): 756 738 return self.attr['type'] in {'nest', 'string'} 757 739 758 - def _free_lines(self, ri, var, ref): 740 + def _free_lines(self, _ri, var, ref): 759 741 lines = [] 760 742 if self.attr['type'] in scalars: 761 743 lines += [f"free({var}->{ref}{self.c_name});"] ··· 819 801 def _complex_member_type(self, ri): 820 802 if 'sub-type' not in self.attr or self.attr['sub-type'] == 'nest': 821 803 return self.nested_struct_type 822 - elif self.attr['sub-type'] in scalars: 804 + if self.attr['sub-type'] in scalars: 823 805 scalar_pfx = '__' if ri.ku_space == 'user' else '' 824 806 return scalar_pfx + self.attr['sub-type'] 825 - elif self.attr['sub-type'] == 'binary' and 'exact-len' in self.checks: 807 + if self.attr['sub-type'] == 'binary' and 'exact-len' in self.checks: 826 808 return None # use arg_member() 827 - else: 828 - raise Exception(f"Sub-type {self.attr['sub-type']} not supported yet") 809 + raise Exception(f"Sub-type {self.attr['sub-type']} not supported yet") 829 810 830 811 def arg_member(self, ri): 831 812 if self.sub_type == 'binary' and 'exact-len' in self.checks: ··· 840 823 def _attr_typol(self): 841 824 if self.attr['sub-type'] in scalars: 842 825 return f'.type = YNL_PT_U{c_upper(self.sub_type[1:])}, ' 843 - elif self.attr['sub-type'] == 'binary' and 'exact-len' in self.checks: 826 + if self.attr['sub-type'] == 'binary' and 'exact-len' in self.checks: 844 827 return f'.type = YNL_PT_BINARY, .len = {self.checks["exact-len"]}, ' 845 - elif self.attr['sub-type'] == 'nest': 828 + if self.attr['sub-type'] == 'nest': 846 829 return f'.type = YNL_PT_NEST, .nest = &{self.nested_render_name}_nest, ' 847 - else: 848 - raise Exception(f"Typol for IndexedArray sub-type {self.attr['sub-type']} not supported, yet") 830 + raise Exception(f"Typol for IndexedArray sub-type {self.attr['sub-type']} not supported, yet") 849 831 850 832 def _attr_get(self, ri, var): 851 833 local_vars = ['const struct nlattr *attr2;'] ··· 880 864 def free_needs_iter(self): 881 865 return self.sub_type == 'nest' 882 866 883 - def _free_lines(self, ri, var, ref): 867 + def _free_lines(self, _ri, var, ref): 884 868 lines = [] 885 869 if self.sub_type == 'nest': 886 870 lines += [ 887 871 f"for (i = 0; i < {var}->{ref}_count.{self.c_name}; i++)", 888 872 f'{self.nested_render_name}_free(&{var}->{ref}{self.c_name}[i]);', 889 873 ] 890 - lines += f"free({var}->{ref}{self.c_name});", 874 + lines += (f"free({var}->{ref}{self.c_name});",) 891 875 return lines 892 876 893 877 class TypeNestTypeValue(Type): 894 - def _complex_member_type(self, ri): 878 + def _complex_member_type(self, _ri): 895 879 return self.nested_struct_type 896 880 897 881 def _attr_typol(self): ··· 937 921 return typol 938 922 939 923 def _attr_get(self, ri, var): 940 - sel = c_lower(self['selector']) 924 + selector = self['selector'] 925 + sel = c_lower(selector) 941 926 if self.selector.is_external(): 942 927 sel_var = f"_sel_{sel}" 943 928 else: 944 929 sel_var = f"{var}->{sel}" 945 930 get_lines = [f'if (!{sel_var})', 946 - 'return ynl_submsg_failed(yarg, "%s", "%s");' % 947 - (self.name, self['selector']), 948 - f"if ({self.nested_render_name}_parse(&parg, {sel_var}, attr))", 931 + f'return ynl_submsg_failed(yarg, "{self.name}", "{selector}");', 932 + f"if ({self.nested_render_name}_parse(&parg, {sel_var}, attr))", 949 933 "return YNL_PARSE_CB_ERROR;"] 950 934 init_lines = [f"parg.rsp_policy = &{self.nested_render_name}_nest;", 951 935 f"parg.data = &{var}->{self.c_name};"] ··· 1004 988 self.in_multi_val = False # used by a MultiAttr or and legacy arrays 1005 989 1006 990 self.attr_list = [] 1007 - self.attrs = dict() 991 + self.attrs = {} 1008 992 if type_list is not None: 1009 993 for t in type_list: 1010 994 self.attr_list.append((t, self.attr_set[t]),) ··· 1036 1020 1037 1021 def external_selectors(self): 1038 1022 sels = [] 1039 - for name, attr in self.attr_list: 1023 + for _name, attr in self.attr_list: 1040 1024 if isinstance(attr, TypeSubMessage) and attr.selector.is_external(): 1041 1025 sels.append(attr.selector) 1042 1026 return sels ··· 1053 1037 super().__init__(enum_set, yaml, prev, value_start) 1054 1038 1055 1039 if prev: 1056 - self.value_change = (self.value != prev.value + 1) 1040 + self.value_change = self.value != prev.value + 1 1057 1041 else: 1058 - self.value_change = (self.value != 0) 1042 + self.value_change = self.value != 0 1059 1043 self.value_change = self.value_change or self.enum_set['type'] == 'flags' 1060 1044 1061 1045 # Added by resolve: ··· 1096 1080 return EnumEntry(self, entry, prev_entry, value_start) 1097 1081 1098 1082 def value_range(self): 1099 - low = min([x.value for x in self.entries.values()]) 1100 - high = max([x.value for x in self.entries.values()]) 1083 + low = min(x.value for x in self.entries.values()) 1084 + high = max(x.value for x in self.entries.values()) 1101 1085 1102 1086 if high - low + 1 != len(self.entries): 1103 1087 return None, None ··· 1236 1220 self.hooks = None 1237 1221 delattr(self, "hooks") 1238 1222 1223 + self.root_sets = {} 1224 + self.pure_nested_structs = {} 1225 + self.kernel_policy = None 1226 + self.global_policy = None 1227 + self.global_policy_set = None 1228 + 1239 1229 super().__init__(file_name, exclude_ops=exclude_ops) 1240 1230 1241 1231 self.fam_key = c_upper(self.yaml.get('c-family-name', self.yaml["name"] + '_FAMILY_NAME')) ··· 1276 1254 1277 1255 self.mcgrps = self.yaml.get('mcast-groups', {'list': []}) 1278 1256 1279 - self.hooks = dict() 1257 + self.hooks = {} 1280 1258 for when in ['pre', 'post']: 1281 - self.hooks[when] = dict() 1259 + self.hooks[when] = {} 1282 1260 for op_mode in ['do', 'dump']: 1283 - self.hooks[when][op_mode] = dict() 1261 + self.hooks[when][op_mode] = {} 1284 1262 self.hooks[when][op_mode]['set'] = set() 1285 1263 self.hooks[when][op_mode]['list'] = [] 1286 1264 1287 1265 # dict space-name -> 'request': set(attrs), 'reply': set(attrs) 1288 - self.root_sets = dict() 1266 + self.root_sets = {} 1289 1267 # dict space-name -> Struct 1290 - self.pure_nested_structs = dict() 1268 + self.pure_nested_structs = {} 1291 1269 1292 1270 self._mark_notify() 1293 1271 self._mock_up_events() ··· 1333 1311 } 1334 1312 1335 1313 def _load_root_sets(self): 1336 - for op_name, op in self.msgs.items(): 1314 + for _op_name, op in self.msgs.items(): 1337 1315 if 'attribute-set' not in op: 1338 1316 continue 1339 1317 ··· 1449 1427 attr_set_queue = list(self.root_sets.keys()) 1450 1428 attr_set_seen = set(self.root_sets.keys()) 1451 1429 1452 - while len(attr_set_queue): 1430 + while attr_set_queue: 1453 1431 a_set = attr_set_queue.pop(0) 1454 1432 for attr, spec in self.attr_sets[a_set].items(): 1455 1433 if 'nested-attributes' in spec: ··· 1532 1510 for k, _ in self.root_sets.items(): 1533 1511 yield k, None # we don't have a struct, but it must be terminal 1534 1512 1535 - for attr_set, struct in all_structs(): 1513 + for attr_set, _struct in all_structs(): 1536 1514 for _, spec in self.attr_sets[attr_set].items(): 1537 1515 if 'nested-attributes' in spec: 1538 1516 child_name = spec['nested-attributes'] ··· 1552 1530 def _load_global_policy(self): 1553 1531 global_set = set() 1554 1532 attr_set_name = None 1555 - for op_name, op in self.ops.items(): 1533 + for _op_name, op in self.ops.items(): 1556 1534 if not op: 1557 1535 continue 1558 1536 if 'attribute-set' not in op: ··· 1635 1613 1636 1614 self.cw = cw 1637 1615 1638 - self.struct = dict() 1616 + self.struct = {} 1639 1617 if op_mode == 'notify': 1640 1618 op_mode = 'do' if 'do' in op else 'dump' 1641 1619 for op_dir in ['request', 'reply']: ··· 1672 1650 if out_file is None: 1673 1651 self._out = os.sys.stdout 1674 1652 else: 1653 + # pylint: disable=consider-using-with 1675 1654 self._out = tempfile.NamedTemporaryFile('w+') 1676 1655 self._out_file = out_file 1677 1656 ··· 1687 1664 if not self._overwrite and os.path.isfile(self._out_file): 1688 1665 if filecmp.cmp(self._out.name, self._out_file, shallow=False): 1689 1666 return 1690 - with open(self._out_file, 'w+') as out_file: 1667 + with open(self._out_file, 'w+', encoding='utf-8') as out_file: 1691 1668 self._out.seek(0) 1692 1669 shutil.copyfileobj(self._out, out_file) 1693 1670 self._out.close() ··· 1802 1779 if not local_vars: 1803 1780 return 1804 1781 1805 - if type(local_vars) is str: 1782 + if isinstance(local_vars, str): 1806 1783 local_vars = [local_vars] 1807 1784 1808 1785 local_vars.sort(key=len, reverse=True) ··· 1822 1799 def writes_defines(self, defines): 1823 1800 longest = 0 1824 1801 for define in defines: 1825 - if len(define[0]) > longest: 1826 - longest = len(define[0]) 1802 + longest = max(len(define[0]), longest) 1827 1803 longest = ((longest + 8) // 8) * 8 1828 1804 for define in defines: 1829 1805 line = '#define ' + define[0] 1830 1806 line += '\t' * ((longest - len(define[0]) + 7) // 8) 1831 - if type(define[1]) is int: 1807 + if isinstance(define[1], int): 1832 1808 line += str(define[1]) 1833 - elif type(define[1]) is str: 1809 + elif isinstance(define[1], str): 1834 1810 line += '"' + define[1] + '"' 1835 1811 self.p(line) 1836 1812 1837 1813 def write_struct_init(self, members): 1838 - longest = max([len(x[0]) for x in members]) 1814 + longest = max(len(x[0]) for x in members) 1839 1815 longest += 1 # because we prepend a . 1840 1816 longest = ((longest + 8) // 8) * 8 1841 1817 for one in members: ··· 2060 2038 _put_enum_to_str_helper(cw, family.c_name + '_op', map_name, 'op') 2061 2039 2062 2040 2063 - def put_enum_to_str_fwd(family, cw, enum): 2041 + def put_enum_to_str_fwd(_family, cw, enum): 2064 2042 args = [enum.user_type + ' value'] 2065 2043 cw.write_func_prot('const char *', f'{enum.render_name}_str', args, suffix=';') 2066 2044 2067 2045 2068 - def put_enum_to_str(family, cw, enum): 2046 + def put_enum_to_str(_family, cw, enum): 2069 2047 map_name = f'{enum.render_name}_strmap' 2070 2048 cw.block_start(line=f"static const char * const {map_name}[] =") 2071 2049 for entry in enum.entries.values(): ··· 2346 2324 2347 2325 def parse_rsp_nested(ri, struct): 2348 2326 if struct.submsg: 2349 - return parse_rsp_submsg(ri, struct) 2327 + parse_rsp_submsg(ri, struct) 2328 + return 2350 2329 2351 2330 parse_rsp_nested_prototype(ri, struct, suffix='') 2352 2331 ··· 2677 2654 2678 2655 2679 2656 def print_rsp_type(ri): 2680 - if (ri.op_mode == 'do' or ri.op_mode == 'dump') and 'reply' in ri.op[ri.op_mode]: 2657 + if ri.op_mode in ('do', 'dump') and 'reply' in ri.op[ri.op_mode]: 2681 2658 direction = 'reply' 2682 2659 elif ri.op_mode == 'event': 2683 2660 direction = 'reply' ··· 2690 2667 ri.cw.block_start(line=f"{type_name(ri, 'reply')}") 2691 2668 if ri.op_mode == 'dump': 2692 2669 ri.cw.p(f"{type_name(ri, 'reply')} *next;") 2693 - elif ri.op_mode == 'notify' or ri.op_mode == 'event': 2670 + elif ri.op_mode in ('notify', 'event'): 2694 2671 ri.cw.p('__u16 family;') 2695 2672 ri.cw.p('__u8 cmd;') 2696 2673 ri.cw.p('struct ynl_ntf_base_type *next;') ··· 2727 2704 2728 2705 2729 2706 def free_rsp_nested_prototype(ri): 2730 - print_free_prototype(ri, "") 2707 + print_free_prototype(ri, "") 2731 2708 2732 2709 2733 2710 def free_rsp_nested(ri, struct): ··· 2953 2930 2954 2931 def print_kernel_op_table(family, cw): 2955 2932 print_kernel_op_table_fwd(family, cw, terminate=False) 2956 - if family.kernel_policy == 'global' or family.kernel_policy == 'per-op': 2933 + if family.kernel_policy in ('global', 'per-op'): 2957 2934 for op_name, op in family.ops.items(): 2958 2935 if op.is_async: 2959 2936 continue ··· 3369 3346 else: 3370 3347 raise Exception('Invalid notification ' + ntf_op_name) 3371 3348 _render_user_ntf_entry(ri, ntf_op) 3372 - for op_name, op in family.ops.items(): 3349 + for _op_name, op in family.ops.items(): 3373 3350 if 'event' not in op: 3374 3351 continue 3375 3352 ri = RenderInfo(cw, family, "user", op, "event") ··· 3441 3418 print('Spec license:', parsed.license) 3442 3419 print('License must be: ((GPL-2.0 WITH Linux-syscall-note) OR BSD-3-Clause)') 3443 3420 os.sys.exit(1) 3444 - except yaml.YAMLError as exc: 3421 + except pyyaml.YAMLError as exc: 3445 3422 print(exc) 3446 3423 os.sys.exit(1) 3447 - return 3448 3424 3449 - cw = CodeWriter(BaseNlLib(), args.out_file, overwrite=(not args.cmp_out)) 3425 + cw = CodeWriter(BaseNlLib(), args.out_file, overwrite=not args.cmp_out) 3450 3426 3451 3427 _, spec_kernel = find_kernel_root(args.spec) 3452 3428 if args.mode == 'uapi' or args.header: ··· 3546 3524 cw.nl() 3547 3525 3548 3526 if parsed.kernel_policy in {'per-op', 'split'}: 3549 - for op_name, op in parsed.ops.items(): 3527 + for _op_name, op in parsed.ops.items(): 3550 3528 if 'do' in op and 'event' not in op: 3551 3529 ri = RenderInfo(cw, parsed, args.mode, op, "do") 3552 3530 print_req_policy_fwd(cw, ri.struct['request'], ri=ri) ··· 3575 3553 print_req_policy(cw, struct) 3576 3554 cw.nl() 3577 3555 3578 - for op_name, op in parsed.ops.items(): 3556 + for _op_name, op in parsed.ops.items(): 3579 3557 if parsed.kernel_policy in {'per-op', 'split'}: 3580 3558 for op_mode in ['do', 'dump']: 3581 3559 if op_mode in op and 'request' in op[op_mode]: ··· 3603 3581 ri = RenderInfo(cw, parsed, args.mode, "", "", attr_set) 3604 3582 print_type_full(ri, struct) 3605 3583 3606 - for op_name, op in parsed.ops.items(): 3584 + for _op_name, op in parsed.ops.items(): 3607 3585 cw.p(f"/* ============== {op.enum_name} ============== */") 3608 3586 3609 3587 if 'do' in op and 'event' not in op: ··· 3636 3614 raise Exception(f'Only notifications with consistent types supported ({op.name})') 3637 3615 print_wrapped_type(ri) 3638 3616 3639 - for op_name, op in parsed.ntfs.items(): 3617 + for _op_name, op in parsed.ntfs.items(): 3640 3618 if 'event' in op: 3641 3619 ri = RenderInfo(cw, parsed, args.mode, op, 'event') 3642 3620 cw.p(f"/* {op.enum_name} - event */") ··· 3686 3664 if struct.reply: 3687 3665 parse_rsp_nested(ri, struct) 3688 3666 3689 - for op_name, op in parsed.ops.items(): 3667 + for _op_name, op in parsed.ops.items(): 3690 3668 cw.p(f"/* ============== {op.enum_name} ============== */") 3691 3669 if 'do' in op and 'event' not in op: 3692 3670 cw.p(f"/* {op.enum_name} - do */") ··· 3714 3692 raise Exception(f'Only notifications with consistent types supported ({op.name})') 3715 3693 print_ntf_type_free(ri) 3716 3694 3717 - for op_name, op in parsed.ntfs.items(): 3695 + for _op_name, op in parsed.ntfs.items(): 3718 3696 if 'event' in op: 3719 3697 cw.p(f"/* {op.enum_name} - event */") 3720 3698
+2
tools/net/ynl/pyynl/ynl_gen_rst.py
··· 19 19 import argparse 20 20 import logging 21 21 22 + # pylint: disable=no-name-in-module,wrong-import-position 22 23 sys.path.append(pathlib.Path(__file__).resolve().parent.as_posix()) 23 24 from lib import YnlDocGenerator # pylint: disable=C0413 24 25 ··· 61 60 rst_file.write(content) 62 61 63 62 63 + # pylint: disable=broad-exception-caught 64 64 def main() -> None: 65 65 """Main function that reads the YAML files and generates the RST files""" 66 66