Install & Compatibility
Where this runs
tested against v0.2.1 · pip install
no network on importno background threads
Install × environment matrix
Each cell = how many times install + import succeeded across repeated harness runs. Partial = flaky.
glibc = Debian/Ubuntu slim · musl = Alpine Linux
muslpy 3.10–3.920 runs
installs and imports cleanly · install 0.0s · import 0.092s · 19.3MB
glibcpy 3.10–3.920 runs
installs and imports cleanly · install 1.8s · import 0.077s · 20MB
17MB installed
● package 17MB
Code
Verified usage
Verified import paths — ran on the pinned version, not inferred.
generate_options
✓ from msgspec_click import generate_options
Struct
✓ from msgspec import Struct
Used to define the data types that msgspec-click converts into Click options.
Meta
✓ from msgspec import Meta
Used within msgspec.Struct fields for custom Click option configuration.
This example demonstrates how to define a `msgspec.Struct` with `Annotated` and `msgspec.Meta` to customize Click options like help text, short flags, prompts, and type handling. The `generate_options` function automatically creates Click options from the `Connection` struct, which are then added to a Click command. The input is then converted back to the `Connection` struct using `msgspec.convert` for validation and type-safe access.
from __future__ import annotations
from typing import Annotated
import click
from msgspec import Meta, Struct, convert
from msgspec_click import generate_options
class Connection(Struct):
user: Annotated[
str,
Meta(extra={'help': 'The user\'s name', 'params': ['-u', '--user']})
] = ""
password: Annotated[
str,
Meta(extra={
'help': 'The user\'s password',
'params': ['-p', '--pass'],
'prompt': True,
'hide_input': True,
'confirmation_prompt': True,
})
] = ""
headers: Annotated[list[str], Meta(extra={'params': ['-H']})] = []
timeout: float = 10.0
allow_insecure: bool = False
@click.command()
def command(**kwargs) -> None:
connection = convert(kwargs, Connection)
print(connection)
command.params.extend(generate_options(Connection))
if __name__ == "__main__":
# To run this, save as script.py and then execute:
# python script.py --user alice -H "Key: Value" --pass
# (the --pass will prompt for password)
command()
Debug
Known issues
gotchaType annotations used within `msgspec.Struct` (e.g., `list[str]`, `str | None`) must be compatible with your Python runtime version. Using modern syntax like `list[str]` (Python 3.9+) or `str | None` (Python 3.10+) on older Python versions will result in runtime errors, even with `from __future__ import annotations`.fixEnsure your Python environment meets the minimum version required for the type annotation syntax you are using. For broader compatibility, use `typing.List[str]` and `typing.Optional[str]` on Python < 3.9 and < 3.10 respectively.
affects: All versions
breakingmsgspec versions (the underlying library) may introduce breaking changes to `msgspec.Struct` definitions (e.g., changes to `UNSET`/`NODEFAULT`, parameter ordering rules, or inheritance). These changes, while not directly in `msgspec-click`, can cause errors in your `msgspec.Struct` definitions which `msgspec-click` depends on.fixConsult the `msgspec` changelog (e.g., for `v0.23.0` and later) when upgrading `msgspec` to adapt your `msgspec.Struct` definitions if you encounter errors like `ValidationError` or `TypeError` related to struct initialization. For example, `msgspec.UNSET` was replaced by `msgspec.NODEFAULT`.
affects: msgspec versions > 0.23 (check msgspec changelog)
gotchaCustomizing Click options requires understanding how `msgspec.Meta(extra={...})` maps to `click.Option` keyword arguments. Misconfigurations, especially with `params`, can lead to unexpected CLI behavior or unrecognized options.fixRefer to the `msgspec-click` documentation on 'How it works' and `Click`'s documentation for `click.Option` parameters. The `params` key in `extra` is special; it's passed as arguments to `click.Option`, while other `extra` keys are passed as keyword arguments.
affects: All versions
deprecatedThe `v0.1.0` release was the initial public release. While `dict` and `typing.TypedDict` support were added in `v0.2.0`, older versions do not provide this functionality, leading to unsupported type errors if used with these types.fixUpgrade to `msgspec-click` version `0.2.0` or higher to use `dict` and `typing.TypedDict` for generating Click options.
affects: <0.2.0
Errors
Common errors & fixes
TypeError: 'list' object is not subscriptable
Attempting to use new-style type annotations (e.g., `list[str]`, `dict[str, int]`) on Python versions older than 3.9. While `from __future__ import annotations` delays evaluation, it doesn't change runtime support.
fixUpgrade your Python interpreter to version 3.9 or newer. Alternatively, use old-style type annotations like `typing.List[str]` or `typing.Dict[str, int]` for compatibility with Python 3.8.
msgspec.ValidationError: Expected `int`, got `str` - at `$.field_name`
The input provided via the command line does not conform to the expected type defined in your `msgspec.Struct`. `msgspec` performs strict validation by default.
fixEnsure the command-line arguments match the types defined in your `msgspec.Struct`. For example, if a field is `int`, `--field 'abc'` will fail. Provide `--field 123` instead. Consider `strict=False` in `msgspec.convert` for laxer conversion if appropriate, but this is generally not recommended for robust CLI input.
Error: Got unexpected extra argument (some-value)
This Click error usually means an argument was passed that doesn't correspond to any defined option or argument. This can happen if a `msgspec.Meta` annotation incorrectly configures a Click option, especially if `params` are missing or wrong for a field.
fixReview the `msgspec.Meta(extra={'params': [...]})` definitions for the relevant `msgspec.Struct` fields. Ensure that the short (`-x`) and long (`--xyz`) parameters you expect are correctly listed in the `params` list. If `params` is not set, the field name becomes the `--field-name` option. Error: Missing option '--required-field'
A field in your `msgspec.Struct` is defined without a default value, making it a required field. `msgspec-click` then generates a Click option with `required=True`, but the user did not provide the option.
fixProvide the missing option on the command line. If the field should be optional, define a default value in your `msgspec.Struct` (e.g., `field: str = ""` or `field: str | None = None`).
Upgrade
Version history
0.2.1latest on PyPI · released Sep 24, 2024
Audit
Dependencies
clickrequiredCore dependency for building command-line interfaces.
msgspecrequiredCore dependency for defining data structures and schema validation.