typantic 0.2.0__tar.gz → 0.2.1__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {typantic-0.2.0 → typantic-0.2.1}/PKG-INFO +3 -2
- {typantic-0.2.0 → typantic-0.2.1}/README.md +2 -1
- {typantic-0.2.0 → typantic-0.2.1}/pyproject.toml +1 -1
- {typantic-0.2.0 → typantic-0.2.1}/src/typantic/_decorator.py +17 -9
- {typantic-0.2.0 → typantic-0.2.1}/src/typantic/__init__.py +0 -0
- {typantic-0.2.0 → typantic-0.2.1}/src/typantic/py.typed +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: typantic
|
|
3
|
-
Version: 0.2.
|
|
3
|
+
Version: 0.2.1
|
|
4
4
|
Summary: Auto-generate Typer CLI interfaces from Pydantic models.
|
|
5
5
|
Keywords: typer,pydantic,cli,validation
|
|
6
6
|
Author: Kilian Schnelle
|
|
@@ -99,7 +99,7 @@ $ python example.py --help
|
|
|
99
99
|
╭─ Options ────────────────────────────────────────────────────╮
|
|
100
100
|
│ * --output PATH Output directory. [required] │
|
|
101
101
|
│ --threshold FLOAT Detection threshold. [default: 0.5]│
|
|
102
|
-
│ --seed INTEGER Random seed.
|
|
102
|
+
│ --seed INTEGER Random seed. [default: (None)] │
|
|
103
103
|
│ --help Show this message and exit. │
|
|
104
104
|
╰──────────────────────────────────────────────────────────────╯
|
|
105
105
|
```
|
|
@@ -126,6 +126,7 @@ Your function receives the **validated model instance** — validators, `default
|
|
|
126
126
|
| `Field(default=...)` | Default value shown in `--help` |
|
|
127
127
|
| `Field(default_factory=...)` | Factory called once at decoration time |
|
|
128
128
|
| `int \| None` | Optional CLI option |
|
|
129
|
+
| `default=None` | Rendered as `[default: (None)]` |
|
|
129
130
|
| `list[Path]` | Variadic positional argument |
|
|
130
131
|
| `AfterValidator`, `BeforeValidator` | Run at call time via Pydantic |
|
|
131
132
|
|
|
@@ -75,7 +75,7 @@ $ python example.py --help
|
|
|
75
75
|
╭─ Options ────────────────────────────────────────────────────╮
|
|
76
76
|
│ * --output PATH Output directory. [required] │
|
|
77
77
|
│ --threshold FLOAT Detection threshold. [default: 0.5]│
|
|
78
|
-
│ --seed INTEGER Random seed.
|
|
78
|
+
│ --seed INTEGER Random seed. [default: (None)] │
|
|
79
79
|
│ --help Show this message and exit. │
|
|
80
80
|
╰──────────────────────────────────────────────────────────────╯
|
|
81
81
|
```
|
|
@@ -102,6 +102,7 @@ Your function receives the **validated model instance** — validators, `default
|
|
|
102
102
|
| `Field(default=...)` | Default value shown in `--help` |
|
|
103
103
|
| `Field(default_factory=...)` | Factory called once at decoration time |
|
|
104
104
|
| `int \| None` | Optional CLI option |
|
|
105
|
+
| `default=None` | Rendered as `[default: (None)]` |
|
|
105
106
|
| `list[Path]` | Variadic positional argument |
|
|
106
107
|
| `AfterValidator`, `BeforeValidator` | Run at call time via Pydantic |
|
|
107
108
|
|
|
@@ -93,6 +93,8 @@ def pydantic_to_typer(
|
|
|
93
93
|
- ``Field(default=...)`` -> Typer default value
|
|
94
94
|
- ``Field(default_factory=...)`` -> factory is called once at
|
|
95
95
|
decoration time to supply the Typer default
|
|
96
|
+
- a ``None`` default -> rendered as ``[default: (None)]`` in
|
|
97
|
+
``--help`` (Click would otherwise omit it entirely)
|
|
96
98
|
|
|
97
99
|
The decorated function receives the **validated** Pydantic model
|
|
98
100
|
instance, so all ``AfterValidator`` / ``BeforeValidator`` logic runs
|
|
@@ -134,6 +136,14 @@ def pydantic_to_typer(
|
|
|
134
136
|
base_type = _extract_base_type(resolved_hints[name])
|
|
135
137
|
help_text = field_info.description or ""
|
|
136
138
|
|
|
139
|
+
default: object
|
|
140
|
+
if field_info.is_required():
|
|
141
|
+
default = inspect.Parameter.empty
|
|
142
|
+
elif field_info.default_factory is not None:
|
|
143
|
+
default = field_info.default_factory() # type: ignore[call-arg]
|
|
144
|
+
else:
|
|
145
|
+
default = field_info.default
|
|
146
|
+
|
|
137
147
|
typer_meta: typer.models.ArgumentInfo | typer.models.OptionInfo
|
|
138
148
|
if field_info.kw_only is False:
|
|
139
149
|
typer_meta = typer.Argument(
|
|
@@ -142,19 +152,17 @@ def pydantic_to_typer(
|
|
|
142
152
|
)
|
|
143
153
|
else:
|
|
144
154
|
panel = _panel_for_field(model_cls, name) if subpanels else None
|
|
145
|
-
typer_meta = typer.Option(
|
|
155
|
+
typer_meta = typer.Option(
|
|
156
|
+
help=help_text,
|
|
157
|
+
rich_help_panel=panel,
|
|
158
|
+
# Click omits `None` defaults entirely; surface them as
|
|
159
|
+
# "[default: (None)]" so optional options are visibly so.
|
|
160
|
+
show_default="None" if default is None else True,
|
|
161
|
+
)
|
|
146
162
|
|
|
147
163
|
annotated = Annotated[base_type, typer_meta] # type: ignore[valid-type]
|
|
148
164
|
new_annotations[name] = annotated
|
|
149
165
|
|
|
150
|
-
default: object
|
|
151
|
-
if field_info.is_required():
|
|
152
|
-
default = inspect.Parameter.empty
|
|
153
|
-
elif field_info.default_factory is not None:
|
|
154
|
-
default = field_info.default_factory() # type: ignore[call-arg]
|
|
155
|
-
else:
|
|
156
|
-
default = field_info.default
|
|
157
|
-
|
|
158
166
|
new_params.append(
|
|
159
167
|
inspect.Parameter(
|
|
160
168
|
name,
|
|
File without changes
|
|
File without changes
|