Lightweight validation for Python mappings and JSON-like documents.
Dictify provides standalone field validation and annotation-first Model classes for dict-shaped data. It keeps mapping access and attribute access together, validates assignments, supports strict or permissive unknown-key handling, and converts models back to plain Python data.
- Python
3.11+ Field(...)for defaults, required fields, and validatorsModelfor mapping-shaped schemasdict(model)for shallow conversion,model.dict()for recursive conversion- Inspectable model signatures for CLI/data-binding tools such as Cyclopts
pip install dictify
from datetime import UTC, datetime from typing import Annotated from dictify import Field, Model class Note(Model): title: Annotated[ str, Field(required=True).verify( lambda value: len(value) <= 300, "Title must be 300 characters or fewer", ), ] content: Annotated[str, Field()] timestamp: Annotated[datetime, Field(default=lambda: datetime.now(UTC))] note = Note(title="Dictify", content="dictify is easy") note.content = "Updated content" note["content"] = "Updated again" assert note["content"] == "Updated again" assert isinstance(note.dict()["timestamp"], datetime)
Model is strict by default. Pass _strict=False to keep undeclared keys as extra model data:
note = Note({"title": "Dictify"}, _strict=False) note.category = "docs" assert note["category"] == "docs"
Standalone fields work without a model:
email = Field(required=True).instance(str).match(r".+@.+") email.value = "[email protected]"
Dictify ships with an optional packaged AI skill installer:
dictify ai-skill-install
Repository-local maintenance commands live under dev/cli:
uv run python -m dev.cli --help uv run python -m dev.cli release-check
See dev/README.md for the command summary and release workflow.