• Stars
    star
    330
  • Rank 123,397 (Top 3 %)
  • Language
    Python
  • License
    MIT License
  • Created almost 6 years ago
  • Updated 4 months ago

Reviews

There are no reviews yet. Be the first to send feedback to the community and the maintainers!

Repository Details

Design-by-contract in Python3 with informative violation messages and inheritance

icontract

Continuous integration https://coveralls.io/repos/github/Parquery/icontract/badge.svg?branch=master PyPI - version

PyPI - Python Version

Documentation Gitter chat

icontract provides design-by-contract to Python3 with informative violation messages and inheritance.

It also gives a base for a flourishing of a wider ecosystem:

Related Projects

There exist a couple of contract libraries. However, at the time of this writing (September 2018), they all required the programmer either to learn a new syntax (PyContracts) or to write redundant condition descriptions ( e.g., contracts, covenant, deal, dpcontracts, pyadbc and pcd).

This library was strongly inspired by them, but we go two steps further.

First, our violation message on contract breach are much more informative. The message includes the source code of the contract condition as well as variable values at the time of the breach. This promotes don't-repeat-yourself principle (DRY) and spare the programmer the tedious task of repeating the message that was already written in code.

Second, icontract allows inheritance of the contracts and supports weakining of the preconditions as well as strengthening of the postconditions and invariants. Notably, weakining and strengthening of the contracts is a feature indispensable for modeling many non-trivial class hierarchies. Please see Section Inheritance. To the best of our knowledge, there is currently no other Python library that supports inheritance of the contracts in a correct way.

In the long run, we hope that design-by-contract will be adopted and integrated in the language. Consider this library a work-around till that happens. You might be also interested in the archived discussion on how to bring design-by-contract into Python language on python-ideas mailing list.

Teasers

We give a couple of teasers here to motivate the library. Please see the documentation available on icontract.readthedocs.io for a full scope of its capabilities.

The script is also available as a repl.it post.

>>> import icontract

>>> @icontract.require(lambda x: x > 3)
... def some_func(x: int, y: int = 5) -> None:
...     pass
...

>>> some_func(x=5)

# Pre-condition violation
>>> some_func(x=1)
Traceback (most recent call last):
  ...
icontract.errors.ViolationError: File <doctest README.rst[1]>, line 1 in <module>:
x > 3:
x was 1
y was 5

# Pre-condition violation with a description
>>> @icontract.require(lambda x: x > 3, "x must not be small")
... def some_func(x: int, y: int = 5) -> None:
...     pass
...
>>> some_func(x=1)
Traceback (most recent call last):
  ...
icontract.errors.ViolationError: File <doctest README.rst[4]>, line 1 in <module>:
x must not be small: x > 3:
x was 1
y was 5

# Pre-condition violation with more complex values
>>> class B:
...     def __init__(self) -> None:
...         self.x = 7
...
...     def y(self) -> int:
...         return 2
...
...     def __repr__(self) -> str:
...         return "instance of B"
...
>>> class A:
...     def __init__(self) -> None:
...         self.b = B()
...
...     def __repr__(self) -> str:
...         return "instance of A"
...
>>> SOME_GLOBAL_VAR = 13
>>> @icontract.require(lambda a: a.b.x + a.b.y() > SOME_GLOBAL_VAR)
... def some_func(a: A) -> None:
...     pass
...
>>> an_a = A()
>>> some_func(an_a)
Traceback (most recent call last):
  ...
icontract.errors.ViolationError: File <doctest README.rst[9]>, line 1 in <module>:
a.b.x + a.b.y() > SOME_GLOBAL_VAR:
SOME_GLOBAL_VAR was 13
a was instance of A
a.b was instance of B
a.b.x was 7
a.b.y() was 2

# Post-condition
>>> @icontract.ensure(lambda result, x: result > x)
... def some_func(x: int, y: int = 5) -> int:
...     return x - y
...
>>> some_func(x=10)
Traceback (most recent call last):
  ...
icontract.errors.ViolationError: File <doctest README.rst[12]>, line 1 in <module>:
result > x:
result was 5
x was 10
y was 5


# Pre-conditions fail before post-conditions.
>>> @icontract.ensure(lambda result, x: result > x)
... @icontract.require(lambda x: x > 3, "x must not be small")
... def some_func(x: int, y: int = 5) -> int:
...    return x - y
...
>>> some_func(x=3)
Traceback (most recent call last):
  ...
icontract.errors.ViolationError: File <doctest README.rst[14]>, line 2 in <module>:
x must not be small: x > 3:
x was 3
y was 5

# Invariant
>>> @icontract.invariant(lambda self: self.x > 0)
... class SomeClass:
...     def __init__(self) -> None:
...         self.x = -1
...
...     def __repr__(self) -> str:
...         return "an instance of SomeClass"
...
>>> some_instance = SomeClass()
Traceback (most recent call last):
 ...
icontract.errors.ViolationError: File <doctest README.rst[16]>, line 1 in <module>:
self.x > 0:
self was an instance of SomeClass
self.x was -1

Installation

  • Install icontract with pip:
pip3 install icontract

Versioning

We follow Semantic Versioning. The version X.Y.Z indicates:

  • X is the major version (backward-incompatible),
  • Y is the minor version (backward-compatible), and
  • Z is the patch version (backward-compatible bug fix).

More Repositories

1

gocontracts

A tool for design-by-contract in Go
Go
105
star
2

swagger-to

Generate server and client code from Swagger (OpenAPI 2.0) specification.
Python
54
star
3

pylddwrap

Python 3 wrapper around ldd *nix utility to determine shared libraries of a program
Python
24
star
4

temppathlib

wrappers around tempfile so that you can directly use them together with pathlib module.
Python
16
star
5

lanms

C++
16
star
6

spurplus

Python3 library to manage remote machines and perform file operations over SSH
Python
14
star
7

revproxyry

a reverse proxy with integrated Let's encrypt client
Go
12
star
8

mapry

Generate polyglot code for de/serializing object graphs from JSONable structures.
C++
11
star
9

gs-wrap

Python wrapper for Google Storage
Python
10
star
10

reconnecting-ftp

Python
9
star
11

pypackagery

package a subset of Python monorepo for deployment
Python
9
star
12

pyicontract-lint

Check statically contracts in Python code.
Python
7
star
13

sphinx-icontract

Extend sphinx to include icontracts.
Python
6
star
14

datetime-glob

Parses date/times from a path given a glob pattern intertwined with date/time format.
Python
6
star
15

lexery

Python
5
star
16

elm-docstyle

a CLI tool for verifying the compliance of Elm source to comment style rules, written in Elm
Elm
3
star
17

elm-heatmap

HTML-based heatmap in pure Elm.
Elm
3
star
18

logthis

a singleton, two-level, colorful, thread-safe, knob-free, logging library for Python in-house software.
Python
2
star
19

persizmq

Python3 library to provide persistance to zeromq
Python
2
star
20

mailgun-relayery

A relaying server to the MailGun API
Go
2
star
21

gsutilwrap

wraps gsutil, a command-line interface to Google Cloud Storage.
Python
1
star
22

gcloudwrap

Python3 library to wrap Google cloud client to facilitate deployment
Python
1
star
23

numenc-py

Python3 library to encode and decode numbers to sortable bytes
Python
1
star