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

2018-10-09 Thread Steven D'Aprano
On Mon, Oct 08, 2018 at 03:34:51PM -0400, Terry Reedy wrote:

> >> I said above that functions may be specified by
> >> process rather than result.
> >
> > Fine. What of it? Can you describe what the function does?
> >
> > "It sorts the list in place."
> >
> > "It deletes the given record from the database."
> 
> > These are all post-conditions.
> 
> No they are not.

Yes they are; they are textual descriptions of the post-condition, not 
executable code, but since software contracts are both specification and 
code, they certainly count as post-conditions.

By the way, you seem to have deleted one of my examples, leaving only 
the two relatively simple ones. I don't understand why you deleted the 
example, but here it is again:

"It deducts the given amount from Account A and transfers it
to Account B, guaranteeing that either both transactions occur
or neither of them, but never one and not the other."



> They are descriptions of the process.  Additional 
> mental work is required to turn them into formal descriptions of the 
> result that can be coded.

Yes. That's called "programming". You might have done it from time to 
time :-)



> Marko appears to claim that such coded formal 
> descriptions are easier to read and understand than the short English 
> description.  I disagree.

What does "sort in place"? *Precisely*? How do you know if the software 
*actually does* sort in place?

They are not rhetorical questions.

You can document that the function sorts in place, but if it actually 
reverses a copy of the list, how would you know?

How do we know the software meets the specified requirements if you 
haven't nailed down the specification, and if the specification exists 
only in documentation and is never checked in the code?

Design By Contract is a methodology that helps ensure that the 
specification is (1) nailed down and (2) actually checked.


> It is therefore not obvious to me that the 
> extra work is worthwhile.

Tell me how you, personally, would find out whether or not the function
actually sorts the list in place. What process would YOU do?

As I see it, you either have to take it on trust, or you have to write 
tests. Would you argue that the "extra work" to write tests are not 
worthwhile?



> >>def append_first(seq):
> >> "Append seq[0] to seq."
> >[...]
> 
> The snipped body (revised to omit irrelevant 'return')
> seq.append(seq[0])
> 
> >>But with duck-typing, no post condition is possible.
> >
> >That's incorrect.
> >
> >def append_first(seq):
> > require:
> > len(seq) > 0
> 
> seq does not neccessarily have a __len__ method

Yes it must, because I wrote the specification and I demand that it 
must support len.

You lost your opportunity to write the spec yourself when you wrongly 
said no post-condition is possible. I just showed that post-conditions 
ARE possible, by writing some.

We could debate what those conditions are: can we just test for the 
Sequence interface, using isinstance() and the Sequence ABC? Do I need 
to bother checking that seq supports __getitem__?

But I'm not really interested in getting bogged down in the minutia of 
what specific post-conditions need to go with this toy function. Its a 
made-up example, so who cares? In practice, you specify in as much 
detail as you need. You can always come back and add more detail later.


> > hasattr(seq, "append")
> 
> The actual precondition is that seq[0] be in the domain of seq.append. 

That is not part of the contract of the append_first function. It 
doesn't care about any domain limits of seq. If an object could be 
appended into seq[0] in the first place, surely it can append again 
later. We don't have to try to detect every imaginable bizarre weird 
piece of code intentionally written to perplex us.


> The only absolutely sure way to test this is to run the code body.

Sure. So what? The code body does actually get run you know. If it 
raises an exception because seq can't append seq[0] to itself, that's a 
bug that needs to be fixed.


> Or 
> one could run seq[0] and check it against the preconditions, if formally 
> specified, of seq.append.

That is not the responsibility of the append_first function.


> > ensure:
> > len(seq) == len(OLD.seq) + 1
> > seq[0] == seq[-1]
> 
> Not even all sequences implement negative indexing.

I don't care. Since I wrote the spec, I demand that only those which 
meet my requirements are used.

But okay, fine, I'll re-write it:

seq[0] == seq[len(seq)-1]

and then you can tell me off for writing un-Pythonic code, and then I'll 
change it back.


> This is true for lists, as I said, but not for every object the meets 
> the preconditions.  As others have said, duck typing means that we don't 
> know what unexpected things methods of user-defined classes might do.

That's not how we use duck-typing. When I call len(obj), I don't expect 
that it will format my hard drive, even though obj.__len__ might do 
that, and 

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

2018-10-08 Thread Terry Reedy

On 10/8/2018 10:26 AM, Steven D'Aprano wrote:

On Sun, Oct 07, 2018 at 04:24:58PM -0400, Terry Reedy wrote:



https://www.win.tue.nl/~wstomv/edu/2ip30/references/design-by-contract/index.html

defines contracts as "precise (legally unambiguous) specifications" (5.2
Business Contracting/Sub-contracting Metaphor)


You are quoting that out of context. The full context says (emphasis
added):

 IN THE BUSINESS WORLD, contracts are precise (legally unambiguous)
 specifications that define the obligations and benefits of the
 (usually two) parties involved.


This is silly.  Every quote that is not complete is literally 'out of 
context'.  However, 'quoting out of context', in the colloquial sense, 
means selectively quoting so as to distort the original meaning, whereas 
I attempted to focus on the core meaning I was about to discuss.


Marko asked an honest question about why things obvious to him are not 
obvious to others.  I attempted to give an honest answer.  If my answer 
suggested that I have not undertstood Marko properly, as is likely, he 
can use it as a hint as to how communicate his position better.


>> I said above that functions may be specified by
>> process rather than result.
>
> Fine. What of it? Can you describe what the function does?
>
> "It sorts the list in place."
>
> "It deletes the given record from the database."

> These are all post-conditions.

No they are not.  They are descriptions of the process.  Additional 
mental work is required to turn them into formal descriptions of the 
result that can be coded.  Marko appears to claim that such coded formal 
descriptions are easier to read and understand than the short English 
description.  I disagree.  It is therefore not obvious to me that the 
extra work is worthwhile.



def append_first(seq):
 "Append seq[0] to seq."

[...]


The snipped body (revised to omit irrelevant 'return')
seq.append(seq[0])


But with duck-typing, no post condition is possible.


That's incorrect.

def append_first(seq):
 require:
 len(seq) > 0


seq does not neccessarily have a __len__ method


 hasattr(seq, "append")


The actual precondition is that seq[0] be in the domain of seq.append. 
The only absolutely sure way to test this is to run the code body.  Or 
one could run seq[0] and check it against the preconditions, if formally 
specified, of seq.append.



 ensure:
 len(seq) == len(OLD.seq) + 1
 seq[0] == seq[-1]


Not even all sequences implement negative indexing.

This is true for lists, as I said, but not for every object the meets 
the preconditions.  As others have said, duck typing means that we don't 
know what unexpected things methods of user-defined classes might do.


class Unexpected():
def __init__(self, first):
self.first = first
def __getitem__(self, key):
if key == 0:
return self.first
else:
raise ValueError(f'key {key} does not equal 0')
def append(self, item):
if isinstance(item, int):
self.last = item
else:
raise TypeError(f'item {item} is not an int')

def append_first(seq):
seq.append(seq[0])

x = Unexpected(42)
append_first(x)
print(x.first, x.last)
# 42 42

A more realistic example:

def add(a, b): return a + b

The simplified precondition is that a.__add__ exists and applies to b or 
that b.__radd__ exists and applies to a.  I see no point in formally 
specifying this as part of 'def add' as it is part of the language 
definition.  It is not just laziness that makes me averse to such 
redundancy.


Even ignoring user classes, a *useful* post-condition that applies to 
both numbers and sequences is hard to write.  I believe + is 
distributive for both, so that a + (b + b) = (a + b) + b, but


--
Terry Jan Reedy

___
Python-ideas mailing list
Python-ideas@python.org
https://mail.python.org/mailman/listinfo/python-ideas
Code of Conduct: http://python.org/psf/codeofconduct/


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

2018-10-08 Thread Steven D'Aprano
On Tue, Oct 09, 2018 at 01:21:57AM +1100, Chris Angelico wrote:

> > > Yet we keep having use-cases shown to us involving one person with one
> > > module, and another person with another module, and the interaction
> > > between the two.
> >
> > Do we? I haven't noticed anything that matches that description,
> > although I admit I haven't read every single post in these threads
> > religiously.
> 
> Try this:

Thanks for the example, that's from one of the posts I haven't read.


> If you're regularly changing your function contracts, such that you
> need to continually test  in case something in the other package
> changed, then yes, that's exactly what I'm talking about.

Presumably you're opposed to continuous integration testing too.


> I'm tired of debating this.

Is that what you were doing? I had wondered.

http://www.montypython.net/scripts/argument.php

*wink*




-- 
Steve
___
Python-ideas mailing list
Python-ideas@python.org
https://mail.python.org/mailman/listinfo/python-ideas
Code of Conduct: http://python.org/psf/codeofconduct/


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

2018-10-08 Thread Marko Ristin-Kaufmann
Hi Chris,

I hope you don't mind me responding though you would like to stop
participating. This message is meant for other readers in case they are
interested.

> Alice tests her package A with some test data D_A. Now assume Betty did
> not write any contracts for her package B. When Alice tests her package,
> she is actually making an integration test. While she controls the inputs
> to B from A, she can only observe the results from B, but not whether they
> are correct by coincidence or B did its job correctly. Let's denote D'_B
> the data that is given to B from her original test data D_A during Alice's
> integration testing.
> >
>
> If you're regularly changing your function contracts, such that you
> need to continually test  in case something in the other package
> changed, then yes, that's exactly what I'm talking about.
>

The user story I put above had nothing to do with change. I was telling how
manually performing integration tests between A and B is tedious for us
(since it involves some form or the other of manual recording of
input/outputs to the module B and adapting unit tests of B) while contracts
are much better (*for us*) since they incur little overhead (write them
once for B, anybody runs them automatically).

I did not want to highlight the *change* in my user story, but the ease of
integration tests with contracts. If it were not for contracts, we would
have never performed them.

Cheers,
Marko



On Mon, 8 Oct 2018 at 16:22, Chris Angelico  wrote:

> On Mon, Oct 8, 2018 at 11:11 PM Steven D'Aprano 
> wrote:
> >
> > On Mon, Oct 08, 2018 at 09:32:23PM +1100, Chris Angelico wrote:
> > > On Mon, Oct 8, 2018 at 9:26 PM Steven D'Aprano 
> wrote:
> > > > > In other words, you change the *public interface* of your functions
> > > > > all the time? How do you not have massive breakage all the time?
> > > >
> > > > I can't comment about Marko's actual use-case, but *in general*
> > > > contracts are aimed at application *internal* interfaces, not so much
> > > > library *public* interfaces.
> > >
> > > Yet we keep having use-cases shown to us involving one person with one
> > > module, and another person with another module, and the interaction
> > > between the two.
> >
> > Do we? I haven't noticed anything that matches that description,
> > although I admit I haven't read every single post in these threads
> > religiously.
>
> Try this:
>
> On Mon, Oct 8, 2018 at 5:11 PM Marko Ristin-Kaufmann
>  wrote:
> > Alice tests her package A with some test data D_A. Now assume Betty did
> not write any contracts for her package B. When Alice tests her package,
> she is actually making an integration test. While she controls the inputs
> to B from A, she can only observe the results from B, but not whether they
> are correct by coincidence or B did its job correctly. Let's denote D'_B
> the data that is given to B from her original test data D_A during Alice's
> integration testing.
> >
>
> If you're regularly changing your function contracts, such that you
> need to continually test  in case something in the other package
> changed, then yes, that's exactly what I'm talking about.
>
> I'm tired of debating this. Have fun. If you love contracts so much,
> marry them. I'm not interested in using them, because nothing in any
> of these threads has shown me any good use-cases that aren't just
> highlighting bad coding practices.
>
> ChrisA
> ___
> Python-ideas mailing list
> Python-ideas@python.org
> https://mail.python.org/mailman/listinfo/python-ideas
> Code of Conduct: http://python.org/psf/codeofconduct/
>
___
Python-ideas mailing list
Python-ideas@python.org
https://mail.python.org/mailman/listinfo/python-ideas
Code of Conduct: http://python.org/psf/codeofconduct/


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

2018-10-08 Thread Steven D'Aprano
On Sun, Oct 07, 2018 at 04:24:58PM -0400, Terry Reedy wrote:

> A mathematical function is defined or specified by a input domain, 
> output range, and a mapping from inputs to outputs.  The mapping can be 
> defined either by an explicit listing of input-output pairs or by a rule 
> specifying either a) the process, what is done to inputs to produce 
> outputs or, b) the result, how the output relates to the input.

Most code does not define pure mathematical functions, unless you're 
writing in Haskall :-)


> https://www.win.tue.nl/~wstomv/edu/2ip30/references/design-by-contract/index.html
>  
> 
> defines contracts as "precise (legally unambiguous) specifications" (5.2 
> Business Contracting/Sub-contracting Metaphor)

You are quoting that out of context. The full context says (emphasis 
added):

IN THE BUSINESS WORLD, contracts are precise (legally unambiguous) 
specifications that define the obligations and benefits of the 
(usually two) parties involved.

and later goes on to say:

How does this apply to software correctness?

Consider the execution of a routine. The called routine provides 
a service - it is a supplier. The caller is the client that is 
requesting the service. We can impose a contract that spells out
precisely the obligations and benefits of both the caller (client)
and the callee (supplier). This contract SERVES AS THE INTERFACE 
SPECIFICATION FOR THE ROUTINE.

(I would add *executable* interface specification.)


> It is not obvious to me 
> that the metaphor of contracts adds anything worthwhile to the idea of 
> 'function'.

It doesn't. That's not what the metaphor is for.

Design By Contract is not a redefinition of "function", it is a software 
methodology, a paradigm for helping programmers reason better about 
functions and specify the interface so that bugs are discovered earlier.


> 1. Only a small sliver of human interactions are governed by formal 
> legal contracts read, understood, and agreed to by both (all) parties.

Irrelevant.


> 2. The idealized definition is naive in practice.  Most legal contracts, 
> unlike the example in the link article, are written in language that 
> most people cannot read. 

Irrelevant. 

Dicts aren't actual paper books filled with definitions of words, floats 
don't actually float, neural nets are not made of neurons nor can you 
catch fish in them, and software contracts are code, not legally binding 
contracts. It is a *metaphor*.


> Many contracts are imprecise and legally 
> ambiguous, which is why we have contract dispute courts.  And even then, 
> the expense means that most people who feel violated in a transaction do 
> not use courts.

Is this a critique of the legal system? What relevance does it have to 
Design By Contract?

Honestly Terry, you seem to be arguing:

"Hiring a lawyer is too expensive, and that's why Design By 
Contract doesn't work as a software methodology."


> Post-conditions specify a function by result.  I claim that this is not 
> always sensible.

In this context, "result" can mean either "the value returned by the 
function" OR "the action performed by the function (its side-effect)".

Post-conditions can check both.


> I said above that functions may be specified by 
> process rather than result. 

Fine. What of it? Can you describe what the function does?

"It sorts the list in place."

"It deletes the given record from the database."

"It deducts the given amount from Account A and transfers it
to Account B, guaranteeing that either both transactions occur
or neither of them, but never one and not the other."

These are all post-conditions. Write them as code, and they are 
contracts. If you can't write them as code, okay, move on to the next 
function.

(By the way, since you started off talking about mathematical functions, 
functions which perform a process rather than return a result aren't 
mathematical functions.)


> Ironically, the contract metaphor 
> reinforces my claim.  Many contracts, such as in teaching and medicine, 
> only specify process and explicitly disclaim any particular result of 
> concern to the client.

Irrelevant.


> >b)//If you write contracts in text, they will become stale over time 
> 
> Not true for good docstrings.  We very seldom change the essential 
> meaning of public functions.

What about public functions while they are still under active 
development with an unstable interface?


> How has "Return the sine of x (measured in radians).", for math.sin, 
> become stale?  Why would it ever?

Of course a stable function with a fixed API is unlikely to change. 
What's your point? The sin() function implementation on many platforms 
probably hasn't changed in 10 or even 20 years. (It probably just calls 
the hardware routines.) Should we conclude that unit testing is 
therefore bunk and nobody needs to write unit tests?


> What formal executable post condition 
> would help someone who does not understand 'sine', 

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

2018-10-08 Thread Chris Angelico
On Mon, Oct 8, 2018 at 11:11 PM Steven D'Aprano  wrote:
>
> On Mon, Oct 08, 2018 at 09:32:23PM +1100, Chris Angelico wrote:
> > On Mon, Oct 8, 2018 at 9:26 PM Steven D'Aprano  wrote:
> > > > In other words, you change the *public interface* of your functions
> > > > all the time? How do you not have massive breakage all the time?
> > >
> > > I can't comment about Marko's actual use-case, but *in general*
> > > contracts are aimed at application *internal* interfaces, not so much
> > > library *public* interfaces.
> >
> > Yet we keep having use-cases shown to us involving one person with one
> > module, and another person with another module, and the interaction
> > between the two.
>
> Do we? I haven't noticed anything that matches that description,
> although I admit I haven't read every single post in these threads
> religiously.

Try this:

On Mon, Oct 8, 2018 at 5:11 PM Marko Ristin-Kaufmann
 wrote:
> Alice tests her package A with some test data D_A. Now assume Betty did not 
> write any contracts for her package B. When Alice tests her package, she is 
> actually making an integration test. While she controls the inputs to B from 
> A, she can only observe the results from B, but not whether they are correct 
> by coincidence or B did its job correctly. Let's denote D'_B the data that is 
> given to B from her original test data D_A during Alice's integration testing.
>

If you're regularly changing your function contracts, such that you
need to continually test  in case something in the other package
changed, then yes, that's exactly what I'm talking about.

I'm tired of debating this. Have fun. If you love contracts so much,
marry them. I'm not interested in using them, because nothing in any
of these threads has shown me any good use-cases that aren't just
highlighting bad coding practices.

ChrisA
___
Python-ideas mailing list
Python-ideas@python.org
https://mail.python.org/mailman/listinfo/python-ideas
Code of Conduct: http://python.org/psf/codeofconduct/


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

2018-10-08 Thread Steven D'Aprano
On Mon, Oct 08, 2018 at 09:32:23PM +1100, Chris Angelico wrote:
> On Mon, Oct 8, 2018 at 9:26 PM Steven D'Aprano  wrote:
> > > In other words, you change the *public interface* of your functions
> > > all the time? How do you not have massive breakage all the time?
> >
> > I can't comment about Marko's actual use-case, but *in general*
> > contracts are aimed at application *internal* interfaces, not so much
> > library *public* interfaces.
> 
> Yet we keep having use-cases shown to us involving one person with one
> module, and another person with another module, and the interaction
> between the two.

Do we? I haven't noticed anything that matches that description, 
although I admit I haven't read every single post in these threads 
religiously.

But "application" != "one module" or "one developer". I fail to see the 
contradiction. An application can be split over dozens of modules, 
written by teams of developers. Whether one or a dozen modules, it still 
has no public interface that third-party code can call. It is *all* 
internal.

Obviously if you are using contracts in public library code, the way 
you will manage them is different from the way you would manage them if 
you are using them for private or internal code.

That's no different from (say) docstrings and doctests: there are 
implied stability promises for those in *some* functions (the public 
ones) but not *other* functions (the private ones).

Of course some devs don't believe in stability promises, and treat all 
APIs as unstable. So what? That has nothing to do with contracts. People 
can "move fast and break everything" in any programming style they like.


> Which way is it? Do the contracts change frequently or not? 

"Mu."

https://en.wikipedia.org/wiki/Mu_(negative)

They change as frequently as you, the developer writing them, chooses to 
change them. Just like your tests, your type annotations, your doc 
strings, and every other part of your code.


> Are they public or not? 

That's up to you.

Contracts were originally designed for application development, where 
the concept of "public" versus "private" is meaningless. The philosophy 
of DbC is always going to be biased towards that mind-set.

Nevertheless, people can choose to use them for library code where there 
is a meaningful distinction. If they do so, then how they choose to 
manage the contracts is up to them.

If you want to make a contract a public part of the interface, then you 
can (but that would rule out disabling that specific contract, at least 
for pre-conditions).

If you only want to use it for internal interfaces, you can do that too. 

If you want to mix and match and make some contracts internal and some 
public, there is no DbC Police to tell you that you can't.


> How are we supposed to understand the point of contracts 

You could start by reading the explanations given on the Eiffel page, 
which I've linked to about a bazillion times. Then you could read about 
another bazillion blog posts and discussions that describe it (some pro, 
some con, some mixed). And you can read the Wikipedia page that shows 
how DbC is supported natively by at least 17 languages (not just Eiffel) 
and via libraries in at least 15 others. Not just new experimental 
languages, but old, established and conservative languages like Java, C 
and Ada.

There are heaps of discussions on DbC on Stackoverflow:

https://stackoverflow.com/search?q=design%20by%20contract

and a good page on wiki.c2:

http://wiki.c2.com/?DesignByContract

TIL: Pre- and postconditions were first supported natively Barbara 
Liskov's CLU in the 1970s.

This is not some "weird bizarre Eiffel thing", as people seem to 
believe. If it hasn't quite gone mainstream, it is surely at least as 
common as functional programming style. It has been around for over 
forty years in one way or another, not four weeks, and is a standard, 
well-established if minority programming style and development process.

Of course it is always valid to debate the pros and cons of DbC versus 
other development paradigms, but questioning the very basis of DbC as 
people here keep doing is as ludicrous and annoying as questioning the 
basis of OOP or FP or TDD would be.

Just as functional programming is a paradigm that says (among other 
things) "no side effects", "no global variables holding state" etc, and 
we can choose to apply that paradigm even in non-FP languages, so DbC is 
in part a paradigm that tells you how to design the internals of your 
application.

We can apply the same design concepts to any code we want, even if we're 
not buying into the whole Contract metaphor:

- pre-conditions can be considered argument validation;

- post-conditions can be considered a kind of test;

- class invariants can be considered a kind of defensive assertion.



> if the use-cases being shown all involve bad code
> and/or bad coding practices?

How do you draw that conclusion?


> Contracts, apparently, allow people to violate 

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

2018-10-08 Thread Marko Ristin-Kaufmann
Hi Crhis,

> In other words, you change the *public interface* of your functions
> > all the time? How do you not have massive breakage all the time?
>
> I can't comment about Marko's actual use-case, but *in general*
> contracts are aimed at application *internal* interfaces, not so much
> library *public* interfaces.
>

Sorry, I might have misunderstood the question -- I was referring to
modules used within the company, not outside. Of course, public libraries
put on pypi don't change their interfaces weekly.

Just to clear the confusion, both Steve and I would claim that the
contracts do count as part of the interface.

For everything internal, we make changes frequently (including the
interface) and more often than not, the docstring is not updated when the
implementation of the function is. Contracts help our team catch breaking
changes more easily. When we change the behavior of the function, we use
"Find usage" in Pycharm, fix manually what we can obviously see that was
affected by the changed implementation, then statically check with mypy
that the changed return type did not affect the callers, and contracts (of
other functions!) catch some of the bugs during testing that we missed when
we changed the implementation. End-to-end test with testing contracts
turned off catch some more bugs on the real data, and then it goes into
production where hopefully we see no errors.

Cheers,
Marko



On Mon, 8 Oct 2018 at 12:32, Chris Angelico  wrote:

> On Mon, Oct 8, 2018 at 9:26 PM Steven D'Aprano 
> wrote:
> > > In other words, you change the *public interface* of your functions
> > > all the time? How do you not have massive breakage all the time?
> >
> > I can't comment about Marko's actual use-case, but *in general*
> > contracts are aimed at application *internal* interfaces, not so much
> > library *public* interfaces.
>
> Yet we keep having use-cases shown to us involving one person with one
> module, and another person with another module, and the interaction
> between the two. Which way is it? Do the contracts change frequently
> or not? Are they public or not? How are we supposed to understand the
> point of contracts if the use-cases being shown all involve bad code
> and/or bad coding practices?
>
> Contracts, apparently, allow people to violate versioning expectations
> and feel good about it.
>
> (Am I really exaggerating all that much here?)
>
> ChrisA
> ___
> Python-ideas mailing list
> Python-ideas@python.org
> https://mail.python.org/mailman/listinfo/python-ideas
> Code of Conduct: http://python.org/psf/codeofconduct/
>
___
Python-ideas mailing list
Python-ideas@python.org
https://mail.python.org/mailman/listinfo/python-ideas
Code of Conduct: http://python.org/psf/codeofconduct/


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

2018-10-08 Thread Chris Angelico
On Mon, Oct 8, 2018 at 9:26 PM Steven D'Aprano  wrote:
> > In other words, you change the *public interface* of your functions
> > all the time? How do you not have massive breakage all the time?
>
> I can't comment about Marko's actual use-case, but *in general*
> contracts are aimed at application *internal* interfaces, not so much
> library *public* interfaces.

Yet we keep having use-cases shown to us involving one person with one
module, and another person with another module, and the interaction
between the two. Which way is it? Do the contracts change frequently
or not? Are they public or not? How are we supposed to understand the
point of contracts if the use-cases being shown all involve bad code
and/or bad coding practices?

Contracts, apparently, allow people to violate versioning expectations
and feel good about it.

(Am I really exaggerating all that much here?)

ChrisA
___
Python-ideas mailing list
Python-ideas@python.org
https://mail.python.org/mailman/listinfo/python-ideas
Code of Conduct: http://python.org/psf/codeofconduct/


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

2018-10-08 Thread Steven D'Aprano
On Mon, Oct 08, 2018 at 04:29:34PM +1100, Chris Angelico wrote:
> On Mon, Oct 8, 2018 at 4:26 PM Marko Ristin-Kaufmann
>  wrote:
> >> Not true for good docstrings.  We very seldom change the essential
> >> meaning of public functions.
> >
> > In my team, we have a stale docstring once every two weeks or even more 
> > often.

"At Resolver we've found it useful to short-circuit any doubt and just
refer to comments in code as 'lies'. "
--Michael Foord paraphrases Christian Muirhead on python-dev, 2009-03-22


> If it weren't for doctests and contracts, I could imagine we would 
> have them even more often :)
> >
> 
> In other words, you change the *public interface* of your functions
> all the time? How do you not have massive breakage all the time?

I can't comment about Marko's actual use-case, but *in general* 
contracts are aimed at application *internal* interfaces, not so much 
library *public* interfaces.

That's not to say that contracts can't be used for libraries at all, but 
they're not so useful for public interfaces that could be called by 
arbitrary third-parties. They are more useful for internal interfaces, 
where you don't break anyone's code but your own if you change the API.

Think about it this way: you probably wouldn't hesitate much to change 
the interface of a _private method or function, aside from discussing it 
with your dev team. Sure it will break some code, but you have tests to 
identify the breakage, and maybe refactoring tools to help. And of 
course the contracts themselves are de facto tests. Such changes are 
manageable. And since its a private function, nobody outside of your 
team need care.

Same with contracts. (At least in the ideal case.)


-- 
Steve
___
Python-ideas mailing list
Python-ideas@python.org
https://mail.python.org/mailman/listinfo/python-ideas
Code of Conduct: http://python.org/psf/codeofconduct/


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

2018-10-08 Thread Marko Ristin-Kaufmann
Hi Chris,

In other words, you change the *public interface* of your functions
> all the time? How do you not have massive breakage all the time?


I suppose that Pycharm helps the most with its refactoring tools. We use
type annotations, contracts, static checks (mypy, pylint, pydocstyle) and
unit, integration and end-to-end tests, so actually unexpected breakages in
production are not that frequent. What does happen often, though, is that
documentation gets stale.

Cheers,
Marko

On Mon, 8 Oct 2018 at 07:29, Chris Angelico  wrote:

> On Mon, Oct 8, 2018 at 4:26 PM Marko Ristin-Kaufmann
>  wrote:
> >> Not true for good docstrings.  We very seldom change the essential
> >> meaning of public functions.
> >
> > In my team, we have a stale docstring once every two weeks or even more
> often. If it weren't for doctests and contracts, I could imagine we would
> have them even more often :)
> >
>
> In other words, you change the *public interface* of your functions
> all the time? How do you not have massive breakage all the time?
>
> ChrisA
> ___
> Python-ideas mailing list
> Python-ideas@python.org
> https://mail.python.org/mailman/listinfo/python-ideas
> Code of Conduct: http://python.org/psf/codeofconduct/
>
___
Python-ideas mailing list
Python-ideas@python.org
https://mail.python.org/mailman/listinfo/python-ideas
Code of Conduct: http://python.org/psf/codeofconduct/


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

