Skip to main content

Use Pydantic models as Click options

Project description

pydanclick

Release Build status codecov Commit activity License

Use Pydantic models as Click options.

Getting started

Install:

pip install pydanclick

Let's assume you have a Pydantic model:

class TrainingConfig(BaseModel):
    epochs: int
    lr: Annotated[float, Field(gt=0)] = 1e-4
    early_stopping: bool = False

Add all its fields as options in your Click command:

from pydanclick import from_pydantic

@click.command()
@from_pydantic("config", TrainingConfig)
def cli(config: TrainingConfig):
    """A simple example with a few parameters and default behavior."""
    # Here, we receive an already validated Pydantic object.
    click.echo(config.model_dump_json(indent=2))
~ python my_app.py --help
Usage: my_app.py [OPTIONS]

  A simple example with a few parameters and default behvior.

Options:
  --early-stopping / --no-early-stopping
  --lr FLOAT RANGE                [x>0]
  --epochs INTEGER                [required]
  --help                          Show this message and exit.
  • Find examples in the examples/ folder
  • See the API Reference for the full list of options

Features

Use native Click types

The following types are converted to native Click types:

Pydantic type Converted to
bool click.BOOL
str click.STRING
int click.INT
float click.FLOAT
conint, Annotated[int, Field(lt=..., ge=...) click.IntRange()
confloat, Annotated[float, Field(lt=..., ge=...) click.FloatRange()
pathlib.Path click.Path()
uuid.UUID click.UUID
datetime.datetime, datetime.date click.DateTime()
Literal click.Choice

More complex validators will be handled through Pydantic usual validation logic: once handled by Click, all arguments will be used to initialize Pydantic model.

Add multiple models

pydanclick.from_pydantic can be called several times with different models.

Use the prefix parameter to namespace the options from different models:

class Foo(BaseModel):
    a: str = ""
    b: str = ""

class Bar(BaseModel):
    x: int = 0
    y: int = 0

@click.command()
@from_pydantic("foo", Foo, prefix="foo")
@from_pydantic("bar", Bar, prefix="bar")
def cli(foo: Foo, bar: Bar):
    pass

will give

~ python cli.py
Usage: cli.py [OPTIONS]

Options:
  --foo-a TEXT
  --foo-b TEXT
  --bar-x INTEGER
  --bar-y INTEGER
  --help           Show this message and exit.

Add regular options and arguments

pydanclick can be used alongside regular options and arguments:

@click.command()
@click.argument("arg")
@click.option("--option")
@from_pydantic("foo", Foo)
def cli(arg, option, foo: Foo):
    pass

will give:

~ python cli.py
Usage: cli.py [OPTIONS] ARG

Options:
  --option TEXT
  --a TEXT
  --b TEXT
  --help         Show this message and exit.

Option documentation

Options added with pydanclick.from_pydantic will appear in the command help page.

Model docstring is used to document options automatically (requires griffe, e.g. pip install pydanclick[griffe]). Enabled by default, use parse_docstring=False to disable. Use docstring_tyle to choose between google, numpy and sphinx coding style.

pydanclick also supports the Field(description=...) syntax from Pydantic.

To specify custom documentation for a given field, use extra_options={"my_field": "my help string"}.

Provided griffe is installed, using:

class Baz(BaseModel):
    """Some demo model.

    Attributes:
        a: this comes from the docstring
    """

    a: int = 0
    b: Annotated[int, Field(description="this comes from the field description")] = 0
    c: int = 0


@click.command()
@from_pydantic("baz", Baz, extra_options={"c": {"help": "this comes from the `extra_options`"}})
def cli(baz: Baz):
    pass

will give:

~ python cli.py --help
Usage: cli.py [OPTIONS]

Options:
  --a INTEGER  this comes from the docstring
  --b INTEGER  this comes from the field description
  --c INTEGER  this comes from the `extra_options`
  --help       Show this message and exit.

Customize option names

Specify option names with prefix and short option names with shorten:

@click.command()
@from_pydantic("foo", Foo, rename={"a": "--alpha", "b": "--beta"}, shorten={"a": "-A", "b": "-B"})
def cli(foo: Foo):
    pass

will give:

~ python cli.py --help
Usage: cli.py [OPTIONS]

Options:
  -A, --alpha TEXT
  -B, --beta TEXT
  --help            Show this message and exit.

Pass extra parameters

Use extra_options to pass extra parameters to click.option for a given field.

API Reference

Functions:

  • from_pydantic – Decorator to add fields from a Pydantic model as options to a Click command.

pydanclick.from_pydantic

from_pydantic(__var, model, *, exclude=(), rename=None, shorten=None, prefix='', parse_docstring=True, docstring_style='google', extra_options=None)

Decorator to add fields from a Pydantic model as options to a Click command.

Example:

@click.command()
@pydanclick.from_pydantic("arg_name", SomePydanticModel)
def my_command(arg_name: SomePydanticModel):
    assert isinstance(arg_name, SomePydanticModel)  # True

Parameters:

  • __var (str) – name of the variable that will receive the Pydantic model in the decorated function
  • model (type[BaseModel]) – Pydantic model
  • exclude (Sequence[str]) – field names that won't be added to the command
  • rename (dict[str, str] | None) – a mapping from field names to command line option names (this will override any prefix). Option names must start with two dashes
  • shorten (dict[str, str] | None) – a mapping from field names to short command line option names. Option names must start with one dash
  • prefix (str) – a prefix to add to option names (without any dash)
  • parse_docstring (bool) – if True and griffe is installed, parse the docstring of the Pydantic model and pass argument documentation to the Click help option
  • docstring_style (str) – style of the docstring (google, numpy or sphinx). Ignored if parse_docstring is False
  • extra_options (dict[str, _ParameterKwargs] | None) – a mapping from field names to a dictionary of options passed to the click.option() function

Returns:

Contributing

Install the environment and the pre-commit hooks with

make install

Run tests with:

pytest

Limitations

pydanclick doesn't support (yet!):

  • Nested models
  • Container types (tuples, lists, dicts) or other complex types
  • Converting fields to arguments, instead of options
  • Some union types won't work
  • Python <3.11

Other missing features:

  • Reading model from file
  • Specifying all field-specific options directly in the Pydantic model (would allow easier re-use)
  • Most Click features should be supported out-of-the-box through the extra_options parameter. However, most of them aren't tested
  • Click and Pydantic both include validation logic. In particular, Click support custom ParamType, validation callbacks and BadParameter errors: it's not clear if we want to fully rely on Pydantic or on Click or on a mixture of both

Repository initiated with fpgmaas/cookiecutter-poetry.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

pydanclick-0.1.0.tar.gz (8.8 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

pydanclick-0.1.0-py3-none-any.whl (9.1 kB view details)

Uploaded Python 3

File details

Details for the file pydanclick-0.1.0.tar.gz.

File metadata

  • Download URL: pydanclick-0.1.0.tar.gz
  • Upload date:
  • Size: 8.8 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: poetry/1.7.1 CPython/3.11.8 Linux/6.2.0-1019-azure

File hashes

Hashes for pydanclick-0.1.0.tar.gz
Algorithm Hash digest
SHA256 3210c48164f99e9236f9021185f8c5a835677f1bbe37110014ee311fd29e1e36
MD5 a4c6099390823fe7353a1a05963707ce
BLAKE2b-256 c339b752fe5cd83277af36c7b175471788579f359a42eda53c6e04bb21d538bd

See more details on using hashes here.

File details

Details for the file pydanclick-0.1.0-py3-none-any.whl.

File metadata

  • Download URL: pydanclick-0.1.0-py3-none-any.whl
  • Upload date:
  • Size: 9.1 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: poetry/1.7.1 CPython/3.11.8 Linux/6.2.0-1019-azure

File hashes

Hashes for pydanclick-0.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 cb24fed618643c473d599b00e0d8f5242dddcf8e2d83466d44da1c29ee8d9c4d
MD5 055eb24692da4b9b308427a2479c8e4c
BLAKE2b-256 2396f749af6efa86228d604057d0add2d43723927e5242ea95784ccaae3d0a3c

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page