mydantic is a small, dependency-light Python library for defining typed data models with validation and coercion. It provides a familiar, minimal API inspired by projects like pydantic while remaining intentionally lightweight for learning and small projects.
- Declarative models via
BaseModeland field descriptors - Built-in field types:
StringField,IntField,FloatField,BoolField,ListField,ModelField - Type coercion for common primitives (str, int, float, bool)
- Nested model parsing via
ModelField - Per-field validators (callables)
- Structured error reporting via
FieldErrorandValidationError
Define models using field descriptors. Fields are descriptors so they validate/coerce on assignment and during model initialization.
from product import BaseModel, StringField, IntField, ListField, ModelField
class Address(BaseModel):
street = StringField()
city = StringField()
class User(BaseModel):
name = StringField()
age = IntField()
address = ModelField(Address)
tags = ListField(item_type=str, default=[])
u = User(name="Manya", age="21", address={"street":"X", "city":"New Delhi"})
print(u.dict())
print(u.json(indent=2))Notes:
ModelFieldaccepts either an instance of the nested model or adictto parse into the nested model.ListField(item_type)will validate each list item and surface index-awareFieldErrors (e.g.field_name[2]).
Errors are represented by FieldError objects and aggregated as ValidationError when multiple field-level errors occur.
FieldError attributes:
field_name: name of the field (may include index or nested path)value: the value that failed validation/coercionexpected: expected type or shapemessage: human-readable messageoriginal_exception: optional underlying exception
Example handling:
try:
User(name=None)
except ValidationError as e:
print(str(e))
for fe in e.errors:
print(fe.to_dict())Primary exports (see product/__init__.py):
BaseModel— metaclass-driven base for declarative models. Key methods:__init__(**kwargs)— validate/assign fieldsparse_obj(obj: dict)— classmethod to parse a mappingdict()— produce a serializable dictjson(**kwargs)— JSON serialization conveniencecopy(**updates)— shallow copy with updates
- Field classes:
Field— base descriptorStringField,IntField,FloatField,BoolField— typed field descriptorsListField(item_type)— list of items with per-item validationModelField(model_class)— nested model field
- Errors:
FieldError,ValidationError
Explore the source files (product/fields.py, product/models.py, product/errors.py) for implementation details and additional behavior (coercion, validators, nested parsing, etc.).
- Fields try to coerce common primitive types (e.g.,
"123"->int). If coercion fails, aValidationErroris raised with aFieldErrorcause. - When nested
ValidationErrors occur (e.g., setting aModelFieldwith invalid nested data), errors are flattened and reported with appropriately prefixed field names. allow_nonecontrols whetherNoneis allowed for a field. If not allowed andNoneis provided, aValidationErroris raised.
Contributions are welcome. Suggested workflow:
- Open an issue describing the problem or enhancement.
- Create a branch for your change.
- Add tests (if applicable) and keep changes minimal and focused.
- Open a pull request and describe the change and rationale.
manyolo. :)