2018-10-08 Thread Marko Ristin-Kaufmann
Hi,
I'd like to share a use pattern for contracts that might have got lost in
the discussion and which I personally grow to like more and more. I'm not
making any claims; this use pattern work for our team and I can't judge how
much of a benefit it would be to others.

Imagine there are two developers, Alice working on a package A, and Betty
working on a package B. Package A depends on package B.

Betty tested her package B with some test data D_B.

Alice tests her package A with some test data D_A. Now assume Betty did not
write any contracts for her package B. When Alice tests her package, she is
actually making an integration test. While she controls the inputs to B
from A, she can only observe the results from B, but not whether they are
correct by coincidence or B did its job correctly. Let's denote D'_B the
data that is given to B from her original test data D_A during Alice's
integration testing.

How can she test that package B gives the correct results on D'_B ? She
needs to manually record the data somehow (by dynamically mocking package B
and intercepting what gets passed from A to B?). She might fetch the tests
from the package B, copy/paste the test cases and append D'_B. Or she could
make a pull request and provide the extra test data directly to package B.
She needs to understand how Betty's unit tests work and see how D'_B fits
in there and what needs to be mocked.

All in all, not a trivial task if Alice is not familiar with the package B
and even less so if Alice and Betty don't work in the same organization.
Most of the time, Alice would not bother to test the dependencies on her
testing data D_A. She would assume that her dependencies work, and just
tests what comes out of them. If the results make sense, she would call it
a tick on her to-do list and move on with the next task.

Let's assume now that Betty wrote some contracts in her code. When Alice
runs the integration test of her package A, the contracts of B are
automatically verified on D'_B. While the contracts might not cover all the
cases that were covered in Betty's unit tests, they still cover some of
them. Alice can be a bit more confident that at least *something* was
checked on D'_B. Without the contracts, she would have checked *nothing* on
D'_B in most of her everyday programming.

You can consider writing contracts as a matter of economy in this story.
Betty might not need contracts for maintaining her package B -- she can
read her code, she can extend her test cases. However, you can see
contracts as a service to the package users, Alice in this case. Betty
helps Alice have some integration tests free-of-charge (free for Alice;
Betty of course pays the overhead of writing and maintaining the
contracts). Alice does not need to understand how B can be tested nor needs
to manually record data that needs to be passed to B. She merely runs her
test code and the checker library will do the testing of B on D'_B
automatically.

The utility of this service tends to grow exponentially in cases where
dependency trees grow exponentially as well. Imagine if we had Carol with
the package C, with the dependencies A -> B -> C. When Carol writes
contracts, she does a service not only to her direct users (Betty) but also
to the users of B (Alice). I don't see how Alice could practically cover
the case with dependencies A -> B -> C and test C with D'_C (*i.e. *test C
with the data coming from D_A) without the contracts unless she really
takes her time and gets familiar with dependencies of all here immediate
dependencies.

We found this pattern helpful in the team, especially during refactorings
where contracts provide an additional security net. We don't have time to
record and add tests of B for D'_B, and even less so of C for D'_C. The
contracts work thus as a good compromise for us (marginal overhead, but
better documentation and "free" integration tests rather than none).

Cheers,
Marko





On Sun, 30 Sep 2018 at 08:17, Marko Ristin-Kaufmann 
wrote:

> Hi,
>
> I compiled a couple of issues on github to provide a more structured
> ground for discussions on icontract features:
> https://github.com/Parquery/icontract/issues (@David Maertz: I also
> included the issue with automatically generated __doc__ in case you are
> still interested in it).
>
> Cheers,
> Marko
>
> On Sat, 29 Sep 2018 at 17:27, Stephen J. Turnbull <
> turnbull.stephen...@u.tsukuba.ac.jp> wrote:
>
>> Steven D'Aprano writes:
>>
>>  > put (x: ELEMENT; key: STRING) is
>>  >  -- Insert x so that it will be retrievable through key.
>>  >  require
>>  >  count <= capacity
>>  >  not key.empty
>>  >  do
>>  >  ... Some insertion algorithm ...
>>  >  ensure
>>  >  has (x)
>>  >  item (key) = x
>>  >  count = old count + 1
>>  >  end
>>  >
>>  > Two pre-conditions, and three post-conditions. That's hardly
>>  > complex.
>>
>> You can already do this:
>>
>> def put(self, 

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

2018-10-07 Thread Chris Angelico
On Mon, Oct 8, 2018 at 4:26 PM Marko Ristin-Kaufmann
 wrote:
>> Not true for good docstrings.  We very seldom change the essential
>> meaning of public functions.
>
> In my team, we have a stale docstring once every two weeks or even more 
> often. If it weren't for doctests and contracts, I could imagine we would 
> have them even more often :)
>

In other words, you change the *public interface* of your functions
all the time? How do you not have massive breakage all the time?

ChrisA
___
Python-ideas mailing list
Python-ideas@python.org
https://mail.python.org/mailman/listinfo/python-ideas
Code of Conduct: http://python.org/psf/codeofconduct/


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

2018-10-07 Thread Marko Ristin-Kaufmann
Hi Terry,

I would encourage you to read all the messages on the thread. The points
you raised were actually already discussed:
* Using formal contracts in the code does not imply that you must specify
*all* the contracts; you specify what you consider meaningful.
* Distinction of result/process (the example that was already discussed was
related to GUIs and pathlib standard library)

> b)//If you write contracts in text, they will become stale over time
>
> Not true for good docstrings.  We very seldom change the essential
> meaning of public functions.


In my team, we have a stale docstring once every two weeks or even more
often. If it weren't for doctests and contracts, I could imagine we would
have them even more often :)

I suppose good docstrings require many reviewers and slow refactoring
processes. Our public interfaces are changing daily and there is one
reviewer per pull request. If github/bitbucket allowed for better
highlighting of docstrings in code reviews (*e.g., *if it highlighted the
docstring of every function that changed), the miss rate would be probably
lower. I'm always happy to hear other experiences how people dealt with
requirements changing at a fast pace and how they dealt with code rot in a
team of limited size and time resources.

I agree with you that a good docstring is not stale by definition. I have
just never experienced a team that had good docstrings in my career.

Cheers,
Marko

On Sun, 7 Oct 2018 at 22:25, Terry Reedy  wrote:

> On 9/24/2018 3:46 AM, Marko Ristin-Kaufmann wrote:
>
> I am responding to your request "Please do point me to what is not
> obvious to you".  I think some of your claims are not only not obvious,
> but are wrong.  I have read some (probably less than half) of the
> responses and avoid saying what I know others have covered adequately.
>
> A mathematical function is defined or specified by a input domain,
> output range, and a mapping from inputs to outputs.  The mapping can be
> defined either by an explicit listing of input-output pairs or by a rule
> specifying either a) the process, what is done to inputs to produce
> outputs or, b) the result, how the output relates to the input.
>
>  >
>
> https://www.win.tue.nl/~wstomv/edu/2ip30/references/design-by-contract/index.html
>
> defines contracts as "precise (legally unambiguous) specifications" (5.2
> Business Contracting/Sub-contracting Metaphor)  It is not obvious to me
> that the metaphor of contracts adds anything worthwhile to the idea of
> 'function'.
>
> 1. Only a small sliver of human interactions are governed by formal
> legal contracts read, understood, and agreed to by both (all) parties.
>
> 2. The idealized definition is naive in practice.  Most legal contracts,
> unlike the example in the link article, are written in language that
> most people cannot read.  Many contracts are imprecise and legally
> ambiguous, which is why we have contract dispute courts.  And even then,
> the expense means that most people who feel violated in a transaction do
> not use courts.
>
> Post-conditions specify a function by result.  I claim that this is not
> always sensible.  I said above that functions may be specified by
> process rather than result.  Ironically, the contract metaphor
> reinforces my claim.  Many contracts, such as in teaching and medicine,
> only specify process and explicitly disclaim any particular result of
> concern to the client.
>
> > b)//If you write contracts in text, they will become stale over time
>
> Not true for good docstrings.  We very seldom change the essential
> meaning of public functions.
>
> How has "Return the sine of x (measured in radians).", for math.sin,
> become stale?  Why would it ever?  What formal executable post condition
> would help someone who does not understand 'sine', or 'sine of x'?  The
> function is only useful for someone who either understands 'sine' or is
> copying a formula written elsewhere without needing to understand it.
>
> Or consider "Stable sort *IN PLACE*." for list.sort.  A formal
> executable post-condition for this *can* be written.  But for someone
> who understands the words 'stable', 'sort', and 'in place', this compact
> English post condition is much more readable than any formal version
> could be.  More over, that addition of 'stable', when we were ready to
> do so, did not make "Sort *IN PLACE*" stale in any sense of being wrong.
>
> I said above that functions definitions and contracts can specify the
> process rather than the result.  For functions, the code is the process,
> and the code may then be the specification and the contract.  For instance,
>
> def append_first(seq):
>  "Append seq[0] to seq."
>
> So seq must have a first element accessed as seq[0] and an append method
> that accepts the first element as an argument.  One might guess the
> minimal body.
>
>  return seq.append(seq[0])
>
> The pre-condition here is that the return value can be calculated as
> specified.  Whenever this is true, 

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

2018-10-07 Thread Terry Reedy

On 9/24/2018 3:46 AM, Marko Ristin-Kaufmann wrote:

I am responding to your request "Please do point me to what is not 
obvious to you".  I think some of your claims are not only not obvious, 
but are wrong.  I have read some (probably less than half) of the 
responses and avoid saying what I know others have covered adequately.


A mathematical function is defined or specified by a input domain, 
output range, and a mapping from inputs to outputs.  The mapping can be 
defined either by an explicit listing of input-output pairs or by a rule 
specifying either a) the process, what is done to inputs to produce 
outputs or, b) the result, how the output relates to the input.


> 
https://www.win.tue.nl/~wstomv/edu/2ip30/references/design-by-contract/index.html 

defines contracts as "precise (legally unambiguous) specifications" (5.2 
Business Contracting/Sub-contracting Metaphor)  It is not obvious to me 
that the metaphor of contracts adds anything worthwhile to the idea of 
'function'.


1. Only a small sliver of human interactions are governed by formal 
legal contracts read, understood, and agreed to by both (all) parties.


2. The idealized definition is naive in practice.  Most legal contracts, 
unlike the example in the link article, are written in language that 
most people cannot read.  Many contracts are imprecise and legally 
ambiguous, which is why we have contract dispute courts.  And even then, 
the expense means that most people who feel violated in a transaction do 
not use courts.


Post-conditions specify a function by result.  I claim that this is not 
always sensible.  I said above that functions may be specified by 
process rather than result.  Ironically, the contract metaphor 
reinforces my claim.  Many contracts, such as in teaching and medicine, 
only specify process and explicitly disclaim any particular result of 
concern to the client.


b)//If you write contracts in text, they will become stale over time 


Not true for good docstrings.  We very seldom change the essential 
meaning of public functions.


How has "Return the sine of x (measured in radians).", for math.sin, 
become stale?  Why would it ever?  What formal executable post condition 
would help someone who does not understand 'sine', or 'sine of x'?  The 
function is only useful for someone who either understands 'sine' or is 
copying a formula written elsewhere without needing to understand it.


Or consider "Stable sort *IN PLACE*." for list.sort.  A formal 
executable post-condition for this *can* be written.  But for someone 
who understands the words 'stable', 'sort', and 'in place', this compact 
English post condition is much more readable than any formal version 
could be.  More over, that addition of 'stable', when we were ready to 
do so, did not make "Sort *IN PLACE*" stale in any sense of being wrong.


I said above that functions definitions and contracts can specify the 
process rather than the result.  For functions, the code is the process, 
and the code may then be the specification and the contract.  For instance,


def append_first(seq):
"Append seq[0] to seq."

So seq must have a first element accessed as seq[0] and an append method 
that accepts the first element as an argument.  One might guess the 
minimal body.


return seq.append(seq[0])

The pre-condition here is that the return value can be calculated as 
specified.  Whenever this is true, python is already testing 
pre-conditions, as efficiently as possible.  We could elaborate the body as


try:
return seq.append(seq[0])
except Exception as e:
raise ValueError('raised ' + repr(e)[0])

and add 'Raise ValueError with explanation on bad input' to the doc string.

If the domain were restricted to lists, we could write a post-condition, 
and use that in a list-based unittest.  However, it likely be less 
readable than the docstring, and would execute in O(n) time (for an O(1) 
function).  The latter is acceptable for unittests, which will use short 
tests, but not for production.  But with duck-typing, no post condition 
is possible.  Neither is a generic unittest.  The code *is* the 
contract.  This is generally true of duck-typed Python code.


--
Terry Jan Reedy

___
Python-ideas mailing list
Python-ideas@python.org
https://mail.python.org/mailman/listinfo/python-ideas
Code of Conduct: http://python.org/psf/codeofconduct/


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

2018-10-01 Thread David Mertz
On Mon, Oct 1, 2018, 9:13 PM Steven D'Aprano  wrote:

> For an application, it doesn't matter if my function sets the computer on
> fire when passed the string "fish", if there is no way for the application
> to pass that string to the function. If it can't happen, it can't happen
> and there's no need to defend against it beyond a regression test.
>

How many times have you written or seen a comment in code similar to "This
can't possibly happen!!" ... Usually in response to a failed debugging
attempt.

It's really hard to understands all possible execution paths that might
result from all possible inputs and program states. "Fail early and fail
hard" is a good principle... And indeed one generally in a spirit
compatible with DbC.

Beware of bugs in the above code; I have only proved it correct, not tried
it.

   - Donald Knuth
___
Python-ideas mailing list
Python-ideas@python.org
https://mail.python.org/mailman/listinfo/python-ideas
Code of Conduct: http://python.org/psf/codeofconduct/


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

2018-10-01 Thread Steven D'Aprano
On Mon, Oct 01, 2018 at 12:36:18PM -0400, David Mertz wrote:

> There's some saying/joke about software testing along the lines of:
> 
> For an argument that should be in range 1-100:
>   try 50; try 1; try 100
>   try 101; try 0;
>   try -1,
>   try 3.14
>   try 1+1j;
>   try the string "fish",
>   try a null pointer;
>   etc.
> 
> Many of those oddball cases can easily be in a list of values to test in
> unit tests, but may be impossible or unlikely to make it to the function
> call in the normal/possible flow of the program.

Right. And for a *library*, you must handle out of range errors, because 
the library cannot trust the input passed to it by third parties. If a 
third party passes "fish" as an argument, that's not a bug in the 
library and the library cannot fix it, it should handle the error 
gracefully with a sensible error message.

But for an *application*, the internal routines are completely under 
control of the one developer team. If an internal routine passes "fish", 
that's a bug that the dev team can and ought to fix. Once that bug is
fixed, there's no need to check for "fish" in production code. Its a 
waste of time.

(In principle at least -- it depends on how confident you or your QA 
team are that all the bugs are ironed out. Do you ship your apps with 
debugging turned off? Then you might ship with contract checking turned 
off, or at least dialled back to a lower level.)

For an application, it doesn't matter if my function sets the computer 
on fire when passed the string "fish", if there is no way for the 
application to pass that string to the function. If it can't happen, it 
can't happen and there's no need to defend against it beyond a 
regression test.

(Modulo comments about how confident you are about the software 
quality.)

For a library, anyone can pass "fish" to anything, so you better handle 
it gracefully rather than setting the computer on fire.

For application developers, the point of contracts is to make error 
conditions *impossible* rather than to just defend against them, so you 
can turn off the defensive error checking in production because they 
aren't needed.



> > I'm curious. When you write a function or method, do you include input
> > checks? Here's an example from the Python stdlib (docstring removed for
> > brevity):
> >
> > # bisect.py
> > def insort_right(a, x, lo=0, hi=None):
> > if lo < 0:
> > raise ValueError('lo must be non-negative')
> > if hi is None:
> > hi = len(a)
> > while lo < hi:
> > mid = (lo+hi)//2
> > if x < a[mid]: hi = mid
> > else: lo = mid+1
> > a.insert(lo, x)
> >
> > Do you consider that check for lo < 0 to be disruptive? How would you
> > put that in a unit test?
> >
> 
> I definitely put in checks like that.  However, I might well write a test
> like:
> 
> assert lo >= 0, "lo must be non-negative"
> 
> That would allow disabling the check for production.

For a library function, I would consider that an abuse of assert, since:

(1) It raises the wrong exception (AssertionError);

(2) It can be disabled;

(3) And it sends the wrong message, telling the reader that lo is an 
internal implementation detail rather than part of the function's 
external API.



> However, I presume
> the stdlib does this for a reason; it presumably wants to allow callers to
> catch a specific exception.  I haven't seen anything in the contract
> discussion that allows raising a particular exception when a contract is
> violated, only a general one for all contracts.

I think that the Eiffel philosophy is that all contract violations are 
assertion errors, but I'm not really confident in my understanding of 
Eiffel's exception mechanism. It doesn't have a generalised try...except 
statement like Python.

If Python had contracts, I'd want to see:

- by default, contract violations raise specific subclasses 
  of AssertionError, e.g. RequireError, EnsureError;

- but there ought to be a mechanism to allow specific errors 
  to raise more specific exceptions.

I haven't given any thought to that mechanism. It might simply be "the 
status quo" -- there's no reason why we *must* move defensive input 
checking into the (hypothetical) require block just because it is 
available. You can still write your test the old fashioned way in the 
body of the function and raise the exception of your choice.


> The case of 'if hi is None' is different.  It's remediation of a missing
> value where it's perfectly fine to impute an unspecified value.  So that
> would be a poor contract.

Since the check for None is not error checking at all, I didn't talk 
about it or make it a precondition test.



-- 
Steve
___
Python-ideas mailing list
Python-ideas@python.org
https://mail.python.org/mailman/listinfo/python-ideas
Code of Conduct: http://python.org/psf/codeofconduct/


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

2018-10-01 Thread David Mertz
On Sun, Sep 30, 2018 at 11:34 AM Steven D'Aprano 
wrote:

> On Sun, Sep 30, 2018 at 10:29:50AM -0400, David Mertz wrote:
> But given that in general unit tests tend to only exercise a handful of
> values (have a look at the tests in the Python stdlib) I think it is
> fair to say that in practice unit tests typically do not have anywhere
> near the coverage of live data used during alpha and beta testing.
>

I still think it's a mixture.  I write tests to also address "this really
shouldn't happen" cases as well (often in a loop, or using a Nose class for
scaffolding).

There's some saying/joke about software testing along the lines of:

For an argument that should be in range 1-100:
  try 50; try 1; try 100
  try 101; try 0;
  try -1,
  try 3.14
  try 1+1j;
  try the string "fish",
  try a null pointer;
  etc.

Many of those oddball cases can easily be in a list of values to test in
unit tests, but may be impossible or unlikely to make it to the function
call in the normal/possible flow of the program.


> I'm curious. When you write a function or method, do you include input
> checks? Here's an example from the Python stdlib (docstring removed for
> brevity):
>
> # bisect.py
> def insort_right(a, x, lo=0, hi=None):
> if lo < 0:
> raise ValueError('lo must be non-negative')
> if hi is None:
> hi = len(a)
> while lo < hi:
> mid = (lo+hi)//2
> if x < a[mid]: hi = mid
> else: lo = mid+1
> a.insert(lo, x)
>
> Do you consider that check for lo < 0 to be disruptive? How would you
> put that in a unit test?
>

I definitely put in checks like that.  However, I might well write a test
like:

assert lo >= 0, "lo must be non-negative"

That would allow disabling the check for production.  However, I presume
the stdlib does this for a reason; it presumably wants to allow callers to
catch a specific exception.  I haven't seen anything in the contract
discussion that allows raising a particular exception when a contract is
violated, only a general one for all contracts.

The case of 'if hi is None' is different.  It's remediation of a missing
value where it's perfectly fine to impute an unspecified value.  So that
would be a poor contract.

-- 
Keeping medicines from the bloodstreams of the sick; food
from the bellies of the hungry; books from the hands of the
uneducated; technology from the underdeveloped; and putting
advocates of freedom in prisons.  Intellectual property is
to the 21st century what the slave trade was to the 16th.
___
Python-ideas mailing list
Python-ideas@python.org
https://mail.python.org/mailman/listinfo/python-ideas
Code of Conduct: http://python.org/psf/codeofconduct/


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

2018-09-30 Thread Steven D'Aprano
On Sun, Sep 30, 2018 at 10:29:50AM -0400, David Mertz wrote:

> I think Steven's is backwards in its own way.
> 
>- Contracts test the space of arguments *actually used during testing
>period* (or during initial production if the performance hit is
>acceptable).
>- Unit tests test the space of arguments *thought of by the developers*.
> 
> *A priori,* either one of those can cover cases not addressed by the
> other.

Fair point.

But given that in general unit tests tend to only exercise a handful of 
values (have a look at the tests in the Python stdlib) I think it is 
fair to say that in practice unit tests typically do not have anywhere 
near the coverage of live data used during alpha and beta testing.


> If unit tests use the hypothesis library or similar approaches,
> unit tests might very well examine arguments unlikely to be encountered in
> real-world (or test phase) use... 

Indeed.

We can consider all of these things as complementary:

- doctests give us confidence that the documentation hasn't rotted;

- unit tests give us confidence that corner cases are tested;

- contracts give us confidence that regular and common cases are tested;

- regression tests give us confidence that bugs aren't re-introduced;

- smoke tests give us confidence that the software at least will run;

- static type checking allows us to drop type checks from our unit 
  tests and contracts;

but of course there can be overlap. And that's perfectly fine.


[...]
> - Half of the checks are very far away, in a separate file, assuming
> >   I even remembered or bothered to write the test.
> >
> 
> To me, this is the GREATEST VIRTUE of unit tests over DbC.  It puts the
> tests far away where they don't distract from reading and understanding the
> function itself.  I rarely want my checks proximate since I wear a very
> different hat when thinking about checks than when writing functionality
> (ideally, a lot of the time, I wear the unit test hat *before* I write the
> implementation; TDD is usually good practice).

I'm curious. When you write a function or method, do you include input 
checks? Here's an example from the Python stdlib (docstring removed for 
brevity):

# bisect.py
def insort_right(a, x, lo=0, hi=None):
if lo < 0:
raise ValueError('lo must be non-negative')
if hi is None:
hi = len(a)
while lo < hi:
mid = (lo+hi)//2
if x < a[mid]: hi = mid
else: lo = mid+1
a.insert(lo, x)

Do you consider that check for lo < 0 to be disruptive? How would you 
put that in a unit test?

That check is effectively a pre-condition. Putting aside the question of 
which exception should be raised (AssertionError or ValueError), we 
could re-write that as a contract:

def insort_right(a, x, lo=0, hi=None):
require:
lo >= 0
# implementation follows, as above
if hi is None:
hi = len(a)
while lo < hi:
mid = (lo+hi)//2
if x < a[mid]: hi = mid
else: lo = mid+1
a.insert(lo, x)

Do you consider that precondition check for lo >= to be disruptive? More 
or less disruptive than when it was in the body of the function 
implementation?



> > - The post-conditions aren't checked unless I run my test suite, and
> >   then they only check the canned input in the test suite.
> >
> 
> Yes, this is a great advantage of unit tests.  No cost until you explicitly
> run them.

If you're worried about the cost of verifying your program does the 
right thing during testing and development, I think you're doing 
something wrong :-)

If there are specific functions/classes where the tests are insanely 
expensive, that's one thing. I have some code that wants to verify that 
a number is prime as part of an informal post-condition check, but if it 
is a *big* prime that check is too costly so I skip it.

But in general, if I'm testing or under active development, what do I 
care if the program takes 3 seconds to run instead of 2.5 seconds? 
Either way, its finished by the time I come back from making my coffee
:-)

But more seriously, fine, if a particular contract is too expensive to 
run, disable it or remove it and add some unit tests. And then your 
devs will complain that the unit tests are too slow, and stop running 
them, and that's why we can't have nice things... *wink*


-- 
Steve
___
Python-ideas mailing list
Python-ideas@python.org
https://mail.python.org/mailman/listinfo/python-ideas
Code of Conduct: http://python.org/psf/codeofconduct/


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

2018-09-30 Thread David Mertz
On Sat, Sep 29, 2018 at 7:20 AM Steven D'Aprano  wrote:

> On Wed, Sep 26, 2018 at 04:03:16PM +0100, Rhodri James wrote:
> > Assuming that you
> > aren't doing some kind of wide-ranging static analysis (which doesn't
> > seem to be what we're talking about), all that the contracts have bought
> > you is the assurance that *this* invocation of the function with *these*
> > parameters giving *this* result is what you expected.  It does not say
> > anything about the reliability of the function in general.
>
> This is virtually the complete opposite of what contracts give us. What
> you are describing is the problem with *unit testing*, not contracts.
>

I think Steven's is backwards in its own way.

   - Contracts test the space of arguments *actually used during testing
   period* (or during initial production if the performance hit is
   acceptable).
   - Unit tests test the space of arguments *thought of by the developers*.

*A priori,* either one of those can cover cases not addressed by the
other.  If unit tests use the hypothesis library or similar approaches,
unit tests might very well examine arguments unlikely to be encountered in
real-world (or test phase) use... these are nonetheless edge cases that are
important to assure correct behavior on ("correct" can mean various things,
of course: exceptions, recovery, default values whatever).

In contrast, contracts might well find arguments that the developers of
unit tests had not thought of.  I tend to think someone sitting down trying
to think of edge cases is going to be able to write more thorough tests
than the accident of "what did we see during this run" ... but it could go
either way.

Of course... my own approach to this concern would more likely be to use a
logging decorator rather than a DbC one.  Then collect those logs that show
all the arguments that were passed to a given function during a testing
period, and roll those back into the unit tests.  My approach is a bit more
manual work, but also more flexible and more powerful.

- Half of the checks are very far away, in a separate file, assuming
>   I even remembered or bothered to write the test.
>

To me, this is the GREATEST VIRTUE of unit tests over DbC.  It puts the
tests far away where they don't distract from reading and understanding the
function itself.  I rarely want my checks proximate since I wear a very
different hat when thinking about checks than when writing functionality
(ideally, a lot of the time, I wear the unit test hat *before* I write the
implementation; TDD is usually good practice).


> - The post-conditions aren't checked unless I run my test suite, and
>   then they only check the canned input in the test suite.
>

Yes, this is a great advantage of unit tests.  No cost until you explicitly
run them.


> - No class invariants.
> - Inheritance is not handled correctly.
>

These are true.  Also they are things I care very little about.

-- 
Keeping medicines from the bloodstreams of the sick; food
from the bellies of the hungry; books from the hands of the
uneducated; technology from the underdeveloped; and putting
advocates of freedom in prisons.  Intellectual property is
to the 21st century what the slave trade was to the 16th.
___
Python-ideas mailing list
Python-ideas@python.org
https://mail.python.org/mailman/listinfo/python-ideas
Code of Conduct: http://python.org/psf/codeofconduct/


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

2018-09-30 Thread Steven D'Aprano
On Fri, Sep 28, 2018 at 01:49:01PM +0100, Paul Moore wrote:

> There's clearly a number of trade-offs going on here:
> 
> * Conditions should be short, to avoid clutter
> * Writing helper functions that are *only* used in conditions is more
> code to test or get wrong

This is no different from any other refactoring. If you have a function 
that checks its input:

def spam(arg):
if condition(arg) and other_condition(arg) or alt_condition(arg):
raise ValueError

and refactor it to a helper:

def invalid(arg):
return condition(arg) and other_condition(arg) or alt_condition(arg)

def spam(arg):
if invalid(arg):
raise ValueError

how is that a bad thing just because we call it a "precondition" instead 
of calling it "error checking"?

Of course we don't necessarily want the proliferation of masses and 
masses of tiny helper functions, but nor should we fear them. Helpers 
should carry their own weight, and if they do, we should use them. 
Whether they are used for contracts or not makes zero difference.


> * Sometimes it's just plain hard to express a verbal constraint in code

Indeed.

People seem to be arguing against some strawman of "Design By Contract 
is a magic bullet that solves every imaginable problem". Of course it 
doesn't. Some constraints are too hard to specify as code. Okay, then 
don't do that.

DbC isn't "all or nothing". If you can't write a contract for something, 
don't. You still get value from the contracts you do write.


[...]
> But given that *all* the examples I've seen of contracts have this
> issue (difficult to read expressions) I suspect the problem is
> inherent.

Are you specifically talking about *Python* examples? Or contracts in 
general?

I don't know Eiffel very well, but I find this easy to read and 
understand (almost as easy as Python). The trickiest thing is the 
implicit "self".

