--- /dev/null
+#! python
+
+import sys
+import cgitb
+import inspect
+
+DEBUG_INCREMENT = 5
+DEBUG_LEVEL_DEBUG = DEBUG_INCREMENT * -2
+DEBUG_LEVEL_LOW = DEBUG_INCREMENT * -1
+DEBUG_LEVEL_MEDIUM = DEBUG_INCREMENT * 0
+DEBUG_LEVEL_HIGH = DEBUG_INCREMENT * 1
+DEBUG_LEVEL = DEBUG_LEVEL_MEDIUM
+
+__stackTraceEnabled = True
+
+def stackTraceEnabled(value):
+ global __stackTraceEnabled
+ __stackTraceEnabled = value
+
+def setDebugLevel(level):
+ global DEBUG_LEVEL
+ DEBUG_LEVEL = level
+
+def isBoundMethod(stackFrame):
+ """Checks to see if the method that is running in the specified stackFrame is
+a bound method.
+Returns a 2-tuple containing if it is a bound method, and the object that it is
+bound to if it is bound."""
+ def errout():
+ return (False, None)
+
+ if stackFrame.f_code.co_argcount < 1:
+ return errout()
+ firstVarName = stackFrame.f_code.co_varnames[0]
+ firstVar = stackFrame.f_locals[firstVarName]
+ if not hasattr(firstVar, stackFrame.f_code.co_name):
+ return errout()
+ if not hasattr(getattr(firstVar, stackFrame.f_code.co_name), 'func_code'):
+ return errout()
+ if getattr(getattr(firstVar, stackFrame.f_code.co_name), 'func_code') == stackFrame.f_code:
+ return (True, firstVar)
+ else:
+ return errout()
+
+def createStackTrace(stackList):
+ if not __stackTraceEnabled:
+ return ''
+ strStackList = []
+ for stackItem in stackList:
+ stackItemRepr = ""
+ bm = isBoundMethod(stackItem[0]) # stackframe
+ if bm[0]:
+ stackItemRepr = '%s.' % bm[1].__class__.__name__
+ stackItemRepr += stackItem[3] # Function Name
+ del bm # Help remove circular dependencies (reduces memory useage)
+ strStackList.append(stackItemRepr)
+
+ return '=>'.join(strStackList)
+
+def debug(message, level=DEBUG_LEVEL_MEDIUM, indent_level = None):
+ if level >= DEBUG_LEVEL:
+ stack = inspect.stack()[1:-1] # Ignore this method
+ stack.reverse()
+ if indent_level == None:
+ indent_level = len(stack)
+ for line in message.split('\n'):
+ print >>sys.stderr, '%s %s [%s]' %('>' * indent_level, line, createStackTrace(stack))
+
+def tracebackHook(etype, evalue, etb):
+ print cgitb.text( (etype, evalue, etb), context = 5)