edornd / argdantic

Typed command line interfaces with argparse and pydantic
MIT License
40 stars 4 forks source link

Dynamic sources not parsing nested fields correctly #59

Open edornd opened 2 weeks ago

edornd commented 2 weeks ago

With a configuration like this:

from typing import Optional

from pydantic import BaseModel

from argdantic import ArgParser
from argdantic.sources import YamlFileLoader, from_file

class LossConfig(BaseModel):
    factor: int = 2
    enforce_order: Optional[bool] = True
    order_factor: Optional[float] = 1

class ModuleConfig(BaseModel):
    loss: LossConfig = LossConfig()
    # loss: LossConfig = None

@from_file(loader=YamlFileLoader, required=False)
class Config(BaseModel):
    name: str = "default"
    module: ModuleConfig = ModuleConfig()

cli = ArgParser()

@cli.command()
def main(config: Config = Config()):
    print(config)

if __name__ == "__main__":
    cli()

The loss config should be updatable by file and cli. However, when passing arguments such as: --config config.yml --config.module.loss.order-factor 11, the CLI argument takes precedence over everything, also overriding fields that didn't change.

This is probably an issue due to how dict of values gets updated inside the source (does not work recursively).