put (x: ELEMENT; key: STRING) is
-- Insert x so that it will be retrievable through key.
require
count <= capacity
not key.empty
do
... Some insertion algorithm ...
ensure
has (x)
item (key) = x 
count = old count + 1
end

https://www.eiffel.com/values/design-by-contract/introduction/


Here are a couple of examples from Cobra:

def fraction( numer as int, denom as int) as float
require
numer > 0
denom <> 0
body
  ...

def bumpState( incr as int) as int
require
incr > 0
ensure 
result >= incr
.state = old.state + incr 
body
  .state += incr
  return .state


http://cobra-language.com/trac/cobra/wiki/Contracts


If you find them difficult to read, I don't know what to say :-)



> Another thing that I haven't yet seen clearly explained. How do these
> contracts get *run*? Are they checked on every call to the function,

Yes, that's the point of them. In development they're always on. Every 
time you run your dev code, it tests itself.


> even in production code? 

That's up to you, but typical practice is to check pre-conditions (your 
input) but not post-conditions (your output) in production.


> Is there a means to turn them off? What's the
> runtime overhead of a "turned off" contract (even if it's just an
> if-test per condition, that can still add up)?


Other languages may offer different options, but in Eiffel, contracts 
checking can be set to:

no:assertions have no run-time effect.
require:   monitor preconditions only, on routine entry.
ensure:preconditions on entry, postconditions on exit.
invariant: same as ensure, plus class invariant on both entry
   and exit for qualified calls.
all:   same as invariant, plus check instructions, 
   loop invariants and loop variants.

You can set the checking level globally, or class-by-class. The default 
is to check only preconditions. That is, for methods to validate their 
inputs. Quoting from the Eiffel docs:

When releasing the final version of a system, it is usually 
appropriate to turn off assertion monitoring, or bring it down
to the ``require`` level. The exact policy depends on the 
circumstances; it is a trade off between efficiency considerations, 
the potential cost of mistakes, and how much the developers and 
quality assurance team trust the product. When developing the 
software, however, you should always assume -- to avoid loosening 
your guard -- that in the end monitoring will be turned off. 

https://www.eiffel.org/doc/eiffel/ET-_Design_by_Contract_%28tm%29%2C_Assertions_and_Exceptions


The intention for Python would be similar:

- we ought to be able disable contract checking globally;

- and preferrably on a case-by-case basis;

- a disabled contact ought to be like a disabled assertion, 
  that is, completely gone with no 

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

2018-09-30 Thread Marko Ristin-Kaufmann
Hi,

I compiled a couple of issues on github to provide a more structured ground
for discussions on icontract features:
https://github.com/Parquery/icontract/issues (@David Maertz: I also
included the issue with automatically generated __doc__ in case you are
still interested in it).

Cheers,
Marko

On Sat, 29 Sep 2018 at 17:27, Stephen J. Turnbull <
turnbull.stephen...@u.tsukuba.ac.jp> wrote:

> Steven D'Aprano writes:
>
>  > put (x: ELEMENT; key: STRING) is
>  >  -- Insert x so that it will be retrievable through key.
>  >  require
>  >  count <= capacity
>  >  not key.empty
>  >  do
>  >  ... Some insertion algorithm ...
>  >  ensure
>  >  has (x)
>  >  item (key) = x
>  >  count = old count + 1
>  >  end
>  >
>  > Two pre-conditions, and three post-conditions. That's hardly
>  > complex.
>
> You can already do this:
>
> def put(self, x: Element, key: str) -> None:
> """Insert x so that it will be retrievable through key."""
>
> # CHECKING PRECONDITIONS
> _old_count = self.count
> assert self.count <= self.capacity,
> assert key
>
> # IMPLEMENTATION
> ... some assertion algorithm ...
>
> # CHECKING POSTCONDITIONS
> assert x in self
> assert self[key] == x
> assert self.count == _old_count
>
> return
>
> I don't see a big advantage to having syntax, unless the syntax allows
> you to do things like turn off "expensive" contracts only.  Granted,
> you save a little bit of typing and eye movement (you can omit
> "assert" and have syntax instead of an assignment for checking
> postconditions dependent on initial state).
>
> A document generator can look for the special comments (as with
> encoding cookies), and suck in all the asserts following until a
> non-assert line of code (or the next special comment).  The
> assignments will need special handling, an additional special comment
> or something.  With PEP 572, I think you could even do this:
>
> assert ((_old_count := self.count),)
>
> to get the benefit of python -O here.
>
>  > If I were writing this in Python, I'd write something like this:
>  >
>  > def put(self, x, key):
>  > """Insert x so that it will be retrievable through key."""
>  > # Input checks are pre-conditions!
>  > if self.count > capacity:
>  > raise DatabaseFullError
>  > if not key:
>  > raise ValueError
>  > # .. Some insertion algorithm ...
>
> But this is quite different, as I understand it.  Nothing I've seen in
> the discussion so far suggests that a contract violation allows
> raising differentiated exceptions, and it seems very unlikely from the
> syntax in your example above.  I could easily see both of these errors
> being retryable:
>
> for _ in range(3):
> try:
> db.put(x, key)
> except DatabaseFullError:
> db.resize(expansion_factor=1.5)
> db.put(x, key)
> except ValueError:
> db.put(x, alternative_key)
>
>  > and then stick the post-conditions in a unit test, usually in a
>  > completely different file:
>
> If you like the contract-writing style, why would you do either of
> these instead of something like the code I wrote above?
>
>  > So what's wrong with the status quo?
>  >
>  > - The pre-condition checks are embedded right there in the
>  >   method implementation, mixing up the core algorithm with the
>  >   associated error checking.
>
> You don't need syntax to separate them, you can use a convention, as I
> did above.
>
>  > - Which in turn makes it hard to distinguish the checks from
>  >   the implementation, and impossible to do so automatically.
>
> sed can do it, why can't we?
>
>  > - Half of the checks are very far away, in a separate file,
>  >   assuming I even remembered or bothered to write the test.
>
> That was your choice.  There's nothing about the assert statement that
> says you're not allowed to use it at the end of a definition.
>
>  > - The post-conditions aren't checked unless I run my test suite, and
>  >   then they only check the canned input in the test suite.
>
> Ditto.
>
>  > - The pre-conditions can't be easily disabled in production.
>
> What's so hard about python -O?
>
>  > - No class invariants.
>
> Examples?
>
>  > - Inheritance is not handled correctly.
>
> Examples?  Mixins and classes with additional functionality should
> work fine AFAICS.  I guess you'd have to write the contracts in each
> subclass of an abstract class, which is definitely a minus for some of
> the contracts.  But I don't see offhand why you would expect that the
> full contract of a method of a parent class would typically make sense
> without change for an overriding implementation, and might not make
> sense for a class with restricted functionality.
>
>  > The status quo is all so very ad-hoc and messy. Design By Contract
>  > syntax would 

Re: [Python-ideas] Why is design-by-contracts not widely

2018-09-29 Thread Chris Angelico
On Sun, Sep 30, 2018 at 12:43 AM Steven D'Aprano  wrote:
>
> On Sat, Sep 29, 2018 at 10:15:42PM +1000, Chris Angelico wrote:
>
> [...]
> > As are all the things that are "undefined behaviour" in C, like the
> > result of integer overflow in a signed variable. They are "Here be
> > dragons" territory, but somehow that's not okay for you. I don't
> > understand why you can hate on C for having behaviours where you're
> > told "don't do that, we can't promise anything", but it's perfectly
> > acceptable for Python to have the exact same thing.
>
> They're not the same thing, not even close to the same thing.
>
> Undefined behaviour in C is a radically different concept to the
> *implementation-defined behaviour* you describe in Python and most
> (all?) other languages. I don't know how to communicate that message any
> better than the pages I linked to before.

Considering that many people here, myself included, still haven't
understood what you're so het up about, I think you may need to work
on communicating that better. It's still just "stuff you should never
do". The compiler is allowed to assume you will never do it. How is
that even slightly different from "the CPython interpreter is allowed
to assume you won't use ctypes to change a reference count"?

ChrisA
___
Python-ideas mailing list
Python-ideas@python.org
https://mail.python.org/mailman/listinfo/python-ideas
Code of Conduct: http://python.org/psf/codeofconduct/


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

2018-09-29 Thread Stephen J. Turnbull
Steven D'Aprano writes:

 > put (x: ELEMENT; key: STRING) is
 >  -- Insert x so that it will be retrievable through key.
 >  require
 >  count <= capacity
 >  not key.empty
 >  do
 >  ... Some insertion algorithm ...
 >  ensure
 >  has (x)
 >  item (key) = x 
 >  count = old count + 1
 >  end
 > 
 > Two pre-conditions, and three post-conditions. That's hardly
 > complex.

You can already do this:

def put(self, x: Element, key: str) -> None:
"""Insert x so that it will be retrievable through key."""

# CHECKING PRECONDITIONS
_old_count = self.count
assert self.count <= self.capacity,
assert key

# IMPLEMENTATION
... some assertion algorithm ...

# CHECKING POSTCONDITIONS
assert x in self
assert self[key] == x
assert self.count == _old_count

return

I don't see a big advantage to having syntax, unless the syntax allows
you to do things like turn off "expensive" contracts only.  Granted,
you save a little bit of typing and eye movement (you can omit
"assert" and have syntax instead of an assignment for checking
postconditions dependent on initial state).

A document generator can look for the special comments (as with
encoding cookies), and suck in all the asserts following until a
non-assert line of code (or the next special comment).  The
assignments will need special handling, an additional special comment
or something.  With PEP 572, I think you could even do this:

assert ((_old_count := self.count),)

to get the benefit of python -O here.

 > If I were writing this in Python, I'd write something like this:
 > 
 > def put(self, x, key):
 > """Insert x so that it will be retrievable through key."""
 > # Input checks are pre-conditions!
 > if self.count > capacity:
 > raise DatabaseFullError
 > if not key:
 > raise ValueError
 > # .. Some insertion algorithm ...

But this is quite different, as I understand it.  Nothing I've seen in
the discussion so far suggests that a contract violation allows
raising differentiated exceptions, and it seems very unlikely from the
syntax in your example above.  I could easily see both of these errors
being retryable:

for _ in range(3):
try:
db.put(x, key)
except DatabaseFullError:
db.resize(expansion_factor=1.5)
db.put(x, key)
except ValueError:
db.put(x, alternative_key)

 > and then stick the post-conditions in a unit test, usually in a 
 > completely different file:

If you like the contract-writing style, why would you do either of
these instead of something like the code I wrote above?

 > So what's wrong with the status quo?
 > 
 > - The pre-condition checks are embedded right there in the 
 >   method implementation, mixing up the core algorithm with the 
 >   associated error checking.

You don't need syntax to separate them, you can use a convention, as I
did above.

 > - Which in turn makes it hard to distinguish the checks from
 >   the implementation, and impossible to do so automatically.

sed can do it, why can't we?

 > - Half of the checks are very far away, in a separate file,
 >   assuming I even remembered or bothered to write the test.

That was your choice.  There's nothing about the assert statement that
says you're not allowed to use it at the end of a definition.

 > - The post-conditions aren't checked unless I run my test suite, and
 >   then they only check the canned input in the test suite.

Ditto.

 > - The pre-conditions can't be easily disabled in production.

What's so hard about python -O?

 > - No class invariants.

Examples?

 > - Inheritance is not handled correctly.

Examples?  Mixins and classes with additional functionality should
work fine AFAICS.  I guess you'd have to write the contracts in each
subclass of an abstract class, which is definitely a minus for some of
the contracts.  But I don't see offhand why you would expect that the
full contract of a method of a parent class would typically make sense
without change for an overriding implementation, and might not make
sense for a class with restricted functionality.

 > The status quo is all so very ad-hoc and messy. Design By Contract 
 > syntax would allow (not force, allow!) us to add some structure to the 
 > code:
 > 
 > - requirements of the function
 > - the implementation of the function
 > - the promise made by the function

Possible already as far as I can see.  OK, you could have the compiler
enforce the structure to some extent, but the real problem IMO is
going to be like documentation and testing: programmers just won't do
it regardless of syntax to make it nice and compiler checkable.

 > Most of us already think about these as three separate things, and 
 > document them as such. Our code should reflect the structure of how we 
 > think 

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

2018-09-29 Thread Stephen J. Turnbull
Steven D'Aprano writes:

 > I just wish we didn't have to fight so hard to justify the very
 > idea of contracts themselves.

You don't.  You need to justify putting them in the stdlib.  That's a
pretty high bar.  And as crappy as the contracts in Marko's pathlib
rewrite look to me, I suspect you'll need syntactic support (eg, for
"implies", see my post replying to Marko).  If people want checking in
production where reasonable (seems to be one of the nice things about
contracts), you'll probably want a language change to support that
syntax efficiently, which is usually a prohibitively high bar.

___
Python-ideas mailing list
Python-ideas@python.org
https://mail.python.org/mailman/listinfo/python-ideas
Code of Conduct: http://python.org/psf/codeofconduct/


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

2018-09-29 Thread Stephen J. Turnbull
Marko Ristin-Kaufmann writes:

 > I annotated pathlib with contracts:
 > https://github.com/mristin/icontract-pathlib-poc. I zipped the HTML docs

Thank your for completing this task so quickly.

I'm sorry, but I didn't find it convincing.  I'll leave others to
discuss the docs, as they are clearly "proof of concept" and I expect
will be improved greatly.

Part of the problem is the style of contracts, which can probably be
improved with syntactic support.  For example, the many double
negatives of the form "not (not (X)) or Y".  I guess the idea is to
express all implications "X implies Y" in the equivalent form "not X
or Y".  I tried a few in the form "Y if X else True" but didn't find
that persuasive.  I also found the lambdas annoying.

I conclude that there's good reason to prefer the style where the
condition is expressed as a str, and eval'ed by the contract machinery.
This would get rid of the lambdas, and allow writing a contract parser
so you could write implications in a more natural form.  I haven't
tried rewriting that way, and of course, I don't have a parser to
actually run stuff.

 >- not list(self.iterdir()) (??? There must be a way to check
 >  this more optimally)

You might define a function like this:

def is_empty_dir(d):
for _ in os.scandir(d):
return False
return True

or the function could catch the StopIteration from next() directly
(but I think that's considered bad style).  I don't think there's any
way to do this without a function call.  Note that the implementation
of iterdir calls os.listdir, so this function isn't necessarily much
more efficient than "not list(self.iterdir())".  (I'm pretty sure that
in this case the iterator keeps a copy of the list internally, and
listification probably involves object creation overhead, a memory
allocation and a machine-language block copy.)  I'm not sure whether
scandir is any better.  And I don't know how big a directory needs to
be before the overhead of function call and exception handling become
great enough to make it worthwhile.

 > [You] want to convey the message: dear user, if you are iterating
 > through a list of paths, use this function to decide if you should
 > call rmdir() or unlink(). Analogously with the first contract: dear
 > user, please check if the directory is empty before calling rmdir()
 > and this is what you need to call to actually check that.

I don't understand this logic.  I don't think I'd be looking at random
contracts for individual to learn how to handle filesystem objects.
I'd be more likely to do this kind of thing in most of my code:

def rmtree(path: Path) -> None:
try:
path.unlink()
except PermissionError:
for p in path.iterdir():
rmtree(p)
path.rmdir()

I wrote all of that without being a Path user and without checking
docs.  (I cheated on PermissionError by testing in the interpreter,
I'd probably just use Exception if I didn't have an interpreter to
hand already.)

Note that this function is incorrect: PermissionError could occur
because I don't have write permission on the parent directory.  I also
don't learn anything about PermissionError from your code, so your
contract is incomplete.  *DbC is just not a guarantee of anything* --
if there's a guarantee, it derives from the quality of the development
organization that uses DbC.

 > I also finally assembled the puzzle. Most of you folks are all
 > older and were exposed to DbC in the 80ies championed by DbC
 > zealots who advertised it as *the *tool for software
 > development. You were repulsed [...].

Please don't make statements that require mind-reading.  You do not
know that (I for example am 60, and have *heard of* design-by-contract
before but this is the first time I've seen it *seriously proposed for
use* or implementation in any project I participate in).

More important, several posters have explained why they don't see a
need for DbC in Python.  Two common themes are proliferation of
conditions making both code and documentation hard to read, and
already using methods of similar power such as TDD or other systems
using unit tests.  It's bad form to discount such explicit statements.

 > And that's why I said that the libraries on pypi meant to be used by
 > multiple people and which already have type annotations would obviously
 > benefit from contracts -- while you were imagining that all of these
 > libraries need to be DbC'ed 100%, I was imagining something much more
 > humble. Thus the misunderstanding.

No, the misunderstanding is caused by your wording and by your lack of
attention to the costs of writing contracts.  Criticizing yourself is
a much more effective strategy: you can control your words, but not
how others understand them.  Your best bet is to choose words that are
hard to misunderstand.

 > Similarly with rmdir() -- "the directory must be empty" -- but how
 > exactly am I supposed to check that?


Re: [Python-ideas] Why is design-by-contracts not widely

2018-09-29 Thread Steven D'Aprano
On Sat, Sep 29, 2018 at 10:15:42PM +1000, Chris Angelico wrote:

[...]
> As are all the things that are "undefined behaviour" in C, like the
> result of integer overflow in a signed variable. They are "Here be
> dragons" territory, but somehow that's not okay for you. I don't
> understand why you can hate on C for having behaviours where you're
> told "don't do that, we can't promise anything", but it's perfectly
> acceptable for Python to have the exact same thing.

They're not the same thing, not even close to the same thing.

Undefined behaviour in C is a radically different concept to the 
*implementation-defined behaviour* you describe in Python and most 
(all?) other languages. I don't know how to communicate that message any 
better than the pages I linked to before.


> AIUI, the only difference is that C compilers are more aggressive
> about assuming you won't invoke undefined behaviour, whereas there are
> no known Python interpreters that make such expectations.

I don't know any other language which has the same concept of undefined 
behaviour as C, neither before nor after. What does that tell you? If C 
undefined behaviour is such a good idea, why don't more languages do the 
same thing?

Undefined behaviour allows C compilers to generate really fast code, 
even if the code does something completely and radically different from 
what the source code says. Consequently, undefined behaviour in C is a 
HUGE source of bugs, including critical security bugs, and the C 
language is full of landmines for the unwary and inexpert, code which 
looks correct but could do *absolutely anything at all*.

The C language philosophy is to give up correctness in favour of 
speed. I hate that idea. If there was a Zen of C, it would say

"Errors should not just be silent, they're an opportunity
to win benchmark competitions."



-- 
Steve
___
Python-ideas mailing list
Python-ideas@python.org
https://mail.python.org/mailman/listinfo/python-ideas
Code of Conduct: http://python.org/psf/codeofconduct/


Re: [Python-ideas] Why is design-by-contracts not widely

2018-09-29 Thread Chris Angelico
On Sat, Sep 29, 2018 at 9:43 PM Steven D'Aprano  wrote:
>
> On Sat, Sep 29, 2018 at 10:32:16AM +1000, Chris Angelico wrote:
>
> > What should happen here?
> >
> > >>> import ctypes
> > >>> ctypes.cast(id(1), ctypes.POINTER(ctypes.c_int))[6] = 0
> > >>> 1
> >
> > Nothing here invokes C's undefined behaviour. Or what about here:
> >
> > >>> import sys; sys.setrecursionlimit(2147483647)
> > >>> def f(): f()
> > ...
> > >>> f()
>
> I'm not fussed about such edge cases. ctypes is not "Python", and other
> implementations don't support it. Mucking about with the interpreter
> internals is clear "Here be dragons" territory, and that's okay.

As are all the things that are "undefined behaviour" in C, like the
result of integer overflow in a signed variable. They are "Here be
dragons" territory, but somehow that's not okay for you. I don't
understand why you can hate on C for having behaviours where you're
told "don't do that, we can't promise anything", but it's perfectly
acceptable for Python to have the exact same thing.

AIUI, the only difference is that C compilers are more aggressive
about assuming you won't invoke undefined behaviour, whereas there are
no known Python interpreters that make such expectations.

ChrisA
___
Python-ideas mailing list
Python-ideas@python.org
https://mail.python.org/mailman/listinfo/python-ideas
Code of Conduct: http://python.org/psf/codeofconduct/


Re: [Python-ideas] Why is design-by-contracts not widely

2018-09-29 Thread Steven D'Aprano
On Sat, Sep 29, 2018 at 10:32:16AM +1000, Chris Angelico wrote:

> What should happen here?
> 
> >>> import ctypes
> >>> ctypes.cast(id(1), ctypes.POINTER(ctypes.c_int))[6] = 0
> >>> 1
> 
> Nothing here invokes C's undefined behaviour. Or what about here:
> 
> >>> import sys; sys.setrecursionlimit(2147483647)
> >>> def f(): f()
> ...
> >>> f()

I'm not fussed about such edge cases. ctypes is not "Python", and other 
implementations don't support it. Mucking about with the interpreter 
internals is clear "Here be dragons" territory, and that's okay.

 
> Python has its own set of "well don't do that then" situations. In
> fact, I would say that *most* languages do.

Indeed, but that's not really what I'm talking about.

As I said earlier, Python's semantics are relatively simply in the sense 
that it is governed by a particular execution model (a virtual machine) 
that isn't hugely complex, but there are some corner cases which are 
complex. Overall Python is very rich and non-minimalist. I wouldn't 
describe it as "simple" except in comparison to languages like C++.

BASIC is a simple language, with only two scalar data types (strings and 
numbers) and one array type, and only a handful of fairly simple flow 
control tools: if, loops, GOTO/GOSUB. (Of course, modern BASICs may be 
more complex.)

Python has a rich set of builtin data types (ints, floats, strings, 
bytes, lists, tuples, dicts...), even more in the standard library, 
OOP, and on top of the familiar BASIC-like flow control (for 
loops, while loops, if...else) we have comprehensions, with statements 
and exception handling. (Did I miss anything?) But not GOTO :-)



-- 
Steve
___
Python-ideas mailing list
Python-ideas@python.org
https://mail.python.org/mailman/listinfo/python-ideas
Code of Conduct: http://python.org/psf/codeofconduct/


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

2018-09-29 Thread Steven D'Aprano
On Wed, Sep 26, 2018 at 05:40:45AM +1000, Chris Angelico wrote:

> > There are 150K projects on pypi.org. Each one of them would benefit 
> > if annotated with the contracts.
> 
> This is the extraordinary claim. To justify it, you have to show that
> virtually ANY project would benefit from contracts. So far, I haven't
> seen any such proof.

As per my previous email, I think the extraordinary claim is that there 
exists even a single project which wouldn't benefit from at least one 
contract.

Honestly, you sound almost like somebody saying 

"Projects would benefit from getting an automated test 
suite? Ridiculous!"

But to give you a charitable interpretation, I'll grant that given the 
cost to benefit ratio of code churn, human effort, refactoring etc, it 
is certainly possible that adding contracts to some especially mature 
and high-quality projects, or quick-and-dirty low-quality projects where 
nobody cares about bugs, would cost more than the benefit gained. 
There's benefit, but not *nett* benefit.

That goes especially for Python code since the available interfaces for 
contracts are so poor. But that's why we're talking about this on 
Python-Ideas.

I just wish we didn't have to fight so hard to justify the very idea of 
contracts themselves. That's like having to justify the idea of test 
suites, documentation and error checking.


-- 
Steve
___
Python-ideas mailing list
Python-ideas@python.org
https://mail.python.org/mailman/listinfo/python-ideas
Code of Conduct: http://python.org/psf/codeofconduct/


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

2018-09-29 Thread Steven D'Aprano
On Tue, Sep 25, 2018 at 08:01:28PM +1200, Robert Collins wrote:
> On Mon, 24 Sep 2018 at 19:47, Marko Ristin-Kaufmann
>  wrote:
[...]
> > There are 150K projects on pypi.org. Each one of them would 
> > benefit if annotated with the contracts.
> 
> You'll lose folks attention very quickly when you try to tell folk
> what they do and don't understand.
> 
> Claiming that DbC annotations will improve the documentation of every
> single library on PyPI is an extraordinary claim, and such claims
> require extraordinary proof.

This is not a scientific paper, or an edited book. Its an email forum, 
and communication is not always as precise as it could be. We should 
read such statements charitably, not literally and pedantically.

But having said that... would it be an "extraordinary claim" to state 
that all 150K projects on PyPI would benefit with better documentation, 
tests or error checking? I don't think so.

I think it would be extraordinary to claim that there was even a single 
project that *wouldn't* benefit from at least one such patch. I'd like 
to see this glorious example of software perfection, and bow down in awe 
to its author.

Contracts combine error checking, documentation and testing all in one. 
Ergo, if a project would benefit from any of those things, it would 
benefit from a contract.

Anticipating an objection: like tests and documentation and error 
checking, contracts do not need to be "all or nothing". A contract can 
be incomplete and still provide benefit. We can add contracts 
incrementally. Even a single pre- or post-condition check is better than 
no check at all.

So I'm with Marko here: every project on PyPI would, in principle, 
benefit from some contracts. I say in principle only because in 
practice, the available APIs for adding contracts to Python code are so 
clunky that the cost of contracts are excessive. We're paying a syntax 
tax on contracts which blows the cost all out of proportion.

Just as languages like Java pay a syntax tax on static typing (compared 
to languages like ML and Haskell with type inference and few 
declarations needed), and languages like COBOL have a syntax tax on, 
well, everything.


> I can think of many libraries where necessary pre and post conditions
> (such as 'self is still locked') are going to be noisy, and at risk of
> reducing comprehension if the DbC checks are used to enhance/extended
> documentation.

So long as my editor lets me collapse the contract blocks, I don't need 
to read them unless I want to. And automatically generated documentation 
always tends towards the verbose. Just look at the output of help() in 
the Python REPL. We learn to skim, and dig deeper only when needed.


