Skip to main content

A minimalist, zero-coercion validation library for Python.

Project description

iron-monk logo

iron-monk

Business constraint validation for people who hate data mutation.

The fastest Pure-Python validator. 0 Dependencies. 100% Type-Safe.

PyPI version Python Versions CI/CD Coverage: 100% Zero Dependencies License


📖 Read the official documentation here: benesgarage.github.io/iron-monk

🤖 Using an AI coding agent? Point it at llms.txt for a single-fetch index of the public API, llms-ctx.txt for a token-trimmed essentials digest, or llms-full.txt for the concatenated full docs. Agents working inside your project will also pick up AGENTS.md automatically.


Installation

Install via your preferred package manager:

# Using pip
pip install iron-monk

# Using uv
uv add iron-monk

# Using poetry
poetry add iron-monk

iron-monk uses the monk namespace. Always import monk in your code.

Quickstart

from typing import Annotated
from monk import monk, validate
from monk.constraints import Email, Interval, Len

@monk
class User:
    # No base class, no magic. Just your data.
    email: Annotated[str, Email]
    age:   Annotated[int, Interval(ge=18)]
    tags:  list[Annotated[str, Len(min_len=2)]]   # auto per-element validation

user = User(email="not-an-email", age=12, tags=["a"])
validate(user)  # Aggregates ALL THREE errors. Never fails fast.

When validation fails, iron-monk returns every failure in one structured response:

from monk.exceptions import ValidationError

try:
    validate(user)
except ValidationError as e:
    print(e.errors)
    # [{'field': 'email', 'message': 'Must be a valid email address.', 'code': 'Email'},
    #  {'field': 'age',   'message': 'Must be greater than or equal to 18.', 'code': 'Interval'},
    #  {'field': 'tags[0]', 'message': 'Must have a minimum length of 2.',   'code': 'Len'}]

    print(e.flatten())          # → list[str] for logs
    print(e.to_rfc7807())       # → RFC 7807 problem-detail dict for HTTP APIs

Custom constraints in 3 lines

from monk import constraint

@constraint
class DivisibleBy:
    divisor: int

    def validate(self, value: int) -> None:
        if value % self.divisor != 0:
            raise ValueError(f"Must be divisible by {self.divisor}.")

The Toolkit

A comprehensive suite of 60+ built-in constraints — including the kind most libraries punt on:

  • CSV — validate comma-separated strings in place, no list allocation
  • Cron — POSIX and AWS EventBridge scheduling strings
  • Hash / CreditCard / ISBN — checksum-verified identifiers, zero third-party deps
  • Ref + When / Switch — declarative cross-field validation that resolves at runtime
  • PATCH semanticsvalidate_dict(payload, Schema, partial=True) for incremental updates
  • Not / AnyOf / AllOf — invert and compose any constraint into richer rules

Plus the usual suspects (Email, URL, UUID, JWT, Slug, IPAddress, …) and string/numeric/datetime/path guards.

👉 Browse the full catalog →

Performance

iron-monk doesn't compromise on speed.

Tested on Python 3.14.4, primarily executing 100,000 simple primitive validations.

Metric iron-monk
(v0.26.0)
msgspec
(v0.21.1)
pydantic
(v2.13.4)
attrs
(v26.1.0)
marshmallow
(v4.3.0)
Package Size 0.10 MB 0.44 MB 5.88 MB 0.21 MB 0.17 MB
Cold Start 39.46ms 43.40ms 75.17ms 50.59ms 61.94ms
Object (100k) 0.158s 0.013s 0.054s 0.086s N/A
Dict (100k) 0.095s 0.058s 0.051s N/A 0.440s
Nested Dict (100k) 0.324s 0.071s 0.056s N/A 1.403s
Invalid Dict (100k) 0.235s 0.082s 0.075s N/A 1.017s
Sanitized Dict (100k) 0.104s 0.060s 0.050s N/A 0.429s
Partial Dict (100k) 0.065s N/A N/A N/A 0.267s
Union Dict (100k) 0.119s 0.056s 0.033s N/A N/A
Large List (10k × 1k items) 1.085s 0.056s 0.185s N/A N/A
Refs / Cross-Field (100k) 0.235s N/A N/A N/A N/A
Guard Access (1M attr reads) 0.257s (plain dataclass: 0.025s) N/A N/A N/A N/A
Function Call (100k) 0.171s N/A 0.050s N/A N/A

