from xml.dom.minidom import getDOMImplementation
import atexit
import pickle
+import cStringIO
+import bz2
if sys.platform.startswith("win"):
import win32api
return ""
def stop_here(self, frame):
- if( self._userBreak ):
+ if self._userBreak:
return True
if _VERBOSE: print "Before calling server close on breakpoint server"
self._server.server_close()
if _VERBOSE: print "Calling server close on breakpoint server"
+ self._server = None
class DebuggerHarness(object):
self._server.register_function(self.clear_breakpoint)
self._server.register_function(self.set_all_breakpoints)
self._server.register_function(self.attempt_introspection)
+ self._server.register_function(self.execute_in_frame)
self._server.register_function(self.add_watch)
+ self._server.register_function(self.request_frame_document)
+ self.frame_stack = []
self.message_frame_dict = {}
self.introspection_list = []
atexit.register(self.do_exit)
tp, val, tb = sys.exc_info()
return self.get_exception_document(tp, val, tb)
return ""
-
+
+ def execute_in_frame(self, frame_message, command):
+ frame = self.message_frame_dict[frame_message]
+ output = cStringIO.StringIO()
+ out = sys.stdout
+ err = sys.stderr
+ sys.stdout = output
+ sys.stderr = output
+ try:
+ code = compile(command, '<string>', 'single')
+ exec code in frame.f_globals, frame.f_locals
+ return output.getvalue()
+ sys.stdout = out
+ sys.stderr = err
+ except:
+ sys.stdout = out
+ sys.stderr = err
+
+ tp, val, tb = sys.exc_info()
+ output = cStringIO.StringIO()
+ traceback.print_exception(tp, val, tb, file=output)
+ return output.getvalue()
+
def attempt_introspection(self, frame_message, chain):
try:
frame = self.message_frame_dict[frame_message]
item_node.setAttribute('value', wholeStack)
item_node.setAttribute('name', str(name))
top_element.appendChild(item_node)
+
+ cantIntro = [types.FunctionType,
+ types.LambdaType,
+ types.UnicodeType,
+ types.StringType,
+ types.NoneType,
+ types.IntType,
+ types.LongType,
+ types.FloatType,
+ types.BooleanType]
def addAny(self, top_element, name, item, doc, ply):
tp = type(item)
- if ply < 1:
- self.addNode(top_element,name, self.saferepr(item), doc)
+
+ if tp in DebuggerHarness.cantIntro or ply < 1:
+ self.addNode(top_element,name, item, doc)
elif tp is types.TupleType or tp is types.ListType:
self.addTupleOrList(top_element, name, item, doc, ply - 1)
elif tp is types.DictType or tp is types.DictProxyType:
self.addModule(top_element, name, item, doc, ply -1)
elif inspect.isclass(item) or tp is types.InstanceType:
self.addClass(top_element, name, item, doc, ply -1)
- #elif hasattr(item, '__dict__'):
- # self.addDictAttr(top_element, name, item, doc, ply -1)
elif hasattr(item, '__dict__'):
- self.addDict(top_element, name, item.__dict__, doc, ply -1)
+ self.addDictAttr(top_element, name, item, doc, ply -1)
else:
- self.addNode(top_element,name, self.saferepr(item), doc)
+ self.addNode(top_element,name, item, doc)
+
+ def canIntrospect(self, item):
+ tp = type(item)
+ if tp in DebuggerHarness.cantIntro:
+ return False
+ elif tp is types.TupleType or tp is types.ListType:
+ return len(item) > 0
+ elif tp is types.DictType or tp is types.DictProxyType:
+ return len(item) > 0
+ elif inspect.ismodule(item):
+ return True
+ elif inspect.isclass(item) or tp is types.InstanceType:
+ if hasattr(item, '__dict__'):
+ return True
+ elif hasattr(item, '__name__'):
+ return True
+ elif hasattr(item, '__module__'):
+ return True
+ elif hasattr(item, '__doc__'):
+ return True
+ else:
+ return False
+ elif hasattr(item, '__dict__'):
+ return len(item.__dict__) > 0
+ else:
+ return False
+
+ def addNode(self, parent_node, name, item, document):
+ item_node = document.createElement("dict_nv_element")
+ item_node.setAttribute('value', self.saferepr(item))
+ item_node.setAttribute('name', str(name))
+ introVal = str(self.canIntrospect(item))
+ item_node.setAttribute('intro', str(introVal))
+ parent_node.appendChild(item_node)
+
+
def addTupleOrList(self, top_node, name, tupple, doc, ply):
tupleNode = doc.createElement('tuple')
tupleNode.setAttribute('name', str(name))
- tupleNode.setAttribute('value', str(type(tupple)))
+ tupleNode.setAttribute('value', self.saferepr(tupple))
top_node.appendChild(tupleNode)
count = 0
for item in tupple:
self.addAny(tupleNode, name +'[' + str(count) + ']',item, doc, ply -1)
count += 1
-
- def getFrameXML(self, base_frame):
- doc = getDOMImplementation().createDocument(None, "stack", None)
- top_element = doc.documentElement
-
- stack = []
- frame = base_frame
- while frame is not None:
- if((frame.f_code.co_filename.count('DebuggerHarness.py') == 0) or _DEBUG_DEBUGGER):
- stack.append(frame)
- frame = frame.f_back
- stack.reverse()
- self.message_frame_dict = {}
- for f in stack:
- self.addFrame(f,top_element, doc)
- return doc.toxml()
-
- def addFrame(self, frame, root_element, document):
- frameNode = document.createElement('frame')
- root_element.appendChild(frameNode)
-
- code = frame.f_code
- filename = code.co_filename
- frameNode.setAttribute('file', str(filename))
- frameNode.setAttribute('line', str(frame.f_lineno))
- message = self._adb.frame2message(frame)
- frameNode.setAttribute('message', message)
- #print "Frame: %s %s %s" %(message, frame.f_lineno, filename)
- self.message_frame_dict[message] = frame
- self.addDict(frameNode, "locals", frame.f_locals, document, 2)
- self.addNode(frameNode, "globals", "", document)
-
- def getRepr(self, varName, globals, locals):
- try:
- return repr(eval(varName, globals, locals))
- except:
- return 'Error: Could not recover value.'
-
- def addNode(self, parent_node, name, value, document):
- item_node = document.createElement("dict_nv_element")
- item_node.setAttribute('value', self.saferepr(value))
- item_node.setAttribute('name', str(name))
- parent_node.appendChild(item_node)
-
def addDictAttr(self, root_node, name, thing, document, ply):
dict_node = document.createElement('thing')
- root_node.setAttribute('name', name)
- root_node.setAttribute('value', str(type(dict)) + " add attr")
- self.addDict(root_node, name, thing.__dict__, document, ply) # Not decreminting ply
-
- def saferepr(self, thing):
- try:
- return repr(thing)
- except:
- tp, val, tb = sys.exc_info()
- return repr(val)
-
- def addDict(self, root_node, name, dict, document, ply):
- dict_node = document.createElement('dict')
dict_node.setAttribute('name', name)
- dict_node.setAttribute('value', str(type(dict)) + " add dict")
+ dict_node.setAttribute('value', self.saferepr(thing))
root_node.appendChild(dict_node)
+ self.addDict(dict_node, '', thing.__dict__, document, ply) # Not decreminting ply
+
+ def addDict(self, root_node, name, dict, document, ply):
+ if name != '':
+ dict_node = document.createElement('dict')
+ dict_node.setAttribute('name', name)
+ dict_node.setAttribute('value', self.saferepr(dict))
+ root_node.appendChild(dict_node)
+ else:
+ dict_node = root_node
for key in dict.keys():
strkey = str(key)
try:
- self.addAny(dict_node, strkey, dict[key], document, ply-1)
+ value = dict[key]
+ self.addAny(dict_node, strkey, value, document, ply-1)
except:
- tp,val,tb=sys.exc_info()
if _VERBOSE:
+ tp,val,tb=sys.exc_info()
print "Error recovering key: ", str(key), " from node ", str(name), " Val = ", str(val)
traceback.print_exception(tp, val, tb)
- self.addAny(dict_node, strkey, "Exception getting " + str(name) + "[" + strkey + "]: " + str(val), document, ply -1)
def addClass(self, root_node, name, class_item, document, ply):
item_node = document.createElement('class')
item_node.setAttribute('name', str(name))
+ item_node.setAttribute('value', self.saferepr(class_item))
root_node.appendChild(item_node)
try:
if hasattr(class_item, '__dict__'):
- self.addAny(item_node, '__dict__', class_item.__dict__, document, ply -1)
+ self.addDict(item_node, '', class_item.__dict__, document, ply -1)
except:
tp,val,tb=sys.exc_info()
if _VERBOSE:
traceback.print_exception(tp, val, tb)
- self.addAny(item_node, '__dict__', "Exception getting __dict__: " + str(val), document, ply -1)
try:
if hasattr(class_item, '__name__'):
self.addAny(item_node,'__name__',class_item.__name__, document, ply -1)
tp,val,tb=sys.exc_info()
if _VERBOSE:
traceback.print_exception(tp, val, tb)
- self.addAny(item_node,'__name__',"Exception getting class.__name__: " + val, document, ply -1)
try:
if hasattr(class_item, '__module__'):
self.addAny(item_node, '__module__', class_item.__module__, document, ply -1)
tp,val,tb=sys.exc_info()
if _VERBOSE:
traceback.print_exception(tp, val, tb)
- self.addAny(item_node, '__module__', "Exception getting class.__module__: " + val, document, ply -1)
try:
if hasattr(class_item, '__doc__'):
self.addAny(item_node, '__doc__', class_item.__doc__, document, ply -1)
tp,val,tb=sys.exc_info()
if _VERBOSE:
traceback.print_exception(tp, val, tb)
- self.addAny(item_node, '__doc__', "Exception getting class.__doc__: " + val, document, ply -1)
try:
if hasattr(class_item, '__bases__'):
self.addAny(item_node, '__bases__', class_item.__bases__, document, ply -1)
tp,val,tb=sys.exc_info()
if _VERBOSE:
traceback.print_exception(tp, val, tb)
- self.addAny(item_node, '__bases__', "Exception getting class.__bases__: " + val, document, ply -1)
def addModule(self, root_node, name, module_item, document, ply):
item_node = document.createElement('module')
item_node.setAttribute('name', str(name))
+ item_node.setAttribute('value', self.saferepr(module_item))
root_node.appendChild(item_node)
try:
if hasattr(module_item, '__file__'):
except:
pass
+
+
+ def getFrameXML(self, base_frame):
+
+ self.frame_stack = []
+ frame = base_frame
+ while frame is not None:
+ if((frame.f_code.co_filename.count('DebuggerHarness.py') == 0) or _DEBUG_DEBUGGER):
+ self.frame_stack.append(frame)
+ frame = frame.f_back
+ self.frame_stack.reverse()
+ self.message_frame_dict = {}
+ doc = getDOMImplementation().createDocument(None, "stack", None)
+ top_element = doc.documentElement
+ numberFrames = len(self.frame_stack)
+ for index in range(numberFrames):
+ frame = self.frame_stack[index]
+ message = self._adb.frame2message(frame)
+ # We include globals and locals only for the last frame as an optimization for cases
+ # where there are a lot of frames.
+ self.addFrame(frame, top_element, doc, includeContent=(index == numberFrames - 1))
+ return doc.toxml()
+
+ def addFrame(self, frame, root_element, document, includeContent=False):
+ frameNode = document.createElement('frame')
+ root_element.appendChild(frameNode)
+
+ code = frame.f_code
+ filename = code.co_filename
+ frameNode.setAttribute('file', str(filename))
+ frameNode.setAttribute('line', str(frame.f_lineno))
+ message = self._adb.frame2message(frame)
+ frameNode.setAttribute('message', message)
+ self.message_frame_dict[message] = frame
+ if includeContent:
+ self.addDict(frameNode, "locals", frame.f_locals, document, 2)
+ self.addNode(frameNode, "globals", frame.f_globals, document)
+
+ def request_frame_document(self, message):
+ frame = self.message_frame_dict[message]
+ doc = getDOMImplementation().createDocument(None, "stack", None)
+ top_element = doc.documentElement
+ if frame:
+ self.addFrame(frame, top_element, doc, includeContent=True)
+ return xmlrpclib.Binary(bz2.compress(doc.toxml()))
+
+ def getRepr(self, varName, globals, locals):
+ try:
+ return repr(eval(varName, globals, locals))
+ except:
+ return 'Error: Could not recover value.'
+
+
+ def saferepr(self, thing):
+ try:
+ try:
+ return repr(thing)
+ except:
+ return str(type(thing))
+ except:
+ tp, val, tb = sys.exc_info()
+ #traceback.print_exception(tp, val, tb)
+ return repr(val)
+
# The debugger calls this method when it reaches a breakpoint.
def interaction(self, message, frame, info):
if _VERBOSE:
print 'hit debug side interaction'
- self._userBreak = False
+ self._adb._userBreak = False
self._currentFrame = frame
done = False
while not done:
try:
- import bz2
xml = self.getFrameXML(frame)
arg = xmlrpclib.Binary(bz2.compress(xml))
if _VERBOSE:
try:
harness = DebuggerHarness()
harness.run()
+ harness.do_exit(kill=True)
except SystemExit:
print "Exiting..."
except: