Re: [Python-ideas] Simplicity of C (was why is design-by-contracts not widely)

2018-10-01 Thread Marko Ristin-Kaufmann
Hi Steven (D'Aprano),

Right now, that choice is very restrictive, and I personally don't like
> the look and feel of existing contract libraries. I would give my right
> eye for Cobra-like syntax for contracts in Python:
>
> http://cobra-language.com/trac/cobra/wiki/Contracts
>

You might be interested in the discussion on transpiling contracts back and
forth. See the other thread  "Transpile contracts" and the issue in github:
https://github.com/Parquery/icontract/issues/48
___
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] Transpiling contracts

2018-10-01 Thread Marko Ristin-Kaufmann
Hi James,

I had another take at it. I wrote it down in the github issue (
https://github.com/Parquery/icontract/issues/48#issuecomment-426147468):

SLOW=os.environ.get("SOME_ENVIRONMENT_VARIABLE", "") != ""
class SomeClass:
def __init__(self)->None:
self.some_prop = 1984
def some_func(arg1: List[int], arg2: List[int])->SomeClass:
with requiring:
len(arg1) > 3, "some description"
len(arg2) > 5, ValueError("some format {} {}".format(arg1, arg2))

if SLOW:
all(elt in arg2 for elt in arg1)
len(arg2) == len(set(arg2))

result = None  # type: SomeClass
with ensuring, oldie as O:
len(arg1) == len(O.arg1)
result.some_prop < len(arg2)


This transpiles to/from:

SLOW=os.environ.get("SOME_ENVIRONMENT_VARIABLE", "") != ""
class SomeClass:
def __init__(self)->None:
self.some_prop = 1984
@requires(lambda P: len(P.arg1) > 3, "some
description")@requires(lambda P: len(P.arg2),
  error=lambda P: ValueError("some format {}
{}".format(P.arg1, P.arg2)))@requires(lambda P: all(elt in P.arg2 for
elt in P.arg1), enabled=SLOW)@requires(lambda P: len(arg2) ==
len(set(arg2)))@ensures(lambda O, P: len(P.arg1) ==
len(O.arg1))@ensures(lambda P, result: result.some_prop <
len(P.arg2))def some_func(arg1: List[int], arg2:
List[int])->SomeClass:
...


2. What’s the use case for preferring block syntax over lambda syntax? Is
> the block syntax only better when multiple statements are needed to test a
> single contract condition?
>
Actually no. The condition must be a single statement (specified as a
boolean expression) regardless of the form (readable or executable).

My idea was that contracts would be a more readable + easier to type and
group by the respective enabled flags. It should be a 1-to-1 back and forth
transformation. I didn't aim for any other advantages other than
readability/easier modification.

The use case I have in mind is not to separate each file into two
(executable and readable). I'm more thinking of a tool that I can attach to
key shortcuts in the IDE that let me quickly transform the contracts into
readable form when I need to read them / make my modifications and then
convert them back into executable form.

3. When we do need multiple statements to formally verify/specify, is it
> usually a better idea to factor out major functionality of the contract
> testing to an external function? (So other contracts can use the same
> external function and the intent of the contract is clear trough the
> function name)
>

I would say so (i.e. no multi-statement conditions) . Making
multi-statement conditions would be rather confusing and also harder to put
into documentation. And it would be hard to implement :)

4. If this is true, is it a good idea to include a contracts/ folder at the
> same folder level or a .contracts.py file to list “helper” or verification
> functions for a contract?
>

So far, we never had to make a function external to a contract -- it was
often the signal that something had to be refactored out of the function if
the condition became complex, but the resulting functions usually either
stayed in the same file or were more general and had to move to a separate
module anyhow. Our Python code base has about 95K LOC, I don't know how
contracts behave on larger code bases or how they would need to be
structured.

Cheers,
Marko



On Mon, 1 Oct 2018 at 17:18, James Lu  wrote:

