From 95a3df8bed8a326e6a172793b24f56a3bc7e1ec6 Mon Sep 17 00:00:00 2001 From: hygienic-books Date: Mon, 21 Mar 2022 02:57:54 +0100 Subject: [PATCH] Options parsing --- kodi-nfo-feeder.py | 87 ++++++++++++++++++++++++++++++++++++++++++++++ requirements.in | 3 +- requirements.txt | 2 ++ 3 files changed, 91 insertions(+), 1 deletion(-) diff --git a/kodi-nfo-feeder.py b/kodi-nfo-feeder.py index 7fd63b5..b486b3d 100644 --- a/kodi-nfo-feeder.py +++ b/kodi-nfo-feeder.py @@ -1,8 +1,15 @@ import os import logging +import sys from rich.logging import RichHandler from rich.traceback import install import configparser +import inflect + + +# Exit codes +# 1: Config file invalid, it has no sections +# 2: Config file invalid, sections must define at least CONST.CFG_MANDATORY class CONST(object): @@ -57,7 +64,87 @@ class ConfigParser( return super().options(section) +p = inflect.engine() + ini_defaults = [] internal_defaults = {default["key"]: default["value"] for default in CONST.CFG_KNOWN_DEFAULTS} config = ConfigParser(defaults=internal_defaults) config.read(CONST.CFG_DEFAULT_FILENAME) + + +def print_section_header( + header: str) -> str: + return f"Loading config section '[{header}]' ..." + + +def validate_default_section( + config_obj: configparser.ConfigParser()) -> None: + log.debug(f"Loading config from file '{CONST.CFG_DEFAULT_ABS_PATH}' ...") + if not config_obj.sections(): + log.error(f"No config sections found in '{CONST.CFG_DEFAULT_ABS_PATH}'. Exiting 1 ...") + sys.exit(1) + if config.defaults(): + log.debug(f"Symbol legend:\n" + f"* Global default from section '[{config_obj.default_section}]'\n" + f"~ Local option, doesn't exist in '[{config_obj.default_section}]'\n" + f"+ Local override of a value from '[{config_obj.default_section}]'\n" + f"= Local override, same value as in '[{config_obj.default_section}]'") + log.debug(print_section_header(config_obj.default_section)) + for default in config_obj.defaults(): + ini_defaults.append({default: config_obj[config_obj.default_section][default]}) + log.debug(f"* {default} = {config_obj[config_obj.default_section][default]}") + else: + log.debug(f"No defaults defined") + + +def config_has_valid_section( + config_obj: configparser.ConfigParser()) -> bool: + has_valid_section = False + for config_obj_section in config_obj.sections(): + if set(CONST.CFG_MANDATORY).issubset(config_obj.options(config_obj_section)): + has_valid_section = True + break + return has_valid_section + + +def is_default( + config_key: str) -> bool: + return any(config_key in ini_default for ini_default in ini_defaults) + + +def is_same_as_default( + config_kv_pair: dict) -> bool: + return config_kv_pair in ini_defaults + + +def validate_config_sections( + config_obj: configparser.ConfigParser()) -> None: + for this_section in config_obj.sections(): + log.debug(print_section_header(this_section)) + if not set(CONST.CFG_MANDATORY).issubset(config_obj.options(this_section, no_defaults=True)): + log.warning(f"Config section '[{this_section}]' does not have all mandatory options " + f"{CONST.CFG_MANDATORY} set, skipping section ...") + config_obj.remove_section(this_section) + else: + for key in config_obj.options(this_section, no_defaults=True): + kv_prefix = "~" + if is_default(key): + kv_prefix = "+" + if is_same_as_default({key: config_obj[this_section][key]}): + kv_prefix = "=" + log.debug(f"{kv_prefix} {key} = {config_obj[this_section][key]}") + + +if __name__ == '__main__': + validate_default_section(config) + if config_has_valid_section(config): + validate_config_sections(config) + else: + log.error(f"No valid config section found. A valid config section has at least the mandatory " + f"""{p.plural("option", len(CONST.CFG_MANDATORY))} """ + f"{CONST.CFG_MANDATORY} set. Exiting 1 ...") + sys.exit(1) + + log.debug(f"Iterating over config sections ...") + for section in config.sections(): + log.debug(f"Processing section '[{section}]' ...") diff --git a/requirements.in b/requirements.in index c94be38..92edb97 100644 --- a/requirements.in +++ b/requirements.in @@ -1 +1,2 @@ -rich \ No newline at end of file +rich +inflect \ No newline at end of file diff --git a/requirements.txt b/requirements.txt index a3f3a84..93c3c73 100644 --- a/requirements.txt +++ b/requirements.txt @@ -6,6 +6,8 @@ # commonmark==0.9.1 # via rich +inflect==5.4.0 + # via -r requirements.in pygments==2.11.2 # via rich rich==12.0.0