> Some of the examples you've been giving would be better expressed with
> a more capable type system in my view (e.g. Rust's), but I have no
> good idea about adding that into Python  :/.

Indeed.

A lot of things which could be preconditions in Python would be 
type-checks in Eiffel. With gradual typing and type annotations, we 
could move some pre-condition and post-condition checks into the type 
checker.

(Static typing is another thing which doesn't need to be "all or 
nothing".)


> Anyhow, the thing I value most about python is its pithyness: its
> extremely compact, allowing great developer efficiency,

None of that changes. The beauty of contracts is that you can have as 
many or as few as make sense for each specific class or function, or for 
that matter each project. If your project is sufficiently lightweight 
and the cost of bugs is small enough, you might not bother with tests or 
error checking, or contracts.


-- 
Steve
___
Python-ideas mailing list
Python-ideas@python.org
https://mail.python.org/mailman/listinfo/python-ideas
Code of Conduct: http://python.org/psf/codeofconduct/


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

2018-09-28 Thread Steven D'Aprano
On Sat, Sep 29, 2018 at 12:30:45PM +1200, Greg Ewing wrote:
> Chris Angelico wrote:
> >But as a part of the
> >function's declared intent, it's fine to have a postcondition of "the
> >directory will be empty" even though something could drop a file into
> >it.
> 
> If you only intend the contract to serve as documentation,
> I suppose that's okay, but it means you can't turn on runtime
> checking of contracts, otherwise your program could suffer
> spurious failures.

If your code can cope with a particular file system state ("directory 
isn't empty") then you don't need to specify it as a precondition. If it 
can't cope, then it isn't a spurious failure, its a real failure. You 
either get an error when the condition is checked, up front, or you get 
an error in the middle of processing the directory.

Of course for many things (especially file system operations) you need 
to be prepared to handle I/O errors *even if the precondition passed*. 
So what? That hasn't changed, and nobody said that contracts were a cure 
for Time Of Check To Time Of Use bugs.

Contracts are a tool to help developers write better code, not a magic 
wand. You still need to write your code in a way which isn't vulnerable 
to TOCTTOU failures, contracts or not.

Anticipating an objection: why bother with the precondition check if the 
code has to handle an error anyway?

Because it is better to get an upfront error than an error halfway 
through processing. In general you get a better, more informative error 
message, closer to the place where it matters, if you fail fast.

Yes yes yes, in theory you might have a precondition requirement which 
would fail up front but resolve itself before it matters:

directory not empty
start running your program
precondition check fails
... later
directory is emptied by another process
your program actually needs to use the empty directory

but do you really think it is good practice to design your code on the 
basis of that? Better to write your code conservatively: if the 
directory isn't empty up front, don't hope it will empty itself, fail 
fast, but be prepared to handle the error case as well.


-- 
Steve
___
Python-ideas mailing list
Python-ideas@python.org
https://mail.python.org/mailman/listinfo/python-ideas
Code of Conduct: http://python.org/psf/codeofconduct/


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

2018-09-28 Thread Steven D'Aprano
On Sun, Sep 23, 2018 at 07:09:37AM +0200, Marko Ristin-Kaufmann wrote:

> After the discussion we had on the list and after browsing the internet a
> bit, I'm still puzzled why design-by-contract was not more widely adopted
> and why so few languages support it.
[...]

> *. *After properly reading about design-by-contract and getting deeper into
> the topic, there is no rational argument against it and the benefits are
> obvious. And still, people just wave their hand and continue without
> formalizing the contracts in the code and keep on writing them in the
> descriptions.
> 
> * Why is that so?
[...]

You are asking a question about human psychology but expecting logical, 
technical answers. I think that's doomed to failure.

There is no nice way to say this, because it isn't nice.

Programmers and language designers don't use DbC because it is new and 
different and therefore scary and wrong. Programmers, as a class, are 
lazy (they even call laziness a virtue), deeply conservative, 
superstitious, and don't like change. They do what they do because 
they're used to it, not because it is the technically correct thing to 
do, unless it is by accident.

(Before people's hackles raise too much, I'm speaking in generalities, 
not about you personally. Of course you are one of the 1% awesomely 
logical, technically correct programmers who know what you are doing and 
do it for the right reasons after careful analysis. I'm talking about 
the other 99%, you know the ones. You probably work with them. You've 
certainly read their answers on Stackoverflow or The Daily WTF and a 
million blogs.)

They won't use it until there is a critical mass of people using it, and 
then it will suddenly flip from "that weird shit Eiffel does" to "oh 
yeah, this is a standard technique that everyone uses, although we don't 
make a big deal about it".

Every innovation in programming goes through this. Whether the 
innovation goes mainstream or not depends on getting a critical mass, 
and that is all about psychology and network effects and nothing to do 
with the merit of the idea.

Remember the wars over structured programming? Probably not. In 2018, 
the idea that people would *seriously argue against writing subroutines* 
seems insane, but they did. As late as 1999, a former acquaintance of 
mine was working on a BASIC project for a manager who insisted they use 
GOTO and GOSUB in preference to subroutines.

Testing: the idea that we should have *repeatable automated tests* took 
a long time to be accepted, and is still resisted by both developers and 
their managers. What's wrong with just sitting a person down in front of 
the program and checking for bugs by hand? We still sometimes have to 
fight for an automated test suite, never mind something like test driven 
development.

ML-based languages have had type inference for decades, and yet people 
still think of type checking in terms of C and Java declarations. Or 
they still think in terms of static VERSUS dynamic typing, instead of 
static PLUS dynamic typing.

I could go on, but I think I've made my point.

I can give you some technical reasons why I don't use contracts in my 
own Python code, even though I want to:

(1) Many of my programs are too small to bother. If I'm writing a quick 
script, I don't even write tests. Sometimes "be lazy" is the right 
answer, when the cost of bugs is small enough and the effort to avoid 
them is greater. And that's fine. Nobody says that contracts must be 
mandatory.

(2) Python doesn't make it easy to write contracts. None of the 
solutions I've seen are nice. Ironically, the least worst I've seen is a 
quick and dirty metaclass solution given by Guido in an essay way back 
in Python 1.5 days:

https://www.python.org/doc/essays/metaclasses/

His solution relies only on a naming convention, no decorators, no 
lambdas:

class C(Eiffel):
def method(self, arg):
return whatever
def method_pre(self, arg):
assert arg > 0
def method_post(self, Result, arg):
assert Result > arg


Still not pretty, but at least we get some block structure instead of a 
wall of decorators.

Syntax matters. Without good syntax that makes it easy to write 
contracts, it will never be anything but niche.


(3) In a sense, *of course I write contracts*. Or at least precondition 
checks. I just don't call them that, and I embed them in the 
implementation of the method, and have no way to turn them off. Nearly 
all of us have done the same, we start with a method like this:

class C:
def method(self, alist, astring, afloat):
# do some work...

using nothing but naming conventions and an informal (and often vague) 
specification in the docstring, and while that is sometimes enough in 
small projects, the third time we get bitten we start adding defensive 
checks so we get sensible exceptions:

def method(self, alist, astring, afloat):
if not isinstance(alist, list):
raise 

Re: [Python-ideas] Why is design-by-contracts not widely

2018-09-28 Thread Dan Sommers

On 9/28/18 8:32 PM, Chris Angelico wrote:

On Sat, Sep 29, 2018 at 10:22 AM Dan Sommers
<2qdxy4rzwzuui...@potatochowder.com> wrote:


On 9/28/18 7:39 PM, Steven D'Aprano wrote:

But none of that compares to C undefined behaviour. People who think
that they are equivalent, don't understand C undefined behaviour.


Well, yes:  Some syntactically legal C results in nasal demons, and some
of that code is harder to spot than others.  AFAIK, syntactically legal
Python can only do that if the underlying C code invokes undefined
behaviour.


What should happen here?


[examples of what Steven would call non-sensible, non-non-weird objects
doing non-non-weird things snipped]

AFAIK, "AFAIK" is a weasel word:  It allows me to proclaim my own
ignorance without providing further examples, evidence, or counter
examples.  :-)


Python has its own set of "well don't do that then" situations. In
fact, I would say that *most* languages do.


Yep.
___
Python-ideas mailing list
Python-ideas@python.org
https://mail.python.org/mailman/listinfo/python-ideas
Code of Conduct: http://python.org/psf/codeofconduct/


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

2018-09-28 Thread Dan Sommers

On 9/28/18 8:12 PM, Chris Angelico wrote:

On Sat, Sep 29, 2018 at 7:19 AM Greg Ewing  wrote:


Chris Angelico wrote:

It is still fundamentally difficult to make assertions about the file
system as pre/post contracts.


When you consider race conditions, I'd say it's impossible.
A postcondition check involving the file system could fail
even if the function does its job perfectly.


I guess that depends on the meaning of "contract". If it means "there
is a guarantee that this is true after this function returns", then
yes, the race condition means it's impossible. But as a part of the
function's declared intent, it's fine to have a postcondition of "the
directory will be empty" even though something could drop a file into
it.

But if it's the latter... contracts are just a different way of
defining unit tests and we're right back where we started.


At the risk of pedantry (on a Python list?  I'm *shocked*):

I call BS on any contract that requires on entry or guarantees on exit
the state of the file system.  At best, a function can guarantee that it
will make (or made) a request to the OS, and that the OS returned
"success" before the function continued.

Then again, a function that guarantees to work in a particular way based
on some condition of the file system would be okay.  For example, a
function might claim to create a temporary file with some content *if*
some directory exists when the function tries to create the temporary
file.  But as I think both of you are claiming, the best that function
can guarantee on exit is that it asked the OS to write to the file, and
that the OS agreed to do so.  The function cannot guarantee that the
file or the content still exists when the function finally returns.
___
Python-ideas mailing list
Python-ideas@python.org
https://mail.python.org/mailman/listinfo/python-ideas
Code of Conduct: http://python.org/psf/codeofconduct/


Re: [Python-ideas] Why is design-by-contracts not widely

2018-09-28 Thread Chris Angelico
On Sat, Sep 29, 2018 at 10:22 AM Dan Sommers
<2qdxy4rzwzuui...@potatochowder.com> wrote:
>
> On 9/28/18 7:39 PM, Steven D'Aprano wrote:
> > But none of that compares to C undefined behaviour. People who think
> > that they are equivalent, don't understand C undefined behaviour.
>
> Well, yes:  Some syntactically legal C results in nasal demons, and some
> of that code is harder to spot than others.  AFAIK, syntactically legal
> Python can only do that if the underlying C code invokes undefined
> behaviour.

What should happen here?

>>> import ctypes
>>> ctypes.cast(id(1), ctypes.POINTER(ctypes.c_int))[6] = 0
>>> 1

Nothing here invokes C's undefined behaviour. Or what about here:

>>> import sys; sys.setrecursionlimit(2147483647)
>>> def f(): f()
...
>>> f()


Python has its own set of "well don't do that then" situations. In
fact, I would say that *most* languages do.

ChrisA
___
Python-ideas mailing list
Python-ideas@python.org
https://mail.python.org/mailman/listinfo/python-ideas
Code of Conduct: http://python.org/psf/codeofconduct/


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

2018-09-28 Thread Greg Ewing

Chris Angelico wrote:

But as a part of the
function's declared intent, it's fine to have a postcondition of "the
directory will be empty" even though something could drop a file into
it.


If you only intend the contract to serve as documentation,
I suppose that's okay, but it means you can't turn on runtime
checking of contracts, otherwise your program could suffer
spurious failures.

--
Greg
___
Python-ideas mailing list
Python-ideas@python.org
https://mail.python.org/mailman/listinfo/python-ideas
Code of Conduct: http://python.org/psf/codeofconduct/


Re: [Python-ideas] Why is design-by-contracts not widely

2018-09-28 Thread Dan Sommers

On 9/28/18 7:39 PM, Steven D'Aprano wrote:

On Fri, Sep 28, 2018 at 07:18:54PM +0200, 2qdxy4rzwzuui...@potatochowder.com 
wrote:


On 9/28/18 12:45 PM, Steven D'Aprano wrote:

On Tue, Sep 25, 2018 at 09:59:53PM +1000, Hugh Fisher wrote:


C and Python (currently) are known as simple languages.


o_O

That's a usage of "simple" I haven't come across before. Especially in
the case of C, which is a minefield of *intentionally* underspecified
behaviour which makes it near to impossible for the developer to tell
what a piece of syntactically legal C code will actually do in practice.


s/C/Python/

s/underspecified/dynamic/

;-)


I see the wink, but I don't see the relevance. Are you agreeing with me
or disagreeing?


I agree that Hugh's use of "simple" is unfamiliar.

I disagree that C is is a bigger offender than Python when it comes to a
developer telling what a piece of syntactically legal code will actually
do in practice.  If that's not what you meant by "Especially in the case
of C...," then I mis-interpreted or read too much into your wording.


Python is "simple" in the sense that the execution model is *relatively*
simple, but its not a minimalist language by any definition. And as you
say, the execution model is dynamic: we can't be sure what legal code
will do until you know the runtime state.


That's my point:  What you emphasized about C can be applied equally to
Python.  In C, it's because the standard is intentionally
underspecified; in Python, it's y because the language is intentionally
dynamic.

When you said "underspecified," I didn't make the leap to "undefined
behaviour" (although I think I know from past experience how you feel
about C and its undefined behaviour).  Instead, I jumped to things like
the ambiguity in the size of an int, or the freedom the compiler has to
pack/align struct values or implement integers as something other than
two's complement.


(Although we can often guess, based on assumptions about sensible,
non-weird objects that don't do weird things.)


Again, the same is true of C.  In Python, weird objects might override
getattr; in C weird objects might point to hardware registers, or depend
on implementation specific detail(s).


But none of that compares to C undefined behaviour. People who think
that they are equivalent, don't understand C undefined behaviour.


Well, yes:  Some syntactically legal C results in nasal demons, and some
of that code is harder to spot than others.  AFAIK, syntactically legal
Python can only do that if the underlying C code invokes undefined
behaviour.
___
Python-ideas mailing list
Python-ideas@python.org
https://mail.python.org/mailman/listinfo/python-ideas
Code of Conduct: http://python.org/psf/codeofconduct/


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

2018-09-28 Thread Chris Angelico
On Sat, Sep 29, 2018 at 7:19 AM Greg Ewing  wrote:
>
> Chris Angelico wrote:
> > It is still fundamentally difficult to make assertions about the file
> > system as pre/post contracts.
>
> When you consider race conditions, I'd say it's impossible.
> A postcondition check involving the file system could fail
> even if the function does its job perfectly.

I guess that depends on the meaning of "contract". If it means "there
is a guarantee that this is true after this function returns", then
yes, the race condition means it's impossible. But as a part of the
function's declared intent, it's fine to have a postcondition of "the
directory will be empty" even though something could drop a file into
it.

But if it's the latter... contracts are just a different way of
defining unit tests and we're right back where we started.

ChrisA
___
Python-ideas mailing list
Python-ideas@python.org
https://mail.python.org/mailman/listinfo/python-ideas
Code of Conduct: http://python.org/psf/codeofconduct/


Re: [Python-ideas] Why is design-by-contracts not widely

2018-09-28 Thread Steven D'Aprano
On Fri, Sep 28, 2018 at 07:18:54PM +0200, 2qdxy4rzwzuui...@potatochowder.com 
wrote:
> 
> On 9/28/18 12:45 PM, Steven D'Aprano wrote:
> >On Tue, Sep 25, 2018 at 09:59:53PM +1000, Hugh Fisher wrote:
> >
> >>C and Python (currently) are known as simple languages.
> >
> >o_O
> >
> >That's a usage of "simple" I haven't come across before. Especially in
> >the case of C, which is a minefield of *intentionally* underspecified
> >behaviour which makes it near to impossible for the developer to tell
> >what a piece of syntactically legal C code will actually do in practice.
> 
> s/C/Python/
> 
> s/underspecified/dynamic/
> 
> ;-)

I see the wink, but I don't see the relevance. Are you agreeing with me 
or disagreeing?

Python is "simple" in the sense that the execution model is *relatively* 
simple, but its not a minimalist language by any definition. And as you 
say, the execution model is dynamic: we can't be sure what legal code 
will do until you know the runtime state.

(Although we can often guess, based on assumptions about sensible, 
non-weird objects that don't do weird things.)

But none of that compares to C undefined behaviour. People who think 
that they are equivalent, don't understand C undefined behaviour.

https://blog.regehr.org/archives/213

http://blog.llvm.org/2011/05/what-every-c-programmer-should-know_14.html



-- 
Steve
___
Python-ideas mailing list
Python-ideas@python.org
https://mail.python.org/mailman/listinfo/python-ideas
Code of Conduct: http://python.org/psf/codeofconduct/


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

2018-09-28 Thread James Lu
Many editors highlight decorators in a different color that makes it easier to 
ignore and can also fold decorators. 

Contracts can also sometimes actively improve the flow of code. 

I personally find a formal contract easier to read than informal documentation.

It also reduces the times where you need to spend time figuring out if 
documentation actually accurate and up to date
___
Python-ideas mailing list
Python-ideas@python.org
https://mail.python.org/mailman/listinfo/python-ideas
Code of Conduct: http://python.org/psf/codeofconduct/


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

2018-09-28 Thread Greg Ewing

Chris Angelico wrote:

It is still fundamentally difficult to make assertions about the file
system as pre/post contracts.


When you consider race conditions, I'd say it's impossible.
A postcondition check involving the file system could fail
even if the function does its job perfectly.

--
Greg

___
Python-ideas mailing list
Python-ideas@python.org
https://mail.python.org/mailman/listinfo/python-ideas
Code of Conduct: http://python.org/psf/codeofconduct/


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

2018-09-28 Thread Brendan Barnwell

On 2018-09-28 05:23, David Mertz wrote:

On Thu, Sep 27, 2018, 9:25 PM Marko Ristin-Kaufmann
mailto:marko.ris...@gmail.com>> wrote:

Try to question whether the contracts I wrote are so obvious to
everybody even if they are obvious to you and keep in mind that the
user does not look into the implementation.


I had missed this comment, but this seems to be the biggest disconnect,
or talking past each other.

I'm a user of many libraries. I USUALLY look at the implementation when
in doubt about a function. If contracts are meant only for users who
don't look at code, the detrimental effect on code readability is mitigated.


	I agree with you that this seems to be a major disconnect in the 
discussion here.  However, on the issue itself, I quite agree with Marko 
that it is *much* more important for the documentation to be readable 
than for the function to be readable.  I too read the source of 
functions sometimes, and whenever I find myself having to do so, I 
grouse at the authors of whatever libraries I'm using for not making the 
documentation more clear.  Ideally, no user should *ever* have to read 
the function source code, because the documentation should make it 
completely clear how to use the function without knowing *anything* 
about how it is implemented.


	Of course, this ideal will never be achieved, but I think it's 
something to aim towards, and the idea that adding a few lines of DbC 
decorators makes the source code too cluttered seems quite incorrect to 
me.  I glanced through the source code and didn't find it hard to read 
at all.  The contracts are all cleanly separated from the function 
bodies because they're in decorators up front.  I'm frankly quite 
baffled that other people on this thread find that hard to read.


	The problem with reading the source code is that you can't tell what 
parts of the behavior are specified and which are implementation 
details.  The appeal of something like DbC is that it encourages (some 
might say painfully forces) programmers to be very explicit about what 
behavior they want to guarantee.


	Whether writing these guarantees as Python expressions is better than 
writing them as prose is another matter.  Personally I do see some value 
in the modifications that Marko made to pathlib.  In a sense, writing 
"documentation as Python code" is like annotating the source code to 
mark which specific parts of the implementation are guarantees and which 
may be implementation details.  I think there is significant value in 
knowing precisely what an API allows, in an explicit and verifiable form 
such as that provided by DbC, rather than using human language, which is 
much less precise, can leave room for misinterpretation, and, perhaps 
most importantly, is harder to verify automatically.


	Ultimately, I'm firmly of the opinion that, in publicly distributed 
code, the function *IS* its documentation, not its source code.  When a 
function's actual behavior conflicts with its documented behavior, that 
is a bug.  When meaningful aspects of a functions behavior are not 
specified in the documentation, that is also a bug. These may be bugs in 
the documentation or in the behavior, but either way the point is that 
reading the source code is not an acceptable substitute for making the 
documentation a complete and self-sufficient vehicle for total 
understanding of the function's behavior.   It doesn't matter if the 
function behaves as the author intended; it only matters if it behaves 
as documented.


--
Brendan Barnwell
"Do not follow where the path may lead.  Go, instead, where there is no 
path, and leave a trail."

   --author unknown
___
Python-ideas mailing list
Python-ideas@python.org
https://mail.python.org/mailman/listinfo/python-ideas
Code of Conduct: http://python.org/psf/codeofconduct/


Re: [Python-ideas] Why is design-by-contracts not widely

2018-09-28 Thread 2qdxy4rzwzuuilue



On 9/28/18 12:45 PM, Steven D'Aprano wrote:

On Tue, Sep 25, 2018 at 09:59:53PM +1000, Hugh Fisher wrote:


C and Python (currently) are known as simple languages.


o_O

That's a usage of "simple" I haven't come across before. Especially in
the case of C, which is a minefield of *intentionally* underspecified
behaviour which makes it near to impossible for the developer to tell
what a piece of syntactically legal C code will actually do in practice.


s/C/Python/

s/underspecified/dynamic/

;-)


___
Python-ideas mailing list
Python-ideas@python.org
https://mail.python.org/mailman/listinfo/python-ideas
Code of Conduct: http://python.org/psf/codeofconduct/


Re: [Python-ideas] Why is design-by-contracts not widely

2018-09-28 Thread Steven D'Aprano
On Tue, Sep 25, 2018 at 09:59:53PM +1000, Hugh Fisher wrote:

> C and Python (currently) are known as simple languages.

o_O

That's a usage of "simple" I haven't come across before. Especially in 
the case of C, which is a minefield of *intentionally* underspecified 
behaviour which makes it near to impossible for the developer to tell 
what a piece of syntactically legal C code will actually do in practice.


-- 
Steve
___
Python-ideas mailing list
Python-ideas@python.org
https://mail.python.org/mailman/listinfo/python-ideas
Code of Conduct: http://python.org/psf/codeofconduct/


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

2018-09-28 Thread Marko Ristin-Kaufmann
Hi,

(Posting from work, so sorry for the short response.)

@Paul Moore  icontract.pre/post/inv have the enabled
argument; if not enabled, the contract is ignored.

Similarly with rmdir() -- "the directory must be empty" -- but how exactly
>> am I supposed to check that?
>>
>
> Isn't that the whole point? The prose statement "the directory must be
> empty" is clear. But the exact code check isn't - and may be best handled
> by a series of unit tests, rather than a precondition.
>

I meant "check" as a user, not as a developer. As in "What did the
implementer think -- how am I supposed to check that the directory is
empty?" A la: "Dear user, if you want to rmdir, here is what you need to
check that it is indeed a dir, and here is what you need to check that it
is empty. If both checks pass, run me."

@David patching __doc__ automatically is on the short-term todo list. I
suppose we'll just add sphinx directives (:requires:, :ensures: etc.)

* Marko isn't that familiar with the codebase, so there may be better
> ways to express certain things
>

This is true :)

* Sometimes it's just plain hard to express a verbal constraint in code
>

In these cases you simply don't express it in code. Why would you? If it's
complex code, possibility that you have an error is probably equal or
higher than that your comment rots.

