Counting Sheeps with Contracts in Python

27 pointsposted 10 months ago
by Leo_Germond

18 Comments

Leo_Germond

10 months ago

Hello everyone, I'm starting a new blog where I'm trying to mix my passion and experience for safe programming in critical contexts, and my (over)use of Python, and other techs that are used in... less safe contexts. The "investment hypothesis" if you will is that pieces of tech used daily in critical systems could see a broader use if they stopped being hidden behind mumbo jumbo, bad UX, and general lack of consideration for the common developper. In this blog I'll try to go and discuss fuzzing, contracts, why not some amount of lightweight proofing... and to mix them with application that are hopefully fun and nice to study.

This first post is about counting sheeps, with a design-by-contract twist.

Let me know what you guys think, it's my first blog at all, so I'm a taker for all matters of feedback, as long as it comes from the heart that is ;)

lmeyerov

10 months ago

One of the most 'nice' thing about contract systems is automating blame checking in higher-order code. They handle the lambda/method param wrapping and blame direction assignment for you, which is annoying to do via manual assertions.

I didn't see a link to DBC, is that in there? Or some other use of contracts that is hard via just asserts, like in test amplification?

We are always looking for ways to improve our Python codebase, and I hadn't expected to see modern investment here!

kortex

10 months ago

Cool stuff! Might be fun to integrate with a type validation library like Pydantic or Msgspec to provide in-line coercion/assertion.

What is the performance hit like? I could see these getting pretty expensive (but correctness is invaluable). Seems like it would be great for something like aws lambda in python where you have already decided performance isn't an utmost priority and scrutability is difficult, so any correctness you can bolt on is a boon.

throwaway13337

9 months ago

Value types with contracts should be the focus here. Specifically, the story should not be of type str, but rather of type story that is only allowed to exist when it meets certain conditions.

This approach ensures only a single point of validation, a lower mental overhead as you are certain it is valid everywhere, and fast failure when it's not - by contract, even.

There are a few places where this concept is discussed, but the most concise phrase is: “Parse, don’t validate.”

Zod (TypeScript) is a good example of a library like this, as it is oriented around types. I’m not sure if Python has something similar.

However, overvalidation can make your code overly verbose, which is something I’ve fallen into before. Use it sparingly.

BiteCode_dev

10 months ago

Python shouldn't need special lib to design by contract, `assert cond, "reason"` and `if __debug__` work very well for that.

Unfortunately, people don't know they are made to be stripped in prod with `-OO` so that the perf hit is zero. This means you can never be sure a 3rd party lib you depend on is not using an assert somewhere for a very important check you are going to disable.

https://www.bitecode.dev/p/the-best-python-feature-you-canno...

djoldman

10 months ago

This isn't meant as a dig, I'm genuinely curious: how is this not simply imposing static typing in python?

GrantMoyer

10 months ago

The pre and post conditions are checked at runtime. Also, typically static type sytems are not expressive enough to statically check more than relatively basic pre and post conditions, even in languages with advanced type systems like Haskell or Scala.

Kaethar

10 months ago

You can have preconditions that check stuff not related to typing (e.g: check that a connection is open before calling the function).

maleldil

9 months ago

It kind of is, but pre/post-conditions can be more than that. Also, I'd consider it bad form to have type signatures (which they have) and runtime checking the same types. The whole point of having static typing is decreasing the need for the latter, but you have to actually run a type checker for it to be useful.

antman

9 months ago

Can this be disabled at runtime?

bofaGuy

10 months ago

At this point just use Java instead.

sevensor

9 months ago

The assurance you get from the examples in the article are pretty basic, but there are contracts you’ll have a lot of trouble encoding in the type system, like “arguments are integers in ascending order.”