From 7ecfc3dd9df157975940f84c28758549098ab6f8 Mon Sep 17 00:00:00 2001 From: Andrea Righi Date: Mon, 13 Feb 2023 08:33:41 +0100 Subject: [PATCH] UBUNTU: [Packaging] annotations: various code cleanups kconfig: Fix pylint violations Fix the following: R0205: Class 'Config' inherits from object, can be safely removed from bases in python3 (useless-object-inheritance) E1101: Instance of 'Config' has no '_parse' member (no-member) W0613: Unused argument 'arch' (unused-argument) W0613: Unused argument 'flavour' (unused-argument) W1514: Using open without explicitly specifying an encoding (unspecified-encoding) R0201: Method could be a function (no-self-use) E1101: Instance of 'Config' has no 'config' member (no-member) W0707: Consider explicitly re-raising using the 'from' keyword (raise-missing-from) W0105: String statement has no effect (pointless-string-statement) W0123: Use of eval (eval-used) W0102: Dangerous default value [] as argument (dangerous-default-value) R1723: Unnecessary "elif" after "break" (no-else-break) R1705: Unnecessary "elif" after "return" (no-else-return) R1704: Redefining argument with the local name 'arch' (redefined-argument-from-local) Signed-off-by: Juerg Haefliger Signed-off-by: Andrea Righi --- debian/scripts/misc/annotations | 32 +++++++--- debian/scripts/misc/kconfig/annotations.py | 73 +++++++++++++--------- 2 files changed, 68 insertions(+), 37 deletions(-) diff --git a/debian/scripts/misc/annotations b/debian/scripts/misc/annotations index 5caa3b2aa70f..ea6bc9b5157d 100755 --- a/debian/scripts/misc/annotations +++ b/debian/scripts/misc/annotations @@ -8,9 +8,10 @@ sys.dont_write_bytecode = True import os import argparse import json -from kconfig.annotations import Annotation, KConfig from signal import signal, SIGPIPE, SIG_DFL +from kconfig.annotations import Annotation, KConfig + VERSION = '0.1' SKIP_CONFIGS = ( @@ -28,6 +29,7 @@ SKIP_CONFIGS = ( 'CONFIG_BINDGEN_VERSION_TEXT', ) + def make_parser(): parser = argparse.ArgumentParser( description='Manage Ubuntu kernel .config and annotations', @@ -68,18 +70,22 @@ def make_parser(): help='Validate kernel .config with annotations') return parser + _ARGPARSER = make_parser() + def arg_fail(message): print(message) _ARGPARSER.print_usage() - exit(1) + sys.exit(1) + def print_result(config, res): if res is not None and config not in res: res = {config or '*': res} print(json.dumps(res, indent=4)) + def do_query(args): if args.arch is None and args.flavour is not None: arg_fail('error: --flavour requires --arch') @@ -87,19 +93,23 @@ def do_query(args): res = a.search_config(config=args.config, arch=args.arch, flavour=args.flavour) print_result(args.config, res) + def do_autocomplete(args): a = Annotation(args.file) res = (c.removeprefix('CONFIG_') for c in a.search_config()) - print('complete -W "{}" annotations'.format(' '.join(res))) + res_str = ' '.join(res) + print(f'complete -W "{res_str}" annotations') + def do_source(args): if args.config is None: arg_fail('error: --source requires --config') if not os.path.exists('tags'): print('tags not found in the current directory, try: `make tags`') - exit(1) + sys.exit(1) os.system(f'vim -t {args.config}') + def do_note(args): if args.config is None: arg_fail('error: --note requires --config') @@ -116,6 +126,7 @@ def do_note(args): res = a.search_config(config=args.config) print_result(args.config, res) + def do_write(args): if args.config is None: arg_fail('error: --write requires --config') @@ -135,6 +146,7 @@ def do_write(args): res = a.search_config(config=args.config) print_result(args.config, res) + def do_export(args): if args.arch is None: arg_fail('error: --export requires --arch') @@ -143,6 +155,7 @@ def do_export(args): if conf: print(a.to_config(conf)) + def do_import(args): if args.arch is None: arg_fail('error: --arch is required with --import') @@ -159,6 +172,7 @@ def do_import(args): # Save back to annotations a.save(args.file) + def do_update(args): if args.arch is None: arg_fail('error: --arch is required with --update') @@ -174,6 +188,7 @@ def do_update(args): # Save back to annotations a.save(args.file) + def do_check(args): # Determine arch and flavour if args.arch is None: @@ -208,7 +223,8 @@ def do_check(args): total += 1 print(f"check-config: {good}/{total} checks passed -- exit {ret}") - exit(ret) + sys.exit(ret) + def autodetect_annotations(args): if args.file: @@ -216,11 +232,12 @@ def autodetect_annotations(args): # If --file/-f isn't specified try to automatically determine the right # location of the annotations file looking at debian/debian.env. try: - with open('debian/debian.env', 'rt') as fd: + with open('debian/debian.env', 'rt', encoding='utf-8') as fd: args.file = fd.read().rstrip().split('=')[1] + '/config/annotations' - except Exception: + except (FileNotFoundError, IndexError): arg_fail('error: could not determine DEBDIR, try using: --file/-f') + def main(): # Prevent broken pipe errors when showing output in pipe to other tools # (less for example) @@ -252,5 +269,6 @@ def main(): else: do_query(args) + if __name__ == '__main__': main() diff --git a/debian/scripts/misc/kconfig/annotations.py b/debian/scripts/misc/kconfig/annotations.py index 1711257bd7ab..a1ad28284310 100644 --- a/debian/scripts/misc/kconfig/annotations.py +++ b/debian/scripts/misc/kconfig/annotations.py @@ -7,20 +7,26 @@ import json import re import shutil import tempfile + +from abc import abstractmethod from ast import literal_eval from os.path import dirname, abspath -class Config(object): - def __init__(self, fname: str, arch: str = None, flavour: str = None): + +class Config(): + def __init__(self, fname): """ Basic configuration file object """ self.fname = fname + self.config = {} + raw_data = self._load(fname) self._parse(raw_data) - def _load(self, fname: str) -> str: - with open(fname, 'rt') as fd: + @staticmethod + def _load(fname: str) -> str: + with open(fname, 'rt', encoding='utf-8') as fd: data = fd.read() return data.rstrip() @@ -28,12 +34,17 @@ class Config(object): """ Return a JSON representation of the config """ return json.dumps(self.config, indent=4) + @abstractmethod + def _parse(self, data: str): + pass + + class KConfig(Config): """ Parse a .config file, individual config options can be accessed via .config[] """ - def _parse(self, data: str) -> dict: + def _parse(self, data: str): self.config = {} for line in data.splitlines(): m = re.match(r'^# (CONFIG_.*) is not set$', line) @@ -45,6 +56,7 @@ class KConfig(Config): self.config[m.group(1)] = literal_eval("'" + m.group(2) + "'") continue + class Annotation(Config): """ Parse body of annotations file @@ -104,17 +116,17 @@ class Annotation(Config): raise Exception('syntax error') self.config[conf] = entry except Exception as e: - raise Exception(str(e) + f', line = {line}') + raise Exception(str(e) + f', line = {line}') from e continue # Invalid line raise Exception(f'invalid line: {line}') - """ - Parse main annotations file, individual config options can be accessed via - self.config[] - """ - def _parse(self, data: str) -> dict: + def _parse(self, data: str): + """ + Parse main annotations file, individual config options can be accessed + via self.config[] + """ self.config = {} self.arch = [] self.flavour = [] @@ -135,7 +147,7 @@ class Annotation(Config): self.flavour = list(m.group(1).split(' ')) m = re.match(r'^# FLAVOUR_DEP: (.*)', line) if m: - self.flavour_dep = eval(m.group(1)) + self.flavour_dep = literal_eval(m.group(1)) self.header += line + "\n" else: break @@ -180,12 +192,12 @@ class Annotation(Config): flavour = arch self.config[config]['policy'][flavour] = value else: - for arch in self.arch: - self.config[config]['policy'][arch] = value + for a in self.arch: + self.config[config]['policy'][a] = value if note is not None: self.config[config]['note'] = "'" + note.replace("'", '') + "'" - def update(self, c: KConfig, arch: str, flavour: str = None, configs: list = []): + def update(self, c: KConfig, arch: str, flavour: str = None, configs: list = None): """ Merge configs from a Kconfig object into Annotation object """ # Determine if we need to import all configs or a single config @@ -257,7 +269,7 @@ class Annotation(Config): for flavour in arch_flavours: if flavour not in self.config[conf]['policy']: break - elif value is None: + if value is None: value = self.config[conf]['policy'][flavour] elif value != self.config[conf]['policy'][flavour]: break @@ -279,7 +291,8 @@ class Annotation(Config): if not self.config[conf]['policy']: del self.config[conf] - def _sorted(self, config): + @staticmethod + def _sorted(config): """ Sort configs alphabetically but return configs with a note first """ w_note = [] wo_note = [] @@ -359,31 +372,31 @@ class Annotation(Config): if config is None and arch is None: # Get all config options for all architectures return self.config - elif config is None and arch is not None: + if config is None and arch is not None: # Get config options of a specific architecture ret = {} - for c in self.config: - if 'policy' not in self.config[c]: + for c, val in self.config.items(): + if 'policy' not in val: continue - if flavour in self.config[c]['policy']: - ret[c] = self.config[c]['policy'][flavour] - elif generic != flavour and generic in self.config[c]['policy']: - ret[c] = self.config[c]['policy'][generic] - elif arch in self.config[c]['policy']: - ret[c] = self.config[c]['policy'][arch] + if flavour in val['policy']: + ret[c] = val['policy'][flavour] + elif generic != flavour and generic in val['policy']: + ret[c] = val['policy'][generic] + elif arch in val['policy']: + ret[c] = val['policy'][arch] return ret - elif config is not None and arch is None: + if config is not None and arch is None: # Get a specific config option for all architectures return self.config[config] if config in self.config else None - elif config is not None and arch is not None: + if config is not None and arch is not None: # Get a specific config option for a specific architecture if config in self.config: if 'policy' in self.config[config]: if flavour in self.config[config]['policy']: return {config: self.config[config]['policy'][flavour]} - elif generic != flavour and generic in self.config[config]['policy']: + if generic != flavour and generic in self.config[config]['policy']: return {config: self.config[config]['policy'][generic]} - elif arch in self.config[config]['policy']: + if arch in self.config[config]['policy']: return {config: self.config[config]['policy'][arch]} return None