> Hi Marko,
>
> I’m going to refer to the transpiler syntax as “block syntax.”
>
> 1. How does Eiffel do formal contracts?
> 2. What’s the use case for preferring block syntax over lambda syntax? Is
> the block syntax only better when multiple statements are needed to test a
> single contract condition?
> 2. If the last proposition is true, how often do we need multiple
> statements to test or specify a single contract condition?
> 3. When we do need multiple statements to formally verify/specify, is it
> usually a better idea to factor out major functionality of the contract
> testing to an external function? (So other contracts can use the same
> external function and the intent of the contract is clear trough the
> function name)
> 4. If this is true, is it a good idea to include a contracts/ folder at
> the same folder level or a .contracts.py file to list “helper” or
> verification functions for a contract?
>
> I think we should answer questions two and three by looking at real code.
> —
>
> If MockP is supported, it could be used for all the contract decorators:
> @snapshot(var=P.self.name)
> @post(var=R.attr == P.old.var)
>
> The decorator can also check the type of the returned object, and if it’s
> MockP it will use MockP protocol and otherwise it will check the object is
> callable and treat it as a lambda.
>
> Your approach has better type hinting, but I’m not sure if type hinting
> would be that useful if you’re adding a contract whilst writing the
> function.
>
> James Lu
>
> On Oct 1, 2018, at 1:01 AM, 

Re: [Python-ideas] Renaming icontract to pcontract

2018-10-01 Thread Marko Ristin-Kaufmann
Ok, let's keep icontract as it was already referenced a couple of times at
least on this list.

I'll rename the pypi package to icontract2 and the module as well as soon
as I change the interface.

On Mon, 1 Oct 2018 at 20:43, James Lu  wrote:

> I think the confusion would be minimal and not worth the hassle of
> renaming to pcontract. People would just say “Python icontract” when it’s
> ambiguous.
>
> Sent from my iPhone
>
> On Oct 1, 2018, at 3:28 AM, Marko Ristin-Kaufmann 
> wrote:
>
> Hi Cameron,
> A nerdy way to make it sound like a sentence: "I contract that ...".
>
> Pcontract would stand for python contract. Pycontract is already taken.
>
> Cheers,
> Marko
>
> Le lun. 1 oct. 2018 à 09:15, Cameron Simpson  a écrit :
>
>> On 01Oct2018 07:25, Marko Ristin-Kaufmann  wrote:
>> >I'd like to rename icontract into pcontract to avoid name conflict with
>> >java's icontract library.
>> >
>> >Do you have any better suggestion?
>>
>> No, sounds ok to me. What was the "i" for in the old name?
>>
>> Cheers,
>> Cameron Simpson 
>> ___
>> 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/
>
>
___
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] Simplicity of C (was why is design-by-contracts not widely)

2018-10-01 Thread Steven D'Aprano
On Tue, Oct 02, 2018 at 02:43:57AM +0900, Stephen J. Turnbull wrote:
> Steven D'Aprano writes:
> 
>  > I'm not sure how Stephen went from my comment that you can't unit test 
>  > loop invariants to the idea that loop invariants aren't in the 
>  > implementation.
> 
> Obviously I didn't.  I went from your statement that (1) contracts are
> separated from the implementation and the inference from (7) that
> contracts can specify loop invariants to the question of whether both
> can be true at the same time.

Okay, fair enough.

The loop invariant is separate in the sense that it is in a distinctly 
named block. But it connected in the sense that the loop invariant is 
attached to the loop, which is inside the function implementation, 
rather than in a separate block outside of the implementation.

In Python terms, we might say something like:

for x in sequence:
BLOCK
else:
BLOCK
invariant:
BLOCK

Static tools could parse the source and extract the invariant blocks, 
editors could allow you to collapse them out of sight. But unlike the 
(hypothetical) require and ensure blocks, its right there inside the 
function implementation.

We presumably wouldn't want the invariant to be far away from the loop:

