From 539d207329c61795ae7f9da7d7a89de6ee58af98 Mon Sep 17 00:00:00 2001 From: Andrea Righi Date: Thu, 15 Jun 2023 17:54:55 +0200 Subject: [PATCH] fix pylint warnings Signed-off-by: Andrea Righi --- Makefile | 4 +- kconfig/annotations.py | 257 +++++++++++++++++++++++------------------ kconfig/run.py | 205 ++++++++++++++++++++------------ setup.py | 48 ++++---- 4 files changed, 296 insertions(+), 218 deletions(-) diff --git a/Makefile b/Makefile index aa3f97f..5ccbbd1 100644 --- a/Makefile +++ b/Makefile @@ -5,7 +5,7 @@ all: lint lint: flake8 pylint flake8: - flake8 sanitize-annotations annotations . + flake8 bin/sanitize-annotations kconfig/run.py kconfig/annotations.py kconfig/version.py . pylint: - pylint sanitize-annotations annotations kconfig + pylint bin/sanitize-annotations kconfig diff --git a/kconfig/annotations.py b/kconfig/annotations.py index 1d5e40c..7a23d2b 100644 --- a/kconfig/annotations.py +++ b/kconfig/annotations.py @@ -13,7 +13,7 @@ from ast import literal_eval from os.path import dirname, abspath -class Config(): +class Config: def __init__(self, fname): """ Basic configuration file object @@ -26,12 +26,12 @@ class Config(): @staticmethod def _load(fname: str) -> str: - with open(fname, 'rt', encoding='utf-8') as fd: + with open(fname, "rt", encoding="utf-8") as fd: data = fd.read() return data.rstrip() def __str__(self): - """ Return a JSON representation of the config """ + """Return a JSON representation of the config""" return json.dumps(self.config, indent=4) @abstractmethod @@ -44,14 +44,15 @@ class KConfig(Config): Parse a .config file, individual config options can be accessed via .config[] """ + def _parse(self, data: str): self.config = {} for line in data.splitlines(): - m = re.match(r'^# (CONFIG_.*) is not set$', line) + m = re.match(r"^# (CONFIG_.*) is not set$", line) if m: self.config[m.group(1)] = literal_eval("'n'") continue - m = re.match(r'^(CONFIG_[A-Za-z0-9_]+)=(.*)$', line) + m = re.match(r"^(CONFIG_[A-Za-z0-9_]+)=(.*)$", line) if m: self.config[m.group(1)] = literal_eval("'" + m.group(2) + "'") continue @@ -61,12 +62,13 @@ class Annotation(Config): """ Parse body of annotations file """ + def _parse_body(self, data: str, parent=True): for line in data.splitlines(): # Replace tabs with spaces, squeeze multiple into singles and # remove leading and trailing spaces - line = line.replace('\t', ' ') - line = re.sub(r' +', ' ', line) + line = line.replace("\t", " ") + line = re.sub(r" +", " ", line) line = line.strip() # Ignore empty lines @@ -74,12 +76,12 @@ class Annotation(Config): continue # Catpure flavors of included files - if line.startswith('# FLAVOUR: '): - self.include_flavour += line.split(' ')[2:] + if line.startswith("# FLAVOUR: "): + self.include_flavour += line.split(" ")[2:] continue # Ignore comments - if line.startswith('#'): + if line.startswith("#"): continue # Handle includes (recursively) @@ -87,44 +89,47 @@ class Annotation(Config): if m: if parent: self.include.append(m.group(1)) - include_fname = dirname(abspath(self.fname)) + '/' + m.group(1) + include_fname = dirname(abspath(self.fname)) + "/" + m.group(1) include_data = self._load(include_fname) self._parse_body(include_data, parent=False) continue # Handle policy and note lines - if re.match(r'.* (policy|note)<', line): + if re.match(r".* (policy|note)<", line): try: - conf = line.split(' ')[0] + conf = line.split(" ")[0] if conf in self.config: entry = self.config[conf] else: - entry = {'policy': {}} + entry = {"policy": {}} match = False - m = re.match(r'.* policy<(.*?)>', line) + m = re.match(r".* policy<(.*?)>", line) if m: match = True try: - entry['policy'] |= literal_eval(m.group(1)) + entry["policy"] |= literal_eval(m.group(1)) except TypeError: - entry['policy'] = {**entry['policy'], **literal_eval(m.group(1))} + entry["policy"] = { + **entry["policy"], + **literal_eval(m.group(1)), + } - m = re.match(r'.* note<(.*?)>', line) + m = re.match(r".* note<(.*?)>", line) if m: - entry['oneline'] = match + entry["oneline"] = match match = True - entry['note'] = "'" + m.group(1).replace("'", '') + "'" + entry["note"] = "'" + m.group(1).replace("'", "") + "'" if not match: - raise SyntaxError('syntax error') + raise SyntaxError("syntax error") self.config[conf] = entry except Exception as e: - raise SyntaxError(str(e) + f', line = {line}') from e + raise SyntaxError(str(e) + f", line = {line}") from e continue # Invalid line - raise SyntaxError(f'invalid line: {line}') + raise SyntaxError(f"invalid line: {line}") def _parse(self, data: str): """ @@ -136,20 +141,20 @@ class Annotation(Config): self.flavour = [] self.flavour_dep = {} self.include = [] - self.header = '' + self.header = "" self.include_flavour = [] # Parse header (only main header will considered, headers in includes # will be treated as comments) for line in data.splitlines(): - if re.match(r'^#.*', line): - m = re.match(r'^# ARCH: (.*)', line) + if re.match(r"^#.*", line): + m = re.match(r"^# ARCH: (.*)", line) if m: - self.arch = list(m.group(1).split(' ')) - m = re.match(r'^# FLAVOUR: (.*)', line) + self.arch = list(m.group(1).split(" ")) + m = re.match(r"^# FLAVOUR: (.*)", line) if m: - self.flavour = list(m.group(1).split(' ')) - m = re.match(r'^# FLAVOUR_DEP: (.*)', line) + self.flavour = list(m.group(1).split(" ")) + m = re.match(r"^# FLAVOUR_DEP: (.*)", line) if m: self.flavour_dep = literal_eval(m.group(1)) self.header += line + "\n" @@ -162,9 +167,9 @@ class Annotation(Config): # Sanity check: Verify that all FLAVOUR_DEP flavors are valid for src, tgt in self.flavour_dep.items(): if src not in self.flavour: - raise SyntaxError(f'Invalid source flavour in FLAVOUR_DEP: {src}') + raise SyntaxError(f"Invalid source flavour in FLAVOUR_DEP: {src}") if tgt not in self.include_flavour: - raise SyntaxError(f'Invalid target flavour in FLAVOUR_DEP: {tgt}') + raise SyntaxError(f"Invalid target flavour in FLAVOUR_DEP: {tgt}") def _remove_entry(self, config: str): if self.config[config]: @@ -175,34 +180,40 @@ class Annotation(Config): return if arch is not None: if flavour is not None: - flavour = f'{arch}-{flavour}' + flavour = f"{arch}-{flavour}" else: flavour = arch - del self.config[config]['policy'][flavour] - if not self.config[config]['policy']: + del self.config[config]["policy"][flavour] + if not self.config[config]["policy"]: self._remove_entry(config) else: self._remove_entry(config) - def set(self, config: str, arch: str = None, flavour: str = None, - value: str = None, note: str = None): + def set( + self, + config: str, + arch: str = None, + flavour: str = None, + value: str = None, + note: str = None, + ): if value is not None: if config not in self.config: - self.config[config] = {'policy': {}} + self.config[config] = {"policy": {}} if arch is not None: if flavour is not None: - flavour = f'{arch}-{flavour}' + flavour = f"{arch}-{flavour}" else: flavour = arch - self.config[config]['policy'][flavour] = value + self.config[config]["policy"][flavour] = value else: for a in self.arch: - self.config[config]['policy'][a] = value + self.config[config]["policy"][a] = value if note is not None: - self.config[config]['note'] = "'" + note.replace("'", '') + "'" + self.config[config]["note"] = "'" + note.replace("'", "") + "'" def update(self, c: KConfig, arch: str, flavour: str = None, configs: list = None): - """ Merge configs from a Kconfig object into Annotation object """ + """Merge configs from a Kconfig object into Annotation object""" # Determine if we need to import all configs or a single config if not configs: @@ -210,63 +221,72 @@ class Annotation(Config): try: configs |= self.search_config(arch=arch, flavour=flavour).keys() except TypeError: - configs = {**configs, **self.search_config(arch=arch, flavour=flavour).keys()} + configs = { + **configs, + **self.search_config(arch=arch, flavour=flavour).keys(), + } # Import configs from the Kconfig object into Annotations if flavour is not None: - flavour = arch + f'-{flavour}' + flavour = arch + f"-{flavour}" else: flavour = arch for conf in configs: if conf in c.config: val = c.config[conf] else: - val = '-' + val = "-" if conf in self.config: - if 'policy' in self.config[conf]: - self.config[conf]['policy'][flavour] = val + if "policy" in self.config[conf]: + self.config[conf]["policy"][flavour] = val else: - self.config[conf]['policy'] = {flavour: val} + self.config[conf]["policy"] = {flavour: val} else: - self.config[conf] = {'policy': {flavour: val}} + self.config[conf] = {"policy": {flavour: val}} def _compact(self): # Try to remove redundant settings: if the config value of a flavour is # the same as the one of the main arch simply drop it. for conf in self.config.copy(): - if 'policy' not in self.config[conf]: + if "policy" not in self.config[conf]: continue for flavour in self.flavour: - if flavour not in self.config[conf]['policy']: + if flavour not in self.config[conf]["policy"]: continue - m = re.match(r'^(.*?)-(.*)$', flavour) + m = re.match(r"^(.*?)-(.*)$", flavour) if not m: continue arch = m.group(1) - if arch in self.config[conf]['policy']: - if self.config[conf]['policy'][flavour] == self.config[conf]['policy'][arch]: - del self.config[conf]['policy'][flavour] + if arch in self.config[conf]["policy"]: + if ( + self.config[conf]["policy"][flavour] + == self.config[conf]["policy"][arch] + ): + del self.config[conf]["policy"][flavour] continue if flavour not in self.flavour_dep: continue generic = self.flavour_dep[flavour] - if generic in self.config[conf]['policy']: - if self.config[conf]['policy'][flavour] == self.config[conf]['policy'][generic]: - del self.config[conf]['policy'][flavour] + if generic in self.config[conf]["policy"]: + if ( + self.config[conf]["policy"][flavour] + == self.config[conf]["policy"][generic] + ): + del self.config[conf]["policy"][flavour] continue # Remove rules for flavours / arches that are not supported (not # listed in the annotations header). - for flavour in self.config[conf]['policy'].copy(): + for flavour in self.config[conf]["policy"].copy(): if flavour not in list(set(self.arch + self.flavour)): - del self.config[conf]['policy'][flavour] + del self.config[conf]["policy"][flavour] # Remove configs that are all undefined across all arches/flavours # (unless we have includes) if not self.include: - if 'policy' in self.config[conf]: - if list(set(self.config[conf]['policy'].values())) == ['-']: - self.config[conf]['policy'] = {} + if "policy" in self.config[conf]: + if list(set(self.config[conf]["policy"].values())) == ["-"]: + self.config[conf]["policy"] = {} # Drop empty rules - if not self.config[conf]['policy']: + if not self.config[conf]["policy"]: del self.config[conf] else: # Compact same value across all flavour within the same arch @@ -274,16 +294,16 @@ class Annotation(Config): arch_flavours = [i for i in self.flavour if i.startswith(arch)] value = None for flavour in arch_flavours: - if flavour not in self.config[conf]['policy']: + if flavour not in self.config[conf]["policy"]: break if value is None: - value = self.config[conf]['policy'][flavour] - elif value != self.config[conf]['policy'][flavour]: + value = self.config[conf]["policy"][flavour] + elif value != self.config[conf]["policy"][flavour]: break else: for flavour in arch_flavours: - del self.config[conf]['policy'][flavour] - self.config[conf]['policy'][arch] = value + del self.config[conf]["policy"][flavour] + self.config[conf]["policy"][arch] = value # After the first round of compaction we may end up having configs that # are undefined across all arches, so do another round of compaction to # drop these settings that are not needed anymore @@ -291,34 +311,34 @@ class Annotation(Config): if not self.include: for conf in self.config.copy(): # Remove configs that are all undefined across all arches/flavours - if 'policy' in self.config[conf]: - if list(set(self.config[conf]['policy'].values())) == ['-']: - self.config[conf]['policy'] = {} + if "policy" in self.config[conf]: + if list(set(self.config[conf]["policy"].values())) == ["-"]: + self.config[conf]["policy"] = {} # Drop empty rules - if not self.config[conf]['policy']: + if not self.config[conf]["policy"]: del self.config[conf] @staticmethod def _sorted(config): - """ Sort configs alphabetically but return configs with a note first """ + """Sort configs alphabetically but return configs with a note first""" w_note = [] wo_note = [] for c in sorted(config): - if 'note' in config[c]: + if "note" in config[c]: w_note.append(c) else: wo_note.append(c) return w_note + wo_note def save(self, fname: str): - """ Save annotations data to the annotation file """ + """Save annotations data to the annotation file""" # Compact annotations structure self._compact() # Save annotations to disk - with tempfile.NamedTemporaryFile(mode='w+t', delete=False) as tmp: + with tempfile.NamedTemporaryFile(mode="w+t", delete=False) as tmp: # Write header - tmp.write(self.header + '\n') + tmp.write(self.header + "\n") # Write includes for i in self.include: @@ -335,40 +355,45 @@ class Annotation(Config): marker = False for conf in self._sorted(self.config): new_val = self.config[conf] - if 'policy' not in new_val: + if "policy" not in new_val: continue # If new_val is a subset of old_val, skip it unless there are # new notes that are different than the old ones. old_val = tmp_a.config.get(conf) - if old_val and 'policy' in old_val: + if old_val and "policy" in old_val: try: - can_skip = old_val['policy'] == old_val['policy'] | new_val['policy'] + can_skip = ( + old_val["policy"] == old_val["policy"] | new_val["policy"] + ) except TypeError: - can_skip = old_val['policy'] == {**old_val['policy'], **new_val['policy']} + can_skip = old_val["policy"] == { + **old_val["policy"], + **new_val["policy"], + } if can_skip: - if 'note' not in new_val: + if "note" not in new_val: continue - if 'note' in old_val and 'note' in new_val: - if old_val['note'] == new_val['note']: + if "note" in old_val and "note" in new_val: + if old_val["note"] == new_val["note"]: continue # Write out the policy (and note) line(s) - val = dict(sorted(new_val['policy'].items())) + val = dict(sorted(new_val["policy"].items())) line = f"{conf : <47} policy<{val}>" - if 'note' in new_val: - val = new_val['note'] - if new_val.get('oneline', False): + if "note" in new_val: + val = new_val["note"] + if new_val.get("oneline", False): # Single line - line += f' note<{val}>' + line += f" note<{val}>" else: # Separate policy and note lines, # followed by an empty line - line += f'\n{conf : <47} note<{val}>\n' + line += f"\n{conf : <47} note<{val}>\n" elif not marker: # Write out a marker indicating the start of annotations # without notes - tmp.write('\n# ---- Annotations without notes ----\n\n') + tmp.write("\n# ---- Annotations without notes ----\n\n") marker = True tmp.write(line + "\n") @@ -376,11 +401,13 @@ class Annotation(Config): tmp.flush() shutil.move(tmp.name, fname) - def search_config(self, config: str = None, arch: str = None, flavour: str = None) -> dict: - """ Return config value of a specific config option or architecture """ + def search_config( + self, config: str = None, arch: str = None, flavour: str = None + ) -> dict: + """Return config value of a specific config option or architecture""" if flavour is None: - flavour = 'generic' - flavour = f'{arch}-{flavour}' + flavour = "generic" + flavour = f"{arch}-{flavour}" if flavour in self.flavour_dep: generic = self.flavour_dep[flavour] else: @@ -392,14 +419,14 @@ class Annotation(Config): # Get config options of a specific architecture ret = {} for c, val in self.config.items(): - if 'policy' not in val: + if "policy" not in val: continue - 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] + 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 if config is not None and arch is None: # Get a specific config option for all architectures @@ -407,24 +434,24 @@ class Annotation(Config): 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]} - if generic != flavour and generic in self.config[config]['policy']: - return {config: self.config[config]['policy'][generic]} - if arch in self.config[config]['policy']: - return {config: self.config[config]['policy'][arch]} + if "policy" in self.config[config]: + if flavour in self.config[config]["policy"]: + return {config: self.config[config]["policy"][flavour]} + if generic != flavour and generic in self.config[config]["policy"]: + return {config: self.config[config]["policy"][generic]} + if arch in self.config[config]["policy"]: + return {config: self.config[config]["policy"][arch]} return None @staticmethod def to_config(data: dict) -> str: - """ Convert annotations data to .config format """ - s = '' + """Convert annotations data to .config format""" + s = "" for c in data: v = data[c] - if v == 'n': + if v == "n": s += f"# {c} is not set\n" - elif v == '-': + elif v == "-": pass else: s += f"{c}={v}\n" diff --git a/kconfig/run.py b/kconfig/run.py index cf133b3..cfea2e7 100644 --- a/kconfig/run.py +++ b/kconfig/run.py @@ -4,7 +4,6 @@ # Copyright © 2022 Canonical Ltd. import sys -sys.dont_write_bytecode = True import os import argparse import json @@ -13,83 +12,127 @@ from argcomplete import autocomplete from kconfig.annotations import Annotation, KConfig -VERSION = '0.1' +VERSION = "0.1" SKIP_CONFIGS = ( # CONFIG_VERSION_SIGNATURE is dynamically set during the build - 'CONFIG_VERSION_SIGNATURE', + "CONFIG_VERSION_SIGNATURE", # Allow to use a different versions of toolchain tools - 'CONFIG_GCC_VERSION', - 'CONFIG_CC_VERSION_TEXT', - 'CONFIG_AS_VERSION', - 'CONFIG_LD_VERSION', - 'CONFIG_LLD_VERSION', - 'CONFIG_CLANG_VERSION', - 'CONFIG_PAHOLE_VERSION', - 'CONFIG_RUSTC_VERSION_TEXT', - 'CONFIG_BINDGEN_VERSION_TEXT', + "CONFIG_GCC_VERSION", + "CONFIG_CC_VERSION_TEXT", + "CONFIG_AS_VERSION", + "CONFIG_LD_VERSION", + "CONFIG_LLD_VERSION", + "CONFIG_CLANG_VERSION", + "CONFIG_PAHOLE_VERSION", + "CONFIG_RUSTC_VERSION_TEXT", + "CONFIG_BINDGEN_VERSION_TEXT", ) def make_parser(): parser = argparse.ArgumentParser( - description='Manage Ubuntu kernel .config and annotations', + description="Manage Ubuntu kernel .config and annotations", + ) + parser.add_argument( + "--version", "-v", action="version", version=f"%(prog)s {VERSION}" + ) + + parser.add_argument( + "--file", + "-f", + action="store", + help="Pass annotations or .config file to be parsed", + ) + parser.add_argument("--arch", "-a", action="store", help="Select architecture") + parser.add_argument( + "--flavour", "-l", action="store", help='Select flavour (default is "generic")' + ) + parser.add_argument( + "--config", "-c", action="store", help="Select a specific config option" + ) + parser.add_argument("--query", "-q", action="store_true", help="Query annotations") + parser.add_argument( + "--note", + "-n", + action="store", + help="Write a specific note to a config option in annotations", + ) + parser.add_argument( + "--autocomplete", + action="store_true", + help="Enable config bash autocomplete: `source <(annotations --autocomplete)`", + ) + parser.add_argument( + "--source", + "-t", + action="store_true", + help="Jump to a config definition in the kernel source code", + ) + + ga = parser.add_argument_group(title="Action").add_mutually_exclusive_group( + required=False + ) + ga.add_argument( + "--write", + "-w", + action="store", + metavar="VALUE", + dest="value", + help="Set a specific config value in annotations (use 'null' to remove)", + ) + ga.add_argument( + "--export", + "-e", + action="store_true", + help="Convert annotations to .config format", + ) + ga.add_argument( + "--import", + "-i", + action="store", + metavar="FILE", + dest="import_file", + help="Import a full .config for a specific arch and flavour into annotations", + ) + ga.add_argument( + "--update", + "-u", + action="store", + metavar="FILE", + dest="update_file", + help="Import a partial .config into annotations (only resync configs specified in FILE)", + ) + ga.add_argument( + "--check", + "-k", + action="store", + metavar="FILE", + dest="check_file", + help="Validate kernel .config with annotations", ) - parser.add_argument('--version', '-v', action='version', version=f'%(prog)s {VERSION}') - - parser.add_argument('--file', '-f', action='store', - help='Pass annotations or .config file to be parsed') - parser.add_argument('--arch', '-a', action='store', - help='Select architecture') - parser.add_argument('--flavour', '-l', action='store', - help='Select flavour (default is "generic")') - parser.add_argument('--config', '-c', action='store', - help='Select a specific config option') - parser.add_argument('--query', '-q', action='store_true', - help='Query annotations') - parser.add_argument('--note', '-n', action='store', - help='Write a specific note to a config option in annotations') - parser.add_argument('--autocomplete', action='store_true', - help='Enable config bash autocomplete: `source <(annotations --autocomplete)`') - parser.add_argument('--source', '-t', action='store_true', - help='Jump to a config definition in the kernel source code') - - ga = parser.add_argument_group(title='Action').add_mutually_exclusive_group(required=False) - ga.add_argument('--write', '-w', action='store', - metavar='VALUE', dest='value', - help='Set a specific config value in annotations (use \'null\' to remove)') - ga.add_argument('--export', '-e', action='store_true', - help='Convert annotations to .config format') - ga.add_argument('--import', '-i', action='store', - metavar="FILE", dest='import_file', - help='Import a full .config for a specific arch and flavour into annotations') - ga.add_argument('--update', '-u', action='store', - metavar="FILE", dest='update_file', - help='Import a partial .config into annotations (only resync configs specified in FILE)') - ga.add_argument('--check', '-k', action='store', - metavar="FILE", dest='check_file', - help='Validate kernel .config with annotations') return parser _ARGPARSER = make_parser() -def arg_fail(message): +def arg_fail(message, show_usage=True): print(message) - _ARGPARSER.print_usage() + if show_usage: + _ARGPARSER.print_usage() sys.exit(1) def print_result(config, res): if res is not None and config not in res: - res = {config or '*': 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') + arg_fail("error: --flavour requires --arch") a = Annotation(args.file) res = a.search_config(config=args.config, arch=args.arch, flavour=args.flavour) print_result(args.config, res) @@ -97,23 +140,23 @@ def do_query(args): def do_autocomplete(args): a = Annotation(args.file) - res = (c.removeprefix('CONFIG_') for c in a.search_config()) - res_str = ' '.join(res) + res = (c.removeprefix("CONFIG_") for c in a.search_config()) + 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`') + arg_fail("error: --source requires --config") + if not os.path.exists("tags"): + print("tags not found in the current directory, try: `make tags`") sys.exit(1) - os.system(f'vim -t {args.config}') + os.system(f"vim -t {args.config}") def do_note(args): if args.config is None: - arg_fail('error: --note requires --config') + arg_fail("error: --note requires --config") # Set the note in annotations a = Annotation(args.file) @@ -130,14 +173,20 @@ def do_note(args): def do_write(args): if args.config is None: - arg_fail('error: --write requires --config') + arg_fail("error: --write requires --config") # Set the value in annotations ('null' means remove) a = Annotation(args.file) - if args.value == 'null': + if args.value == "null": a.remove(args.config, arch=args.arch, flavour=args.flavour) else: - a.set(args.config, arch=args.arch, flavour=args.flavour, value=args.value, note=args.note) + a.set( + args.config, + arch=args.arch, + flavour=args.flavour, + value=args.value, + note=args.note, + ) # Save back to annotations a.save(args.file) @@ -150,7 +199,7 @@ def do_write(args): def do_export(args): if args.arch is None: - arg_fail('error: --export requires --arch') + arg_fail("error: --export requires --arch") a = Annotation(args.file) conf = a.search_config(config=args.config, arch=args.arch, flavour=args.flavour) if conf: @@ -159,11 +208,11 @@ def do_export(args): def do_import(args): if args.arch is None: - arg_fail('error: --arch is required with --import') + arg_fail("error: --arch is required with --import") if args.flavour is None: - arg_fail('error: --flavour is required with --import') + arg_fail("error: --flavour is required with --import") if args.config is not None: - arg_fail('error: --config cannot be used with --import (try --update)') + arg_fail("error: --config cannot be used with --import (try --update)") # Merge with the current annotations a = Annotation(args.file) @@ -176,7 +225,7 @@ def do_import(args): def do_update(args): if args.arch is None: - arg_fail('error: --arch is required with --update') + arg_fail("error: --arch is required with --update") # Merge with the current annotations a = Annotation(args.file) @@ -193,7 +242,7 @@ def do_update(args): def do_check(args): # Determine arch and flavour if args.arch is None: - arg_fail('error: --arch is required with --check') + arg_fail("error: --arch is required with --check") print(f"check-config: loading annotations from {args.file}") total = good = ret = 0 @@ -211,11 +260,11 @@ def do_check(args): if conf in SKIP_CONFIGS: continue entry = a.search_config(config=conf, arch=args.arch, flavour=args.flavour) - expected = entry[conf] if entry else '-' - value = c.config[conf] if conf in c.config else '-' + expected = entry[conf] if entry else "-" + value = c.config[conf] if conf in c.config else "-" if value != expected: - policy = a.config[conf] if conf in a.config else 'undefined' - if 'policy' in policy: + policy = a.config[conf] if conf in a.config else "undefined" + if "policy" in policy: policy = f"policy<{policy['policy']}>" print(f"check-config: FAIL: ({value} != {expected}): {conf} {policy})") ret = 1 @@ -233,10 +282,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', encoding='utf-8') as fd: - args.file = fd.read().rstrip().split('=')[1] + '/config/annotations' + with open("debian/debian.env", "rt", encoding="utf-8") as fd: + args.file = fd.read().rstrip().split("=")[1] + "/config/annotations" except (FileNotFoundError, IndexError): - arg_fail('error: could not determine DEBDIR, try using: --file/-f') + arg_fail( + "error: could not determine DEBDIR, try using: --file/-f", show_usage=False + ) def main(): @@ -249,8 +300,8 @@ def main(): args = _ARGPARSER.parse_args() autodetect_annotations(args) - if args.config and not args.config.startswith('CONFIG_'): - args.config = 'CONFIG_' + args.config + if args.config and not args.config.startswith("CONFIG_"): + args.config = "CONFIG_" + args.config if args.value: do_write(args) @@ -272,5 +323,5 @@ def main(): do_query(args) -if __name__ == '__main__': +if __name__ == "__main__": main() diff --git a/setup.py b/setup.py index 622a856..c8e377e 100755 --- a/setup.py +++ b/setup.py @@ -1,38 +1,38 @@ #!/usr/bin/env python3 import os -import sys from setuptools import setup from kconfig.version import VERSION setup( - name='annotations', + name="annotations", version=VERSION, - author='Andrea Righi', - author_email='andrea.righi@canonical.com', - description='Manage Ubuntu kernel .config', - url='https://git.launchpad.net/~arighi/+git/annotations-tools', - license='GPLv2', - long_description=open(os.path.join(os.path.dirname(__file__), - 'README.rst'), 'r').read(), + author="Andrea Righi", + author_email="andrea.righi@canonical.com", + description="Manage Ubuntu kernel .config", + url="https://git.launchpad.net/~arighi/+git/annotations-tools", + license="GPLv2", + long_description=open( + os.path.join(os.path.dirname(__file__), "README.rst"), "r" + ).read(), long_description_content_type="text/x-rts", - packages=['kconfig'], - install_requires=['argcomplete'], - entry_points = { - 'console_scripts': [ - 'annotations = kconfig.run:main', + packages=["kconfig"], + install_requires=["argcomplete"], + entry_points={ + "console_scripts": [ + "annotations = kconfig.run:main", ] }, - scripts = [ - 'bin/sanitize-annotations', + scripts=[ + "bin/sanitize-annotations", ], include_package_data=True, - classifiers=['Environment :: Console', - 'Intended Audience :: Developers', - 'Intended Audience :: System Administrators', - 'License :: OSI Approved :: GNU General Public License v2 (GPLv2)', - 'Operating System :: POSIX :: Linux', - ], - - zip_safe = False, + classifiers=[ + "Environment :: Console", + "Intended Audience :: Developers", + "Intended Audience :: System Administrators", + "License :: OSI Approved :: GNU General Public License v2 (GPLv2)", + "Operating System :: POSIX :: Linux", + ], + zip_safe=False, ) -- 2.31.1