I started working with SQLObject like 2 weeks ago, went I started with turbogears, since I was new some errors look really bad for me, and i wasted some time checking them, and they end up behing stupid things (like a typo). My 1st error in TG was a big stack trace just because I put 'test', instead of 'text' in a FK call.

I don't think that 1 typo in the class should fail all the way down in the db.

So i decided to write this, it is a small function that checks if your model.py (in turbogears), or any other file that has classes that extend SQLObject will render a valid SQL structure, basically it parses the file with regexp, finds matches to references of classes, compares them and prints functions calls with errors, in a way that resembles python errors. And all this is necesary due to the work around of having strings as params to SQLObjects methods ('RelatedJoin','ForeignKey','MultipleJoin')

if you think this is good enough for SQLObject, then message me with some improvements and i'll fix them, or maybe someone can clean this up or just take the idea and do a rewrite.

I haven't test it extensible but i did with diferent file with at most 10 classes, with diferent errors, it even detects invalid identifiers in method class and i tested it on mysql (4.1.14), with TG 0.8a2 that comes with SQLObject 0.7.0
import re

def process(filename=None):
 identifierPattern=r'([A-Za-z_]+[\w]*)' #a normal python identifier
 singleParameterPattern=r'\([\'"](.*)[\'"]\)' #a single string parametter enclosed in '' or ""

 classPattern=r'class[\W]+%s' % identifierPattern 
# class declarations 
 functionNames=('RelatedJoin','ForeignKey','MultipleJoin'
) #SQLObject, functions to check
 functionPatterns=(re.compile(function+
singleParameterPattern) for function in functionNames) #re patters for all SQLObject functions


 #read the source (filename)
 f = file(filename,"rU")
 input = f.read()
 f.close()

 functionCalls=[]
 for pattern in functionPatterns:
  functionCalls.extend(re.findall(pattern,input
))#make one long list with all call to all SQLObject Funtions in the source
  
 classes=re.findall(classPattern,input)
#get all class declarations on the soruce 
 print classes
 list(set(functionCalls))
 print functionCalls

 input=input.split(
'\n')#split the source in lines, so we can tell the user the line number of the error
 output=[]
 for call in functionCalls:
  if call not in classes:
   for cont in range(len(
input)):#sorry but i need the index number
    if call in input[cont]:
     output.append((cont+1,call))
 if not output:# no errors found
  print "Ur code is bug free"
  return
 def sort(x,y):
  if x[0]>y[
0]:
   return 1
  else:
   return -1
 output.sort(cmp=sort)
 for error in output:
  print "Error, line %d, class %s
 not found" % error

def main():
 import sys
 process(sys.argv[1])

if __name__ == '__main__':
 main()