Files
BiogasControllerApp/lib/config.py
Janis Hutz 7905cb851a Config, Lots of docs, Format
Added a config validator and documented code that was previously
undocumented, for the plot_generator scripts, documented them.
2025-06-16 16:36:18 +02:00

145 lines
4.0 KiB
Python

import configparser
from typing import List
# Load the config
config = configparser.ConfigParser()
config.read("./config.ini")
global first_error
first_error = True
global is_verbose
is_verbose = True
def set_verbosity(verbose: bool):
global is_verbose
is_verbose = verbose
print("\n", "-" * 20, "\nValidating configuration...\n")
def str_to_bool(val: str) -> bool | None:
"""Convert a string to boolean, converting "True" and "true" to True, same for False
Args:
val: The value to try to convert
Returns:
Returns either a boolean if conversion was successful, or None if not a boolean
"""
return {"True": True, "true": True, "False": False, "false": False}.get(val, None)
def read_config(
key_0: str,
key_1: str,
default: str,
valid_entries: List[str] = [],
type_to_validate: str = "",
) -> str:
"""Read the configuration, report potential configuration issues and validate each entry
Args:
key_0: The first key (top level)
key_1: The second key (where the actual key-value pair is)
default: The default value to return if the check fails
valid_entries: [Optiona] The entries that are valid ones to check against
type_to_validate: [Optional] Data type to validate
Returns:
[TODO:return]
"""
# Try loading the keys
tmp = {}
try:
tmp = config[key_0]
except KeyError:
print_config_error(key_0, key_1, "", default, "unknown", index=1)
return default
value = ""
try:
value = tmp[key_1]
except KeyError:
print_config_error(key_0, key_1, "", default, "unknown")
return default
if len(value) == 0:
print_config_error(key_0, key_1, value, default, "not_empty")
# Validate input
if type_to_validate != "":
# Need to validate
if type_to_validate == "int":
try:
int(value)
except ValueError:
print_config_error(key_0, key_1, value, default, "int")
return default
if type_to_validate == "float":
try:
float(value)
except ValueError:
print_config_error(key_0, key_1, value, default, "float")
return default
if type_to_validate == "bool":
if str_to_bool(value) == None:
print_config_error(key_0, key_1, value, default, "bool")
return default
if len(valid_entries) > 0:
# Need to validate the names
try:
valid_entries.index(value)
except ValueError:
print_config_error(
key_0, key_1, value, default, "oneof", valid_entries=valid_entries
)
return default
return value
def print_config_error(
key_0: str,
key_1: str,
value: str,
default: str,
expected: str,
valid_entries: List[str] = [],
msg: str = "",
index: int = 1,
):
"""Print configuration errors to the shell
Args:
key_0: The first key (top level)
key_1: The second key (where the actual value is to be found)
expected: The data type expected. If unknown key, set to "unknown" and set index; If should be one of, use "oneof" and set valid_entries list
msg: The message to print
index: The index in the chain (i.e. if key_0 or key_1)
"""
if not is_verbose:
return
print(f" ==> Using default setting ({default}) for {key_0}.{key_1}")
if expected == "unknown":
# The field was unknown
print(f' -> Unknown field "{key_0 if index == 0 else key_1}"')
elif expected == "oneof":
print(
f' -> Invalid name "{value}". Has to be one of', ", ".join(valid_entries)
)
elif expected == "not_empty":
print(" -> Property is unexpectedly None")
elif expected == "bool":
print(f' -> Boolean property expected, but instead found "{value}".')
else:
print(f" -> Expected a config option of type {expected}.")
if msg != "":
print(msg)