Config
This module provides a base class for configs that can be loaded from
files, environment variables or command line arguments (via yuio.app
).
Derive your config from the Config
base class. Inside of its body,
define config fields using type annotations, just like dataclasses
:
class AppConfig(Config):
#: trained model to execute
model: pathlib.Path
#: input data for the model
data: pathlib.Path
#: enable or disable gpu
use_gpu: bool = True
Then use config’s constructors and the update()
method
to load it from various sources:
# Load config from a file.
config = config.load_from_json_file('~/.my_app_cfg.json')
# Update config with values from env.
config.update(AppConfig.load_from_env())
Config base class
- class yuio.config.Config(*args, **kwargs)[source]
Base class for configs.
Pass keyword args to set fields, or pass another config to copy it:
Config(config1, config2, ..., field1=value1, ...)
Upon creation, all fields that aren’t explicitly initialized and don’t have defaults are considered missing. Accessing them will raise
AttributeError
.- update(other: _Self | Dict[str, Any], /)[source]
Update fields in this config with fields from another config.
This function is similar to
dict.update()
.Nested configs are updated recursively.
- classmethod load_from_json_file(path: str | Path, /, *, ignore_unknown_fields: bool = False, ignore_missing_file: bool = False) _Self [source]
Load config from a
.json
file.
- classmethod load_from_yaml_file(path: str | Path, /, *, ignore_unknown_fields: bool = False, ignore_missing_file: bool = False) _Self [source]
Load config from a
.yaml
file.This requires PyYaml package to be installed.
- classmethod load_from_toml_file(path: str | Path, /, *, ignore_unknown_fields: bool = False, ignore_missing_file: bool = False) _Self [source]
Load config from a
.toml
file.
- classmethod load_from_parsed_file(parsed: Dict[str, object], /, *, ignore_unknown_fields: bool = False) _Self [source]
Load config from parsed config file.
This method takes a dict with arbitrary values that you’d get from parsing type-rich configs such as yaml or json.
For example:
with open('conf.yaml') as file: config = Config.load_from_parsed_file(yaml.load(file))
Advanced field configuration
By default, Config
infers names for env variables and flags,
appropriate parsers, and other things from field’s name, type hint, and comments.
If you need to override them, theres the field()
function:
- yuio.config.field(default: ~typing.Any = _Placeholders.MISSING, *, parser: ~yuio.parse.Parser[~typing.Any] | None = None, help: str | ~typing.Literal[<disabled>] | None = None, env: str | ~typing.Literal[<disabled>] | None = None, flags: str | ~typing.List[str] | ~typing.Literal[<positional>] | ~typing.Literal[<disabled>] | None = None, completer: ~yuio.complete.Completer | None = None) Any [source]
Field descriptor, used for additional configuration of fields.
- Parameters:
default – default value for config field, used if field is missing from config.
parser – parser that will be used to parse env vars, configs and CLI arguments.
help –
Help message that will be used in CLI argument description.
Pass
DISABLED
to remove this field from CLI help.By default, help message is inferred from comments right above the field definition (comments must start with
#:
).Help messages are formatted using Markdown (see
yuio.md
).env –
Name of environment variable that will be used for this field.
Pass
DISABLED
to disable loading this field form environment variable.Pass an empty string to disable prefixing nested config variables.
flags –
List of names (or a single name) of CLI flags that will be used for this field.
This setting is used with
yuio.app
to configure CLI arguments parsers.Pass
DISABLED
to disable loading this field form CLI arguments.Pass
POSITIONAL
to make this argument positional (only in apps, seeyuio.app
).Pass an empty string to disable prefixing nested config flags.
completer –
completer that will be used for autocompletion in CLI.
This setting is used with
yuio.app
to configure CLI arguments parsers.
- yuio.DISABLED: Literal[<disabled>] = _Placeholders.DISABLED
Indicates that some functionality is disabled.
- yuio.MISSING: Literal[<missing>] = _Placeholders.MISSING
Indicates that some value is missing.
- yuio.POSITIONAL: Literal[<positional>] = _Placeholders.POSITIONAL
Used with
field()
to enable positional arguments.
There is also a helper for inlining nested configs:
Nesting configs
You can nest configs to achieve modularity:
class ExecutorConfig(Config):
#: number of threads to use
threads: int
#: enable or disable gpu
use_gpu: bool = True
class AppConfig(Config):
#: executor parameters
executor: ExecutorConfig
#: trained model to execute
model: pathlib.Path
To initialise a nested config, pass either an instance of if or a dict with its variables to the config’s constructor:
# The following lines are equivalent:
config = AppConfig(executor={'threads': 16})
config = AppConfig(executor=ExecutorConfig(threads=16))
Parsing environment variables
You can load config from environment through load_from_env()
.
Names of environment variables are just capitalized field names.
Use the field()
function to override them:
class KillCmdConfig(Config):
# Will be loaded from `SIGNAL`.
signal: int
# Will be loaded from `PROCESS_ID`.
pid: int = field(env='PROCESS_ID')
In nested configs, environment variable names are prefixed with name of a field that contains the nested config:
class BigConfig(Config):
# `kill_cmd.signal` will be loaded from `KILL_CMD_SIGNAL`.
kill_cmd: KillCmdConfig
# `copy_cmd_2.signal` will be loaded from `KILL_SIGNAL`.
kill_cmd_2: KillCmdConfig = field(env='KILL')
# `kill_cmd_3.signal` will be loaded from `SIGNAL`.
kill_cmd_3: KillCmdConfig = field(env='')
You can also disable loading a field from an environment altogether:
class Config(Config):
# Will not be loaded from env.
pid: int = field(env=yuio.DISABLED)
To prefix all variable names with some string, pass the prefix parameter
to the load_from_env()
function:
# config.kill_cmd.field will be loaded
# from `MY_APP_KILL_CMD_SIGNAL`
config = BigConfig.load_from_env('MY_APP')
Parsing config files
You can load config from structured config files, such as json, yaml or toml:
class ExecutorConfig(Config):
threads: int
use_gpu: bool = True
class AppConfig(Config):
executor: ExecutorConfig
model: pathlib.Path
config = AppConfig.load_from_json_file('~/.my_app_cfg.json')
In this example, contents of the above config would be:
{
"executor": {
"threads": 16,
"use_gpu": true
},
"model": "/path/to/model"
}
Note that, unlike with environment variables, there is no way to inline nested configs.