@pre(lambda args, result: not any(Path(arg).is_absolute() for arg in args)
> or
> (result == [pth for arg in args for pth in [Path(arg)] if
> pth.is_absolute()][-1]),
> "When several absolute paths are given, the last is taken as an anchor
> (mimicking os.path.join()’s behaviour)")
>

I'm really not familiar with the code base nor with how to write stuff nice
and succinct in python. This particular contract was hard to define because
there were no last() and no arg_is_absolute() functions.

Otherwise, it would have read:

@pre(lambda args, result: not any(arg_is_absolute(arg) for arg in args) or
result == Path(last(arg for arg in args if arg_is_absolute(arg)))

When rendered, this wouldn't look too bad to read.

@Chris

> It is still fundamentally difficult to make assertions about the file
> system as pre/post contracts. Are you becoming aware of this?
> Contracts, as has been stated multiple times, look great for
> mathematically pure functions that have no state outside of their own
> parameters and return values (and 'self', where applicable), but are
> just poor versions of unit tests when there's anything external to
> consider.
>

I never thought of these particular contracts as running in the production.
I would set them to run only in testing and only on part of the tests where
they are safe from race conditions (e.g., setting
enabled=test_pathlib.SERIAL; toggling mechanism is something I haven't
spent too much thought about either and would also need to be
discussed/implemented.).

I really thought about them as documentation, not for correctness (or at
best deeper tests during the testing in a "safe" local environment, for
example when you want to check if all the contracts also hold on situations
in *my *testsuite, not only during the test suite of pathlib).

In the end, I'm calling it the day. I really got tired in the last few
days. Standardizing contracts for python is not worth the pain. We'll
continue to develop icontract for our internal needs and keep it open
source, so anybody who's interested can have a look. Thank you all for a
very lively discussions!

Cheers,
Marko



On Fri, 28 Sep 2018 at 14:49, Paul Moore  wrote:

> On Fri, 28 Sep 2018 at 13:23, David Mertz  wrote:
> > I agree that all the Sphinx documentation examples shown are very nice.
> Prose descriptions would often be nicer still, but the Boolean expressions
> are helpful for those unusual cases where I don't want to look at the code.
>
> I'm ambivalent about the Sphinx examples. I find the highly detailed
> code needed to express a condition fairly unreadable (and I'm an
> experienced Python programmer). For example
>
> @pre(lambda args, result: not any(Path(arg).is_absolute() for arg in args)
> or
> (result == [pth for arg in args for pth in [Path(arg)] if
> pth.is_absolute()][-1]),
> "When several absolute paths are given, the last is taken as an anchor
> (mimicking os.path.join()’s behaviour)")
>
> The only way I'd read that is by looking at the summary text - I'd
> never get the sense of what was going on from the code alone. There's
> clearly a number of trade-offs going on here:
>
> * Conditions should be short, to avoid clutter
> * Writing helper functions that are *only* used in conditions is more
> code to test or get wrong
> * Sometimes it's just plain hard to express a verbal constraint in code
> * Marko isn't that familiar with the codebase, so there may be better
> ways to express certain things
>
> But given that *all* the examples I've seen of contracts have this
> issue (difficult to read expressions) I suspect the problem is
> inherent.
>
> Another thing that I haven't yet seen clearly explained. 

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

2018-09-28 Thread Paul Moore
On Fri, 28 Sep 2018 at 13:23, David Mertz  wrote:
> I agree that all the Sphinx documentation examples shown are very nice. Prose 
> descriptions would often be nicer still, but the Boolean expressions are 
> helpful for those unusual cases where I don't want to look at the code.

I'm ambivalent about the Sphinx examples. I find the highly detailed
code needed to express a condition fairly unreadable (and I'm an
experienced Python programmer). For example

@pre(lambda args, result: not any(Path(arg).is_absolute() for arg in args) or
(result == [pth for arg in args for pth in [Path(arg)] if
pth.is_absolute()][-1]),
"When several absolute paths are given, the last is taken as an anchor
(mimicking os.path.join()’s behaviour)")

The only way I'd read that is by looking at the summary text - I'd
never get the sense of what was going on from the code alone. There's
clearly a number of trade-offs going on here:

* Conditions should be short, to avoid clutter
* Writing helper functions that are *only* used in conditions is more
code to test or get wrong
* Sometimes it's just plain hard to express a verbal constraint in code
* Marko isn't that familiar with the codebase, so there may be better
ways to express certain things

But given that *all* the examples I've seen of contracts have this
issue (difficult to read expressions) I suspect the problem is
inherent.

Another thing that I haven't yet seen clearly explained. How do these
contracts get *run*? Are they checked on every call to the function,
even in production code? Is there a means to turn them off? What's the
runtime overhead of a "turned off" contract (even if it's just an
if-test per condition, that can still add up)? And what happens if a
contract fails - is it an exception/traceback (which is often
unacceptable in production code such as services)? The lack of any
clear feel for the cost of adding contracts is part of what makes
people reluctant to use them (particularly in the face of the
unfortunately still common assertion that "Python is slow" :-()

Paul
___
Python-ideas mailing list
Python-ideas@python.org
https://mail.python.org/mailman/listinfo/python-ideas
Code of Conduct: http://python.org/psf/codeofconduct/


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

2018-09-28 Thread David Mertz
On Thu, Sep 27, 2018, 9:25 PM Marko Ristin-Kaufmann 
wrote:

> Try to question whether the contracts I wrote are so obvious to everybody
> even if they are obvious to you and keep in mind that the user does not
> look into the implementation.
>

I had missed this comment, but this seems to be the biggest disconnect, or
talking past each other.

I'm a user of many libraries. I USUALLY look at the implementation when in
doubt about a function. If contracts are meant only for users who don't
look at code, the detrimental effect on code readability is mitigated.

The other place I look, if not the actual implementation, is at the
docstring. I don't remember if icontracts patches the docstring when it
decorates a function. If not, that would be very helpful.

I agree that all the Sphinx documentation examples shown are very nice.
Prose descriptions would often be nicer still, but the Boolean expressions
are helpful for those unusual cases where I don't want to look at the code.
___
Python-ideas mailing list
Python-ideas@python.org
https://mail.python.org/mailman/listinfo/python-ideas
Code of Conduct: http://python.org/psf/codeofconduct/


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

2018-09-28 Thread David Mertz
On Fri, Sep 28, 2018, 4:38 AM Paul Moore  wrote:

> On Fri, 28 Sep 2018 at 02:24, Marko Ristin-Kaufmann <
> marko.ris...@gmail.com> wrote:
>
>> I annotated pathlib with contracts:
>> https://github.com/mristin/icontract-pathlib-poc. I zipped the HTML docs
>> into
>> https://github.com/mristin/icontract-pathlib-poc/blob/master/contracts-pathlib-poc.zip,
>> you can just unpack and view the index.html.
>>
>
> The thing that you didn't discuss in the above was the effect on the
> source code. Looking at your modified sources, I found it *significantly*
> harder to read your annotated version than the original. Basically every
> function and class was cluttered with irrelevant[1] conditions, which
> obscured the logic and the basic meaning of the code.
>

My reaction was just the same as Paul's. I read the modified source, and
found that the invariant declarations made it *dramatically* harder to
read. The ratio was almost exactly as I characterized in a recent note: 15
lines of pre/post-conditions on a 10 like function.

Like Paul, I understand the documentation and testing value of these, but
they were highly disruptive to the readability of the functions themselves.

As a result of reading the example, I'd be somewhat less likely to use a
DbC library, and much more strongly opposed to having one in the standards
library (and aghast at the idea of dedicated syntax)
___
Python-ideas mailing list
Python-ideas@python.org
https://mail.python.org/mailman/listinfo/python-ideas
Code of Conduct: http://python.org/psf/codeofconduct/


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

2018-09-28 Thread Paul Moore
On Fri, 28 Sep 2018 at 10:37, Chris Angelico  wrote:
>
> On Fri, Sep 28, 2018 at 7:29 PM Jonathan Fine  wrote:
> >
> > I like this discussion. I'd like to add another theme, namely what
> > should happen when there is an error. (This is prompted by race
> > hazards when performing file system operations.)
> >
> > Suppose fn_a() calls fn_b(), and fn_b() raises an exception. What then
> > should fn_a() do? It may be that this exception has left part or all
> > of the system in an inconsistent (invalid) state.
>
> That's why try/finally exists. You shouldn't have to worry about
> contracts for that.
>
> (Similarly, context managers, which are a way of wrapping up
> try/finally into a convenient package.)

However, a contract would need to be able to express "Returns a fully
initialised widget or raises a BrokenWidget exception". Unit tests do
this sort of thing all the time.

Paul
___
Python-ideas mailing list
Python-ideas@python.org
https://mail.python.org/mailman/listinfo/python-ideas
Code of Conduct: http://python.org/psf/codeofconduct/


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

2018-09-28 Thread Chris Angelico
On Fri, Sep 28, 2018 at 7:29 PM Jonathan Fine  wrote:
>
> I like this discussion. I'd like to add another theme, namely what
> should happen when there is an error. (This is prompted by race
> hazards when performing file system operations.)
>
> Suppose fn_a() calls fn_b(), and fn_b() raises an exception. What then
> should fn_a() do? It may be that this exception has left part or all
> of the system in an inconsistent (invalid) state.

That's why try/finally exists. You shouldn't have to worry about
contracts for that.

(Similarly, context managers, which are a way of wrapping up
try/finally into a convenient package.)

ChrisA
___
Python-ideas mailing list
Python-ideas@python.org
https://mail.python.org/mailman/listinfo/python-ideas
Code of Conduct: http://python.org/psf/codeofconduct/


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

2018-09-28 Thread Jonathan Fine
I like this discussion. I'd like to add another theme, namely what
should happen when there is an error. (This is prompted by race
hazards when performing file system operations.)

Suppose fn_a() calls fn_b(), and fn_b() raises an exception. What then
should fn_a() do? It may be that this exception has left part or all
of the system in an inconsistent (invalid) state.

At this level of abstraction, it's not possible to sensibly answer
this question. Sometimes the whole system should be stopped. Other
times, an invalidation of an object is enough. And sometimes, a
rollback of the transaction is what's wanted.

Here's a well-known example (overflow exception in Ariane 5), which to
me shows that these problems can be very hard to get right.
https://en.wikipedia.org/wiki/Cluster_(spacecraft)

According to wikipedia (above) this failure resulted in "the first
example of large-scale static code analysis by abstract
interpretation".

I expect that in some situations design-by-contract will help here, by
encouraging a focus on providing a more complete specification of
behaviour. It would be good to have some real-life Python examples.
I'd afraid I don't have any (although I've looked either).

-- 
Jonathan
___
Python-ideas mailing list
Python-ideas@python.org
https://mail.python.org/mailman/listinfo/python-ideas
Code of Conduct: http://python.org/psf/codeofconduct/


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

2018-09-28 Thread Chris Angelico
On Fri, Sep 28, 2018 at 11:25 AM Marko Ristin-Kaufmann
 wrote:
>
> Hi,
>
> I annotated pathlib with 
> contracts:https://github.com/mristin/icontract-pathlib-poc. I zipped the HTML 
> docs into 
> https://github.com/mristin/icontract-pathlib-poc/blob/master/contracts-pathlib-poc.zip,
>  you can just unpack and view the index.html.
>
> One thing I did observe was that there were contracts written in text all 
> over the documentation -- I tried to formulate most of them in code. Since 
> I'm not the implementer nor very familiar with the module, please consider 
> that many of these contracts can be definitely made more beautiful. There 
> were some limitations to icontract-sphinx extension and icontracts which I 
> noted at the top of the document.
>

You do a lot of contracts that involve is_absolute and other checks.
But the postcondition on is_absolute merely says:

not result or self.root != ""

(Also: I'm not sure, but I think maybe that should be _root?? Leaving
that aside.)

So I'm not sure how much you can really ascertain about absolute
paths. You guarantee that is_absolute will return something plausible,
but unless you guarantee that it's returning the correct value,
depending on it for your preconditions seems dubious. A buggy
is_absolute could break basically everything, and your contracts
wouldn't notice.

It is still fundamentally difficult to make assertions about the file
system as pre/post contracts. Are you becoming aware of this?
Contracts, as has been stated multiple times, look great for
mathematically pure functions that have no state outside of their own
parameters and return values (and 'self', where applicable), but are
just poor versions of unit tests when there's anything external to
consider.

ChrisA
___
Python-ideas mailing list
Python-ideas@python.org
https://mail.python.org/mailman/listinfo/python-ideas
Code of Conduct: http://python.org/psf/codeofconduct/


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

2018-09-28 Thread Paul Moore
On Fri, 28 Sep 2018 at 02:24, Marko Ristin-Kaufmann 
wrote:

> Hi,
>
> I annotated pathlib with contracts:
> https://github.com/mristin/icontract-pathlib-poc. I zipped the HTML docs
> into
> https://github.com/mristin/icontract-pathlib-poc/blob/master/contracts-pathlib-poc.zip,
> you can just unpack and view the index.html.
>

Thanks, for doing this! It's probably not going to result in the reaction
you hoped for (see below) but I appreciate you taking the time to do it.

Some of the contracts might seem trivial -- but mind that you, as a writer,
> want to tell the user what s/he is expected to fulfill before calling the
> function. For example, if you say:
> rmdir()
>
> Remove this directory. The directory must be empty.
> Requires:
>
>- not list(self.iterdir()) (??? There must be a way to check this more
>optimally)
>- self.is_dir()
>
>
> self.is_dir() contract might seem trivial -- but it's actually not. You
> actually want to convey the message: dear user, if you are iterating
> through a list of paths, use this function to decide if you should call
> rmdir() or unlink(). Analogously with the first contract: dear user, please
> check if the directory is empty before calling rmdir() and this is what you
> need to call to actually check that.
>

The problem (IMO) with both of these is precisely that they are written as
Python expressions. Your prose descriptions of what they mean are fine, and
*those* are what I would hope to see in documentation. This is far more
obvious in later examples, where the code needed to check certain
conditions is extremely unclear unless you spend time trying to interpret
it.


> I also finally assembled the puzzle. Most of you folks are all older and
> were exposed to DbC in the 80ies championed by DbC zealots who advertised
> it as *the *tool for software development. You were repulsed by their
> fanaticism -- the zealots also pushed for all the contracts to be defined,
> and none less. Either you have 100% DbC or no sane software development at
> all.
>

Well, yes, but your claims were *precisely* the same as those I saw back
then. "All projects on PyPI would benefit", "the benefits are obvious", ...

As I said, DbC is a reasonable methodology, but the reason it's not more
widely used is (in the first instance) because it has a *marketing*
problem. Solving that with more of the same style of marketing won't help.
Once you get beyond the marketing, there are *still* questions (see above
and below), but if you can't even get people past the first step, you've
lost.


> And that's why I said that the libraries on pypi meant to be used by
> multiple people and which already have type annotations would obviously
> benefit from contracts -- while you were imagining that all of these
> libraries need to be DbC'ed 100%, I was imagining something much more
> humble. Thus the misunderstanding.
>

No, I was imagining that some libraries were small, some were used by
small, specialised groups, and some were immensely successful without DbC.
So claiming that they would "obviously" benefit is a very strong claim.


> After annotating pathlib, I find that it actually needs contracts more
> thain if it had type annotations. For example:
> stat()
>
> Return the result of the stat() system call on this path, like os.stat()
> does.
> Ensures:
>
>- result is not None ⇒ self.exists()
>- result is not None ⇒ os.stat(str(self)).__dict__ == result.__dict__
>(??? This is probably not what it was meant with ‘like os.stat() does’?)
>
>
> But what does it mean "like os.stat() does"? I wrote equality over
> __dict__'s in the contract. That was my idea of what the implementer was
> trying to tell me. But is that the operator that should be applied? Sure,
> the contract merits a description. But without it, how am I supposed to
> know what "like" means?
>
> Similarly with rmdir() -- "the directory must be empty" -- but how exactly
> am I supposed to check that?
>

Isn't that the whole point? The prose statement "the directory must be
empty" is clear. But the exact code check isn't - and may be best handled
by a series of unit tests, rather than a precondition.

Anyhow, please have a look at the contracts and let me know what you think.
> Please consider it an illustration. Try to question whether the contracts I
> wrote are so obvious to everybody even if they are obvious to you and keep
> in mind that the user does not look into the implementation. And please try
> to abstract away the aesthetics: neither icontract library that I wrote nor
> the sphinx extension are of sufficient quality. We use them for our company
> code base, but they still need a lot of polishing. So please try to focus
> only on the content. We are still talking about contracts in general, not
> about the concrete contract implementation
>

The thing that you didn't discuss in the above was the effect on the source
code. Looking at your modified sources, I found it *significantly* harder
to read your 

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

2018-09-27 Thread Marko Ristin-Kaufmann
Hi,

I annotated pathlib with contracts:
https://github.com/mristin/icontract-pathlib-poc. I zipped the HTML docs
into
https://github.com/mristin/icontract-pathlib-poc/blob/master/contracts-pathlib-poc.zip,
you can just unpack and view the index.html.

One thing I did observe was that there were contracts written in text all
over the documentation -- I tried to formulate most of them in code. Since
I'm not the implementer nor very familiar with the module, please consider
that many of these contracts can be definitely made more beautiful. There
were some limitations to icontract-sphinx extension and icontracts which I
noted at the top of the document.

(Note also that I had to rename the file to avoid import conflicts.)

Some of the contracts might seem trivial -- but mind that you, as a writer,
want to tell the user what s/he is expected to fulfill before calling the
function. For example, if you say:
rmdir()

Remove this directory. The directory must be empty.
Requires:

   - not list(self.iterdir()) (??? There must be a way to check this more
   optimally)
   - self.is_dir()


self.is_dir() contract might seem trivial -- but it's actually not. You
actually want to convey the message: dear user, if you are iterating
through a list of paths, use this function to decide if you should call
rmdir() or unlink(). Analogously with the first contract: dear user, please
check if the directory is empty before calling rmdir() and this is what you
need to call to actually check that.

I also finally assembled the puzzle. Most of you folks are all older and
were exposed to DbC in the 80ies championed by DbC zealots who advertised
it as *the *tool for software development. You were repulsed by their
fanaticism -- the zealots also pushed for all the contracts to be defined,
and none less. Either you have 100% DbC or no sane software development at
all.

I, on the other side, were introduced to DbC in university much later --
Betrand held most of our software engineering lectures (including
introduction to programming which was in Eiffel ;)). I started going to uni
in 2004; by that time there was no fanaticism about DbC around -- not even
by Bertrand himself. We were taught to use it just as yet another tool in
our toolbox along unit testing and formal proofs. Not as a substitute for
unit testing! Just as yet another instrument for correctness. There was no
100% DbC -- and we did quite some realistic school projects such as a
backend for a flight-booking website in Eiffel (with contracts ;)). I
remember that we got minus points if you wrote something in the
documentation that could have been easily formalized. But nobody pushed for
all the contracts; everybody was pragmatic. Nobody didn't even think about
proposing to abolish unit testing and staff all the tests in the contracts
to be smoke-tested.

While you read my proposals in the light of these 80ies style DbC
proponents, I think always only about a much more minor thing: a simple
tool to make *some part* of the documentation verifiable.

One lesson that I learned from all these courses was to what degree our
understandings (especially among non-native speakers) differ. Even simple
statements such as "x must be positive" can mean x > 0 and x >= 0 to
different people. For me it became obvious that "x > 0" is clearer than "x
must be positive" -- and this is that "obvious" which I always refer in my
posts on this list. If a statement can not be formalized easily and
introduces confusion, that's a different pair of shoes. But if it can --
why shouldn't you formalize it? I still can't wrap my head around the idea
that it's not obvious that you should take the formal version over the
informal version *if both are equally readable*, but one is far less
unambiguous. It feels natural to me that if you want to kick out one, kick
out the more ambiguous informal one. What's the point of all the maths if
the informal languages just do as well?

And that's why I said that the libraries on pypi meant to be used by
multiple people and which already have type annotations would obviously
benefit from contracts -- while you were imagining that all of these
libraries need to be DbC'ed 100%, I was imagining something much more
humble. Thus the misunderstanding.

After annotating pathlib, I find that it actually needs contracts more
thain if it had type annotations. For example:
stat()

Return the result of the stat() system call on this path, like os.stat()
does.
Ensures:

   - result is not None ⇒ self.exists()
   - result is not None ⇒ os.stat(str(self)).__dict__ == result.__dict__
   (??? This is probably not what it was meant with ‘like os.stat() does’?)


But what does it mean "like os.stat() does"? I wrote equality over
__dict__'s in the contract. That was my idea of what the implementer was
trying to tell me. But is that the operator that should be applied? Sure,
the contract merits a description. But without it, how am I supposed to
know what "like" means?

Similarly with 

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

2018-09-27 Thread Marko Ristin-Kaufmann
Hi Paul,
I only had a contracts library in mind (standardized so that different
modules with contracts can interact and that the ecosystem for automic
testing could emerge). I was never thinking about the philosophy or design
methodology (where you write _all_ the contracts first and then have the
implementation fulfill them). I should have clarified that more. I
personally also don't think that such a methodology is practical.

I really see contracts as verifiable docs that rot less fast than human
text and are formally precise / less unambiguous than human text. Other
aspects such as deeper tests and hand-braking (e.g., as postconditions
which can't be practically implemented in python without exit stack context
manager) are also nice to have.

I should be done with pathlib contracts by tonight if I manage to find some
spare time in the evening.

Cheers,
Marko

Le jeu. 27 sept. 2018 à 10:43, Paul Moore  a écrit :

> On Thu, 27 Sep 2018 at 08:03, Greg Ewing 
> wrote:
> >
> > David Mertz wrote:
> > > the reality is that they really ARE NOT much different
> > > from assertions, in either practice or theory.
> >
> > Seems to me that assertions is exactly what they are. Eiffel just
> > provides some syntactic sugar for dealing with inheritance, etc.
> > You can get the same effect in present-day Python if you're
> > willing to write the appropriate code.
>
> Assertions, as far as I can see, are the underlying low level
> *mechanism* that contracts would use. Just like they are the low level
> mechanism behind unit tests (yeah, it's really exceptions, but close
> enough). But like unit tests, contracts seem to me to be a philosophy
> and a library / programming technique layered on top of that base. The
> problem seems to me to be that DbC proponents tend to evangelise the
> philosophy, and ignore requests to show the implementation (often
> pointing to Eiffel as an "example" rather than offering something
> appropriate to the language at hand). IMO, people don't tend to
> emphasise the "D" in DbC enough - it's a *design* approach, and more
> useful in that context than as a programming construct.
>
> For me, the philosophy seems like a reasonable way of thinking, but
> pretty old hat (I learned about invariants and pre-/post-conditions
> and their advantages for design when coding in PL/1 in the 1980's,
> about the same time as I was learning Jackson Structured Programming).
> I don't think in terms of contracts as often as I should - but it's
> unit tests that make me remember to do so. Would a dedicated
> "contracts" library help? Probably not much, but maybe (if it were
> lightweight enough) I could get used to the idea.
>
> Like David, I find that having contracts inline is the biggest problem
> with them. I try to keep my function definitions short, and contracts
> can easily add 100% overhead in terms of lines of code. I'd much
> prefer contracts to be in a separate file. (Which is basically what
> unit tests written with DbC as a principle in mind would be). If I
> have a function definition that's long enough to benefit from
> contracts, I'd usually think "I should refactor this" rather than "I
> should add contracts".
>
> Paul
> ___
> Python-ideas mailing list
> Python-ideas@python.org
> https://mail.python.org/mailman/listinfo/python-ideas
> Code of Conduct: http://python.org/psf/codeofconduct/
>
___
Python-ideas mailing list
Python-ideas@python.org
https://mail.python.org/mailman/listinfo/python-ideas
Code of Conduct: http://python.org/psf/codeofconduct/


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

2018-09-27 Thread Paul Moore
On Thu, 27 Sep 2018 at 08:03, Greg Ewing  wrote:
>
> David Mertz wrote:
> > the reality is that they really ARE NOT much different
> > from assertions, in either practice or theory.
>
> Seems to me that assertions is exactly what they are. Eiffel just
> provides some syntactic sugar for dealing with inheritance, etc.
> You can get the same effect in present-day Python if you're
> willing to write the appropriate code.

Assertions, as far as I can see, are the underlying low level
*mechanism* that contracts would use. Just like they are the low level
mechanism behind unit tests (yeah, it's really exceptions, but close
enough). But like unit tests, contracts seem to me to be a philosophy
and a library / programming technique layered on top of that base. The
problem seems to me to be that DbC proponents tend to evangelise the
philosophy, and ignore requests to show the implementation (often
pointing to Eiffel as an "example" rather than offering something
appropriate to the language at hand). IMO, people don't tend to
emphasise the "D" in DbC enough - it's a *design* approach, and more
useful in that context than as a programming construct.

For me, the philosophy seems like a reasonable way of thinking, but
pretty old hat (I learned about invariants and pre-/post-conditions
and their advantages for design when coding in PL/1 in the 1980's,
about the same time as I was learning Jackson Structured Programming).
I don't think in terms of contracts as often as I should - but it's
unit tests that make me remember to do so. Would a dedicated
"contracts" library help? Probably not much, but maybe (if it were
lightweight enough) I could get used to the idea.

Like David, I find that having contracts inline is the biggest problem
with them. I try to keep my function definitions short, and contracts
can easily add 100% overhead in terms of lines of code. I'd much
prefer contracts to be in a separate file. (Which is basically what
unit tests written with DbC as a principle in mind would be). If I
have a function definition that's long enough to benefit from
contracts, I'd usually think "I should refactor this" rather than "I
should add contracts".

Paul
___
Python-ideas mailing list
Python-ideas@python.org
https://mail.python.org/mailman/listinfo/python-ideas
Code of Conduct: http://python.org/psf/codeofconduct/


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

2018-09-27 Thread Greg Ewing

David Mertz wrote:
the reality is that they really ARE NOT much different 
from assertions, in either practice or theory.


Seems to me that assertions is exactly what they are. Eiffel just
provides some syntactic sugar for dealing with inheritance, etc.
You can get the same effect in present-day Python if you're
willing to write the appropriate code.

--
Greg
___
Python-ideas mailing list
Python-ideas@python.org
https://mail.python.org/mailman/listinfo/python-ideas
Code of Conduct: http://python.org/psf/codeofconduct/


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

2018-09-26 Thread Stephen J. Turnbull
Chris Angelico writes:

 > Okay, but what is the contract that's being violated when you use
 > data= ? How would you define the contract that this would track?
 > That's what I'm asking.

The output is input to some other component.  In production, that
component would not be under your control, perhaps, but in testing it
surely is.  The contract would be associated with the other component,
and it would be "my input is JSON".

Alternatively, if "your" component is being used in a protocol that
specifies JSON, the contract could be "what I post is JSON".  Presumably
that contract can't be checked in production, but in testing it could
be.  If the inputs to your component satisfy their contracts, but JSON
isn't coming out, the problem is in your component.

Ie, I don't see how DbC can diagnose *how* a component is broken, in
general.  It *can* localize the breakage, and provide some hints based
on the particular contract that is "violated".

I think this shows that in a broad class of cases, for existing code,
DbC doesn't do much that a developer with a debugger (such as print()
;-) can't already do, and the developer can do it much more flexibly.

However, getting meta,

 > Just had a confused developer wondering why calling an API with
 > session.post(, data={...some object dict here}) didn't work
 > properly. (Solved by s/data/json)

session.post seems to be a pretty horrible API.  You'd think this
would either be

session.post_json(..., data={...})

or

session.post(..., data={...}, format='json')

with the former preferred (and session.post deprecated in favor of
session.form_encoded; I guess you could also use the latter and
require the 'format' argument).

How would this help in the DbC context?  Your server (if you own it),
or your mock server in the test suite, will complain that its contract
"my input is JSON" is being violated, because it's explicitly an entry
condition, your programmer looks at the component that's supposed to
produce JSON, sees "form_encoded" either in the function name or the
format argument's value, and the likelihood of confusion is small.

The contribution of DbC here is not in the contract itself, but in the
discipline of thinking "how would I write this contract so that its
violation would point me to the coding error?", which leads to
refactoring the 'post' method.

Is DbC better than the server doing "assert is_valid_json(input)"?
That too works best with the suggested refactoring.  Evidently it's
not better, but there are things that assert can't do.  For
example, the server might incrementally parse the JSON, yielding
useful subobjects as you go along.  Then you can't just assert
is_valid_json at the beginning of the response generator; you need to
do this at the server level.  A DbC toolkit would presumably provide a
way to decorate the server with

try:
server.accept_json_object()
except JSONParseError as e:
report_contract_violation(e)

This is, of course, all imaginary, and I have no idea whether it would
work as suggested in practice.  It will be interesting to me to see,
not only Marko's contracts in a DbC-ized module, but also places where
he demands refactoring so that an *informative* contract can be
written.

Steve

___
Python-ideas mailing list
Python-ideas@python.org
https://mail.python.org/mailman/listinfo/python-ideas
Code of Conduct: http://python.org/psf/codeofconduct/


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

2018-09-26 Thread Stephen J. Turnbull
Paul Moore writes:

 > With provisos. Figuring out contracts in sufficient detail to use
 > the code is *in many cases* simple. For harder cases, agreed. But
 > that's why this is simply a proof that contracts *can* be useful,
 > not that 100% of code would benefit from them.

Note that that is not what Marko wrote: he wrote that 100% of projects
on PyPI would benefit.  Like others, I'd like to see at least a
before/after on *one* whole project (that's not tiny, so it has
several meaningful APIs and several calls for at least a few of them),
to see *how much* of that project actually benefits, and how much of
that benefit derives from "more sophisticated than assert" DbC tech.

For now, I think the whole thread is technically speaking off-topic,
though.  Let's stipulate that DbC is a valuable technology that Python
programmers should have available.

(1) Why is it so valuable that it needs to be in the python.org
distribution?  We already have asserts for the simplest cases.
Won't PyPI do for the full-blown Meyer-style implementation?
Development discussion for that implementation should take place
on GitHub[1] or a similar channel, IMO.

(2) We don't have an implementation to include, or if you like there
are many PoCs, and there's no good reason to suppose that there
will be consensus on the candidate for inclusion in this decade.
Again, development discussions for those implementations should
take place on GitHub before coming here to discuss (a) which is
best for the stdlib, (b) whether it's good enough, and (c) whether
it's needed in the stdlib at all.  Is there a clear, leading
candidate that could be proposed "soon", icontracts maybe?

(3) The syntaxes proposed so far require inelegant constructs, like
lambdas or strs, so that decorator arguments can be evaluated
lazily.  Lazy evaluation of arguments is something that newcomers
often want after being burned by "def foo(l=[]):".  But there are
at least two plausible ways to handle this.  One is like Lisp
macros:  "defmacro mfoo(not, one, of, its, args, is, evaluated)".
Another would be a marker for args to be returned unevalled:
"def foo(eval_me, eval_me_not: unevalled, eval_me_too)".[2]

Thus, unevalled arguments *may* be a plausible syntax change that
would help support DbC as well as other possibly desirable use
cases, but we have no proposal to discuss.  Do we?

I'm not yet suggesting that this thread *should* be terminated here
(and that's not to avoid charges of hypocrisy as I post to other
subthreads ;-).  But I think we should be continuously aware of the
three questions I posed above.


Footnotes: 
[1]  Personally, I'd prefer it be GitLab. :-)

[2]  Yes, I'm teasing the type annotations folks, I doubt this syntax
will fly.


___
Python-ideas mailing list
Python-ideas@python.org
https://mail.python.org/mailman/listinfo/python-ideas
Code of Conduct: http://python.org/psf/codeofconduct/


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

2018-09-26 Thread Chris Angelico
On Thu, Sep 27, 2018 at 3:31 PM Greg Ewing  wrote:
>
> Chris Angelico wrote:
> > if you let your API
> > docs rot when you make changes that callers need to be aware of, you
> > have failed your callers.
>
> Yes, I find that documentation auto-generated from code is
> usually a poor substitute for human-written documentation.
> Dumping your formally-written contracts into the docs makes
> the reader reverse-engineer them to figure out what the
> programmer was really trying to say.
>
> Which do you find easier to grok at a glance:
>
> all(L[i] <= L[i+1] for i in range(len(L) - 1))
>
> or
>
> # The list is now sorted
>

Well, with that particular example, you're capitalizing on the known
meaning of the English word "sorted". So to be fair, you should do the
same in Python:

postcondition: L == sorted(L)

This would be inappropriate for an actual sorting function, but let's
say you're altering the value of an item in a sorted list, and
shifting it within that list to get it to the new position, or
something like that.python-ideas 

But yes, in general I do agree: it's frequently cleaner to use an
English word than to craft a Python equivalent.

ChrisA
___
Python-ideas mailing list
Python-ideas@python.org
https://mail.python.org/mailman/listinfo/python-ideas
Code of Conduct: http://python.org/psf/codeofconduct/


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

2018-09-26 Thread Greg Ewing

Chris Angelico wrote:

if you let your API
docs rot when you make changes that callers need to be aware of, you
have failed your callers.


Yes, I find that documentation auto-generated from code is
usually a poor substitute for human-written documentation.
Dumping your formally-written contracts into the docs makes
the reader reverse-engineer them to figure out what the
programmer was really trying to say.

Which do you find easier to grok at a glance:

   all(L[i] <= L[i+1] for i in range(len(L) - 1))

or

   # The list is now sorted

--
Greg
___
Python-ideas mailing list
Python-ideas@python.org
https://mail.python.org/mailman/listinfo/python-ideas
Code of Conduct: http://python.org/psf/codeofconduct/


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

2018-09-26 Thread Stephen J. Turnbull
Robert Collins writes:

 > I think the underlying problem is that you're treating this as a
 > logic problem (what does logic say applies here), rather than an
 > engineering problem (what can we measure and what does it tell us
 > about whats going on).

Pure gold.  I'm glad your name is "Robert Collins", or I would have
skipped the post and just muted the thread.

 > My suspicion, for which I have only anecdata, is that its really in c)
 > today. Kind of where TDD was in the early 2000's (and as I understand
 > the research, its been shown to be a wash: you do get more tests than
 > test-last or test-during,

That's a pretty big deal though, if it means the shop doesn't need The
Big Nurse to prod you to write more tests.

 > and more tests is correlated with quality and ease of evolution,
 > but if you add that test coverage in test-during or test-last, you
 > end up with the same benefits).

"No Silver Bullet." QED

I think Watts Humphrey should have titled his classic, "Any Discipline
for Software Engineering", and subtitled it "'Whatever' Works, as Long
as You Actually Do It".[1]  All of his books on the practice of
software engineering really do say that, by the way.  He recommends
*starting* with *his* way because it worked for him and many students,
so you can just follow the cookbook until "actually doing" becomes
natural.  Then change to doing what comes more naturally to you.


Footnotes: 
[1]  Fred Brooks would have done that, I think.  Humphrey was way too
stuffy to do that. :-)

___
Python-ideas mailing list
Python-ideas@python.org
https://mail.python.org/mailman/listinfo/python-ideas
Code of Conduct: http://python.org/psf/codeofconduct/


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

2018-09-26 Thread David Mertz
I'm not sure what to do with the repeated assurance that that various
things "are obvious."  It really is NOT the case that me, or Paul Moore, or
Hugh Fisher, or Greg Ewing are simply too simple minded to understand what
DbC is.

The off-putting evangelical quality around DbC is something like the
similar evangelical insistence that OOP solves all problems that one tended
to hear in the late-1980s to mid-1990s especially.  The fact that no one
can quite pin down just *what* this special quality of DbC is doesn't
help... the reality is that they really ARE NOT much different from
assertions, in either practice or theory.

Actually, the evangelical OOP thing connects with the evangelical DbC.  One
of the "advantages" of DbC is often stated as support for inheritance.  But
the truth is, I hardly ever use inheritance in my code, or at most very
shallow inheritance in ways where invariants are mostly not preserved.  My
use of OOP in Python is basically mixins plus magic methods... and no, it's
not because I don't understand OOP (I wrote, for example, some of the most
widely read papers on metaclass programming in Python, and designed and
wrote about making a—toy, admittedly—method resolution order and OOP system
for R; my frequent co-author wrote the canonical paper on C3 linearization,
in which I'm acknowledged for my edits, but am not an author).

I also wrote an article or two about DbC in Python in the early 2000s.
None of this is very new.

