Skip to content

Zentiph/ironclad

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

129 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

ironclad

ironclad helps developers write defensive, self-documenting Python code.

It enforces parameter types, constrains values with predicates or enums, and raises precise errors on violation—keeping interfaces explicit and code clean. Simple, composable guards harden functions and classes with correctness and security, with minimal overhead and maximum readability.

GitHub License Contributors
GitHub commit activity Last Commit
Code Style: Ruff Linter: Ruff

Features

  • Strict type checks: Fail fast on mismatches with clear TypeErrors.
  • Value constraints: Allowlists, enums, ranges, and custom predicates.
  • Composable guards: Combine checks for rich, readable contracts.
  • Low-boilerplate API: Keep validation close to the signature, not scattered.
  • Security-minded: Reduce attack surface from unexpected inputs.

Installation

You can install ironclad in one of two ways:

  1. Install via pip:
pip install ironclad
  1. Clone this repository:
git clone https://github.com/Zentiph/ironclad

Quick Start

Importing the library:

>>> import ironclad as ic

Ensuring strict type enforcements on functions:

>>> # enforcing types with instance/type spec checks
>>> @ic.enforce_types(price=float, tax_rate=float)
... def add_sales_tax(price, tax_rate):
...     return price * (1 + tax_rate)
...
>>> add_sales_tax(50.0, 0.08)
54.0
>>> add_sales_tax(50.0, "0.08")
TypeError: add_sales_tax(): 'tax_rate' expected 'float', got 'str' with value '0.08'
>>>
>>> # enforcing types with type annotations
>>> @ic.enforce_annotations()
... def get_even(l: list[int]) -> list[int]:
...     return [e for e in l if e % 2 == 0]
...
>>> get_even([1, 2, 3])
[2]
>>> get_even([1.0, 2.0, 3.0])
TypeError: get_even(): 'l' expected 'list[int]', got 'list' with value [1.0, 2.0, 3.0]

Creating type-enforced runtime overloads:

>>> @ic.runtime_overload
... def describe(x: int):
...     return f"int: {x}"
...
>>> @describe.overload
... def _(x: str):
...     return f"str: '{x}'"
...
>>> describe(1)
'int: 1'
>>> describe("hi")
"str: 'hi'"
>>> describe(2.3)
InvalidOverloadError: No overload of describe() matches (float). Candidates: describe(x: int) | describe(x: str)

Creating predicates

>>> is_pos = ic.predicates.Predicate[int](
...     lambda x: x > 0, "is positive"
... )
>>> is_pos(4)
True
>>> is_pos(-1)
False

Documentation

ironclad's documentation is deployed on GitHub Pages.

Contributions

See the contributing page.

License

See the license page.

About

ironclad helps developers write defensive, self-documenting Python code.

Topics

Resources

License

Contributing

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors

Languages