Tuesday, June 1, 2010

Bitemporality in Python

A few years ago I published a Java framework to deal with bitemporal issues in rich domain models. The code is freely available under a BSD style license.

As a first piece of non-trivial Python programming I coded up an equivalent framework in Python 2.5, available here. The framework allows you to set up a class with bitemporal properties that track the history and evolution of the value assigned to those properties. Here's a small example that should give you a feel for what you can do:
from bitemporal import *

class Person:

 def __init__(self, name):
  self.name = name
  self.address = BitemporalProperty()

p = Person("John Doe");
p.address.assign("Smallville", Interval(date(1975, 4, 3), date.max))
p.address.assign("Bigtown", Interval(date(1994, 8, 26), date.max))

print p.address.now() # Bigtown
print p.address.on(date(1980, 1, 1)) # Smallville

I'm looking for feedback on this code, which right now is only about 300 lines long. Is this code pythonic? Or is this Java-style Python code? If so, what areas need to be improved? Personally, I have doubts about at least a few things:
  • The type checks in the TimeFrame class (and a few other classes) feel iffy:
    @classmethod
    def set_reference(cls, value):
     if type(value) == date:
      cls.reference = datetime.combine(value, time())
     else:
      cls.reference = value
    
    But how else do I ensure that a timeframe always holds a datetime?
  • The BitemporalWrapper class feels Java-like. It decorates another object with bitemporal information and functionality. Is there a better way to do this in a dynamically typed language?
  • I considered using @property for the assign() method on the BitemporalProperty class, but the problem is that you often want to pass in a validity interval, which rules out use of "=".
Does anybody have any tips how this code can be improved?