Skip to content

Nested Example

In this third example, our Pydantic model itself contains Pydantic models. Nested fields can be overridden from the command-line:

from typing import Literal

import click
from pydantic import BaseModel, Field

from pydanclick import from_pydantic


class Foo(BaseModel):
    """Foo.

    Attributes:
        a: first letter
        b: second letter
    """

    a: int = 1
    b: bool = True


class Baz(BaseModel):
    """Baz.

    Attributes:
        c: third letter
    """

    c: Literal["a", "b"] = "a"


class Bar(BaseModel):
    """Bar.

    Attributes:
        a: an argument
        b: another one
        baz: a third one
    """

    a: float = 0.1
    b: str = "b"
    baz: Baz = Field(default_factory=Baz)


class Obj(BaseModel):
    """Obj.

    Attributes:
        foo: foo attribute
        bar: bar attribute
    """

    foo: Foo = Field(default_factory=Foo)
    bar: Bar = Field(default_factory=Bar)


@click.command()
@from_pydantic("obj", Obj, rename={"bar.baz": "baz"})
def cli(obj: Obj):
    click.echo(obj.model_dump_json(indent=2))


if __name__ == "__main__":
    cli()
~ python examples/nested.py --help                                                                                                                               <aws:tooling>
Usage: nested.py [OPTIONS]

Options:
  --foo-a INTEGER       first letter
  --foo-b / --no-foo-b  second letter
  --bar-a FLOAT         an argument
  --bar-b TEXT          another one
  --baz-c [a|b]         third letter
  --help                Show this message and exit.

Some observations:

  • you can rename any field by using its dotted name (here, bar.baz)
  • same notation can be used for exclude, shorten, extra_options
  • when a field is renamed, all its subfields are renamed, too