Hooks, aspect-oriented programming, and design by contract

Luigi Ballabio ballabio at mac.com
Tue Jan 22 13:28:47 CET 2002

	maybe I'm just reinventing the wheel, but I just noted that Alex's 
Aspecter function can easily be twitched to enforce some kind of design by 
contract (which of course can be considered an aspect).
Here's my first shot at it. Corrections and improvements are much welcome.


def AddInvariant(cls, predicate, message=None):
     base_getattribute = cls.__getattribute__
     message = message or "class invariant violation"
     def __getattribute__(self, name):
         attr = base_getattribute(self, name)
         if callable(attr):
             attr = wrap_predicate(predicate, message, self, attr)
         return attr
     cls.__getattribute__ = __getattribute__

def wrap_predicate(predicate, message, self, method):
     def wrapper(*args):
         result = method(*args)
         if not predicate(self):
             raise Exception, message
         return result
     return wrapper

# Let's use it now

# Silly example class
class Account(object):
     def __init__(self):
         self.amount = 0.0
     def deposit(self,amount):
         self.amount += amount
     def withdraw(self,amount):
         self.amount -= amount

# We don't give any credit to anybody
AddInvariant(Account, lambda self: self.amount >= 0.0, "negative balance")

savings = Account()
savings.withdraw(50)    # this works
savings.withdraw(70)    # this raises "negative balance"

More information about the Python-list mailing list