Usage

Importing the right module

code-contracts is split into two different modules: contract and assertion.

To use contracts, just import the following module:

>>> from contracts import contract

To use assertions, import the following module:

>>> from contracts import assertion

Expected behavior

When a contract or an assertion fails, you can expect it to raise an exception as follows:

Entity Exception(s) raised
contract TypeError, ValueError or AttributeError
assertion AssertionError

The contracts provided are intended to be used as preconditions, meaning that requirements will be checked before executing a function.

Contracts’ behavior

Here’s what happens when a contract fails:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
from contracts import contract


def build_rocket(name):
    contract.is_not_empty(name)

    print("You built a {0} rocket".format(name))

if __name__ == "__main__":
    build_rocket(None)
Traceback (most recent call last):
  File "/contracts/samples/contract_failure_example.py", line 14, in <module>
    build_rocket(None, 9, "SpaceX")
  File "/contracts/samples/contract_failure_example.py", line 7, in build_rocket
    contract.is_not_empty(name)
  File /contracts/contracts/contract.py", line 37, in is_not_empty
    raise ValueError("{0} was empty.".format(_get_parameter_name()))
ValueError: name was empty.

So when you run this script, the contract raises a ValueError indicating that the name parameter is empty. Typically, you want this error to bubble up and crash your program as demonstrated. This way, you can more easily track the error and fix the calling code accordingly.

Assertions’ behavior

Here’s what happens when an assertion fails:

1
2
3
4
5
from contracts import assertion


if __name__ == "__main__":
    assertion.does_not_raise(ValueError, build_rocket, None)
Traceback (most recent call last):
  File "/contracts/contracts/assertion.py", line 21, in does_not_raise
    callable_obj(*args, **kwargs)
  File "/contracts/samples/contract_failure_example.py", line 7, in build_rocket
    contract.is_not_empty(name)
  File "/contracts/contracts/contract.py", line 37, in is_not_empty
    raise ValueError("{0} was empty.".format(_get_parameter_name()))
ValueError: name was empty.

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "/contracts/samples/assertion_failure_example.py", line 8, in <module>
    assertion.does_not_raise(ValueError, build_rocket, None)
  File "/contracts/contracts/assertion.py", line 25, in does_not_raise
    raise AssertionError("{0} raised by {1}().".format(exception_cls.__name__, callable_obj.__name__))
AssertionError: ValueError raised by build_rocket().

So when you run this script, the assertion raises an AssertionError indicating that build_rocket() itself raises a ValueError. Again, this is because the name parameter is empty.

As you can see, assertions are very handy to validate the expected behavior of a function or method. Note that it’s a bit more common to use assertions in the context of more formal unit tests, like when using the unittest module, as it handles AssertionError a little bit more gracefully.

Available contracts

code-contracts contains the following contract functions:

Function Description Example
is_not_none() Checks that the specified value is not equal to None.
def contract_is_not_none_demo(a):
    contract.is_not_none(a)

contract_is_not_none_demo("abc")
is_not_empty() Checks that the specified value is not empty.
def contract_is_not_empty_demo(a):
    contract.is_not_empty(a)

contract_is_not_empty_demo("abc")
is_equal_to_any() Checks that the specified value is equal to at least one of the expected values.
def contract_is_equal_to_any_demo(a):
    contract.is_equal_to_any(a, [1, 2, 3])

contract_is_equal_to_any_demo(1)
is_true() Checks that the specified value is equal to True.
def contract_is_true_demo(a):
    contract.is_true(a)

contract_is_true_demo(2 > 1)
is_false() Checks that the specified value is equal to False.
def contract_is_false_demo(a):
    contract.is_false(a)

contract_is_false_demo(1 > 2)
is_equal() Checks that the specified value is strictly equal to the expected value.
def contract_is_equal_demo(a):
    contract.is_equal(a, 1)

contract_is_equal_demo(1)
is_greater_than() Checks that the specified value is greater than the expected value.
def contract_is_greater_than_demo(a):
    contract.is_greater_than(a, 1)

contract_is_greater_than_demo(2)
is_greater_than_or_equal() Checks that the specified value is greater than or strictly equal to the expected value.
def contract_is_greater_than_or_equal(a):
    contract.is_greater_than_or_equal(a, 1)

contract_is_greater_than_or_equal(2)
all_have_attribute() Checks that all objects contained in value - be it a single object or an Iterable of objects - have the specified attribute.
class ClassA:
    abc = 1


class ClassB:
    abc = 1
    xyz = 2


def contract_all_have_attribute(a):
    contract.all_have_attribute(a, "abc")

contract_all_have_attribute([ClassA(), ClassB()])
all_have_method() Checks that all objects contained in value - be it a single object or an Iterable of objects have the specified method.
class ClassC:
    def my_method(self):
        pass


def contract_all_have_method(a):
    contract.all_have_method(a, "my_method")

contract_all_have_method(ClassC())
is_callable() Checks that the specified value is a callable object (i.e. has a ‘__call__’ attribute).
def contract_is_callable(a):
    contract.is_callable(a)

contract_is_callable(ClassC().my_method)
is_instance() Checks that the specified value is an instance of the given class.
def contract_is_instance(a):
    contract.is_instance(a, int)

contract_is_instance(1)

Note

Some of these contract functions contain an optional parameter named expression_str. Its purpose is to allow you to pass a string representation of the value passed to the function. This is especially useful if, for example, the value isn’t a single, discrete value, but a boolean expression such as x > y. In such a case, you can pass ‘x > y’ in expression_str. This expression will be used to create a more meaningful error message if the contract fails.

Available assertions

code-contracts contains the following assertion functions:

Function Description Example
does_not_raise() Asserts that the specified callable object does not raise an exception of the specified class when called.
assertion.does_not_raise(ValueError, lambda: None)
raises() Asserts that the specified callable object raises an exception of the specified class when called.
def raises():
    raise ValueError("Error!")

assertion.raises(ValueError, raises)
raises_with_msg() Asserts that the specified callable object raises an exception of the specified type with the specified message when called.
def raises():
    raise ValueError("Error!")

assertion.raises_with_msg(ValueError, raises, "Error!")
not_called_with() Asserts that the specified mock object was never called with a specific sequence of arguments.
mock = Mock()
mock.my_method.side_effect = lambda a: a + 1
assertion.not_called_with(mock.my_method, 123)
contains_one_element_of_class() Asserts that the specified iterable object contains one and only one element of the specified class.
assertion.contains_one_element_of_class(int, [1])