method preconditions, method postconditions and class invariants for Python.

PyDBC provides a Python 2.2 metaclass which implements precondition, postcondition and invariant functionality.

PyDBC operates by rewriting method calls and variable accesses at module load time. Method calls are modified to call other methods representing pre/post conditions and class invariants, while varable accesses are modified to call a method representing class invariants.

There are a few great things about implementing these features using a rewriting metaclass:

  1. We changed the Python semantics without having to compile anything; it's pure Python.
  2. When time comes to release, you can turn off the rewriting by unsetting a single environment variable.
  3. Since the rewriting is done once at module load time, there is no time overhead imposed by unused condition checks (if you don't have a precondition for a particular method, not even a single "if" will be wasted trying to handle its precondition).
  4. When rewriting is disabled, the only overhead on your program is that you have a few method definitions that never get called. The code implementing contract checks is never even created.

Using PyDBC in your program is very easy:

  import dbc
  __metaclass__ = dbc.DBC

  class Foo:
      def __invar(self):
          assert isinstance(self.a, int)

      def __init__(self, a):
          self.a = a

      def foo(self, a):
          self.a *= a

      def foo__pre(self, a):
          assert a > 0

      def foo__post(self, rval):
          assert rval is None
foo__pre, foo__post and __invar are a precondition, a post condition and the class invariant, respectively.

Convinced yet? If not, take a look at this. Otherwise, head on over to the download page and grab the latest release.

PyDBC is the work of Daniel Arbuckle