User documentation
Developer documentation
PyContracts public API reference¶
This section provides a reference to PyContracts’ public interface.
- See API for specifying contracts for a more friendly discussion.
- See Language reference for a reference on the domain-specific language.
Decorating a function¶
-
contracts.
contract
(*args, **kwargs)[source]¶ Decorator for adding contracts to functions.
It is smart enough to support functions with variable number of arguments and keyword arguments.
There are three ways to specify the contracts. In order of precedence:
As arguments to this decorator. For example:
@contract(a='int,>0',b='list[N],N>0',returns='list[N]') def my_function(a, b): # ... pass
As annotations (supported only in Python 3):
@contract def my_function(a:'int,>0', b:'list[N],N>0') -> 'list[N]': # ... pass
Using
:type:
and:rtype:
tags in the function’s docstring:@contract def my_function(a, b):
-
contracts.
decorate
(function_, modify_docstring=True, **kwargs)¶ An explicit way to decorate a given function. The decorator
decorate()
calls this function internally.
Exceptions¶
Manually checking values¶
-
contracts.
check
(contract, object, desc=None, **context)[source]¶ Checks that
object
satisfies the contract described bycontract
.Parameters: - contract (str) – The contract string.
- object (
*
) – Any object. - desc (
None|str
) – An optional description of the error. If given, it is included in the error message.
-
contracts.
check_multiple
(couples, desc=None)[source]¶ Checks multiple couples of (contract, value) in the same context.
This means that the variables in each contract are shared with the others.
Parameters: - couples (
list[>0](tuple(str, *))
) – A list of tuple (contract, value) to check. - desc (
None|str
) – An optional description of the error. If given, it is included in the error message.
- couples (
-
contracts.
parse
(spec)¶ spec can be either a Contract, a type, or a contract string. In the latter case, the usual parsing takes place
-
contracts.
new_contract
(*args)[source]¶ Defines a new contract type. Used both as a decorator and as a function.
1) Use as a function. The first parameter must be a string. The second parameter can be either a string or a callable function.
new_contract('new_contract_name', 'list[N]') new_contract('new_contract_name', lambda x: isinstance(x, list) )
If it is a string, it is interpreted as contract expression; the given identifier will become an alias for that expression.
If it is a callable, it must accept one parameter, and either:
- return True or None, to signify it accepts.
- return False or raise ValueError or AssertionError, to signify it doesn’t.
If ValueError is raised, its message is used in the error.
2) Use as a decorator.
Or, it can be used as a decorator (without arguments). The function name is used as the identifier.
@new_contract def new_contract_name(x): return isinstance(x, list)
This function returns a
Contract
object. It might be useful to check right away if the declaration is what you meant, usingContract.check()
andContract.fail()
.Parameters: - identifier (str) – The identifier must be a string not already in use
(you cannot redefine
list
,tuple
, etc.). - condition (
type|callable|str
) – Definition of the new contract.
Returns: The equivalent contract – might be useful for debugging.
Return type:
-
class
contracts.
Contract
(where)[source]¶ -
-
fail
(value)[source]¶ Checks that the value does not respect this contract. Raises an exception if it does.
Raise: ValueError
-
__repr__
()[source]¶ Returns a string representation of a contract that can be evaluated by Python’s
eval()
.It must hold that:
eval(contract.__repr__()) == contract
. This is checked in the unit-tests.Example:
>>> from contracts import parse >>> contract = parse('list[N]') >>> contract.__repr__() "List(BindVariable('N',int),None)"
All the symbols you need to eval() the expression are in
contracts.library
.>>> from contracts.library import * >>> contract == eval("%r"%contract) True
-
__str__
()[source]¶ Returns a string representation of a contract that can be reparsed by
contracts.parse()
.It must hold that:
parse(str(contract)) == contract
. This is checked in the unit-tests.Example:
>>> from contracts import parse >>> spec = 'list[N]' >>> contract = parse(spec) >>> contract List(BindVariable('N',int),None) >>> str(contract) == spec True
The expressions generated by
Contract.__str__()
will be exactly the same as what was parsed (this is checked in the unittests as well) if and only if the expression is “minimal”. If it isn’t (there is whitespace or redundant symbols), the returned expression will be an equivalent minimal one.Example with extra parenthesis and whitespace:
>>> from contracts import parse >>> verbose_spec = 'list[((N))]( int, > 0)' >>> contract = parse(verbose_spec) >>> str(contract) 'list[N](int,>0)'
Example that removes extra parentheses around arithmetic operators:
>>> verbose_spec = '=1+(1*2)+(2+4)' >>> str(parse(verbose_spec)) '=1+1*2+2+4'
This is an example with logical operators precedence. The AND operator
,
(comma) has more precedence than the OR (|
).>>> verbose_spec = '(a|(b,c)),e' >>> str(parse(verbose_spec)) '(a|b,c),e'
Not that only the outer parenthesis is kept as it is the only one needed.
-