On Mon, Sep 24, 2018 at 3:47 AM Marko Ristin-Kaufmann <
marko.ris...@gmail.com> wrote:

> *Obvious benefits*
> You both seem to misconceive the contracts. The goal of the
> design-by-contract is not reduced to testing the correctness of the code,
> as I reiterated already a couple of times in the previous thread. The
> contracts document *formally* what the caller and the callee expect and
> need to satisfy when using a method, a function or a class. This is meant
> for a module that is used by multiple people which are not necessarily
> familiar with the code. They are *not *a niche. There are 150K projects
> on pypi.org. Each one of them would benefit if annotated with the
> contracts.
>

Greg Ewing, Chris Angelica, and Paul Moore make the point very well that
MOST code is simply not the sort of thing that is amenable to having
contracts.  What one needs to state is either Turing complete or trivially
reducible to type declarations.  Or the behavior is duck typed loosely
enough that it can do the right thing without being able to specify the
pre- and post-conditions more precisely than "do what this function does."
Very often, that looseness is simply NOT a problem, and is part of what
makes Python flexible and successful.

*Contracts are difficult to read.*
> David wrote:
>
>> To me, as I've said, DbC imposes a very large cost for both writers and
>> readers of code.
>>
>
> This is again something that eludes me and I would be really thankful if
> you could clarify. Please consider for an example, pypackagery (
> https://pypackagery.readthedocs.io/en/latest/packagery.html) and the
> documentation of its function resolve_initial_paths:
>

The documentation you show below is definitely beautiful  I guess that's
generated by your Sphinx enhancement, right?  There are similar systems for
pulling things out of docstrings that follow conventions, but there's a
small incremental value in making them live tests at the same time.

But reading the end-user documentation is not the *reading* I'm talking
about.  The reading I mean is looking at the actual source code files.
Stating all the invariants you want code to follow makes the definitions of
functions/methods longer and more cognitive effort to parse.  A ten line
function body is likely to be accompanied by 15 lines of invariants that
one can state about hopes for the function behavior.  That's not always
bad... but it's definitely not always good.

This is why unit tests are often much better, organizationally.  The
function definitions can remain relatively concise and clean because most
of the time when you are reading or modifying them you don't WANT to think
about those precise contracts.  Sure, maybe some tool support like folding
of contracts could make the burden less; but not less than putting them in
entirely separate files.

Most of the time, I'd like to look at the simplest expression of the code
possible.  Then on a different day, or with a different set of eyes, I can
look at the completely distinct file that has arbitrarily many unit tests
to check invariants I'd like functions to maintain.  Yes, the issues are a
little bit different in classes and nested hierarchies... but like I said,
I never write those, and tend not to like code that does.

> packagery.resolve_initial_paths(*initial_paths*)
>
> Resolve the initial paths of the dependency graph by recursively adding
> *.py files beneath given directories.
> Parameters:
>
> *initial_paths* (List[Path]) – initial paths as absolute paths
> Return type:
>
> 

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

2018-09-26 Thread Greg Ewing

Chris Angelico wrote:

For example, matplotlib's
plt.show() method guarantees that... a plot will be shown, and the
user will have dismissed it, before it returns. Unless you're inside
Jupyter/iPython, in which case it's different. Or if you're in certain
other environments, in which case it's different again. How do you
define the contract for something that is fundamentally interactive?


Indeed, this is what bothers me about DbC fanaticism. It seems to
have been conceived by people thinking about very computer-sciency
kinds of problems, e.g. you're implenenting a data structure which
has certain important invariants that can be expressed mathematically,
and code can be written that checks them reasonably efficiently.
All very neat and self-contained.

But a lot of real-world code isn't like that -- much of the time,
the correctness of a piece of code can't be tested without reference
to things outside that piece of code, or even outside of the program
altogether. How would you write DbC contracts for a GUI, for
example? Most of the postconditions consist of "an image looking
something like this appears on the screen", where "this" is a very
complicated function of the previous state of the system and the
user's input.

IMO, the reason DbC hasn't taken off is that it assumes an idealised
model of what programming consists of that doesn't match reality
well enough.

--
Greg
___
Python-ideas mailing list
Python-ideas@python.org
https://mail.python.org/mailman/listinfo/python-ideas
Code of Conduct: http://python.org/psf/codeofconduct/


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

2018-09-26 Thread Chris Angelico
On Thu, Sep 27, 2018 at 10:07 AM Robert Collins
 wrote:
>
> On 27 September 2018 at 11:50, Chris Angelico  wrote:
>
> > Okay, but what is the contract that's being violated when you use
> > data= ? How would you define the contract that this would track?
> > That's what I'm asking.
>
> I don't know :). From a modelling perspective the correctness of the
> behaviour here depends on state in the server :/.

Exactly. It's the same problem as with trying to write contracts for
matplotlib's plt.show() - its job is fundamentally external, so you
can't define preconditions and postconditions for it. This is one of
the limitations of contracts, or at least that's my understanding.
Maybe I can be proven wrong here?

ChrisA
___
Python-ideas mailing list
Python-ideas@python.org
https://mail.python.org/mailman/listinfo/python-ideas
Code of Conduct: http://python.org/psf/codeofconduct/


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

2018-09-26 Thread Robert Collins
On 27 September 2018 at 11:50, Chris Angelico  wrote:

> Okay, but what is the contract that's being violated when you use
> data= ? How would you define the contract that this would track?
> That's what I'm asking.

I don't know :). From a modelling perspective the correctness of the
behaviour here depends on state in the server :/.

-Rob
___
Python-ideas mailing list
Python-ideas@python.org
https://mail.python.org/mailman/listinfo/python-ideas
Code of Conduct: http://python.org/psf/codeofconduct/


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

2018-09-26 Thread Chris Angelico
On Thu, Sep 27, 2018 at 9:22 AM Robert Collins
 wrote:
>
> On Thu., 27 Sep. 2018, 11:00 Chris Angelico,  wrote:
>>
>> On Thu, Sep 27, 2018 at 8:53 AM Robert Collins
>>  wrote:
>> >
>> > On Thu, 27 Sep 2018 at 00:44, Marko Ristin-Kaufmann
>> >  wrote:
>> > >
>> > > P.S. My offer still stands: I would be very glad to annotate with 
>> > > contracts a set of functions you deem representative (e.g., from a 
>> > > standard library or from some widely used library). Then we can discuss 
>> > > how these contracts. It would be an inaccurate estimate of the benefits 
>> > > of DbC in Python, but it's at least better than no estimate. We can have 
>> > > as little as 10 functions for the start. Hopefully a couple of other 
>> > > people would join, so then we can even see what the variance of 
>> > > contracts would look like.
>> >
>> > i think requests would be a very interesting library to annotate. Just
>> > had a confused developer wondering why calling an API with
>> > session.post(, data={...some object dict here}) didn't work
>> > properly. (Solved by s/data/json), but perhaps illustrative of
>> > something this might help with?
>>
>> Not sure what you mean by not working; my suspicion is that it DID
>> work, but didn't do what you thought it did (it would form-encode).
>> Contracts wouldn't help there, because it's fully legal and correct.
>
>
> Giving post a data= results in form encoding, as you say.
> Giving it a json= results in json encoding.
>
> Works is a bit of a weasel word.
>
> The python code did not crash. However it did not perform as desired, either.
>
> And since that is pretty much the entire value proposition of DbC... it seems 
> like a good case to dissect.

Okay, but what is the contract that's being violated when you use
data= ? How would you define the contract that this would track?
That's what I'm asking.

ChrisA
___
Python-ideas mailing list
Python-ideas@python.org
https://mail.python.org/mailman/listinfo/python-ideas
Code of Conduct: http://python.org/psf/codeofconduct/


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

2018-09-26 Thread Robert Collins
On Thu., 27 Sep. 2018, 11:00 Chris Angelico,  wrote:

> On Thu, Sep 27, 2018 at 8:53 AM Robert Collins
>  wrote:
> >
> > On Thu, 27 Sep 2018 at 00:44, Marko Ristin-Kaufmann
> >  wrote:
> > >
> > > P.S. My offer still stands: I would be very glad to annotate with
> contracts a set of functions you deem representative (e.g., from a standard
> library or from some widely used library). Then we can discuss how these
> contracts. It would be an inaccurate estimate of the benefits of DbC in
> Python, but it's at least better than no estimate. We can have as little as
> 10 functions for the start. Hopefully a couple of other people would join,
> so then we can even see what the variance of contracts would look like.
> >
> > i think requests would be a very interesting library to annotate. Just
> > had a confused developer wondering why calling an API with
> > session.post(, data={...some object dict here}) didn't work
> > properly. (Solved by s/data/json), but perhaps illustrative of
> > something this might help with?
>
> Not sure what you mean by not working; my suspicion is that it DID
> work, but didn't do what you thought it did (it would form-encode).
> Contracts wouldn't help there, because it's fully legal and correct.
>

Giving post a data= results in form encoding, as you say.
Giving it a json= results in json encoding.

Works is a bit of a weasel word.

The python code did not crash. However it did not perform as desired,
either.

And since that is pretty much the entire value proposition of DbC... it
seems like a good case to dissect.


(Unless session.post() differs from requests.post(), but I doubt that
> that'd be the case.)
>

It doesn't.

Rob

>
___
Python-ideas mailing list
Python-ideas@python.org
https://mail.python.org/mailman/listinfo/python-ideas
Code of Conduct: http://python.org/psf/codeofconduct/


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

2018-09-26 Thread Chris Angelico
On Thu, Sep 27, 2018 at 8:53 AM Robert Collins
 wrote:
>
> On Thu, 27 Sep 2018 at 00:44, Marko Ristin-Kaufmann
>  wrote:
> >
> > P.S. My offer still stands: I would be very glad to annotate with contracts 
> > a set of functions you deem representative (e.g., from a standard library 
> > or from some widely used library). Then we can discuss how these contracts. 
> > It would be an inaccurate estimate of the benefits of DbC in Python, but 
> > it's at least better than no estimate. We can have as little as 10 
> > functions for the start. Hopefully a couple of other people would join, so 
> > then we can even see what the variance of contracts would look like.
>
> i think requests would be a very interesting library to annotate. Just
> had a confused developer wondering why calling an API with
> session.post(, data={...some object dict here}) didn't work
> properly. (Solved by s/data/json), but perhaps illustrative of
> something this might help with?

Not sure what you mean by not working; my suspicion is that it DID
work, but didn't do what you thought it did (it would form-encode).
Contracts wouldn't help there, because it's fully legal and correct.

(Unless session.post() differs from requests.post(), but I doubt that
that'd be the case.)

ChrisA
___
Python-ideas mailing list
Python-ideas@python.org
https://mail.python.org/mailman/listinfo/python-ideas
Code of Conduct: http://python.org/psf/codeofconduct/


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

2018-09-26 Thread Robert Collins
On Thu, 27 Sep 2018 at 00:44, Marko Ristin-Kaufmann
 wrote:
>
> P.S. My offer still stands: I would be very glad to annotate with contracts a 
> set of functions you deem representative (e.g., from a standard library or 
> from some widely used library). Then we can discuss how these contracts. It 
> would be an inaccurate estimate of the benefits of DbC in Python, but it's at 
> least better than no estimate. We can have as little as 10 functions for the 
> start. Hopefully a couple of other people would join, so then we can even see 
> what the variance of contracts would look like.

i think requests would be a very interesting library to annotate. Just
had a confused developer wondering why calling an API with
session.post(, data={...some object dict here}) didn't work
properly. (Solved by s/data/json), but perhaps illustrative of
something this might help with?

-Rob
___
Python-ideas mailing list
Python-ideas@python.org
https://mail.python.org/mailman/listinfo/python-ideas
Code of Conduct: http://python.org/psf/codeofconduct/


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

2018-09-26 Thread Chris Angelico
On Thu, Sep 27, 2018 at 5:07 AM Chris Barker  wrote:
>
> On Tue, Sep 25, 2018 at 10:10 PM Lee Braiden  wrote:
>>
>> It's the reason why type checking exists, and why bounds checking exists, 
>> and why unit checking exists too.
>
> And yet Python has none of those. They all provide safety, but also place a 
> burden on the developer.

Type checking? Depends on your definition. Since objects are typed,
Python is safe against the old "I passed an integer when it expected
an array" problem (which probably would result in a junk memory read,
in C), whether the function's arguments are type-checked or not. And
if you want actual type checking, that's available too, just not as
part of the core language (and it has language support for its
syntax).

Bounds checking? Most definitely exists. If you try to subscript a
string or list with a value greater than its length, you get an
exception.

Unit checking? If that's "unit testing", that's part of the standard
library, so yes, that definitely exists in Python.

ChrisA
___
Python-ideas mailing list
Python-ideas@python.org
https://mail.python.org/mailman/listinfo/python-ideas
Code of Conduct: http://python.org/psf/codeofconduct/


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

2018-09-26 Thread Chris Barker via Python-ideas
On Tue, Sep 25, 2018 at 10:10 PM Lee Braiden  wrote:

> It's the reason why type checking exists, and why bounds checking exists,
> and why unit checking exists too.
>

And yet Python has none of those. They all provide safety, but also place a
burden on the developer.

So why use Python? I’m not arguing that all those features don’t have their
advantages, but I am wondering why add them all to Python, rather than
using a language designed for safety?

But Python has such a great ecosystem of packages! Yes, it does — but you
might ask yourself why that is.

All that being said — do go and make a nice DbC package for Python — maybe
all us naysayers will grow to love it!

But could we please stop cluttering this list with discussion of how great
or not great it is?

These meta-conversations are getting really tiresome.

-CHB


-- 

Christopher Barker, Ph.D.
Oceanographer

Emergency Response Division
NOAA/NOS/OR(206) 526-6959   voice
7600 Sand Point Way NE   (206) 526-6329   fax
Seattle, WA  98115   (206) 526-6317   main reception

chris.bar...@noaa.gov
___
Python-ideas mailing list
Python-ideas@python.org
https://mail.python.org/mailman/listinfo/python-ideas
Code of Conduct: http://python.org/psf/codeofconduct/


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

2018-09-26 Thread Marko Ristin-Kaufmann
Hi David,
I'm writing contracts for pathlib as a proof-of-concept.

See pypackagery for an example of a project on pypi that uses contracts:
https://pypi.org/project/pypackagery/

The docs with contracts are available at:
https://pypackagery.readthedocs.io/en/latest/packagery.html

Mind that the interface to icontract might change soon so I'd wait a month
or two before it stabilizes.

Cheers,
Marko

Le mer. 26 sept. 2018 à 20:12, David Stanek  a écrit :

> On Wed, Sep 26, 2018 at 12:49 AM Marko Ristin-Kaufmann
>  wrote:
> >
> >> An extraordinary claim is like "DbC can improve *every single project*
> >> on PyPI". That requires a TON of proof. Obviously we won't quibble if
> >> you can only demonstrate that 99.95% of them can be improved, but you
> >> have to at least show that the bulk of them can.
> >
> >
> > I tried to give the "proof" (not a formal one, though) in my previous
> message.
> >
>
> I have to admit that I haven't kept up with the discussion today, but
> I was also hoping to see some proof. I'm genuinely interested in
> seeing if this is something that can help me and the teams I work
> with. I was very interested in DbC a long time ago, but never found a
> way to make it valuable to me.
>
> I'd like to see a project from PyPI converted to use DbC. This would
> make it easy to see the real world difference between an
> implementation developed using DbC compared to one that is well
> documented, tested and maybe even includes type hints. Toy or
> cherry-picked examples don't help me get a feel for it.
>
> --
> david stanek
> web: https://dstanek.com
> twitter: https://twitter.com/dstanek
> linkedin: https://www.linkedin.com/in/dstanek/
> ___
> Python-ideas mailing list
> Python-ideas@python.org
> https://mail.python.org/mailman/listinfo/python-ideas
> Code of Conduct: http://python.org/psf/codeofconduct/
>
___
Python-ideas mailing list
Python-ideas@python.org
https://mail.python.org/mailman/listinfo/python-ideas
Code of Conduct: http://python.org/psf/codeofconduct/


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

2018-09-26 Thread David Stanek
On Wed, Sep 26, 2018 at 12:49 AM Marko Ristin-Kaufmann
 wrote:
>
>> An extraordinary claim is like "DbC can improve *every single project*
>> on PyPI". That requires a TON of proof. Obviously we won't quibble if
>> you can only demonstrate that 99.95% of them can be improved, but you
>> have to at least show that the bulk of them can.
>
>
> I tried to give the "proof" (not a formal one, though) in my previous message.
>

I have to admit that I haven't kept up with the discussion today, but
I was also hoping to see some proof. I'm genuinely interested in
seeing if this is something that can help me and the teams I work
with. I was very interested in DbC a long time ago, but never found a
way to make it valuable to me.

I'd like to see a project from PyPI converted to use DbC. This would
make it easy to see the real world difference between an
implementation developed using DbC compared to one that is well
documented, tested and maybe even includes type hints. Toy or
cherry-picked examples don't help me get a feel for it.

-- 
david stanek
web: https://dstanek.com
twitter: https://twitter.com/dstanek
linkedin: https://www.linkedin.com/in/dstanek/
___
Python-ideas mailing list
Python-ideas@python.org
https://mail.python.org/mailman/listinfo/python-ideas
Code of Conduct: http://python.org/psf/codeofconduct/


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

2018-09-26 Thread James Lu
> It's easy to say that they're boolean expressions. But that's like
> saying that unit tests are just a bunch of boolean expressions too.
> Why do we have lots of different forms of test, rather than just a big
> fat "assert this and this and this and this and this and this"?
> Because the key to unit testing is not "boolean expressions", it's a
> language that can usefully describe what it is we're testing.
> Contracts aren't just boolean expressions - they're a language (or a
> mini-language) that lets you define WHAT the contract entails.
Please read the earlier discussion from Marko. Contracts are like unit tests 
but acts as documentation that is right next to the function definition. It’s 
also much shorter in number of lines to define. You can write a simple unit 
smoke test to turn a contract into a unit test. Contracts serve unit testing 
and documentation at the same time.

Sent from my iPhone

> On Sep 26, 2018, at 3:18 AM, Chris Angelico  wrote:
> 
> It's easy to say that they're boolean expressions. But that's like
> saying that unit tests are just a bunch of boolean expressions too.
> Why do we have lots of different forms of test, rather than just a big
> fat "assert this and this and this and this and this and this"?
> Because the key to unit testing is not "boolean expressions", it's a
> language that can usefully describe what it is we're testing.
> Contracts aren't just boolean expressions - they're a language (or a
> mini-language) that lets you define WHAT the contract entails.
___
Python-ideas mailing list
Python-ideas@python.org
https://mail.python.org/mailman/listinfo/python-ideas
Code of Conduct: http://python.org/psf/codeofconduct/


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

2018-09-26 Thread Paul Moore
On Wed, 26 Sep 2018 at 16:04, Rhodri James  wrote:
> Marko is making some very big assertions about how much of a benefit
> Design by Contract is.  I flat-out don't believe him.  It's up to him to
> provide some evidence, since he's the one pressing for change.

And to be fair, he's now offered to put some time into producing such
a demonstration, so asking for some facts has had a positive outcome.
(As well as demonstrating that Marko is happy to back up his position
and not just make unsubstantiated assertions - so that in itself is
good to know).

Paul
___
Python-ideas mailing list
Python-ideas@python.org
https://mail.python.org/mailman/listinfo/python-ideas
Code of Conduct: http://python.org/psf/codeofconduct/


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

2018-09-26 Thread Rhodri James

On 25/09/18 21:09, Lee Braiden wrote:

Eh. It's too easy to cry "show me the facts" in any argument.  To do that
too often is to reduce all discussion to pendantry.


I will resist pointing out the spelling mistake... oh damn :-)

The trouble with not crying "show me the facts" is that it is very easy 
to make beautiful sounding assertions into a vacuum that fall apart the 
moment you subject them to reality.  I'm sure we can all think of 
politicians of a variety of parties and nationalities with an 
unfortunate habit of doing exactly that.


Marko is making some very big assertions about how much of a benefit 
Design by Contract is.  I flat-out don't believe him.  It's up to him to 
provide some evidence, since he's the one pressing for change.



That verifying data against the contract a function makes code more
reliable should be self evident to anyone with even the most rudimentary
understanding of a function call, let alone a library or large
application.


Let's assume that the contracts are meaningful and useful (which I'm 
pretty sure won't be 100% true; some people are bound to assume that 
writing contracts means they don't have to think).  Assuming that you 
aren't doing some kind of wide-ranging static analysis (which doesn't 
seem to be what we're talking about), all that the contracts have bought 
you is the assurance that *this* invocation of the function with *these* 
parameters giving *this* result is what you expected.  It does not say 
anything about the reliability of the function in general.


It seems to me that a lot of the DbC philosophy seems to assume that 
functions are complex black-boxes whose behaviours are difficult to 
grasp.  In my experience this is very rarely true.  Most functions I 
write are fairly short and easily grokked, even if they do complicated 
things.  That's part of the skill of breaking a problem down, IMHO; if 
the function is long and horrible-looking, I've already got it wrong and 
no amount of protective scaffolding like DbC is going to help.



It's the reason why type checking exists,


Except Python doesn't type check so much as try operations and see if 
they work.



and why bounds checking exists,


Not in C, not most of the time :-)


and why unit checking exists too.


Unit tests are good when you can do them.  A fair bit of the embedded 
code I write isn't very susceptible to automated testing, though, not 
without spending twice as long writing (and testing!) the test 
environment as the code.


--
Rhodri James *-* Kynesim Ltd
___
Python-ideas mailing list
Python-ideas@python.org
https://mail.python.org/mailman/listinfo/python-ideas
Code of Conduct: http://python.org/psf/codeofconduct/


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

2018-09-26 Thread Marko Ristin-Kaufmann
Hi Paul,
Quite a few people replied on this thread and the previous one before the
fork that dbc is either useless in Python or at best useful in
avionics/niche applications.

I'm really only saying that contracts are a superior (complementary) tool
to informal documentation, doctests, reading the implementation, reading
the tests and trial-and-error.

For every library that have the contracts which can be written down
formally in a pragmatic way, and when the users of the library are multiple
-- then these libraries would benefit from dbc.

That's all that I'm saying and it might have come over as arrogant due to
limits of the medium. It was not my intention to sound so.

I'll have a look at pathlib then.

Cheers,
Marko



Le mer. 26 sept. 2018 à 15:15, Paul Moore  a écrit :

> On Wed, 26 Sep 2018 at 14:04, Marko Ristin-Kaufmann
>  wrote:
> >
> > @Chris Angelico  would annotating pathlib convince you that contracts
> are useful? Is it general enough to start with?
>
> Whoa - be careful here. No-one is saying that "contracts aren't
> useful" (at least not that I'd heard). We're saying that contracts
> *aren't a solution for every library in existence* (which was
> essentially your claim). Annotating pathlib can't convince anyone of
> that claim. At best (and this is all that I'm imagining) it might give
> some indication of why you have such an apparently-unreasonable level
> of confidence in contracts.
>
> I do not expect *ever* to believe you when you say that all projects
> would benefit from contracts. What I might get from such an exercise
> is a better understanding of what you're imagining when you talk about
> a real project "using contracts". Best case scenario - I might be
> persuaded to use them occasionally. Worst case scenario - I find them
> distracting and unhelpful, and we agree to differ on their value.
>
> Paul
>
___
Python-ideas mailing list
Python-ideas@python.org
https://mail.python.org/mailman/listinfo/python-ideas
Code of Conduct: http://python.org/psf/codeofconduct/


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

2018-09-26 Thread Paul Moore
On Wed, 26 Sep 2018 at 14:04, Marko Ristin-Kaufmann
 wrote:
>
> @Chris Angelico  would annotating pathlib convince you that contracts are 
> useful? Is it general enough to start with?

Whoa - be careful here. No-one is saying that "contracts aren't
useful" (at least not that I'd heard). We're saying that contracts
*aren't a solution for every library in existence* (which was
essentially your claim). Annotating pathlib can't convince anyone of
that claim. At best (and this is all that I'm imagining) it might give
some indication of why you have such an apparently-unreasonable level
of confidence in contracts.

I do not expect *ever* to believe you when you say that all projects
would benefit from contracts. What I might get from such an exercise
is a better understanding of what you're imagining when you talk about
a real project "using contracts". Best case scenario - I might be
persuaded to use them occasionally. Worst case scenario - I find them
distracting and unhelpful, and we agree to differ on their value.

Paul
___
Python-ideas mailing list
Python-ideas@python.org
https://mail.python.org/mailman/listinfo/python-ideas
Code of Conduct: http://python.org/psf/codeofconduct/


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

2018-09-26 Thread Chris Angelico
On Wed, Sep 26, 2018 at 11:04 PM Marko Ristin-Kaufmann
 wrote:
> @Chris Angelico  would annotating pathlib convince you that contracts are 
> useful? Is it general enough to start with?
>

I won't promise it'll convince me, but it'll certainly be a
starting-point for real discussion. Also, it's a fairly coherent
"library-style" module - a nice warm-up. So, when you're ready for a
REAL challenge, annotate tkinter :)

Actually, annotating the builtins might be worth doing too. Either
instead of or after pathlib.

ChrisA
___
Python-ideas mailing list
Python-ideas@python.org
https://mail.python.org/mailman/listinfo/python-ideas
Code of Conduct: http://python.org/psf/codeofconduct/


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

2018-09-26 Thread Marko Ristin-Kaufmann
Hi Paul,

Are we talking here about coding explicit executable contracts in the
> source code of the library, or using (formally described in terms of
> (pseudo-)code) contract-style descriptions in the documentation, or
> simply using the ideas of contract-based thinking in designing and
> writing code?
>

The current implementation of icontract uses decorators to decorate the
functions and classes (and metaclasses to support inheritance of
contracts). You have an "enabled" flag which you can set on/off if you want
to disable the contract in some situations.

We are talking about the explicit executable contracts :).

You didn't address my question "does this apply to the stdlib"? If it
> doesn't, your argument has a huge hole - how did you decide that the
> solution you're describing as "beneficial to all libraries" doesn't
> improve the stdlib? If it does, then why not demonstrate your case?
> Give concrete examples - look at some module in the stdlib (for
> example, pathlib) and show exactly what contracts you'd add to the
> code, what the result would look like to the library user (who
> normally doesn't read the source code) and to the core dev (who does).
> Remember that pathlib (like all of the stdlib) doesn't use type
> annotations, and that is a *deliberate* choice, mandated by Guido when
> he first introduced type annotations. So you're not allowed to add
> contracts like "arg1 is a string", nor are you allowed to say that the
> lack of type annotations makes the exercise useless.


Sorry, I missed that point; the messages are getting long :) Yes, the
contracts would make sense in stdlib as well, I'd say.

@Chris Angelico   would annotating pathlib convince you
that contracts are useful? Is it general enough to start with?

On Wed, 26 Sep 2018 at 14:58, Paul Moore  wrote:

> On Wed, 26 Sep 2018 at 13:40, Marko Ristin-Kaufmann
>  wrote:
>
> > Please mind that I said: any library would benefit from it, as in the
> users of any library on pipy would benefit from better, formal and more
> precise documentation. That doesn't imply that all the contracts need to be
> specified or that you have to specify the contract for every function, or
> that you omit the documentation altogether. Some contracts are simply too
> hard to get explicitly. Some are not meaningful even if you could write
> them down. Some you'd like to add, but run only at test time since too slow
> in production. Some run in production, but are not included in the
> documentation (e.g., to prevent the system to enter a bad state though it
> is not meaningful for the user to actually read that contract).
> >
> > Since contracts are formally written, they can be verified. Human text
> can not. Specifying all the contracts is in most cases not meaningful. In
> my day-to-day programming, I specify contracts on the fly and they help me
> express formally to the next girl/guy who will use my code what to expect
> or what not. That does not mean that s/he can just skip the documentation
> or that contracts describe fully what the function does. They merely help
> -- help him/her what arguments and results are expected. That does not mean
> that I fully specified all the predicates on the arguments and the result.
> It's merely a help à la
> > * "Ah, this argument needs to be bigger than that argument!"
> > * "Ah, the resulting dictionary is shorter than the input list!"
> > * "Ah, the result does not include the input list"
> > * "Ah, this function accepts only files (no directories) and relative
> paths!"
> > * "Ah, I put the bounding box outside of the image -- something went
> wrong!"
> > * "Ah, this method allows me to put the bounding box outside of the
> image and will fill all the outside pixels with black!" etc.
>
> Whoops, I think the rules changed under me again :-(
>
> Are we talking here about coding explicit executable contracts in the
> source code of the library, or using (formally described in terms of
> (pseudo-)code) contract-style descriptions in the documentation, or
> simply using the ideas of contract-based thinking in designing and
> writing code?
>
> > For example, if I have an object detector operating on a
> region-of-interest and returning bounding boxes of the objects, the
> postconditions will not be: "all the bounding boxes are cars", that would
> impossible. But the postcondition might check that all the bounding boxes
> are within the region-of-interest or slightly outside, but not completely
> outside etc.
>
> I understand that you have to pick an appropriate level of strictness
> when writing contracts. That's not ever been in question (at least in
> my mind).
>
> > Let's be careful not to make a straw-man here, i.e. to push DbC ad
> absurdum and then discard it that way.
>
> I'm not trying to push DbC to that point. What I *am* trying to do is
> make it clear that your arguments (and in particular the fact that you
> keep insisting that "everything" can benefit) are absurd. If you'd
> tone back on the 

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