... code
... more code
for x in sequence:
   BLOCK
... more code
... more code
...
# and far, far away
invariant:
BLOCK

Even if we had some mechanism to connect the two (some sort of label, 
as you suggest) it would suck from a readability perspective to have to 
jump backwards and forwards from the loop to the loop invariant.

Things which are closely connected ought to be close together.



-- 
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 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] Renaming icontract to pcontract

2018-10-01 Thread James Lu
I think the confusion would be minimal and not worth the hassle of renaming to 
pcontract. People would just say “Python icontract” when it’s ambiguous.

Sent from my iPhone

> On Oct 1, 2018, at 3:28 AM, Marko Ristin-Kaufmann  
> wrote:
> 
> Hi Cameron,
> A nerdy way to make it sound like a sentence: "I contract that ...".
> 
> Pcontract would stand for python contract. Pycontract is already taken.
> 
> Cheers,
> Marko
> 
>> Le lun. 1 oct. 2018 à 09:15, Cameron Simpson  a écrit :
>> On 01Oct2018 07:25, Marko Ristin-Kaufmann  wrote:
>> >I'd like to rename icontract into pcontract to avoid name conflict with
>> >java's icontract library.
>> >
>> >Do you have any better suggestion?
>> 
>> No, sounds ok to me. What was the "i" for in the old name?
>> 
>> Cheers,
>> Cameron Simpson 
>> ___
>> 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/
___
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] Simplicity of C (was why is design-by-contracts not widely)

2018-10-01 Thread Stephen J. Turnbull
Marko Ristin-Kaufmann writes:

 > Do you mean annotating an abstract class with contracts or
 > annotating the actual functions in abc module?

I mean the functions in the abc module.

 > Inheriting of contracts also proved useful when you define an
 > interface as a group of functions together with the contracts. You
 > define the functions as an ABC with purely static methods (no
 > state) and specify the contracts in that abstract class.

I can envision how that would work in a situation with application-
specific classes, even in a deep hierarchy, with some discipline.
However, Python does not necessarily conform to that kind of
discipline.  I suspect that Pythonic programming styles are not
terribly amenable to inheritance of contracts.  I think the ABC module
is most likely to provide a strong evidence that I'm wrong: if
contract inheritance, and in general the contracting style of
programming, works well for that module, it will work for anything
written in Python.

By the way, I'm not asking you to do this; you've already provided
both the icontract module and a rather complete annotation of a
sizeable stdlib module.  Your work is appreciated!  Of course I'd be
happy to see a similar treatment of abc, but it's also a reasonable
candidate for thought experiments, or a sample of a few cases.

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] Simplicity of C (was why is design-by-contracts not widely)

2018-10-01 Thread Stephen J. Turnbull
Steven D'Aprano writes:

 > I'm not sure how Stephen went from my comment that you can't unit test 
 > loop invariants to the idea that loop invariants aren't in the 
 > implementation.

Obviously I didn't.  I went from your statement that (1) contracts are
separated from the implementation and the inference from (7) that
contracts can specify loop invariants to the question of whether both
can be true at the same time.

 > Obviously the loop invariant has to be attached to the loop. You
 > can't attach a loop invariant to a method or class, because they
 > might contain more than one loop.

That's not so obvious.  At least in theory you could provide a label
for the loop (Common Lisp for example has named blocks), and refer to
that in an "invariant" section outside the function.  I couldn't
imagine a pleasing syntax without help from someone who's used
contracts, though.  That's why I asked.

It's not a big deal that they aren't both simultaneously true in
practice, it's just that there are a huge number of abstract claims
being made for contracts, and for my money they don't look anywhere
near as much of an improvement over asserts in practice as they sound
in the abstract, in decorator form or in Eiffel syntax.

As I said before, since a number of people are asking for them, I'm at
least +0 on including a contracts module with attractive syntax for
contracts in the stdlib on the general principle that we should
provide batteries for as many common patterns or styles as possible.
But I'm not ready to go that high for language changes for this
purpose, at least not yet.  Since I don't expect to be using contracts
any time soon, I'll leave the definition of "attractive" up to those
who expect to have to read them frequently.

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] Simplicity of C (was why is design-by-contracts not widely)

2018-10-01 Thread Steven D'Aprano
On Sun, Sep 30, 2018 at 06:33:08PM +1000, Chris Angelico wrote:
> On Sun, Sep 30, 2018 at 6:03 PM Steven D'Aprano  wrote:
> >
> > On Sun, Sep 30, 2018 at 02:50:28PM +1000, Chris Angelico wrote:
> >
> > > And yet all the examples I've seen have just been poor substitutes for
> > > unit tests. Can we get some examples that actually do a better job of
> > > selling contracts?
> >
> > In no particular order...
> >
> > (1) Distance
> 
> Don't doctests deal with this too? With the exact same downsides?

I'm not sure that I understand the question.

Yes, doctests are usually (but not always) close to the function too. 
That's a plus in favour of doctests. The downside is that if you want to 
show a metric tonne of examples, your docstring becomes huge. (Or move 
it out into a separate text file, which doctest can still run.)

Sometimes its a real struggle to write a good docstring that isn't huge.

But on the other hand, a good editor should allow you to collapse 
docstrings to a single line.


> > (2) Self-documenting code
> 
> Ditto

Sorry, are you asking if doctests are self-documenting code?

Since they aren't part of the implementation of the function, no they 
aren't.


> > (3) The "Have you performed the *right* tests?" problem
> 
> Great if your contracts can actually be perfectly defined.

Why do you think the contracts have to be perfectly defined?

I keep reading people accusing pro-Contracts people of being zealots who 
believe that Contracts are a magic bullet that solve every problem 100% 
perfectly. I don't know where people get this idea.

Contracts are a tool, like unit tests. Just as a single unit test is 
better than no unit tests, and two unit tests is better than one, same 
goes for contracts. If you have an imperfect (incomplete, not buggy!) 
contract, that's better than *no* contract at all.

If you would like to check five things, but can only specify three of 
them in a contract, that's better than not specifying any of them.


> Every time
> a weird case is mentioned, those advocating contracts (mainly Marko)
> give examples showing "hey, contracts can do that too", and they're
> just testing specifics.

Can you give an example?

Of course, contracts *can* be specific (at least in Eiffel), the syntax 
allows it. In pseudo-code:

def spam(x, y):
require:
if x is None:
y > 0
# implementation goes here...

The precondition checks that if x is None, y must be greater than zero. 
On its own, that's not a very good contract since it tells us nothing 
about the case when x is not None, but (as per my comments above) its 
better than nothing.

How would you do this as a unit test? For starters, you need to move the 
precondition into the function implementation block, giving it an 
explicit raise:

def spam(x, y):
if x is None and y <= 0:
raise SomeError
# implementation continues...


Now you've given up any hope of disabling that specific check, short of 
editing the source code.

Then you have to make a unit test to check that it works the way you 
think it does:

 def test_if_x_is_none_y_cannot_be_negative_or_zero(self):
 # Naming things is hard...
 self.AssertRaise(SomeError, spam, None, -1)
 self.AssertRaise(SomeError, spam, None, 0)

Great! Now we know that if spam is passed None and -1, or None and 0, it 
will correctly fail. But the unit test doesn't give us any confidence 
that None and -9137 will fail, since we haven't tested that case.

Work-around: I often write unit tests like this:

 def test_if_x_is_none_y_cannot_be_negative_or_zero(self):
 for i in range(20):
 # I never know how many or how few values to check...
 n = random.randint(1, 1000)  # or which values...
 self.AssertRaise(SomeError, spam, None, -n)
 self.AssertRaise(SomeError, spam, None, 0)


As David points out in another post, it is true that Contracts also can 
only check the values that you actually pass to the application during 
the testing phase, but that is likely to be a larger set of values than 
those we put in the unit tests, which lets us gain confidence in the 
code more quickly and with less effort. Rather than write lots of 
explicit tests, we can just exercise the routine with realistic data and 
see if the contract checks fail.



[...]
> > (6) Separation of concerns: function algorithm versus error checking
> 
> Agreed, so long as you can define the contract in a way that isn't
> just duplicating the function's own body.

Sure. That's a case where contracts aren't really suitable and a few 
unit tests would be appropriate, but that's only likely to apply to 
post-conditions, not pre-conditions.


> Contracts are great for some situations, but I'm seeing a lot of cases
> where they're just plain not, yet advocates still say "use contracts,
> use contracts". Why?

For the same reason advocates say "Use tests, use tests" despite there 
being 

Re: [Python-ideas] Transpiling contracts

2018-10-01 Thread James Lu
Hi Marko,

I’m going to refer to the transpiler syntax as “block syntax.”

1. How does Eiffel do formal contracts?
2. What’s the use case for preferring block syntax over lambda syntax? Is the 
block syntax only better when multiple statements are needed to test a single 
contract condition? 
2. If the last proposition is true, how often do we need multiple statements to 
test or specify a single contract condition?
3. When we do need multiple statements to formally verify/specify, is it 
usually a better idea to factor out major functionality of the contract testing 
to an external function? (So other contracts can use the same external function 
and the intent of the contract is clear trough the function name)
4. If this is true, is it a good idea to include a contracts/ folder at the 
same folder level or a .contracts.py file to list “helper” or verification 
functions for a contract?

I think we should answer questions two and three by looking at real code.
—

If MockP is supported, it could be used for all the contract decorators:
@snapshot(var=P.self.name)
@post(var=R.attr == P.old.var)

The decorator can also check the type of the returned object, and if it’s MockP 
it will use MockP protocol and otherwise it will check the object is callable 
and treat it as a lambda.

Your approach has better type hinting, but I’m not sure if type hinting would 
be that useful if you’re adding a contract whilst writing the function. 

James Lu

> On Oct 1, 2018, at 1:01 AM, Marko Ristin-Kaufmann  
> wrote:
> 
> Hi James,
> 
>> Regarding the “transpile into Python” syntax with with statements: Can I see 
>> an example of this syntax when used in pathlib? I’m a bit worried this 
>> syntax is too long and “in the way”, unlike decorators which are before the 
>> function body. Or do you mean that both MockP and your syntax should be 
>> supported?
>> 
>> Would
>> 
>> with requiring: assert arg1 < arg2, “message”
>> 
>> Be the code you type or the code that’s actually run?
> 
> 
> That's the code you would type. Let me make a full example (I'm omitting 
> "with contracts" since we actually don't need it).
> 
> You would read/write this:
> def some_func(arg1: List[int])->int:
>   with requiring:
> assert len(arg1) > 3, "some description"
> 
>   with oldie as O, resultie as result, ensuring:
> if SLOW:
>   O.var1 = sum(arg1)
>   assert result > sum(arg1) > O.var1
> 
> assert len(result) > 5
> 
> This would run:
> @requires(lambda P: len(P.arg1) > 3, "some description")
> @snapshot(lambda P, var1: sum(P.arg1), enabled=SLOW)
> @ensures(lambda O, P, result: result > sum(arg1) > O.var1, enabled=SLOW)
> @ensures(lambda result: len(result) > 5)
> 
> I omitted in the example how to specify a custom exception to avoid confusion.
> 
> If we decide that transpiler is the way to go, I'd say it's easier to just 
> stick with lambdas and allow no mock-based approach in transpilation.
> 
> Cheers,
> Marko
>  
> 
> 
___
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] Simplicity of C (was why is design-by-contracts not widely)

2018-10-01 Thread Steven D'Aprano
On Sun, Sep 30, 2018 at 06:19:11PM -0400, Eric V. Smith wrote:
> On 9/30/2018 8:11 AM, Stephen J. Turnbull wrote:
> >Steven D'Aprano writes:
> >  > (7) You can't unit test loop invariants
> >
> >I don't see how a loop invariant can be elegantly specified without
> >mixing it in to the implementation.  Can you show an example of code
> >written in a language with support for loop invariants *not* mixed
> >into the implementation?
> 
> I'd be very interested in this, too. Any pointers?

I'm not sure how Stephen went from my comment that you can't unit test 
loop invariants to the idea that loop invariants aren't in the 
implementation. Obviously the loop invariant has to be attached to the 
loop. You can't attach a loop invariant to a method or class, because 
they might contain more than one loop.

https://en.wikipedia.org/wiki/Loop_invariant#Eiffel

from
x := 0
invariant
x <= 10
until
x > 10
loop
x := x + 1
end



-- 
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] Simplicity of C (was why is design-by-contracts not widely)

2018-10-01 Thread Marko Ristin-Kaufmann
Hi Steve (Turnbull),

It sounds to me like the proof of the pudding for Python will be
> annotating the ABC module with contracts.  If that turns out to be a
> mostly fruitless exercise, it's hard to see how "real" contracts
> (vs. using asserts to "program in contracting style") are an important
> feature for Python in general.
>

Do you mean annotating an abstract class with contracts or annotating the
actual functions in abc module?

If you meant abstract classes in general, we do that for quite some time in
our code base and had no problems so far. icontract already supports
inheritance of contracts (as well as weakening/strengthening of the
contracts).

Inheriting of contracts also proved useful when you define an interface as
a group of functions together with the contracts. You define the functions
as an ABC with purely static methods (no state) and specify the contracts
in that abstract class. The concrete classes implement the static
functions, but don't need to repeat the contracts since they are inherited
from the abstract class. I can copy/paste from our code base if you are
interested.

Cheers,
Marko

On Mon, 1 Oct 2018 at 15:09, Stephen J. Turnbull <
turnbull.stephen...@u.tsukuba.ac.jp> wrote:

> Elazar writes:
>  > On Sun, Sep 30, 2018, 15:12 Stephen J. Turnbull <
>  > turnbull.stephen...@u.tsukuba.ac.jp> wrote:
>
>  > > What does "inherited" mean?  Just that methods that are not overridden
>  > > retain their contracts?
>  >
>  > Contracts are attached to interfaces, not to specifications. So
>  > when you have abstract base class, it defines contracts, and
>  > implementing classes must adhere to these contracts - the can only
>  > strengthen it, not weaken it.
>
> Stated in words, it sounds very reasonable.
>
> Thinking about the implications for writing Python code, it sounds
> very constraining in the context of duck-typing.  Or, to give a
> contrapositive example, you can write few, if any, contracts for
> dunders beyond their signatures.  For example, len(x) + len(y) ==
> len(x + y) is not an invariant over the classes that define __len__
> (eg, set and dict, taking the "x + y" loosely for them).  Of course if
> you restrict to Sequence, you can impose that invariant.  The question
> is the balance.
>
> It sounds to me like the proof of the pudding for Python will be
> annotating the ABC module with contracts.  If that turns out to be a
> mostly fruitless exercise, it's hard to see how "real" contracts
> (vs. using asserts to "program in contracting style") are an important
> feature for Python in general.
>
> That said, given the passion of the proponents, if we can come up with
> an attractive style for implementing contracts without a language
> change, I'd be +0 at least for adding a module to the stdlib.  But
> this is a Python 3.9 project, given the state of the art.
>
>  > This is precisely like with types, since types are contracts (and
>  > vice versa, in a way).
>
> Not Python types (== classes), though.  As a constraint on behavior,
> subclassing is purely nominal, although Python deliberately makes it
> tedious to turn a subclass of str into a clone of int.
>
> 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/
>
___
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] Simplicity of C (was why is design-by-contracts not widely)

2018-10-01 Thread Stephen J. Turnbull
Elazar writes:
 > On Sun, Sep 30, 2018, 15:12 Stephen J. Turnbull <
 > turnbull.stephen...@u.tsukuba.ac.jp> wrote:

 > > What does "inherited" mean?  Just that methods that are not overridden
 > > retain their contracts?
 > 
 > Contracts are attached to interfaces, not to specifications. So
 > when you have abstract base class, it defines contracts, and
 > implementing classes must adhere to these contracts - the can only
 > strengthen it, not weaken it.

Stated in words, it sounds very reasonable.

Thinking about the implications for writing Python code, it sounds
very constraining in the context of duck-typing.  Or, to give a
contrapositive example, you can write few, if any, contracts for
dunders beyond their signatures.  For example, len(x) + len(y) ==
len(x + y) is not an invariant over the classes that define __len__
(eg, set and dict, taking the "x + y" loosely for them).  Of course if
you restrict to Sequence, you can impose that invariant.  The question
is the balance.

It sounds to me like the proof of the pudding for Python will be
annotating the ABC module with contracts.  If that turns out to be a
mostly fruitless exercise, it's hard to see how "real" contracts
(vs. using asserts to "program in contracting style") are an important
feature for Python in general.

That said, given the passion of the proponents, if we can come up with
an attractive style for implementing contracts without a language
change, I'd be +0 at least for adding a module to the stdlib.  But
this is a Python 3.9 project, given the state of the art.

 > This is precisely like with types, since types are contracts (and
 > vice versa, in a way).

Not Python types (== classes), though.  As a constraint on behavior,
subclassing is purely nominal, although Python deliberately makes it
tedious to turn a subclass of str into a clone of int.

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] Suggestion: Extend integers to include iNaN

2018-10-01 Thread Kyle Lahnakoski


On 2018-09-30 10:45, Anders Hovmöller wrote:
>
>>> I am roughing out such a class and some test cases which will hopefully 
>>> include some cases where the hoped for advantages can be realised.
>>>
>>> My thinking on bitwise operations is to do the same as arithmetic 
>>> operations, i.e. (anything op iNaN) = iNaN and likewise for shift 
>>> operations.
>> Steve,
>>
>> While you are extending a number system, can every int be truthy, while
>> only iNan be falsey?  I found that behaviour more useful because
>> checking if there is a value is more common than checking if it is a
>> zero value.
> I’m not saying you’re wrong in principle but such a change to Python seems 
> extremely disruptive. And if we’re talking about robustness of code then 
> truthiness would be better like in Java (!) imo, where only true is true and 
> false is false and everything else is an error. If we’re actually talking 
> about changing the truth table of Python for basic types then this is the 
> logical next step.
>
> But making any change to the basic types truth table is a big -1 from me. 
> This seems like a Python 2-3 transition to me. 

Sorry, I can see I was unclear:  I was only asking that the new number
system (and the class that implements it) have truthy defined differently. 

My imagination never considered extending ints with iNaN. I would
imagine the iNaN checks on every int operation to be noticeably slower,
so out of the question.

___
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] Suggestion: Extend integers to include iNaN

2018-10-01 Thread Jonathan Fine
Hi Steve

You've suggested that we add to Python an integer NaN object, similar
to the already existing float NaN object.

>>> x = float('nan')
>>> x, type(x)
(nan, )

I've learnt that decimal also has a NaN object, but not fractions.
https://stackoverflow.com/questions/19374254/

>>> from decimal import Decimal
>>> y = Decimal('nan')
>>> y, type(y)
(Decimal('NaN'), )

Numpy has its own fixed size int classes