The Takeaway: Rust-backed libraries win on raw loop speed, but iron-monk is the most efficient choice for the modern cloud. Faster cold starts, zero dependencies, and the only entry on the board that natively handles PATCH updates, payload sanitization, and standalone constraint execution make it the best-in-class validator for AWS Lambda, serverless environments, and CI/CD pipelines where install time and the network round trip are the real bottlenecks.

👉 See our benchmarking methodology →

Why iron-monk

Most validation libraries do too much — they coerce, force you to inherit from a base class, and stop at the first error. iron-monk flips all three.

  • Zero coercion: "123" is never silently rewritten to 123. Wrong format = error.
  • Zero base classes: a @monk class is a plain dataclass. No BaseModel, no metaclass.
  • Zero fail-fast: every field is checked. Get every error in one shot.
  • Annotation is the schema: constraints live inside typing.Annotated. No model layer to keep in sync.

Integrations

iron-monk drops into any modern Python project. Battle-tested recipes for:

  • Strawberry GraphQLerrors-as-data for inputs, Maybe[T] integration
  • Starlette (ASGI) — RFC 7807 exception handlers, dict-mode and DTO-mode handlers
  • SQLAlchemy 2.0 / Tortoise ORM — DTO pattern at the API boundary
  • tyro — validate dataclass-driven CLIs
  • beartype — stack runtime type-checking under business constraints
  • App configuration — fail-fast environment-variable validation on boot

👉 See the recipes →

Feedback

PRs are not currently being accepted (see CONTRIBUTING.md), but bug reports, feature requests, and integration use cases are welcome.

👉 Open an issue →

License

MIT

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

iron_monk-0.31.0.tar.gz (68.4 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

iron_monk-0.31.0-py3-none-any.whl (37.5 kB view details)

Uploaded Python 3

File details

Details for the file iron_monk-0.31.0.tar.gz.

File metadata

  • Download URL: iron_monk-0.31.0.tar.gz
  • Upload date:
  • Size: 68.4 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for iron_monk-0.31.0.tar.gz
Algorithm Hash digest
SHA256 b6085aebcb44fc99c5c7ad851ac3b03633bc545e39dbf2db02d7db250dbcc6af
MD5 2730106fa59969d434a082ff6269d222
BLAKE2b-256 d9516f48602c1dd83a1e2b4d67dab44e2cf46d48f4943f15e04ad989a0c04a0f

See more details on using hashes here.

Provenance

The following attestation bundles were made for iron_monk-0.31.0.tar.gz:

Publisher: publish.yml on benesgarage/iron-monk

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file iron_monk-0.31.0-py3-none-any.whl.

File metadata

  • Download URL: iron_monk-0.31.0-py3-none-any.whl
  • Upload date:
  • Size: 37.5 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for iron_monk-0.31.0-py3-none-any.whl
Algorithm Hash digest
SHA256 7f73a350baf9923239b8f2e2b17ea13c6b1e1650b27d9b74d3b9ea171b462bbc
MD5 bef71329d93747ec6981bbfc50fa915f
BLAKE2b-256 f811c49da862749ac1ccee8d640ed6c9e6a32cfcf6654e43bab90990aa97eb6f

See more details on using hashes here.

Provenance

The following attestation bundles were made for iron_monk-0.31.0-py3-none-any.whl:

Publisher: publish.yml on benesgarage/iron-monk

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page