"""
Configuration
-------------
"""
import typing
[docs]class ConfigAssignException(Exception):
""" An error while writing a config value """
pass
[docs]class InvalidConfigException(Exception):
""" The configuration provided is not valid for this test """
pass
[docs]class Config(dict):
"""
A TBot configuration
Access configuaration items by using a ``.`` separated key-path, eg::
hooks = cfg["uboot.test.hooks"]
By default, this raises an exception if the value was not found. You can
supply a default value that will be returned if the value was not found
instead::
has_venv = cfg["uboot.test.has_venv", True]
The configuration is available as ``tb.config`` in all testcases.
"""
def __getitem__(
self, keys: typing.Union[str, typing.Tuple[str, typing.Any]]
) -> typing.Any:
if isinstance(keys, str):
key = keys
else:
key = keys[0]
try:
key_path = key.split(".")
cfg = self
for key_segment in key_path[:-1]:
try:
cfg = cfg.__getitem__(key_segment)
except KeyError:
new_cfg = Config()
cfg.__setitem__(key_segment, new_cfg)
cfg = new_cfg
if not isinstance(cfg, Config):
raise KeyError(f"{key_segment} is not a config subdir")
return super(Config, cfg).__getitem__(key_path[-1])
except KeyError as key_error:
if isinstance(keys, str):
key_error.args = (key,)
raise
return keys[1]
def __setitem__(self, key: str, value: typing.Any) -> None:
if "." in key:
key_path = key.split(".")
cfg = self
for key_segment in key_path[:-1]:
try:
cfg = super(Config, cfg).__getitem__(key_segment)
except KeyError:
new_cfg = Config()
super(Config, cfg).__setitem__(key_segment, new_cfg)
cfg = new_cfg
if not isinstance(cfg, Config):
raise KeyError(f"{key_segment} is not a config subdir")
cfg.__setitem__(key_path[-1], value)
else:
if isinstance(value, dict):
try:
cfg = super().__getitem__(key)
except KeyError:
cfg = Config()
super().__setitem__(key, cfg)
if not isinstance(cfg, Config):
raise ConfigAssignException(
"Trying to overwrite a value with a subtree"
)
for inner_key, inner_value in value.items():
cfg.__setitem__(inner_key, inner_value)
else:
if key in self and isinstance(super().__getitem__(key), Config):
# We are trying to overwrite a subdir, this should not happen
raise ConfigAssignException(
f"Trying to overwrite a subdir: '{key}'"
)
else:
super().__setitem__(key, value)
def get(self, _key: str, _default: typing.Any = None) -> None:
raise Exception("The get method has been removed, please use [indexing]")