goodconf
goodconf copied to clipboard
Generate config with subclasses
Hi and thanks for this project! I am slowly migrating my configuration management to this wonderful library.
I would like to generate a yaml
or toml
configuration file, but I am having trouble on how to do it using the initial
callable function on a nested class.
Here is a minimal example:
class AppConfig(GoodConf):
"Main configuration file"
class AppDaemon(BaseModel):
"Configuration class for AppDaemon"
latitude: float = 0
longitude: float = 0
elevation: float = 30
time_zone: str = "Europe/Berlin"
appdaemon: AppDaemon = Field(description="AppDaemon", initial=lambda:AppConfig.AppDaemon())
config = AppConfig()
toml_config = config.generate_toml()
I am trying to obtain an output similar to the following:
[appdaemon]
latitude = 0
longitude = 0
elevation = 30
time_zone = "Europe/Berlin"
However I obtain the following error:
../../.pyenv/versions/3.10.8-debug/envs/appdaemon/lib/python3.10/site-packages/goodconf/__init__.py:197: in generate_toml
toml_str = tomlkit.dumps(cls.get_initial(**override))
../../.pyenv/versions/3.10.8-debug/envs/appdaemon/lib/python3.10/site-packages/tomlkit/api.py:51: in dumps
data = item(dict(data), _sort_keys=sort_keys)
../../.pyenv/versions/3.10.8-debug/envs/appdaemon/lib/python3.10/site-packages/tomlkit/items.py:181: in item
val[k] = item(v, _parent=val, _sort_keys=_sort_keys)
ValueError: Invalid type <class 'appdaemon.config.AppConfig.AppDaemon'>
It seems to me that the toml serialization can only handle basic Python types?
The lack of complex types is somewhat intentional to keep the library simple and support importing anything as an environment variable.
Is the goal just to convert yaml from toml? If so, I'd recommend a purpose built tool such as yj.
If you also want to model these in the config, instead of using complex types, I would consider functionality that let you read a config from a specific key prefix in the file. This could work similar to the env_prefix
provided by the BaseSettings
class.
That would support your use case by allowing you to define multiple GoodConf
classes, each with their own key prefix to load from.
Sorry my bad, I made a typo. I meant I was trying to use both yaml
and toml
config files as sources, a feature that this library readily provides.
My question originates from the fact that GoodConf
already loads yaml
or toml
files with complex structures, such as the following:
class AppConfig(GoodConf):
class InnerConfig(BaseModel):
value: str
inner: InnerConfig
class Config:
default_files = ["myproject.yaml", "myproject.toml"]
config = AppConfig()
config.load()
print(config.inner.value)
inner:
value: "test"
[inner]
a = "test"
I also know that for the env variables the only supported format is a (quite ugly) JSON string, as the documentation of pydantic demonstrates.
So my doubt originates from the fact that only the logic implemented in generating the yaml
and toml
files is lacking this ability, since the rest of the stack seems to be ready for it.
Thanks anyway for you comment. Do you suggest to hook into the customise_sources
method to read only the specific key instead of the whole file?