provably.decorators¶
from provably import verified, runtime_checked
from provably.decorators import VerificationError, ContractViolationError
@verified¶
Prove a function's pre/post contract using Z3 at decoration time. Attaches a
ProofCertificate as fn.__proof__. No solver runs at call time. A thin
functools.wraps wrapper is applied; check_contracts=True adds runtime contract checks.
@verified(
pre=lambda a, b: b > 0,
post=lambda a, b, result: (result >= 0) & (result < b),
)
def modulo(a: int, b: int) -> int:
return a % b
modulo.__proof__.verified # True
str(modulo.__proof__) # "[Q.E.D.] modulo"
| Parameter | Type | Default | Description |
|---|---|---|---|
pre |
Callable \| None |
None |
Precondition. Same params as function. Use &/\|/~. |
post |
Callable \| None |
None |
Postcondition. Params + result (last arg). |
raise_on_failure |
bool |
False |
Raise VerificationError if proof fails. |
timeout_ms |
int \| None |
None |
Per-proof Z3 timeout. Overrides configure(). |
contracts |
dict \| None |
None |
Helper contracts for modular verification. |
check_contracts |
bool |
False |
Also enforce pre/post at runtime. |
Use & not and in pre/post lambdas
and short-circuits and silently drops conjuncts. See Contracts.
@runtime_checked¶
Check pre/post at every call using Python evaluation. No Z3 required.
@runtime_checked(
pre=lambda x: x >= 0,
post=lambda x, result: result >= 0,
)
def sqrt_approx(x: float) -> float:
return x ** 0.5
sqrt_approx(4.0) # 2.0
sqrt_approx(-1.0) # raises ContractViolationError
| Parameter | Type | Default | Description |
|---|---|---|---|
pre |
Callable \| None |
None |
Precondition. Evaluated with actual arguments. |
post |
Callable \| None |
None |
Postcondition. Arguments + result. |
raise_on_failure |
bool |
True |
Raise ContractViolationError. If False, log warning. |
VerificationError¶
Raised by @verified(raise_on_failure=True) when proof fails.
try:
@verified(raise_on_failure=True, post=lambda x, result: result > x)
def bad(x: int) -> int:
return x
except VerificationError as e:
e.certificate.counterexample # {'x': 0, '__return__': 0}
ContractViolationError¶
Raised by @runtime_checked (or @verified(check_contracts=True)) on violation.
class ContractViolationError(Exception):
kind: str # "pre" or "post"
func_name: str
args_: tuple
result: Any | None # set for "post" violations
provably.decorators ¶
The @verified decorator — proof-carrying Python functions.
Usage::
from provably import verified
from provably.types import Ge
from typing import Annotated
# Bare decorator — proves refinement type annotations
@verified
def double(x: Annotated[float, Ge(0)]) -> Annotated[float, Ge(0)]:
return x * 2
# With explicit pre/post contracts
@verified(
pre=lambda x, lo, hi: lo <= hi,
post=lambda x, lo, hi, result: (result >= lo) & (result <= hi),
)
def clamp(x: float, lo: float, hi: float) -> float:
if x < lo:
return lo
elif x > hi:
return hi
else:
return x
# Access proof certificate
clamp.__proof__ # ProofCertificate
# Runtime-only checking (no Z3 required)
@runtime_checked(
pre=lambda x: x >= 0,
post=lambda x, result: result >= 0,
)
def sqrt_approx(x: float) -> float:
return x ** 0.5
In pre/post lambdas for @verified, use & instead of 'and',
| instead of 'or', ~ instead of 'not'. Python's boolean operators cannot be overloaded and will not produce Z3 expressions.
Classes¶
ContractViolationError ¶
Bases: Exception
Raised by :func:runtime_checked when a contract is violated at runtime.
Attributes:
| Name | Type | Description |
|---|---|---|
kind |
|
|
args_ |
The positional arguments that triggered the violation. |
|
result |
The return value (only set when |
Source code in src/provably/decorators.py
VerificationError ¶
Bases: Exception
Raised when raise_on_failure=True and verification fails.
The failing :class:~provably.engine.ProofCertificate is available
as exc.certificate.
Source code in src/provably/decorators.py
Functions¶
runtime_checked ¶
runtime_checked(func: F | None = None, *, pre: Callable[..., Any] | None = None, post: Callable[..., Any] | None = None, raise_on_failure: bool = True) -> F | Callable[[F], F]
Decorator that checks pre/post contracts at runtime without Z3.
Unlike :func:verified, this decorator does not perform a static proof.
It simply evaluates the pre and post conditions on every actual call and
raises :class:ContractViolationError when one fails.
This is useful when:
- You want zero solver overhead at runtime.
- The function body uses constructs the translator does not support.
- You want defence-in-depth in addition to a static proof.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
func
|
F | None
|
The function (when used as bare |
None
|
pre
|
Callable[..., Any] | None
|
Precondition callable — takes the same arguments as func. Must return a truthy value when the precondition holds. |
None
|
post
|
Callable[..., Any] | None
|
Postcondition callable — takes |
None
|
raise_on_failure
|
bool
|
If |
True
|
Returns:
| Type | Description |
|---|---|
F | Callable[[F], F]
|
The wrapped function. Identical to the original at call sites |
F | Callable[[F], F]
|
when all contracts pass. |
Example::
@runtime_checked(
pre=lambda x: x >= 0,
post=lambda x, result: result >= 0,
)
def sqrt_approx(x: float) -> float:
return x ** 0.5
Source code in src/provably/decorators.py
verified ¶
verified(func: F | None = None, *, pre: Callable[..., Any] | None = None, post: Callable[..., Any] | None = None, raise_on_failure: bool | None = None, strict: bool | None = None, timeout_ms: int | None = None, contracts: dict[str, dict[str, Any]] | None = None, check_contracts: bool = False) -> F | Callable[[F], F]
Decorator that formally verifies a Python function using Z3.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
func
|
F | None
|
The function (when used as bare |
None
|
pre
|
Callable[..., Any] | None
|
Precondition lambda — takes the same arguments as func.
Use |
None
|
post
|
Callable[..., Any] | None
|
Postcondition lambda — takes |
None
|
raise_on_failure
|
bool | None
|
If |
None
|
strict
|
bool | None
|
Deprecated alias for raise_on_failure. Will be removed in a future version. |
None
|
timeout_ms
|
int | None
|
Z3 solver timeout in milliseconds. Defaults to the global setting (5000ms). |
None
|
contracts
|
dict[str, dict[str, Any]] | None
|
Pre/post contracts of functions called inside func, keyed by function name. Enables modular verification. |
None
|
check_contracts
|
bool
|
If |
False
|
Returns:
| Type | Description |
|---|---|
F | Callable[[F], F]
|
The original function, unchanged at runtime, with a |
F | Callable[[F], F]
|
class: |
F | Callable[[F], F]
|
|
The decorated function is wrapped in a thin functools.wraps
passthrough. No solver overhead at call time (unless
check_contracts=True, which adds runtime contract checks).
Async functions are not translated (Z3 does not support coroutine bodies).
They receive a SKIPPED certificate and the wrapper is a passthrough.