[Python-ideas] Why is design-by-contracts not widely adopted?

Stephen J. Turnbull turnbull.stephen.fw at u.tsukuba.ac.jp
Tue Sep 25 06:08:04 EDT 2018

Marko Ristin-Kaufmann writes:

 > Thanks a lot for pointing us to macropy -- I was not aware of the library,
 > it looks very interesting!
 > Do you have any experience how macropy fit

Sorry, no.  I was speaking as someone who is familiar with macros from
Lisp but doesn't miss them in Python, and who also has been watching
python-dev and python-ideas for about two decades now, so I've heard
of things like MacroPy and know how the core developers think to a
great extent.

 > I'm also a bit worried how macropy would work out in the libraries
 > published to pypi -- imagine if many people start using contracts.
 > Suddenly, all these libraries would not only depend on a contract library
 > but on a macro library as well.

That's right.

 > Is that something we should care about?

Yes.  Most Pythonistas (at least at present) don't much like macros.
They fear turning every program into its own domain-specific language.
I can't claim much experience with dependency hell, but I think that's
much less important from your point of view (see below).

My point is mainly that, as you probably are becoming painfully aware,
getting syntax changes into Python is a fairly drawnout process.  For
an example of the kind of presentation that motivates people to change
their mind from the default state of "if it isn't in Python yet,
YAGNI" to "yes, let's do *this* one", see

Warning: Tim Peters is legendary, though still active occasionally.
All he has to do is post to get people to take notice.  But this
Appendix is an example of why he gets that kind of R-E-S-P-E-C-T.[1]

So the whole thing is a secret plot ;-) to present the most beautiful
syntax possible in your PEP (which will *not* be about DbC, but rather
about a small set of enabling syntax changes, hopefully a singleton),
along with an extended example, or a representative sample, of usage.
Because you have a working implementation using MacroPy (or the less
pretty[2] but fewer dependencies version based on condition strings
and eval) people can actually try it on their own code and (you hope,
they don't :-) they find a nestful of bugs by using it.

 > Potential dependency hell? (I already have a bad feeling about
 > making icontract depend on asttokens and considerin-lining
 > asttokens into icontract particularly for that reason).

I don't think so.  First, inlining an existing library is almost
always a bad idea.  As for the main point, if the user sticks to one
major revision, and only upgrades to compatible bugfixes in the
Python+stdlib distribution, I don't see why two or three libraries
would be a major issue for a feature that the developer/project uses
extremely frequently.  I've rarely experienced dependency hell, and in
both cases it was web frameworks (Django and Zope, to be specific, and
the dependencies involved were more or less internal to those
frameworks).  If you or people you trust have other experience, forget
what I just said. :-)

Of course it depends on the library, but as long as the library is
pretty strict about backward compatibility, you can upgrade it and get
new functionality for other callers in your code base (which are
likely to appear, you know -- human beings cannot stand to leave a
tool unused once they install it!)

 > > Note that this means *you cannot use macros in a file that is run
 > > directly*, as it will not be passed through the import hooks.
 > That would make contracts unusable in any stand-alone script,
 > right?

Yes, but really, no:

    # The run.py described by the MacroPy docs assumes a script that
    # runs by just importing it.  I don't have time to work out
    # whether that makes more sense.  This idiom of importing just a
    # couple of libraries, and then invoking a function with a
    # conventional name such as "run" or "process" is quite common.
    # If you have docutils install, check out rstpep2html.py.

    import macropy.activate
    from my_contractful_library import main

and away you go.  5 years from now that script will be a badge of
honor among Pythonic DbCers, and you won't be willing to give it up!
Just kidding, of course -- the ideal outcome is that the use case is
sufficiently persuasive to justify a syntax change so you don't need
MacroPy, or, perhaps some genius will come along and provide some
obscure construct that is already legal syntax!


[1]  R.I.P. Aretha!

[2]  Urk, I just realized there's another weakness to strings: you get
no help on checking their syntax from the compiler.  For a proof-of-
concept that's OK, but if you end up using the DbC library in your
codebase for a couple years while the needed syntax change gathers
support, that would be really bad.

More information about the Python-ideas mailing list