2018-09-26 Thread Paul Moore
On Wed, 26 Sep 2018 at 13:43, Marko Ristin-Kaufmann
 wrote:
>
> P.S. My offer still stands: I would be very glad to annotate with contracts a 
> set of functions you deem representative (e.g., from a standard library or 
> from some widely used library). Then we can discuss how these contracts. It 
> would be an inaccurate estimate of the benefits of DbC in Python, but it's at 
> least better than no estimate. We can have as little as 10 functions for the 
> start. Hopefully a couple of other people would join, so then we can even see 
> what the variance of contracts would look like.

Our mails crossed in the ether, sorry.

Pathlib.

Paul
___
Python-ideas mailing list
Python-ideas@python.org
https://mail.python.org/mailman/listinfo/python-ideas
Code of Conduct: http://python.org/psf/codeofconduct/


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

2018-09-26 Thread Paul Moore
On Wed, 26 Sep 2018 at 13:40, Marko Ristin-Kaufmann
 wrote:

> Please mind that I said: any library would benefit from it, as in the users 
> of any library on pipy would benefit from better, formal and more precise 
> documentation. That doesn't imply that all the contracts need to be specified 
> or that you have to specify the contract for every function, or that you omit 
> the documentation altogether. Some contracts are simply too hard to get 
> explicitly. Some are not meaningful even if you could write them down. Some 
> you'd like to add, but run only at test time since too slow in production. 
> Some run in production, but are not included in the documentation (e.g., to 
> prevent the system to enter a bad state though it is not meaningful for the 
> user to actually read that contract).
>
> Since contracts are formally written, they can be verified. Human text can 
> not. Specifying all the contracts is in most cases not meaningful. In my 
> day-to-day programming, I specify contracts on the fly and they help me 
> express formally to the next girl/guy who will use my code what to expect or 
> what not. That does not mean that s/he can just skip the documentation or 
> that contracts describe fully what the function does. They merely help -- 
> help him/her what arguments and results are expected. That does not mean that 
> I fully specified all the predicates on the arguments and the result. It's 
> merely a help à la
> * "Ah, this argument needs to be bigger than that argument!"
> * "Ah, the resulting dictionary is shorter than the input list!"
> * "Ah, the result does not include the input list"
> * "Ah, this function accepts only files (no directories) and relative paths!"
> * "Ah, I put the bounding box outside of the image -- something went wrong!"
> * "Ah, this method allows me to put the bounding box outside of the image and 
> will fill all the outside pixels with black!" etc.

Whoops, I think the rules changed under me again :-(

Are we talking here about coding explicit executable contracts in the
source code of the library, or using (formally described in terms of
(pseudo-)code) contract-style descriptions in the documentation, or
simply using the ideas of contract-based thinking in designing and
writing code?

> For example, if I have an object detector operating on a region-of-interest 
> and returning bounding boxes of the objects, the postconditions will not be: 
> "all the bounding boxes are cars", that would impossible. But the 
> postcondition might check that all the bounding boxes are within the 
> region-of-interest or slightly outside, but not completely outside etc.

I understand that you have to pick an appropriate level of strictness
when writing contracts. That's not ever been in question (at least in
my mind).

> Let's be careful not to make a straw-man here, i.e. to push DbC ad absurdum 
> and then discard it that way.

I'm not trying to push DbC to that point. What I *am* trying to do is
make it clear that your arguments (and in particular the fact that you
keep insisting that "everything" can benefit) are absurd. If you'd
tone back on the extreme claims (as Chris has also asked) then you'd
be more likely to get people interested. This is why (as you
originally asked) DbC is not more popular - its proponents don't seem
to be able to accept that it might not be the solution to every
problem. Python users are typically fairly practical, and think in
terms of "if it helps in this situation, I'll use it". Expecting them
to embrace an argument that demands they accept it applies to
*everything* is likely to meet with resistance.

You didn't address my question "does this apply to the stdlib"? If it
doesn't, your argument has a huge hole - how did you decide that the
solution you're describing as "beneficial to all libraries" doesn't
improve the stdlib? If it does, then why not demonstrate your case?
Give concrete examples - look at some module in the stdlib (for
example, pathlib) and show exactly what contracts you'd add to the
code, what the result would look like to the library user (who
normally doesn't read the source code) and to the core dev (who does).
Remember that pathlib (like all of the stdlib) doesn't use type
annotations, and that is a *deliberate* choice, mandated by Guido when
he first introduced type annotations. So you're not allowed to add
contracts like "arg1 is a string", nor are you allowed to say that the
lack of type annotations makes the exercise useless.

I think I've probably said all I can usefully say here. If you do
write up a DbC-enhanced pathlib, I'll be interested in seeing it and
may well have more to say as a result. If not, I think I'm just going
to file your arguments as "not proven".

Paul
___
Python-ideas mailing list
Python-ideas@python.org
https://mail.python.org/mailman/listinfo/python-ideas
Code of Conduct: http://python.org/psf/codeofconduct/


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

2018-09-26 Thread Marko Ristin-Kaufmann
P.S. My offer still stands: I would be very glad to annotate with contracts
a set of functions you deem representative (*e.g., *from a standard library
or from some widely used library). Then we can discuss how these contracts.
It would be an inaccurate estimate of the benefits of DbC in Python, but
it's at least better than no estimate. We can have as little as 10
functions for the start. Hopefully a couple of other people would join, so
then we can even see what the variance of contracts would look like.

On Wed, 26 Sep 2018 at 14:40, Marko Ristin-Kaufmann 
wrote:

> Hi Chris and Paul,
>
> Let me please answer your messages in one go as they are related.
>
> Paul wrote:
>
>> For most single use (or infrequently used) functions, I'd argue that the
>> trade-off *isn't* worth it.
>>
>> Here's a quick example from the pip codebase:
>>
>> # Retry every half second for up to 3 seconds
>> @retry(stop_max_delay=3000, wait_fixed=500)
>> def rmtree(dir, ignore_errors=False):
>> shutil.rmtree(dir, ignore_errors=ignore_errors,
>>   onerror=rmtree_errorhandler)
>
>
> Absolutely, I agree. If it's a single-use or infrequently used function
> that hardly anybody uses, it's not worth it. Moreover, if some contracts
> are harder to figure out than the implementation, then they are probably in
> most cases not worth the effort, too.
>
> Please mind that I said: any *library* would benefit from it, as in the
> users of any library on pipy would benefit from better, formal and more
> precise documentation. That doesn't imply that all the contracts need to be
> specified or that you have to specify the contract for *every *function,
> or that you omit the documentation altogether. Some contracts are simply
> too hard to get explicitly. Some are not meaningful even if you could write
> them down. Some you'd like to add, but run only at test time since too slow
> in production. Some run in production, but are not included in the
> documentation (*e.g., *to prevent the system to enter a bad state though
> it is not meaningful for the user to actually *read* that contract).
>
> Since contracts are formally written, they can be verified. Human text *can
> not*. Specifying all the contracts is in most cases *not *meaningful. In
> my day-to-day programming, I specify contracts on the fly and they help me
> express formally to the next girl/guy who will use my code what to expect
> or what not. That does not mean that s/he can just skip the documentation
> or that contracts describe fully what the function does. They merely help
> -- help him/her what arguments and results are expected. That *does not
> mean *that I fully specified all the predicates on the arguments and the
> result. It's merely a help à la
> * "Ah, this argument needs to be bigger than that argument!"
> * "Ah, the resulting dictionary is shorter than the input list!"
> * "Ah, the result does not include the input list"
> * "Ah, this function accepts only files (no directories) and relative
> paths!"
> * "Ah, I put the bounding box outside of the image -- something went
> wrong!"
> * "Ah, this method allows me to put the bounding box outside of the image
> and will fill all the outside pixels with black!"
>
> *etc.*
> For example, if I have an object detector operating on a
> region-of-interest and returning bounding boxes of the objects, the
> postconditions will not be: "all the bounding boxes are cars", that would
> impossible. But the postcondition might check that all the bounding boxes
> are within the region-of-interest or slightly outside, but not completely
> outside *etc.*
>
> Let's be careful not to make a straw-man here, *i.e. *to push DbC *ad
> absurdum *and then discard it that way.
>
> Also, the implicit contracts code currently has are typically pretty
>> loose. What you need to "figure out" is very general. Explicit contracts
>> are typically demonstrated as being relatively strict, and figuring out and
>> writing such contracts is more work than writing code with loose implicit
>> contracts. Whether the trade-off of defining tight explicit contracts once
>> vs inferring a loose implicit contract every time you call the function is
>> worth it, depends on how often the function is called. For most single use
>> (or  infrequently used)  functions, I'd argue that the trade-off *isn't*
>> worth it.
>
>
> I don't believe such an approach would ever be pragmatical, *i.e. *automatic
> versioning based on the contracts. It might hint it (as a warning: you
> changed a contract, but did not bump the version), but relying solely on
> this mechanism to get the versioning would imply that you specified *all *the
> contracts. Though Bertrand might have always envisioned it as the best
> state of the world, even he himself repeatedly said that it's better to
> specify rather 10% than 0% contracts and 20% rather than 10% contracts.
>
> Chris wrote:
>
>> def fibber(n):
>> return n if n < 2 else fibber(n-1) + fibber(n-2)
>
>
> It depends who 

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

2018-09-26 Thread Marko Ristin-Kaufmann
Hi Chris and Paul,

Let me please answer your messages in one go as they are related.

Paul wrote:

> For most single use (or infrequently used) functions, I'd argue that the
> trade-off *isn't* worth it.
>
> Here's a quick example from the pip codebase:
>
> # Retry every half second for up to 3 seconds
> @retry(stop_max_delay=3000, wait_fixed=500)
> def rmtree(dir, ignore_errors=False):
> shutil.rmtree(dir, ignore_errors=ignore_errors,
>   onerror=rmtree_errorhandler)


Absolutely, I agree. If it's a single-use or infrequently used function
that hardly anybody uses, it's not worth it. Moreover, if some contracts
are harder to figure out than the implementation, then they are probably in
most cases not worth the effort, too.

Please mind that I said: any *library* would benefit from it, as in the
users of any library on pipy would benefit from better, formal and more
precise documentation. That doesn't imply that all the contracts need to be
specified or that you have to specify the contract for *every *function, or
that you omit the documentation altogether. Some contracts are simply too
hard to get explicitly. Some are not meaningful even if you could write
them down. Some you'd like to add, but run only at test time since too slow
in production. Some run in production, but are not included in the
documentation (*e.g., *to prevent the system to enter a bad state though it
is not meaningful for the user to actually *read* that contract).

Since contracts are formally written, they can be verified. Human text *can
not*. Specifying all the contracts is in most cases *not *meaningful. In my
day-to-day programming, I specify contracts on the fly and they help me
express formally to the next girl/guy who will use my code what to expect
or what not. That does not mean that s/he can just skip the documentation
or that contracts describe fully what the function does. They merely help
-- help him/her what arguments and results are expected. That *does not
mean *that I fully specified all the predicates on the arguments and the
result. It's merely a help à la
* "Ah, this argument needs to be bigger than that argument!"
* "Ah, the resulting dictionary is shorter than the input list!"
* "Ah, the result does not include the input list"
* "Ah, this function accepts only files (no directories) and relative
paths!"
* "Ah, I put the bounding box outside of the image -- something went wrong!"
* "Ah, this method allows me to put the bounding box outside of the image
and will fill all the outside pixels with black!"

*etc.*
For example, if I have an object detector operating on a region-of-interest
and returning bounding boxes of the objects, the postconditions will not
be: "all the bounding boxes are cars", that would impossible. But the
postcondition might check that all the bounding boxes are within the
region-of-interest or slightly outside, but not completely outside *etc.*

Let's be careful not to make a straw-man here, *i.e. *to push DbC *ad
absurdum *and then discard it that way.

Also, the implicit contracts code currently has are typically pretty loose.
> What you need to "figure out" is very general. Explicit contracts are
> typically demonstrated as being relatively strict, and figuring out and
> writing such contracts is more work than writing code with loose implicit
> contracts. Whether the trade-off of defining tight explicit contracts once
> vs inferring a loose implicit contract every time you call the function is
> worth it, depends on how often the function is called. For most single use
> (or  infrequently used)  functions, I'd argue that the trade-off *isn't*
> worth it.


I don't believe such an approach would ever be pragmatical, *i.e. *automatic
versioning based on the contracts. It might hint it (as a warning: you
changed a contract, but did not bump the version), but relying solely on
this mechanism to get the versioning would imply that you specified *all *the
contracts. Though Bertrand might have always envisioned it as the best
state of the world, even he himself repeatedly said that it's better to
specify rather 10% than 0% contracts and 20% rather than 10% contracts.

Chris wrote:

> def fibber(n):
> return n if n < 2 else fibber(n-1) + fibber(n-2)


It depends who you are writing this function for -- for example, instead of
the contract, why not just include the code implementation as the
documentation? The only *meaningful* contract I could imagine:
@pre n >= 0

Everything else would be just repetition of the function. If you
implemented some optimized and complex fibber_optimized() function, then
your contracts would probably look like:
@pre n >= 0
@post (n < 2 ) or result == fibber_optimized(n-1) + fibber_optimized(n-2)
@post not (n < 2) or result == n

> Here is my try at the contracts. Assuming that there is a list of figures
> and that they have a property "displayed" and that "State.blocked" global
> variable refers to whether the interface is blocked or not::

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

2018-09-26 Thread Paul Moore
On Wed, 26 Sep 2018 at 09:45, Chris Angelico  wrote:
>
> On Wed, Sep 26, 2018 at 6:36 PM Paul Moore  wrote:
> >
> > On Wed, 26 Sep 2018 at 06:41, Chris Angelico  wrote:
> > >
> > > On Wed, Sep 26, 2018 at 2:47 PM Marko Ristin-Kaufmann
> > >  wrote:
> > > > * The contracts written in documentation as human text inevitably rot 
> > > > and they are much harder to maintain than automatically verified formal 
> > > > contracts.
> > >
> > > Agreed.
> >
> > Agreed, if contracts are automatically verified. But when runtime cost
> > comes up, people suggest that contracts can be disabled in production
> > code - which invalidates the "automatically verified" premise.
>
> Even if they're only verified as a dedicated testing pass ("okay,
> let's run the unit tests, let's run the contract verifier, let's run
> the type checker, cool, we're good"), they're still better off than
> unchecked comments/documentation in terms of code rot.

Absolutely. But if the contracts are checked at runtime, they are
precisely as good as tests - they will flag violations *in any
circumstances you check*. That's great, but nothing new. I understood
that one of the benefits of contracts was that it would handle cases
that you *forgot* to test - like assertions do, in essence - and would
need to be active in production (again, like assertions, if we assume
we've not explicitly chosen to run with assertions disabled) to get
that benefit.

There's certainly benefits for the "contracts as additional tests"
viewpoint. But whenever that's proposed as what people understand by
DbC, the response is "no, it's not like that at all". So going back to
the "why isn't DbC more popular" question - because no-one can get a
clear handle on whether they are "like tests" or "like assertions" or
"something else" :-)

Paul
___
Python-ideas mailing list
Python-ideas@python.org
https://mail.python.org/mailman/listinfo/python-ideas
Code of Conduct: http://python.org/psf/codeofconduct/


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

2018-09-26 Thread Chris Angelico
On Wed, Sep 26, 2018 at 6:37 PM Chris Angelico  wrote:
>
> On Wed, Sep 26, 2018 at 5:51 PM Marko Ristin-Kaufmann
>  wrote:
> >
> > Hi Chris,
> >
> >> It's easy to say that they're boolean expressions. But that's like
> >> saying that unit tests are just a bunch of boolean expressions too.
> >> Why do we have lots of different forms of test, rather than just a big
> >> fat "assert this and this and this and this and this and this"?
> >> Because the key to unit testing is not "boolean expressions", it's a
> >> language that can usefully describe what it is we're testing.
> >> Contracts aren't just boolean expressions - they're a language (or a
> >> mini-language) that lets you define WHAT the contract entails.
> >
> >
> > Sorry, I misunderstood you. You are probably referring to knowing the terms 
> > like "preconditions, postconditions, invariants, strengthening/weakening", 
> > right? In that case, yes, I agree, I presuppose that readers are familiar 
> > with the concepts of DbC. Otherwise, of course, it makes no sense to use 
> > DbC if you assume nobody could actually figure out what it is :).
> >
>
> Let's say you want to define a precondition and postcondition for this 
> function:
>
> def fibber(n):
> return n < 2 ? n : fibber(n-1) + fibber(n-2)

U

def fibber(n):
return n if n < 2 else fibber(n-1) + fibber(n-2)

Let's, uhh, pretend that I didn't just mix languages there.

For the original, we can say:

@post(raises=ProgrammerFailedSanCheckError)

ChrisA
___
Python-ideas mailing list
Python-ideas@python.org
https://mail.python.org/mailman/listinfo/python-ideas
Code of Conduct: http://python.org/psf/codeofconduct/


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

2018-09-26 Thread Chris Angelico
On Wed, Sep 26, 2018 at 6:36 PM Paul Moore  wrote:
>
> On Wed, 26 Sep 2018 at 06:41, Chris Angelico  wrote:
> >
> > On Wed, Sep 26, 2018 at 2:47 PM Marko Ristin-Kaufmann
> >  wrote:
> > > * The contracts written in documentation as human text inevitably rot and 
> > > they are much harder to maintain than automatically verified formal 
> > > contracts.
> >
> > Agreed.
>
> Agreed, if contracts are automatically verified. But when runtime cost
> comes up, people suggest that contracts can be disabled in production
> code - which invalidates the "automatically verified" premise.

Even if they're only verified as a dedicated testing pass ("okay,
let's run the unit tests, let's run the contract verifier, let's run
the type checker, cool, we're good"), they're still better off than
unchecked comments/documentation in terms of code rot. That said,
though: the contract for a function and the documentation for the
function are inextricably linked *already*, and if you let your API
docs rot when you make changes that callers need to be aware of, you
have failed your callers. Wholesale use of contracts would not remove
the need for good documentation; what it might allow is easier version
compatibility testing. It gives you a somewhat automated (or at least
automatable) tool for checking if two similar libraries (eg version
X.Y and version X.Y-1) are compatible with your code. That would be of
some value, if it could be trusted; you could quickly run your code
through a checker and say "hey, tell me what the oldest version of
Python is that will run this", and get back a response without
actually running a gigantic test suite - since it could check based on
the *diffs* in the contracts rather than the contracts themselves. But
that would require a lot of support, all up and down the stack.

ChrisA
___
Python-ideas mailing list
Python-ideas@python.org
https://mail.python.org/mailman/listinfo/python-ideas
Code of Conduct: http://python.org/psf/codeofconduct/


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

2018-09-26 Thread Chris Angelico
On Wed, Sep 26, 2018 at 5:51 PM Marko Ristin-Kaufmann
 wrote:
>
> Hi Chris,
>
>> It's easy to say that they're boolean expressions. But that's like
>> saying that unit tests are just a bunch of boolean expressions too.
>> Why do we have lots of different forms of test, rather than just a big
>> fat "assert this and this and this and this and this and this"?
>> Because the key to unit testing is not "boolean expressions", it's a
>> language that can usefully describe what it is we're testing.
>> Contracts aren't just boolean expressions - they're a language (or a
>> mini-language) that lets you define WHAT the contract entails.
>
>
> Sorry, I misunderstood you. You are probably referring to knowing the terms 
> like "preconditions, postconditions, invariants, strengthening/weakening", 
> right? In that case, yes, I agree, I presuppose that readers are familiar 
> with the concepts of DbC. Otherwise, of course, it makes no sense to use DbC 
> if you assume nobody could actually figure out what it is :).
>

Let's say you want to define a precondition and postcondition for this function:

def fibber(n):
return n < 2 ? n : fibber(n-1) + fibber(n-2)

What would you specify? Can you say, as a postcondition, that the
return value must be a Fibonacci number? Can you say that, for any 'n'
greater than about 30, the CPU temperature will have risen? How do you
describe those as boolean expressions? The art of the contract depends
on being able to adequately define the conditions.

>
> However, contracts can be useful when testing the GUI -- often it is 
> difficult to script the user behavior. What many people do is record a 
> session and re-play it. If there is a bug, fix it. Then re-record. While 
> writing unit tests for GUI is hard since GUI changes rapidly during 
> development and scripting formally the user behavior is tedious, DbC might be 
> an alternative where you specify as much as you can, and then just re-run 
> through the session. This implies, of course, a human tester.
>

That doesn't sound like the function's contract. That sounds like a
test case - of which you would have multiple, using different
"scripted session" inputs and different outputs (some of success, some
of expected failure).

> Here is my try at the contracts. Assuming that there is a list of figures and 
> that they have a property "displayed" and that "State.blocked" global 
> variable refers to whether the interface is blocked or not::
> @post(lambda: all(figure.displayed for figure in figures)
> @post(lambda: not ipython.in_pylab_mode() or not State.blocked)
> @post(lambda: not interactive() or State.blocked)
> matplotlib.pyplot.show()
>

There is no such thing as "State.blocked". It blocks. The function
*does not return* until the figure has been displayed, and dismissed.
There's no way to recognize that inside the function's state.

Contracts are great when every function is 100% deterministic and can
maintain invariants and/or transform from one set of invariants to
another. Contracts are far less clear when the definitions are
muddier.

ChrisA
___
Python-ideas mailing list
Python-ideas@python.org
https://mail.python.org/mailman/listinfo/python-ideas
Code of Conduct: http://python.org/psf/codeofconduct/


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

2018-09-26 Thread Paul Moore
On Wed, 26 Sep 2018 at 06:41, Chris Angelico  wrote:
>
> On Wed, Sep 26, 2018 at 2:47 PM Marko Ristin-Kaufmann
>  wrote:
> >
> > Hi Chris,
> >
> >> An extraordinary claim is like "DbC can improve *every single project*
> >> on PyPI". That requires a TON of proof. Obviously we won't quibble if
> >> you can only demonstrate that 99.95% of them can be improved, but you
> >> have to at least show that the bulk of them can.
> >
> >
> > I tried to give the "proof" (not a formal one, though) in my previous 
> > message.
>
> (Formal proof isn't necessary here; we say "extraordinary proof", but
> it'd be more accurate to say "extraordinary evidence".)
>
> > The assumptions are that:
> > * There are always contracts, they can be either implicit or explicit. You 
> > need always to figure them out before you call a function or use its result.
>
> Not all code has such contracts. You could argue that code which does
> not is inferior to code which does, but not everything follows a
> strictly-definable pattern.

Also, the implicit contracts code currently has are typically pretty
loose. What you need to "figure out" is very general. Explicit
contracts are typically demonstrated as being relatively strict, and
figuring out and writing such contracts is more work than writing code
with loose implicit contracts. Whether the trade-off of defining tight
explicit contracts once vs inferring a loose implicit contract every
time you call the function is worth it, depends on how often the
function is called. For most single use (or infrequently used)
functions, I'd argue that the trade-off *isn't* worth it.

Here's a quick example from the pip codebase:

# Retry every half second for up to 3 seconds
@retry(stop_max_delay=3000, wait_fixed=500)
def rmtree(dir, ignore_errors=False):
shutil.rmtree(dir, ignore_errors=ignore_errors,
  onerror=rmtree_errorhandler)

What contract would you put on this code? The things I can think of:

1. dir is a directory: obvious from the name, not worth the runtime
cost of checking as shutil.rmtree will do that and we don't want to
duplicate work.
2. dir is a string: covered by type declarations, if we used them. No
need for contracts
3. ignore_errors is a boolean: covered by type declarations.
4. dir should exist: Checked by shutil.rmtree, don't want to duplicate work.
5. After completion, dir won't exist. Obvious unless we have doubts
about what shutil.rmtree does (but that would have a contract too).
Also, we don't want the runtime overhead (again).

In addition, adding those contracts to the code would expand it
significantly, making readability suffer (as it is, rmtree is clearly
a thin wrapper around shutil.rmtree).

> > * Figuring out contracts by trial-and-error and reading the code (the 
> > implementation or the test code) is time consuming and hard.
>
> Agreed.

With provisos. Figuring out contracts in sufficient detail to use the
code is *in many cases* simple. For harder cases, agreed. But that's
why this is simply a proof that contracts *can* be useful, not that
100% of code would benefit from them.

> > * The are tools for formal contracts.
>
> That's the exact point you're trying to make, so it isn't evidence for
> itself. Tools for formal contracts exist as third party in Python, and
> if that were good enough for you, we wouldn't be discussing this.
> There are no such tools in the standard library or language that make
> formal contracts easy.
>
> > * The contracts written in documentation as human text inevitably rot and 
> > they are much harder to maintain than automatically verified formal 
> > contracts.
>
> Agreed.

Agreed, if contracts are automatically verified. But when runtime cost
comes up, people suggest that contracts can be disabled in production
code - which invalidates the "automatically verified" premise.

> > * The reader is familiar with formal statements, and hence reading formal 
> > statements is faster than reading the code or trial-and-error.
>
> Disagreed. I would most certainly NOT assume that every reader knows
> any particular syntax for such contracts. However, this is a weaker
> point.

Depends on what "formal statement" means. If it means "short snippet
of Python code", then yes, the reader will be familiar. But there's
only so much you can do in a short snippet of Python, without calling
out to other functions (which may or may not be "obvious" in their
behavour) so whether it's easier to read a contract is somewhat in
conflict with wanting strong contracts.

> So I'll give you two and two halves for that. Good enough to make do.
>
> > I then went on to show why I think, under these assumptions, that formal 
> > contracts are superior as a documentation tool and hence beneficial. Do you 
> > think that any of these assumptions are wrong? Is there a hole in my 
> > logical reasoning presented in my previous message? I would be very 
> > grateful for any pointers!
> >
> > If these assumptions hold and there is no mistake in my 

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

2018-09-26 Thread Marko Ristin-Kaufmann
Hi Chris,

It's easy to say that they're boolean expressions. But that's like
> saying that unit tests are just a bunch of boolean expressions too.
> Why do we have lots of different forms of test, rather than just a big
> fat "assert this and this and this and this and this and this"?
> Because the key to unit testing is not "boolean expressions", it's a
> language that can usefully describe what it is we're testing.
> Contracts aren't just boolean expressions - they're a language (or a
> mini-language) that lets you define WHAT the contract entails.
>

Sorry, I misunderstood you. You are probably referring to knowing the terms
like "preconditions, postconditions, invariants, strengthening/weakening",
right? In that case, yes, I agree, I presuppose that readers are familiar
with the concepts of DbC. Otherwise, of course, it makes no sense to use
DbC if you assume nobody could actually figure out what it is :).

But that's not the objection that is made too often -- what I really read
often is that DbC is not beneficial not because people are not familiar
with or can learn DbC, but really because reading boolean expressions is
hard. That is what I was referring to in my original message.

> Thanks for this clarification (and the download-yt example)! I actually
> only had packages-as-libraries in mind, not the executable scripts; my
> mistake. So, yes, "any Pypi package" should be reformulated to "any library
> on Pypi" (meant to be used by a wider audience than the developers
> themselves).
> >
>
> Okay. Even with that qualification, though, I still think that not
> every library will benefit from this. For example, matplotlib's
> plt.show() method guarantees that... a plot will be shown, and the
> user will have dismissed it, before it returns. Unless you're inside
> Jupyter/iPython, in which case it's different. Or if you're in certain
> other environments, in which case it's different again. How do you
> define the contract for something that is fundamentally interactive?
>
> You can define very weak contracts. For instance, input() guarantees
> that its return value is a string. Great! DbC doing the job of type
> annotations. Can you guarantee anything else about that string? Is
> there anything else useful that can be spelled easily?
>

