(Posting from work, so sorry for the short response.)
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?
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
"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.
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
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!