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.12+ 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 dictifyfrom 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 = "user@example.com"Dictify ships with an optional packaged AI skill installer:
dictify ai-skill-installRepository-local maintenance commands live under dev/cli:
uv run python -m dev.cli --help
uv run python -m dev.cli release-checkSee dev/README.md for the command summary and release workflow.