>>> from numpy import int16
>>> x = int16(2358); x, type(x)
(2358, )
>>> x = x * x; x, type(x)
__main__:1: RuntimeWarning: overflow encountered in short_scalars
(-10396, )

I'm confident that one could create classes similar to numpy.int16, except that

>>> z = int16('nan')
Traceback (most recent call last):
ValueError: invalid literal for int() with base 10: 'nan'

would not raise an exception (and would have the semantics you wish for).

I wonder, would this be sufficient for the use cases you have in mind?
-- 
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] Suggestion: Extend integers to include iNaN

2018-10-01 Thread Oscar Benjamin
On Mon, 1 Oct 2018 at 00:00, Chris Angelico  wrote:
>
> On Mon, Oct 1, 2018 at 8:53 AM Oscar Benjamin
>  wrote:
> >
> > On Sun, 30 Sep 2018 at 02:01, Steven D'Aprano  wrote:
> > >
> > > On Sat, Sep 29, 2018 at 09:43:42PM +0100, Oscar Benjamin wrote:
> > > > On Sat, 29 Sep 2018 at 19:38, Steve Barnes  
> > > > wrote:
> > >
> > > > > > I converted to int because I needed a whole number, this was 
> > > > > > intended to
> > > > > represent some more complex process where a value is converted to a
> > > > > whole number down in the depths of the processing.
> > > >
> > > > Your requirement to have a whole number cannot meaningfully be
> > > > satisfied if your input is nan so an exception is the most useful
> > > > result.
> > >
> > > Not to Steve it isn't.
> > >
> > > Be careful about making value judgements like that: Steve is asking for
> > > an integer NAN because for *him* an integer NAN is more useful than an
> > > exception. You shouldn't tell him that he is wrong, unless you know his
> > > use-case and his code, which you don't.
> >
> > Then he can catch the exception and do something else. If I called
> > int(x) because my subsequent code "needed a whole number" then I would
> > definitely not want to end up with a nan. The proposal requested is
> > that int(x) could return something other than a well defined integer.
> > That would break a lot of code!
>
> At no point was the behaviour of int(x) ever proposed to be changed.
> Don't overreact here.

The context got trimmed a bit too much. You can see here the messages
preceding what is quoted above:
https://mail.python.org/pipermail/python-ideas/2018-September/053840.html

Quoting here:
> One simplistic example would be print(int(float('nan'))) (gives a ValueError) 
> while print(int(iNaN)) should give 'nan' or maybe 'inan'

That would mean that the result of int(x) is no longer guaranteed to
be a well-defined integer.

> The recommended use-case was for a library to
> return iNaN instead of None when it is unable to return an actual
> value.

You can already use None or float('nan') for this. You can also create
your own singleton nan object if you want. When I said I haven't seen
a use-case what I mean is that no one has presented a situation where
the existing language facilities are considered insufficient (apart
from the suggestion about int(iNaN) that I refer to above).

--
Oscar
___
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] Renaming icontract to pcontract

2018-10-01 Thread Marko Ristin-Kaufmann
Hi Cameron,
A nerdy way to make it sound like a sentence: "I contract that ...".

Pcontract would stand for python contract. Pycontract is already taken.

Cheers,
Marko

Le lun. 1 oct. 2018 à 09:15, Cameron Simpson  a écrit :

> On 01Oct2018 07:25, Marko Ristin-Kaufmann  wrote:
> >I'd like to rename icontract into pcontract to avoid name conflict with
> >java's icontract library.
> >
> >Do you have any better suggestion?
>
> No, sounds ok to me. What was the "i" for in the old name?
>
> Cheers,
> Cameron Simpson 
> ___
> 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] Renaming icontract to pcontract

2018-10-01 Thread Cameron Simpson

On 01Oct2018 07:25, Marko Ristin-Kaufmann  wrote:

I'd like to rename icontract into pcontract to avoid name conflict with
java's icontract library.

Do you have any better suggestion?


No, sounds ok to me. What was the "i" for in the old name?

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