Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Generate config with subclasses #32

Open
mion00 opened this issue Mar 4, 2023 · 2 comments · May be fixed by #33
Open

Generate config with subclasses #32

mion00 opened this issue Mar 4, 2023 · 2 comments · May be fixed by #33
Labels
enhancement New feature or request question Further information is requested

Comments

@mion00
Copy link

mion00 commented Mar 4, 2023

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?

mion00 added a commit to mion00/goodconf that referenced this issue Mar 4, 2023
In function generate_toml recursively traverse the various input fields, generating TOML list and tables to contain nested classes and list of other elements, until a base type is found.

lincolnloop#32
@ipmb
Copy link
Member

ipmb commented Mar 4, 2023

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.

@ipmb ipmb added enhancement New feature or request question Further information is requested labels Mar 4, 2023
@mion00
Copy link
Author

mion00 commented Mar 4, 2023

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?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request question Further information is requested
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants