From 420ba065daafec43d3d8f269f261d28639f75859 Mon Sep 17 00:00:00 2001 From: Arksine Date: Tue, 11 May 2021 18:12:08 -0400 Subject: [PATCH] confighelper: add annotations Signed-off-by: Eric Callahan --- moonraker/confighelper.py | 89 +++++++++++++++++++++++++++++---------- 1 file changed, 67 insertions(+), 22 deletions(-) diff --git a/moonraker/confighelper.py b/moonraker/confighelper.py index 8764b04..81f7369 100644 --- a/moonraker/confighelper.py +++ b/moonraker/confighelper.py @@ -3,19 +3,46 @@ # Copyright (C) 2020 Eric Callahan # # This file may be distributed under the terms of the GNU GPLv3 license + +from __future__ import annotations import configparser import os import logging +from utils import SentinelClass + +# Annotation imports +from typing import ( + TYPE_CHECKING, + Any, + Callable, + Type, + IO, + TypeVar, + Union, + Dict, + List, +) +if TYPE_CHECKING: + from argparse import Namespace + from moonraker import Server + _T = TypeVar("_T") + ConfigVal = Union[None, int, float, bool, str] + +SENTINEL = SentinelClass.get_instance() class ConfigError(Exception): pass -class Sentinel: - pass class ConfigHelper: error = ConfigError - def __init__(self, server, config, section, orig_sects, parsed={}): + def __init__(self, + server: Server, + config: configparser.ConfigParser, + section: str, + orig_sects: List[str], + parsed: Dict[str, Dict[str, ConfigVal]] = {} + ) -> None: self.server = server self.config = config self.section = section @@ -26,38 +53,42 @@ class ConfigHelper: self.sections = config.sections self.has_section = config.has_section - def get_server(self): + def get_server(self) -> Server: return self.server - def __getitem__(self, key): + def __getitem__(self, key: str) -> ConfigHelper: return self.getsection(key) - def __contains__(self, key): + def __contains__(self, key: str) -> bool: return key in self.config - def get_name(self): + def get_name(self) -> str: return self.section - def get_options(self): + def get_options(self) -> Dict[str, str]: return dict(self.config[self.section]) - def get_prefix_sections(self, prefix): + def get_prefix_sections(self, prefix: str) -> List[str]: return [s for s in self.sections() if s.startswith(prefix)] - def getsection(self, section): + def getsection(self, section: str) -> ConfigHelper: if section not in self.config: raise ConfigError(f"No section [{section}] in config") return ConfigHelper(self.server, self.config, section, self.orig_sections, self.parsed) - def _get_option(self, func, option, default): + def _get_option(self, + func: Callable[..., Any], + option: str, + default: Union[SentinelClass, _T] + ) -> _T: try: val = func(option, default) except Exception: raise ConfigError( f"Error parsing option ({option}) from " f"section [{self.section}]") - if val == Sentinel: + if isinstance(val, SentinelClass): raise ConfigError( f"No option found ({option}) in section [{self.section}]") if self.section in self.orig_sections: @@ -65,23 +96,35 @@ class ConfigHelper: self.parsed[self.section][option] = val return val - def get(self, option, default=Sentinel): + def get(self, + option: str, + default: Union[SentinelClass, _T] = SENTINEL + ) -> Union[str, _T]: return self._get_option( self.config[self.section].get, option, default) - def getint(self, option, default=Sentinel): + def getint(self, + option: str, + default: Union[SentinelClass, _T] = SENTINEL + ) -> Union[int, _T]: return self._get_option( self.config[self.section].getint, option, default) - def getboolean(self, option, default=Sentinel): + def getboolean(self, + option: str, + default: Union[SentinelClass, _T] = SENTINEL + ) -> Union[bool, _T]: return self._get_option( self.config[self.section].getboolean, option, default) - def getfloat(self, option, default=Sentinel): + def getfloat(self, + option: str, + default: Union[SentinelClass, _T] = SENTINEL + ) -> Union[float, _T]: return self._get_option( self.config[self.section].getfloat, option, default) - def read_supplemental_config(self, file_name): + def read_supplemental_config(self, file_name: str) -> None: cfg_file_path = os.path.normpath(os.path.expanduser(file_name)) if not os.path.isfile(cfg_file_path): raise ConfigError( @@ -91,13 +134,13 @@ class ConfigHelper: except Exception: raise ConfigError(f"Error Reading Config: '{cfg_file_path}'") - def write_config(self, file_obj): + def write_config(self, file_obj: IO[str]) -> None: self.config.write(file_obj) - def get_parsed_config(self): + def get_parsed_config(self) -> Dict[str, Dict[str, ConfigVal]]: return dict(self.parsed) - def validate_config(self): + def validate_config(self) -> None: for sect in self.orig_sections: if sect not in self.parsed: logging.warn( @@ -112,8 +155,10 @@ class ConfigHelper: f"[{sect}]. In the future this will result in a " "startup error.") -def get_configuration(server, system_args): - cfg_file_path = os.path.normpath(os.path.expanduser( +def get_configuration(server: Server, + system_args: Namespace + ) -> ConfigHelper: + cfg_file_path: str = os.path.normpath(os.path.expanduser( system_args.configfile)) if not os.path.isfile(cfg_file_path): raise ConfigError(