In this case, no, I would not add any formal contracts to the function. Not
all contracts can be formulated, and not all contracts are even meaningful.
I suppose interactive functions are indeed a case that it is not possible.
If any string can be returned, than the contract is empty.

However, contracts can be useful when testing the GUI -- often it is
difficult to script the user behavior. What many people do is record a
session and re-play it. If there is a bug, fix it. Then re-record. While
writing unit tests for GUI is hard since GUI changes rapidly during
development and scripting formally the user behavior is tedious, DbC might
be an alternative where you specify as much as you can, and then just
re-run through the session. This implies, of course, a human tester.

Let me take a look at matplotlib show:
matplotlib.pyplot.show(**args*, ***kw*)[source]


Display a figure. When running in ipython with its pylab mode, display all
figures and return to the ipython prompt.

In non-interactive mode, display all figures and block until the figures
have been closed; in interactive mode it has no effect unless figures were
created prior to a change from non-interactive to interactive mode (not
recommended). In that case it displays the figures but does not block.

A single experimental keyword argument, *block*, may be set to True or
False to override the blocking behavior described above.
Here are the contracts as a toy example; (I'm not familiar at all with the
internals of matplotlib. I haven't spent much time really parsing and
analyzing the docstring -- as I'll write below, it also confuses me since
the docstring is not precise enough.)

* If in ipython with its pylab mode, all figures should be displayed.
* If in non-interactive mode, display all figures and block

I'm actually confused with what they mean with:

> In non-interactive mode, display all figures and block until the figures
> have been closed; in interactive mode *it has no effect* *unless figures
> were created prior to a change from non-interactive to interactive mode*
> (not recommended). In that case it displays the figures but does not block.
>
> A single experimental keyword argument, *block*, may be set to True or
> False to override the blocking behavior described above.
>
If only they spelled that out as a contract :)

"it has no effect": What does not have effect? The call to the function? Or
the setting of some parameter? Or the order of the calls?

"unless ...to interactive mode": this would be actually really more
readable as a formal contract. It would imply some refactoring to add a
property when a figure was created (before 

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

2018-09-26 Thread Chris Angelico
On Wed, Sep 26, 2018 at 5:10 PM Marko Ristin-Kaufmann
 wrote:
> The original objection was that DbC in general is not beneficial; not that 
> there are lacking tools for it (this probably got lost in the many messages 
> on this thread). If you assume that there are no suitable tools for DbC, then 
> yes, DbC is certainly not beneficial to any project since using it will be 
> clumsy and difficult. It's a chicken-and-egg problem, so we need to assume 
> that there are good tools for DbC in order for it to be beneficial.
>
>> Disagreed. I would most certainly NOT assume that every reader knows
>> any particular syntax for such contracts. However, this is a weaker
>> point.
>
>
> The contracts are written as boolean expressions. While I agree that many 
> programmers have a hard time with boolean expressions and quantifiers, I 
> don't see this as a blocker to DbC. There is no other special syntax for DbC 
> unless we decide to add it to the core language (which I don't see as 
> probable). What I would like to have is a standard library so that 
> inter-library interactions based on contracts are possible and an ecosystem 
> could emerge around it.
>

It's easy to say that they're boolean expressions. But that's like
saying that unit tests are just a bunch of boolean expressions too.
Why do we have lots of different forms of test, rather than just a big
fat "assert this and this and this and this and this and this"?
Because the key to unit testing is not "boolean expressions", it's a
language that can usefully describe what it is we're testing.
Contracts aren't just boolean expressions - they're a language (or a
mini-language) that lets you define WHAT the contract entails.

>> You might argue that a large proportion of PyPI projects will be
>> "library-style" packages, where the main purpose is to export a bunch
>> of functions. But even then, I'm not certain that they'd all benefit
>> from DbC.
>
>
> Thanks for this clarification (and the download-yt example)! I actually only 
> had packages-as-libraries in mind, not the executable scripts; my mistake. 
> So, yes, "any Pypi package" should be reformulated to "any library on Pypi" 
> (meant to be used by a wider audience than the developers themselves).
>

Okay. Even with that qualification, though, I still think that not
every library will benefit from this. For example, matplotlib's
plt.show() method guarantees that... a plot will be shown, and the
user will have dismissed it, before it returns. Unless you're inside
Jupyter/iPython, in which case it's different. Or if you're in certain
other environments, in which case it's different again. How do you
define the contract for something that is fundamentally interactive?

You can define very weak contracts. For instance, input() guarantees
that its return value is a string. Great! DbC doing the job of type
annotations. Can you guarantee anything else about that string? Is
there anything else useful that can be spelled easily?

> I totally agree. The discussion related to DbC in my mind always revolved 
> around these use cases where type annotations are beneficial as well. Thanks 
> for pointing that out and I'd like to apologize for the confusion! For the 
> future discussion, let's focus on these use cases and please do ignore the 
> rest. I'd still say that there is a plethora of libraries published on Pypi 
> (Is there a way to find out the stats?).
>

Ugh I would love to say "yes", but I can't. I guess maybe you
could look at a bunch of requirements.txt files and see which things
get dragged in that way? All you'll really get is heuristics at best,
and even that, I don't know how to provide. Sorry.

ChrisA
___
Python-ideas mailing list
Python-ideas@python.org
https://mail.python.org/mailman/listinfo/python-ideas
Code of Conduct: http://python.org/psf/codeofconduct/


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

2018-09-26 Thread Marko Ristin-Kaufmann
Hi Chris,

> * There are always contracts, they can be either implicit or explicit.
> You need always to figure them out before you call a function or use its
> result.
>
> Not all code has such contracts. You could argue that code which does
> not is inferior to code which does, but not everything follows a
> strictly-definable pattern.
>

Well, you need to know what to supply to a function and what to expect, at
least subconsciously. The question is just whether you can formulate these
contracts or not; and whether you do or not.

> * The are tools for formal contracts.
>
> That's the exact point you're trying to make, so it isn't evidence for
> itself. Tools for formal contracts exist as third party in Python, and
> if that were good enough for you, we wouldn't be discussing this.
> There are no such tools in the standard library or language that make
> formal contracts easy.
>

The original objection was that DbC in general is not beneficial; not that
there are lacking tools for it (this probably got lost in the many messages
on this thread). If you assume that there are no suitable tools for DbC,
then yes, DbC is certainly *not *beneficial to any project since using it
will be clumsy and difficult. It's a chicken-and-egg problem, so we need to
assume that there are good tools for DbC in order for it to be beneficial.

Disagreed. I would most certainly NOT assume that every reader knows
> any particular syntax for such contracts. However, this is a weaker
> point.


The contracts are written as boolean expressions. While I agree that many
programmers have a hard time with boolean expressions and quantifiers, I
don't see this as a blocker to DbC. There is no other special syntax for
DbC unless we decide to add it to the core language (which I don't see as
probable). What I would like to have is a standard library so that
inter-library interactions based on contracts are possible and an ecosystem
could emerge around it.

Quite some people object that DbC should be rejected as their "average
programmer Joe/Jane" can't deal with the formal expressions. Some readers
have problems parsing "all(i > 0 for i in result) or len(result) < 3" and
can only parse "All numbers in the result are positive and/or the result
has fewer than 3 items". There are also programmers who have a hard time
reading "all(key == value.some_property for key, value in result.items())"
and could only read "The resulting values in the dictionary are keyed by
their some_property attribute.".

I hope that education in computer science is improving and that soon
programmers will be able to read these formal expressions. I'm also not
sure if that is the case for non-English speakers. Hence I assumed that the
readers of the contracts are familiar with formal boolean expressions. If
you assume that readers have hard time parsing quantifiers and boolean
logic then DbC is again certainly not beneficial.

It would make me sad if a feature is rejected on grounds that we have to
accept that many programmers don't master the basics of computer science
(which I consider the boolean expressions to be).

You might argue that a large proportion of PyPI projects will be
> "library-style" packages, where the main purpose is to export a bunch
> of functions. But even then, I'm not certain that they'd all benefit
> from DbC.
>

Thanks for this clarification (and the download-yt example)! I actually
only had packages-as-libraries in mind, not the executable scripts; my
mistake. So, yes, "any Pypi package" should be reformulated to "any library
on Pypi" (meant to be used by a wider audience than the developers
themselves).

People have said the same thing about type checking, too. Would
> *every* project on PyPI benefit from MyPy's type checks? No. Syntax
> for them was added, not because EVERYONE should use them, but  because
> SOME will use them, and it's worth having some language support. You
> would probably do better to argue along those lines than to try to
> claim that every single project ought to be using contracts.


I totally agree. The discussion related to DbC in my mind always revolved
around these use cases where type annotations are beneficial as well.
Thanks for pointing that out and I'd like to apologize for the confusion!
For the future discussion, let's focus on these use cases and please do
ignore the rest. I'd still say that there is a plethora of libraries
published on Pypi (Is there a way to find out the stats?).

but I'm still -0.5 on adding anything of the sort to the stdlib, as I
> don't yet see that *enough* projects would actually benefit.
>

Please see my previous message -- could you maybe say what would convince
you that enough projects would actually benefit from formal contracts?

Cheers,
Marko

On Wed, 26 Sep 2018 at 07:40, Chris Angelico  wrote:

> On Wed, Sep 26, 2018 at 2:47 PM Marko Ristin-Kaufmann
>  wrote:
> >
> > Hi Chris,
> >
> >> An extraordinary claim is like "DbC can improve *every single project*
> >> on PyPI". 

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

2018-09-26 Thread Robert Collins
On Wed, 26 Sep 2018 at 05:19, Marko Ristin-Kaufmann
 wrote:
>
> Hi Robert,
...
>> Claiming that DbC annotations will improve the documentation of every
>> single library on PyPI is an extraordinary claim, and such claims
>> require extraordinary proof.
>
>
> I don't know what you mean by "extraordinary" claim and "extraordinary" 
> proof, respectively.

Chris already addressed this.

> I tried to show that DbC is a great tool and far superior to any other tools 
> currently used to document contracts in a library, please see my message 
> https://groups.google.com/d/msg/python-ideas/dmXz_7LH4GI/5A9jbpQ8CAAJ. Let me 
> re-use the enumeration I used in the message and give you a short summary.

> When you are documenting a method you have the following options:
> 1) Write preconditions and postconditions formally and include them 
> automatically in the documentation (e.g., by using icontract library).
> 2) Write precondtions and postconditions in docstring of the method as human 
> text.
> 3) Write doctests in the docstring of the method.
> 4) Expect the user to read the actual implementation.
> 5) Expect the user to read the testing code.

So you can also:

0) Write clear documentation

e.g. just document the method without doctests. You can write doctests
in example documentation, or even in unit tests if desired: having use
cases be tested is often valuable.


> The implicit or explicit contracts are there willy-nilly. When you use a 
> module, either you need to figure them out using trial-and-error or looking 
> at the implementation (4), looking at the test cases and hoping that they 
> generalize (5), write them as doctests (3) or write them in docstrings as 
> human text (2); or you write them formally as explicit contracts (1).
>
> I could not identify any other methods that can help you with expectations 
> when you call a function or use a class (apart from formal methods and 
> proofs, which I omitted as they seem too esoteric for the current discussion).
>
> Given that:
> * There is no other method for representing contracts,
> * people are trained and can read formal statements and
> * there is tooling available to write, maintain and represent contracts in a 
> nice way
>
> I see formal contracts (1) as a superior tool. The deficiencies of other 
> approaches are:
> 2) Comments and docstrings inevitably rot and get disconnected from the 
> implementation in my and many other people's experience and studies.
> 3) Doctests are much longer and hence more tedious to read and maintain, they 
> need extra text to signal the intent (is it a simple test or an example how 
> boundary conditions are handled or ...). In any non-trivial case, they need 
> to include even the contract itself.
> 4) Looking at other people's code to figure out the contracts is tedious and 
> usually difficult for any non-trivial function.
> 5) Test cases can be difficult to read since they include much broader 
> testing logic (mocking, set up). Most libraries do not ship with the test 
> code. Identifying test cases which demonstrate the contracts can be difficult.

I would say that contracts *are* a formal method. They are machine
interpretable rules about when the function may be called and about
what it may do and how it must leave things.
https://en.wikipedia.org/wiki/Formal_methods

The critique I offer of DbC in a Python context is the same as for
other formal methods: is the benefit worth the overhead. If you're
writing a rocket controller, Python might not be the best language for
it.

> Any function that is used by multiple developers which operates on the 
> restricted range of input values and gives out structured output values 
> benefits from contracts (1) since the user of the function needs to figure 
> them out to properly call the function and handle its results correctly. I 
> assume that every package on pypi is published to be used by wider audience, 
> and not the developer herself. Hence every package on pypi would benefit from 
> formal contracts.

In theory there is no difference between theory and practice, but in
practice there may be differences between practice and theory :).

Less opaquely, you're using a model to try and extrapolate human
behaviour. This is not an easy thing to do, and you are very likely to
be missing factors. For instance, perhaps training affects perceived
benefits. Perhaps a lack of experimental data affects uptake in more
data driven groups. Perhaps increased friction in changing systems is
felt to be a negative.

And crucially, perhaps some of these things are true. As previously
mentioned, Python has wonderful libraries; does it have more per
developer than languages with DbC built in? If so then that might
speak to developer productivity without these formal contracts: it may
be that where the risks of failure are below the threshold that formal
methods are needed, that we're better off with the tradeoff Python
makes today.

> Some predicates are hard to formulate, 

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

2018-09-25 Thread Chris Angelico
On Wed, Sep 26, 2018 at 2:47 PM Marko Ristin-Kaufmann
 wrote:
>
> Hi Chris,
>
>> An extraordinary claim is like "DbC can improve *every single project*
>> on PyPI". That requires a TON of proof. Obviously we won't quibble if
>> you can only demonstrate that 99.95% of them can be improved, but you
>> have to at least show that the bulk of them can.
>
>
> I tried to give the "proof" (not a formal one, though) in my previous message.

(Formal proof isn't necessary here; we say "extraordinary proof", but
it'd be more accurate to say "extraordinary evidence".)

> The assumptions are that:
> * There are always contracts, they can be either implicit or explicit. You 
> need always to figure them out before you call a function or use its result.

Not all code has such contracts. You could argue that code which does
not is inferior to code which does, but not everything follows a
strictly-definable pattern.

> * Figuring out contracts by trial-and-error and reading the code (the 
> implementation or the test code) is time consuming and hard.

Agreed.

> * The are tools for formal contracts.

That's the exact point you're trying to make, so it isn't evidence for
itself. Tools for formal contracts exist as third party in Python, and
if that were good enough for you, we wouldn't be discussing this.
There are no such tools in the standard library or language that make
formal contracts easy.

> * The contracts written in documentation as human text inevitably rot and 
> they are much harder to maintain than automatically verified formal contracts.

Agreed.

> * The reader is familiar with formal statements, and hence reading formal 
> statements is faster than reading the code or trial-and-error.

Disagreed. I would most certainly NOT assume that every reader knows
any particular syntax for such contracts. However, this is a weaker
point.

So I'll give you two and two halves for that. Good enough to make do.

> I then went on to show why I think, under these assumptions, that formal 
> contracts are superior as a documentation tool and hence beneficial. Do you 
> think that any of these assumptions are wrong? Is there a hole in my logical 
> reasoning presented in my previous message? I would be very grateful for any 
> pointers!
>
> If these assumptions hold and there is no mistake in my reasoning, wouldn't 
> that qualify as a proof?
>

It certainly qualifies as proof that SOME code MAY benefit from
contracts. It does not reach the much higher bar to support the claim
that "there are X projects on PyPI and every single one of them would
benefit". For instance, would youtube-dl benefit from DbC? To most
people, it's an application, not a library. Even if you're invoking it
from within a Python script, it's usually easiest to use the main
entrypoint rather than delve into its internals. Case in point:

https://github.com/Rosuav/MegaClip/blob/master/megaclip.py#L71

It's actually easier to shell out to a subprocess than to call on
youtube-dl as a library. Would DbC benefit youtube-dl's internal
functions? Maybe, but that's for the youtube-dl people to decide; it
wouldn't in the slightest benefit my app.

You might argue that a large proportion of PyPI projects will be
"library-style" packages, where the main purpose is to export a bunch
of functions. But even then, I'm not certain that they'd all benefit
from DbC. Some would, and you've definitely made the case for that;
but I'm still -0.5 on adding anything of the sort to the stdlib, as I
don't yet see that *enough* projects would actually benefit.

People have said the same thing about type checking, too. Would
*every* project on PyPI benefit from MyPy's type checks? No. Syntax
for them was added, not because EVERYONE should use them, but  because
SOME will use them, and it's worth having some language support. You
would probably do better to argue along those lines than to try to
claim that every single project ought to be using contracts.

ChrisA
___
Python-ideas mailing list
Python-ideas@python.org
https://mail.python.org/mailman/listinfo/python-ideas
Code of Conduct: http://python.org/psf/codeofconduct/


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

2018-09-25 Thread Marko Ristin-Kaufmann
Hi Chris,

It's easy to show beautiful examples that may actually depend on other
> things. Whether that's representative of all contracts is another
> question.


I agree. There are also many contracts which are simply too hard to write
down formally. But many are also easily captured in formal manner in my
experience. The question is, of course, how many and you make a fair point
there.

@Chris and others requesting data: my time is way too limited to provide a
large-scale code analysis of many pypi packages (family obligations with a
toddler, 9-6 job). I'm not doing research, and such a study would require
substantial time resources. Is there an alternative request that you think
that I (and other volunteers?)  could accomplish in a reasonable (free)
time? Maybe you could compile a list of 100-200 (or even less) functions
from representative modules and I try to annotate them with contracts and
we see if that's convincing? It's up to you to pick representative
functions and up to me to annotate them with contracts. That would diffuse
the argument that I intentionally picked the functions whose contracts are
easily and nice to annotate.

Cheers,
Marko

On Wed, 26 Sep 2018 at 01:20, Chris Angelico  wrote:

> On Wed, Sep 26, 2018 at 7:59 AM Kyle Lahnakoski 
> wrote:
> > I use DbC occasionally to clarify my thoughts during a refactoring, and
> then only in the places that continue to make mistakes. In general, I am
> not in a domain that benefits from DbC.
> >
> > Contracts are code: More code means more bugs.
>
> Contracts are executable documentation. If you can lift them directly
> into user-readable documentation (and by "user" here I mean the user
> of a library), they can save you the work of keeping your
> documentation accurate.
>
> > This contract does not help me:
> >
> > What is_absolute()?  is "file:///" absolute?
>
> I'd have to assume that is_absolute() is defined elsewhere. Which
> means that the value of this contract depends entirely on having other
> functions, probably ALSO contractually-defined, to explain it.
>
> > How does this code fail?
> > What does a permission access problem look like?
>
> Probably an exception. This is Python code, and I would generally
> assume that problems are reported as exceptions.
>
> > Can initial_paths can be None?
>
> This can be answered from the type declaration. It doesn't say
> Optional, so no, it can't be None.
>
> > Can initial_paths be files? directories?
>
> Presumably not a question you'd get if you were actually using it; the
> point of the function is to "[r]esolve the initial paths of the
> dependency graph by recursively adding *.py files beneath given
> directories", so you'd call it because you have directories and want
> files back.
>
> > What are the side effects?
>
> Hopefully none, other than the normal implications of hitting the file
> system.
>
> It's easy to show beautiful examples that may actually depend on other
> things. Whether that's representative of all contracts is another
> question.
>
> ChrisA
> ___
> Python-ideas mailing list
> Python-ideas@python.org
> https://mail.python.org/mailman/listinfo/python-ideas
> Code of Conduct: http://python.org/psf/codeofconduct/
>
___
Python-ideas mailing list
Python-ideas@python.org
https://mail.python.org/mailman/listinfo/python-ideas
Code of Conduct: http://python.org/psf/codeofconduct/


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

2018-09-25 Thread Marko Ristin-Kaufmann
Hi Kyle,

6) The name of the method
> 7) How the method is called throughout the codebase
>
10) relying on convention inside, and outside, the application
>

Sorry, by formulating 2) as "docstring" I excluded names of the methods as
well as variables. Please assume that 2) actually entails those as well.
They are human text and hence not automatically verifiable, hence qualify
as 2).

8) observing input and output values during debugging
> 9) observing input and output values in production
>

Sorry, again I implicitly subsumed 8-9 under 4), reading the implementation
code (including the trial-and-error). My assumption was that it is
incomparably more costly to apply trial-and-error than read the contracts
given that contracts can be formulated. Of course, not all contracts can be
formulated all the time.

11) Don't communicate - Sometimes / is too high;
> code is not repaired, only replaced.
>

I don't see this as an option for any publicly available, high-quality
module on pypi or in any organization. As I already noted in my message to
Hugh, the argument in favor of* undocumented and/or untested code* are not
the arguments. I assume we want a *maintainable* and *usable* modules. I've
never talked about undocumented throw-away exploratory code. Most of the
Python features become futile in that case (type annotations and static
type checking with mypy, to name only the few).

Does it work on Windows?
>
This is probably impossible to write as a contract, but needs to be tested
(though maybe there is a way to check it and encapsulate the check in a
separate function and put it into the contract).

What is_absolute()?  is "file:///" absolute?
>
Since the type is pathlib.Path (as written in the type annotation), it's
pathlib.Path.is_absolute() method. Please see
https://docs.python.org/3/library/pathlib.html#pathlib.PurePath.is_absolute

At a high level, I can see the allure of DbC:  Programming can be a craft,
> and a person can derive deep personal satisfaction from perfecting the code
> they work on. DbC provides you with more decoration, more elaboration, more
> ornamentation, more control.  This is not bad, but I see all your arguments
> as personal ascetic sense.  DbC is only appealing under certain accounting
> rules.  Please consider the possibility that "the best code" is: low $$$,
> buggy, full of tangles, and mostly gets the job done.   :)

Actually, this goes totally contrary to most of my experience. Bad code is
unmaintainable and ends up being much more costly down the line. It's also
what we were taught in software engineering lectures in the university
(some 10-15 years ago) and I always assumed that the studies presented
there were correct.

Saying that writing down contracts is costly is a straw-man. It is costly
if you need to examine the function and write them down. If you *are
writing *the function and just keep adding the contracts as-you-go, it's
basically very little overhead cost. You make an assumption of the input,
and instead of just coding on, you scroll up, write it down formally, and
go back where you stopped and continue the implementation. Or you think for
a minute what contracts your function needs to expect/satisfy before you
start writing it (or during the design). I don't see how this can be less
efficient than trial-and-error and making possibly wrong assumptions based
on the output that you see without any documentation by running the code of
the module.

Cheers,
Marko

On Tue, 25 Sep 2018 at 23:59, Kyle Lahnakoski 
wrote:

>
> I use DbC occasionally to clarify my thoughts during a refactoring, and
> then only in the places that continue to make mistakes. In general, I am
> not in a domain that benefits from DbC.
>
> Contracts are code: More code means more bugs. Declarative contracts are
> succinct, but difficult to debug when wrong; I believe this because the
> debugger support for contracts is poor; There is no way to step through the
> logic and see the intermediate reasoning in complex contracts.  A contract
> is an incomplete duplication of what the code already does: at some level
> of complexity I prefer to use a duplicate independent implementation and
> compare inputs/outputs.
> Writing contracts cost time and money; and that cost should be weighed
> against the number and flexibility of the customers that use the code.  A
> one-time script, a webapp for you team, an Android app for your startup,
> fraud software, and Facebook make different accounting decisions.  I
> contend most code projects can not justify DbC.
>
>
> On 2018-09-24 03:46, Marko Ristin-Kaufmann wrote:
>
> When you are documenting a method you have the following options:
> 1) Write preconditions and postconditions formally and include them
> automatically in the documentation (*e.g., *by using icontract library).
> 2) Write precondtions and postconditions in docstring of the method as
> human text.
> 3) Write doctests in the docstring of the method.
> 4) Expect the user to read the actual 

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

2018-09-25 Thread Marko Ristin-Kaufmann
Hi Chris,

An extraordinary claim is like "DbC can improve *every single project*
> on PyPI". That requires a TON of proof. Obviously we won't quibble if
> you can only demonstrate that 99.95% of them can be improved, but you
> have to at least show that the bulk of them can.


I tried to give the "proof" (not a formal one, though) in my previous
message. The assumptions are that:
* There are always contracts, they can be either implicit or explicit. You
need always to figure them out before you call a function or use its result.
* Figuring out contracts by trial-and-error and reading the code (the
implementation or the test code) is time consuming and hard.
* The are tools for formal contracts.
* The contracts written in documentation as human text inevitably rot and
they are much harder to maintain than automatically verified formal
contracts.
* The reader is familiar with formal statements, and hence reading formal
statements is faster than reading the code or trial-and-error.

I then went on to show why I think, under these assumptions, that formal
contracts are superior as a documentation tool and hence beneficial. Do you
think that any of these assumptions are wrong? Is there a hole in my
logical reasoning presented in my previous message? I would be very
grateful for any pointers!

If these assumptions hold and there is no mistake in my reasoning, wouldn't
that qualify as a proof?

Cheers,
Marko

On Tue, 25 Sep 2018 at 21:43, Chris Angelico  wrote:

> On Wed, Sep 26, 2018 at 3:19 AM Marko Ristin-Kaufmann
>  wrote:
> >> Claiming that DbC annotations will improve the documentation of every
> >> single library on PyPI is an extraordinary claim, and such claims
> >> require extraordinary proof.
> >
> >
> > I don't know what you mean by "extraordinary" claim and "extraordinary"
> proof, respectively. I tried to show that DbC is a great tool and far
> superior to any other tools currently used to document contracts in a
> library, please see my message
> https://groups.google.com/d/msg/python-ideas/dmXz_7LH4GI/5A9jbpQ8CAAJ.
> Let me re-use the enumeration I used in the message and give you a short
> summary.
> >
>
> An ordinary claim is like "DbC can be used to improve code and/or
> documentation", and requires about as much evidence as you can stuff
> into a single email. Simple claim, low burden of proof.
>
> An extraordinary claim is like "DbC can improve *every single project*
> on PyPI". That requires a TON of proof. Obviously we won't quibble if
> you can only demonstrate that 99.95% of them can be improved, but you
> have to at least show that the bulk of them can.
>
> > There are 150K projects on pypi.org. Each one of them would benefit if
> annotated with the contracts.
>
> This is the extraordinary claim. To justify it, you have to show that
> virtually ANY project would benefit from contracts. So far, I haven't
> seen any such proof.
>
> ChrisA
> ___
> Python-ideas mailing list
> Python-ideas@python.org
> https://mail.python.org/mailman/listinfo/python-ideas
> Code of Conduct: http://python.org/psf/codeofconduct/
>
___
Python-ideas mailing list
Python-ideas@python.org
https://mail.python.org/mailman/listinfo/python-ideas
Code of Conduct: http://python.org/psf/codeofconduct/


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

2018-09-25 Thread Chris Angelico
On Wed, Sep 26, 2018 at 7:59 AM Kyle Lahnakoski  wrote:
> I use DbC occasionally to clarify my thoughts during a refactoring, and then 
> only in the places that continue to make mistakes. In general, I am not in a 
> domain that benefits from DbC.
>
> Contracts are code: More code means more bugs.

Contracts are executable documentation. If you can lift them directly
into user-readable documentation (and by "user" here I mean the user
of a library), they can save you the work of keeping your
documentation accurate.

> This contract does not help me:
>
> What is_absolute()?  is "file:///" absolute?

I'd have to assume that is_absolute() is defined elsewhere. Which
means that the value of this contract depends entirely on having other
functions, probably ALSO contractually-defined, to explain it.

> How does this code fail?
> What does a permission access problem look like?

Probably an exception. This is Python code, and I would generally
assume that problems are reported as exceptions.

> Can initial_paths can be None?

This can be answered from the type declaration. It doesn't say
Optional, so no, it can't be None.

> Can initial_paths be files? directories?

Presumably not a question you'd get if you were actually using it; the
point of the function is to "[r]esolve the initial paths of the
dependency graph by recursively adding *.py files beneath given
directories", so you'd call it because you have directories and want
files back.

> What are the side effects?

Hopefully none, other than the normal implications of hitting the file system.

It's easy to show beautiful examples that may actually depend on other
things. Whether that's representative of all contracts is another
question.

ChrisA
___
Python-ideas mailing list
Python-ideas@python.org
https://mail.python.org/mailman/listinfo/python-ideas
Code of Conduct: http://python.org/psf/codeofconduct/


  1   2   >