Interactive wizard-style CLI for configuring Pydantic v2 models, with YAML serialization.
Project description
pydantic-wizard
Interactive wizard-style CLI for configuring Pydantic v2 models, with YAML serialization.
Point it at any BaseModel subclass and it will walk you through every field — with type-aware prompts, constraint validation, and nested model support — then save the result as a clean YAML file.
Features
- Zero boilerplate — works with any Pydantic v2
BaseModel, no registration needed - Type-aware prompts — booleans get yes/no, enums get dropdowns, nested models recurse automatically
- Constraint enforcement — respects
ge,le,gt,ltand other Pydantic field validators - 15+ built-in type handlers — scalars,
Decimal,Enum,Literal,datetime,Optional,list,set,dict,Union, nested models - YAML round-trip — serialize with metadata, load back, edit, and re-save
- Interactive validation — on error, re-prompts only the failing fields
- Extensible — register custom
TypeHandlerimplementations for domain-specific types - Rich terminal output — field panels, summary tables, and colored messages via Rich
Installation
pip install pydantic-wizard
Or with uv:
uv add pydantic-wizard
Quick Start
Define a model
# myapp/config.py
from decimal import Decimal
from pydantic import BaseModel, Field
class DatabaseConfig(BaseModel):
host: str = Field(description="Database hostname")
port: int = Field(default=5432, ge=1, le=65535)
name: str = Field(description="Database name")
pool_size: int = Field(default=10, ge=1)
timeout: Decimal = Field(default=Decimal("30.0"), ge=0)
ssl_enabled: bool = Field(default=True)
Run the wizard from the CLI
pydantic-wizard new myapp.config.DatabaseConfig -o db.yaml
The wizard will prompt you for each field with type-appropriate inputs, validate the result, and save to db.yaml.
Or use it programmatically
from pydantic_wizard import prompt_model, serialize_to_yaml, validate_and_fix
from myapp.config import DatabaseConfig
from pathlib import Path
# Interactive prompt for all fields
data = prompt_model(DatabaseConfig)
# Validate (re-prompts on errors)
instance = validate_and_fix(DatabaseConfig, data)
# Save to YAML
serialize_to_yaml(data, DatabaseConfig, Path("db.yaml"), model_name="database")
CLI Commands
new — Create a configuration
pydantic-wizard new <MODEL_FQN> [--output, -o PATH]
Walks through every field interactively, validates, and saves to YAML.
edit — Edit an existing configuration
pydantic-wizard edit <CONFIG_FILE> [--output, -o PATH]
Loads an existing YAML file and re-runs the wizard with current values as defaults.
validate — Validate a configuration
pydantic-wizard validate <CONFIG_FILE> [--model, -m FQN]
Validates a YAML file against its Pydantic model. The model class is resolved from YAML metadata or the --model flag.
show-schema — Show model schema
pydantic-wizard show-schema <MODEL_FQN>
Displays a formatted table of all fields, types, defaults, and descriptions.
Supported Types
| Category | Types |
|---|---|
| Scalars | str, int, float, bool, Decimal |
| Enums & Literals | Enum subclasses, Literal["a", "b", "c"] |
| Date & Time | datetime, time, timedelta |
| Optional | T | None, Optional[T] |
| Collections | list[T], set[T], dict[K, V] |
| Unions | A | B | C (type selection prompt) |
| Nested Models | Any BaseModel subclass (recursive prompting) |
Programmatic API
Introspection
from pydantic_wizard import introspect_model, FieldSpec
specs: list[FieldSpec] = introspect_model(DatabaseConfig)
for spec in specs:
print(f"{spec.name}: {spec.inner_type}, required={spec.is_required}")
Custom Type Handlers
Register custom handlers for domain-specific types:
from pydantic_wizard import TypeHandlerRegistry, prompt_model
from pydantic_wizard.type_handlers import TypeHandler
class MoneyHandler:
def can_handle(self, spec):
return spec.inner_type is Money
def prompt(self, spec, default=None):
raw = questionary.text(f" {spec.name} (e.g. 100.00 USD):").ask()
return Money.parse(raw)
def serialize(self, value):
return str(value)
def deserialize(self, raw, spec):
return Money.parse(raw)
# Use the custom registry
registry = TypeHandlerRegistry()
registry.register(MoneyHandler()) # inserted at front, takes priority
data = prompt_model(MyConfig, registry=registry)
YAML Output Format
Generated YAML files include metadata for round-trip support:
_metadata:
model_type: DatabaseConfig
configuration_class: myapp.config.DatabaseConfig
version: 0.1.0
configuration:
host: localhost
port: 5432
name: mydb
pool_size: 10
timeout: "30.0"
ssl_enabled: true
- Decimals are serialized as quoted strings to preserve precision
- Enums are serialized as their
.value - Sets are serialized as sorted lists
- Datetimes use ISO 8601 format
License
MIT
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file pydantic_wizard-0.1.0.tar.gz.
File metadata
- Download URL: pydantic_wizard-0.1.0.tar.gz
- Upload date:
- Size: 19.5 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: uv/0.9.26 {"installer":{"name":"uv","version":"0.9.26","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"macOS","version":null,"id":null,"libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
41955387b1bcb8cf2d6cd6d73203ab56b9e36e58cd21b20e0961d86d13da32a0
|
|
| MD5 |
934f32ad1a25339d77debf1998147f5a
|
|
| BLAKE2b-256 |
b28c483b6d0ecb3c6e7bc5f7db106cb7cd83508d8975f179c4a95ea804938765
|
File details
Details for the file pydantic_wizard-0.1.0-py3-none-any.whl.
File metadata
- Download URL: pydantic_wizard-0.1.0-py3-none-any.whl
- Upload date:
- Size: 17.8 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: uv/0.9.26 {"installer":{"name":"uv","version":"0.9.26","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"macOS","version":null,"id":null,"libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
d92075ca4408134a03a8ab5e44b2e7c656f998219b23ba80c2e02f76119dcd83
|
|
| MD5 |
9185777f9890ebcb1a5661fd82f036f3
|
|
| BLAKE2b-256 |
608f5796005b83ce73c0dc4eb079d2dd4a7e7c303942b58aa321410a4b4ffe1a
|