[Python-ideas] Contracts in python -- a report & next steps

Stéfane Fermigier sf at fermigier.com
Thu Oct 25 03:30:38 EDT 2018


A few thoughts:

1) Just as with with PEP 484, we could distinguish between contract
specification and checking. To achieve some of the goals that you state, we
need to standardise the way people would state contracts in their code (and
provide a small implementation in the stdlib, similar to the typing
module), but how these contracts are verified (at runtime or statically) or
leveraged in the documentation are left to third party projects (similar to
mypy & al).

2) Building momentum is paramount. First, since there are many contracts
libraries out there, some dating more than 15 years (ex: PyDBC), we'd need
to build consensus between the people who wrote and use these libraries.
And of course, get feedback from people who use this approach on
significant projects. I'm willing to try your library on one of my projects.

3) Having contracts for most of the stdlib would be a worthy goal (for
contracts users) but, as noted by some, would come with some speed issues.
And of course, would represent a multi-year effort. Hopefully your project
(i.e. standardising a library, but not "contracting" the stdlib) would
still be valuable if this never happen.

4) Interaction between contracts and typing is an open question.

  S.


On Wed, Oct 24, 2018 at 9:40 AM Marko Ristin-Kaufmann <
marko.ristin at gmail.com> wrote:

> Hi,
> I would like to give you a short report on the development of icontract
> library following the discussion about the introduction of contracts into
> Python (e.g., see [1, 2, 3, 4]).
>
> *Features*
> The functionality of icontract library is basically on par with Eiffel,
> Cobra and other languages supporting contracts except for loop invariants
> and less readable syntax.
>
> The features include:
> * "require", "ensure" and "invariant" decorators to define the contracts
> * "snapshot" decorator to capture the values prior to the function
> invocation to allow postconditions to verify the state transitions
> * inheritance of the contracts (with strengthening/weakening)
> * tracing of the argument values on contract violation
> * informative violation messages automatically parsed from the code of the
> condition function
> * The user can specify custom errors to be raised on a specific contract
> violation
> * individual toggling of the contracts
> * linter to check the contract arguments
> * sphinx extension to render the contracts automatically in the
> documentation (including a sophisticated matching of logical implications)
>
> We covered all the use cases we could find in our code base (at Parquery
> AG) such as:
> * functions
> * instance methods
> * class and static methods
> * property getters, setters and deleters
> * slot wrappers
>
> *Roadblocks*
> During the development, the following roadblocks were encountered:
>
> * We wanted to include the contracts in the output of help().
> Unfortunately, help() renders the __doc__ of the class and not of the
> instance. For functions, this is the class "function" which you can not
> inherit from. See [5] for more details.
>
> * We need to inspect the source code of the condition and error lambdas to
> generate the violation message and infer the error type in the
> documentation, respectively. inspect.getsource(.) is broken on lambdas
> defined in decorators in Python 3.5.2+ (see [6]). We circumvented this bug
> by using inspect.findsource(.), inspect.getsourcefile(.) and examining the
> local source code of the lambda by searching for other decorators above and
> other decorators and a function or class definition below. The decorator
> code is parsed and then we match the condition and error arguments in the
> AST of the decorator. This is brittle as it prevents us from having partial
> definitions of contract functions or from sharing the contracts among
> functions.
>
> Here is a short code snippet to demonstrate where the current
> implementation fails:
> import icontract
>
> require_x_positive = icontract.require(
>     lambda x: x > 0, error=lambda: ValueError("x must be positive"))
>
> @require_x_positive
> def some_func(x: int) -> None:
>     pass
>
> However, we haven't faced a situation in the code base where we would do
> something like the above, so I am unsure whether this is a big issue. As
> long as decorators are directly applied to functions and classes,
> everything worked fine on our code base.
>
>
> *Our Experience*
> We have been using icontract in our team for our production code base
> (~100K LOC) as well as for a couple of open source projects (each <10K LOC)
> since August 1st 2018 (~ 3 months).
>
> In contrast to points raised during the discussions in [1, 2, 3, 4], we
> did not have issues with readability and modifying contracts. Thus far, we
> have not encountered problems with variable renames and major code
> refactorings. We use Pycharm, so it remains open whether this also applies
> to development environments such as emacs and vim.
>
> We confirm that contracts help us improve the documentation, keep the
> documentation up-to-date, better reason about the function's input and
> output and catch bugs early and more easily during the unit and integration
> tests.
>
>
> *Status*
> The library interface is currently frozen after the version bump to 2.0.0
> and is not expected to change in the next six months. All the reported bugs
> have been fixed and no bug fixes are pending.
>
> *Next Steps?*
> I personally doubt that we are enough people to form a party to push for a
> change in the language. A standardized library seems to me like a
> realizable compromise given the state of the discussion on this mail list.
>
> Before we organize a collective to write a proposal to standardize the
> library, I would suggest that a couple of other interested teams adopt
> icontract, apply it to their code bases and report their experiences on
> this mail list. I hope that 2-3 reports would be insightful enough to
> either convince other people that contracts in python are worth
> standardizing (and highlight missing features yet to be implemented) or
> provide solid material to discard the endeavor at the current moment.
>
> In the meanwhile, it would be of great help if somebody could vet the
> documentation and the code of icontract.
>
> *Authors*
> The library was mainly written by me (with some help of my colleague Adam
> Radomski). We discussed the features within the dev team at Parquery
> (Zurich, Switzerland) as well as in email correspondence with James Lu.
>
> [1] https://groups.google.com/forum/#!topic/python-ideas/mvzLsdwGuww
> [2] https://groups.google.com/forum/#!topic/python-ideas/JtMgpSyODTU
> [3] https://groups.google.com/forum/#!topic/python-ideas/mvzLsdwGuww
> [4]
> https://groups.google.com/forum/#!topic/python-ideas/dmXz_7LH4GI%5B1-25%5D
> [5] https://groups.google.com/forum/#!topic/python-ideas/c9ntrVuh6WE
> [6] https://bugs.python.org/issue21217
> _______________________________________________
> Python-ideas mailing list
> Python-ideas at python.org
> https://mail.python.org/mailman/listinfo/python-ideas
> Code of Conduct: http://python.org/psf/codeofconduct/
>


-- 
Stefane Fermigier - http://fermigier.com/ - http://twitter.com/sfermigier -
http://linkedin.com/in/sfermigier
Founder & CEO, Abilian - Enterprise Social Software -
http://www.abilian.com/
Chairman, Free&OSS Group @ Systematic Cluster -
http://www.gt-logiciel-libre.org/
Co-Chairman, National Council for Free & Open Source Software (CNLL) -
http://cnll.fr/
Founder & Organiser, PyParis & PyData Paris - http://pyparis.org/ &
http://pydata.fr/
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.python.org/pipermail/python-ideas/attachments/20181025/0b32a32b/attachment-0001.html>


More information about the Python-ideas mailing list