confighelper: add annotations
Signed-off-by: Eric Callahan <arksine.code@gmail.com>
This commit is contained in:
parent
ca69a10838
commit
420ba065da
|
@ -3,19 +3,46 @@
|
||||||
# Copyright (C) 2020 Eric Callahan <arksine.code@gmail.com>
|
# Copyright (C) 2020 Eric Callahan <arksine.code@gmail.com>
|
||||||
#
|
#
|
||||||
# This file may be distributed under the terms of the GNU GPLv3 license
|
# This file may be distributed under the terms of the GNU GPLv3 license
|
||||||
|
|
||||||
|
from __future__ import annotations
|
||||||
import configparser
|
import configparser
|
||||||
import os
|
import os
|
||||||
import logging
|
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):
|
class ConfigError(Exception):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
class Sentinel:
|
|
||||||
pass
|
|
||||||
|
|
||||||
class ConfigHelper:
|
class ConfigHelper:
|
||||||
error = ConfigError
|
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.server = server
|
||||||
self.config = config
|
self.config = config
|
||||||
self.section = section
|
self.section = section
|
||||||
|
@ -26,38 +53,42 @@ class ConfigHelper:
|
||||||
self.sections = config.sections
|
self.sections = config.sections
|
||||||
self.has_section = config.has_section
|
self.has_section = config.has_section
|
||||||
|
|
||||||
def get_server(self):
|
def get_server(self) -> Server:
|
||||||
return self.server
|
return self.server
|
||||||
|
|
||||||
def __getitem__(self, key):
|
def __getitem__(self, key: str) -> ConfigHelper:
|
||||||
return self.getsection(key)
|
return self.getsection(key)
|
||||||
|
|
||||||
def __contains__(self, key):
|
def __contains__(self, key: str) -> bool:
|
||||||
return key in self.config
|
return key in self.config
|
||||||
|
|
||||||
def get_name(self):
|
def get_name(self) -> str:
|
||||||
return self.section
|
return self.section
|
||||||
|
|
||||||
def get_options(self):
|
def get_options(self) -> Dict[str, str]:
|
||||||
return dict(self.config[self.section])
|
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)]
|
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:
|
if section not in self.config:
|
||||||
raise ConfigError(f"No section [{section}] in config")
|
raise ConfigError(f"No section [{section}] in config")
|
||||||
return ConfigHelper(self.server, self.config, section,
|
return ConfigHelper(self.server, self.config, section,
|
||||||
self.orig_sections, self.parsed)
|
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:
|
try:
|
||||||
val = func(option, default)
|
val = func(option, default)
|
||||||
except Exception:
|
except Exception:
|
||||||
raise ConfigError(
|
raise ConfigError(
|
||||||
f"Error parsing option ({option}) from "
|
f"Error parsing option ({option}) from "
|
||||||
f"section [{self.section}]")
|
f"section [{self.section}]")
|
||||||
if val == Sentinel:
|
if isinstance(val, SentinelClass):
|
||||||
raise ConfigError(
|
raise ConfigError(
|
||||||
f"No option found ({option}) in section [{self.section}]")
|
f"No option found ({option}) in section [{self.section}]")
|
||||||
if self.section in self.orig_sections:
|
if self.section in self.orig_sections:
|
||||||
|
@ -65,23 +96,35 @@ class ConfigHelper:
|
||||||
self.parsed[self.section][option] = val
|
self.parsed[self.section][option] = val
|
||||||
return 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(
|
return self._get_option(
|
||||||
self.config[self.section].get, option, default)
|
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(
|
return self._get_option(
|
||||||
self.config[self.section].getint, option, default)
|
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(
|
return self._get_option(
|
||||||
self.config[self.section].getboolean, option, default)
|
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(
|
return self._get_option(
|
||||||
self.config[self.section].getfloat, option, default)
|
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))
|
cfg_file_path = os.path.normpath(os.path.expanduser(file_name))
|
||||||
if not os.path.isfile(cfg_file_path):
|
if not os.path.isfile(cfg_file_path):
|
||||||
raise ConfigError(
|
raise ConfigError(
|
||||||
|
@ -91,13 +134,13 @@ class ConfigHelper:
|
||||||
except Exception:
|
except Exception:
|
||||||
raise ConfigError(f"Error Reading Config: '{cfg_file_path}'")
|
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)
|
self.config.write(file_obj)
|
||||||
|
|
||||||
def get_parsed_config(self):
|
def get_parsed_config(self) -> Dict[str, Dict[str, ConfigVal]]:
|
||||||
return dict(self.parsed)
|
return dict(self.parsed)
|
||||||
|
|
||||||
def validate_config(self):
|
def validate_config(self) -> None:
|
||||||
for sect in self.orig_sections:
|
for sect in self.orig_sections:
|
||||||
if sect not in self.parsed:
|
if sect not in self.parsed:
|
||||||
logging.warn(
|
logging.warn(
|
||||||
|
@ -112,8 +155,10 @@ class ConfigHelper:
|
||||||
f"[{sect}]. In the future this will result in a "
|
f"[{sect}]. In the future this will result in a "
|
||||||
"startup error.")
|
"startup error.")
|
||||||
|
|
||||||
def get_configuration(server, system_args):
|
def get_configuration(server: Server,
|
||||||
cfg_file_path = os.path.normpath(os.path.expanduser(
|
system_args: Namespace
|
||||||
|
) -> ConfigHelper:
|
||||||
|
cfg_file_path: str = os.path.normpath(os.path.expanduser(
|
||||||
system_args.configfile))
|
system_args.configfile))
|
||||||
if not os.path.isfile(cfg_file_path):
|
if not os.path.isfile(cfg_file_path):
|
||||||
raise ConfigError(
|
raise ConfigError(
|
||||||
|
|
Loading…
Reference in New Issue