Skip to content

Example: Complex Types

Complex container types such as lists or dicts are supported: they must be passed as JSON strings, and will be parsed by Pydantic through the TypeAdapter.validate_json method. Consider the following Pydantic model:

from pathlib import Path
from typing import Dict, List, Literal, Tuple

import click
from pydantic import BaseModel, Field

from pydanclick import from_pydantic


class RunConfig(BaseModel):
    """Configure how to run your container.

    Attributes:
        image: image name
        mounts: how to mount data on your container, as triples `(mount_type, src, dst)`
        ports: port binding
    """

    image: str
    mounts: List[Tuple[Literal["bind", "volume", "tmpfs"], Path, Path]] = Field(default_factory=list)
    ports: Dict[int, int] = Field(default_factory=dict)


@click.command()
@from_pydantic("config", RunConfig)
def cli(config: RunConfig):
    """A fake Docker client."""
    # Here, we receive an already validated Pydantic object.
    click.echo(config.model_dump_json(indent=2))


if __name__ == "__main__":
    cli()

It can be ran with:

python examples/complex_types.py \
    --image foo \
    --mounts '[["tmpfs", "/foo/bar", "foo/"], ["bind", ".", "foo/"]]' \
    --ports '{"80":80, "8888":8888}'

Pay attention to single quotes versus double quotes: quotes are required around the JSON strings to prevent shell extension, and JSON strings must use double quotes.

Such types as marked as JSON STRING in the Click documentation:

~ python examples/complex_types.py --help                                                                                                                        <aws:tooling>
Usage: complex_types.py [OPTIONS]

  A fake Docker client.

Options:
  --image TEXT          image name  [required]
  --mounts JSON STRING  how to mount data on your container, as triples
                        `(mount_type, src, dst)`
  --ports JSON STRING   port binding
  --help                Show this message and exit.

As of now, Pydanclick doesn't provide a mechanism to override this.