X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/ec873c943d71f0d5f13e3398557071448cda6c23..a4027e74873007e3430af3bd77019bcab76f6c04:/wxPython/samples/ide/activegrid/tool/DebuggerHarness.py diff --git a/wxPython/samples/ide/activegrid/tool/DebuggerHarness.py b/wxPython/samples/ide/activegrid/tool/DebuggerHarness.py deleted file mode 100644 index 63452dcb9d..0000000000 --- a/wxPython/samples/ide/activegrid/tool/DebuggerHarness.py +++ /dev/null @@ -1,777 +0,0 @@ -#---------------------------------------------------------------------------- -# Name: DebuggerHarness.py -# Purpose: -# -# Author: Matt Fryer -# -# Created: 7/28/04 -# CVS-ID: $Id$ -# Copyright: (c) 2005 ActiveGrid, Inc. -# License: wxWindows License -#---------------------------------------------------------------------------- -import bdb -import sys -import SimpleXMLRPCServer -import threading -import xmlrpclib -import os -import types -import Queue -import traceback -import inspect -from xml.dom.minidom import getDOMImplementation -import atexit -import pickle -import cStringIO -import bz2 - -if sys.platform.startswith("win"): - import win32api - _WINDOWS = True -else: - _WINDOWS = False - -_VERBOSE = False -_DEBUG_DEBUGGER = False - -class Adb(bdb.Bdb): - - def __init__(self, harness, queue): - bdb.Bdb.__init__(self) - self._harness = harness - self._userBreak = False - self._queue = queue - self._knownCantExpandFiles = {} - self._knownExpandedFiles = {} - - def getLongName(self, filename): - if not _WINDOWS: - return filename - if self._knownCantExpandFiles.get(filename): - return filename - if self._knownExpandedFiles.get(filename): - return self._knownExpandedFiles.get(filename) - try: - newname = win32api.GetLongPathName(filename) - self._knownExpandedFiles[filename] = newname - return newname - except: - self._knownCantExpandFiles[filename] = filename - return filename - - def canonic(self, orig_filename): - if orig_filename == "<" + orig_filename[1:-1] + ">": - return orig_filename - filename = self.getLongName(orig_filename) - - canonic = self.fncache.get(filename) - if not canonic: - canonic = os.path.abspath(filename) - canonic = os.path.normcase(canonic) - self.fncache[filename] = canonic - return canonic - - - # Overriding this so that we continue to trace even if no breakpoints are set. - def set_continue(self): - self.stopframe = self.botframe - self.returnframe = None - self.quitting = 0 - - def do_clear(self, arg): - bdb.Breakpoint.bpbynumber[int(arg)].deleteMe() - - def user_line(self, frame): - if self.in_debugger_code(frame): - self.set_step() - return - message = self.__frame2message(frame) - self._harness.interaction(message, frame, "") - - def user_call(self, frame, argument_list): - if self.in_debugger_code(frame): - self.set_step() - return - if self.stop_here(frame): - message = self.__frame2message(frame) - self._harness.interaction(message, frame, "") - - def user_return(self, frame, return_value): - if self.in_debugger_code(frame): - self.set_step() - return - message = self.__frame2message(frame) - self._harness.interaction(message, frame, "") - - def user_exception(self, frame, (exc_type, exc_value, exc_traceback)): - frame.f_locals['__exception__'] = exc_type, exc_value - if type(exc_type) == type(''): - exc_type_name = exc_type - else: - exc_type_name = exc_type.__name__ - message = "Exception occured: " + repr(exc_type_name) + " See locals.__exception__ for details." - traceback.print_exception(exc_type, exc_value, exc_traceback) - self._harness.interaction(message, frame, message) - - def in_debugger_code(self, frame): - if _DEBUG_DEBUGGER: return False - message = self.__frame2message(frame) - return message.count('DebuggerHarness') > 0 - - def frame2message(self, frame): - return self.__frame2message(frame) - - def __frame2message(self, frame): - code = frame.f_code - filename = code.co_filename - lineno = frame.f_lineno - basename = os.path.basename(filename) - message = "%s:%s" % (basename, lineno) - if code.co_name != "?": - message = "%s: %s()" % (message, code.co_name) - return message - - def runFile(self, fileName): - self.reset() - #global_dict = {} - #global_dict['__name__'] = '__main__' - try: - fileToRun = open(fileName, mode='r') - if _VERBOSE: print "Running file ", fileName - sys.settrace(self.trace_dispatch) - import __main__ - exec fileToRun in __main__.__dict__,__main__.__dict__ - except SystemExit: - pass - except: - tp, val, tb = sys.exc_info() - traceback.print_exception(tp, val, tb) - - sys.settrace(None) - self.quitting = 1 - #global_dict.clear() - - def trace_dispatch(self, frame, event, arg): - if self.quitting: - return # None - # Check for ui events - self.readQueue() - if event == 'line': - return self.dispatch_line(frame) - if event == 'call': - return self.dispatch_call(frame, arg) - if event == 'return': - return self.dispatch_return(frame, arg) - if event == 'exception': - return self.dispatch_exception(frame, arg) - print 'Adb.dispatch: unknown debugging event:', `event` - return self.trace_dispatch - - def readQueue(self): - while self._queue.qsize(): - try: - item = self._queue.get_nowait() - if item.kill(): - self._harness.do_exit(kill=True) - elif item.breakHere(): - self._userBreak = True - elif item.hasBreakpoints(): - self.set_all_breakpoints(item.getBreakpoints()) - except Queue.Empty: - pass - - def set_all_breakpoints(self, dict): - self.clear_all_breaks() - for fileName in dict.keys(): - lineList = dict[fileName] - for lineNumber in lineList: - - if _VERBOSE: print "Setting break at line ", str(lineNumber), " in file ", self.canonic(fileName) - self.set_break(fileName, int(lineNumber)) - return "" - - def stop_here(self, frame): - if self._userBreak: - return True - - - # (CT) stopframe may now also be None, see dispatch_call. - # (CT) the former test for None is therefore removed from here. - if frame is self.stopframe: - return True - while frame is not None and frame is not self.stopframe: - if frame is self.botframe: - return True - frame = frame.f_back - return False - -class BreakNotify(object): - def __init__(self, bps=None, break_here=False, kill=False): - self._bps = bps - self._break_here = break_here - self._kill = kill - - def breakHere(self): - return self._break_here - - def kill(self): - return self._kill - - def getBreakpoints(self): - return self._bps - - def hasBreakpoints(self): - return (self._bps != None) - -class AGXMLRPCServer(SimpleXMLRPCServer.SimpleXMLRPCServer): - def __init__(self, address, logRequests=0): - SimpleXMLRPCServer.SimpleXMLRPCServer.__init__(self, address, logRequests=logRequests) - -class BreakListenerThread(threading.Thread): - def __init__(self, host, port, queue): - threading.Thread.__init__(self) - self._host = host - self._port = int(port) - self._keepGoing = True - self._queue = queue - self._server = AGXMLRPCServer((self._host, self._port), logRequests=0) - self._server.register_function(self.update_breakpoints) - self._server.register_function(self.break_requested) - self._server.register_function(self.die) - - def break_requested(self): - bn = BreakNotify(break_here=True) - self._queue.put(bn) - return "" - - def update_breakpoints(self, pickled_Binary_bpts): - dict = pickle.loads(pickled_Binary_bpts.data) - bn = BreakNotify(bps=dict) - self._queue.put(bn) - return "" - - def die(self): - bn = BreakNotify(kill=True) - self._queue.put(bn) - return "" - - def run(self): - while self._keepGoing: - try: - self._server.handle_request() - except: - if _VERBOSE: - tp, val, tb = sys.exc_info() - print "Exception in BreakListenerThread.run():", str(tp), str(val) - self._keepGoing = False - - def AskToStop(self): - self._keepGoing = False - if type(self._server) is not types.NoneType: - 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): - - def __init__(self): - # Host and port for debugger-side RPC server - self._hostname = sys.argv[1] - self._portNumber = int(sys.argv[2]) - # Name the gui proxy object is registered under - self._breakPortNumber = int(sys.argv[3]) - # Host and port where the gui proxy can be found. - self._guiHost = sys.argv[4] - self._guiPort = int(sys.argv[5]) - # Command to debug. - self._command = sys.argv[6] - # Strip out the harness' arguments so that the process we run will see argv as if - # it was called directly. - sys.argv = sys.argv[6:] - self._currentFrame = None - self._wait = False - # Connect to the gui-side RPC server. - self._guiServerUrl = 'http://' + self._guiHost + ':' + str(self._guiPort) + '/' - if _VERBOSE: print "Connecting to gui server at ", self._guiServerUrl - self._guiServer = xmlrpclib.ServerProxy(self._guiServerUrl,allow_none=1) - - # Start the break listener - self._breakQueue = Queue.Queue(50) - self._breakListener = BreakListenerThread(self._hostname, self._breakPortNumber, self._breakQueue) - self._breakListener.start() - # Create the debugger. - self._adb = Adb(self, self._breakQueue) - - # Create the debugger-side RPC Server and register functions for remote calls. - self._server = AGXMLRPCServer((self._hostname, self._portNumber), logRequests=0) - self._server.register_function(self.set_step) - self._server.register_function(self.set_continue) - self._server.register_function(self.set_next) - self._server.register_function(self.set_return) - self._server.register_function(self.set_breakpoint) - 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) - - def run(self): - self._adb.runFile(self._command) - self.do_exit(kill=True) - - - def do_exit(self, kill=False): - self._adb.set_quit() - self._breakListener.AskToStop() - self._server.server_close() - try: - self._guiServer.quit() - except: - pass - if kill: - try: - sys.exit() - except: - pass - - def set_breakpoint(self, fileName, lineNo): - self._adb.set_break(fileName, lineNo) - return "" - - def set_all_breakpoints(self, dict): - self._adb.clear_all_breaks() - for fileName in dict.keys(): - lineList = dict[fileName] - for lineNumber in lineList: - self._adb.set_break(fileName, int(lineNumber)) - if _VERBOSE: print "Setting break at ", str(lineNumber), " in file ", fileName - return "" - - def clear_breakpoint(self, fileName, lineNo): - self._adb.clear_break(fileName, lineNo) - return "" - - def add_watch(self, name, text, frame_message, run_once): - if len(frame_message) > 0: - frame = self.message_frame_dict[frame_message] - try: - item = eval(text, frame.f_globals, frame.f_locals) - return self.get_watch_document(item, name) - except: - 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, '', '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] - if frame: - name = chain.pop(0) - if name == 'globals': - item = frame.f_globals - elif name == 'locals': - item = frame.f_locals - - for name in chain: - item = self.getNextItem(item, name) - return self.get_introspection_document(item, name) - except: - tp, val, tb = sys.exc_info() - traceback.print_exception(tp, val, tb) - return self.get_empty_introspection_document() - - def getNextItem(self, link, identifier): - tp = type(link) - if self.isTupleized(identifier): - return self.deTupleize(link, identifier) - else: - if tp == types.DictType or tp == types.DictProxyType: - return link[identifier] - else: - if hasattr(link, identifier): - return getattr(link, identifier) - if _VERBOSE or True: print "Failed to find link ", identifier, " on thing: ", self.saferepr(link), " of type ", repr(type(link)) - return None - - def isPrimitive(self, item): - tp = type(item) - return tp is types.IntType or tp is types.LongType or tp is types.FloatType \ - or tp is types.BooleanType or tp is types.ComplexType \ - or tp is types.StringType - - def isTupleized(self, value): - return value.count('[') - - def deTupleize(self, link, string1): - try: - start = string1.find('[') - end = string1.find(']') - num = int(string1[start+1:end]) - return link[num] - except: - tp,val,tb = sys.exc_info() - if _VERBOSE: print "Got exception in deTupleize: ", val - return None - - def wrapAndCompress(self, stringDoc): - import bz2 - return xmlrpclib.Binary(bz2.compress(stringDoc)) - - def get_empty_introspection_document(self): - doc = getDOMImplementation().createDocument(None, "replacement", None) - return self.wrapAndCompress(doc.toxml()) - - def get_watch_document(self, item, identifier): - doc = getDOMImplementation().createDocument(None, "watch", None) - top_element = doc.documentElement - self.addAny(top_element, identifier, item, doc, 2) - return self.wrapAndCompress(doc.toxml()) - - def get_introspection_document(self, item, identifier): - doc = getDOMImplementation().createDocument(None, "replacement", None) - top_element = doc.documentElement - self.addAny(top_element, identifier, item, doc, 2) - return self.wrapAndCompress(doc.toxml()) - - def get_exception_document(self, name, tp, val, tb): - stack = traceback.format_exception(tp, val, tb) - wholeStack = "" - for line in stack: - wholeStack += line - doc = getDOMImplementation().createDocument(None, "watch", None) - top_element = doc.documentElement - item_node = doc.createElement("dict_nv_element") - 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 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.addDict(top_element, name, item, doc, ply -1) - elif inspect.ismodule(item): - 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) - else: - 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', 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 addDictAttr(self, root_node, name, thing, document, ply): - dict_node = document.createElement('thing') - dict_node.setAttribute('name', name) - 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: - value = dict[key] - self.addAny(dict_node, strkey, value, document, ply-1) - except: - 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) - - 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.addDict(item_node, '', class_item.__dict__, document, ply -1) - except: - tp,val,tb=sys.exc_info() - if _VERBOSE: - traceback.print_exception(tp, val, tb) - try: - if hasattr(class_item, '__name__'): - self.addAny(item_node,'__name__',class_item.__name__, document, ply -1) - except: - tp,val,tb=sys.exc_info() - if _VERBOSE: - traceback.print_exception(tp, val, tb) - try: - if hasattr(class_item, '__module__'): - self.addAny(item_node, '__module__', class_item.__module__, document, ply -1) - except: - tp,val,tb=sys.exc_info() - if _VERBOSE: - traceback.print_exception(tp, val, tb) - try: - if hasattr(class_item, '__doc__'): - self.addAny(item_node, '__doc__', class_item.__doc__, document, ply -1) - except: - tp,val,tb=sys.exc_info() - if _VERBOSE: - traceback.print_exception(tp, val, tb) - try: - if hasattr(class_item, '__bases__'): - self.addAny(item_node, '__bases__', class_item.__bases__, document, ply -1) - except: - tp,val,tb=sys.exc_info() - if _VERBOSE: - traceback.print_exception(tp, val, tb) - - 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__'): - self.addAny(item_node, '__file__', module_item.__file__, document, ply -1) - except: - pass - try: - if hasattr(module_item, '__doc__'): - self.addAny(item_node,'__doc__', module_item.__doc__, document, ply -1) - 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._adb._userBreak = False - - self._currentFrame = frame - done = False - while not done: - try: - xml = self.getFrameXML(frame) - arg = xmlrpclib.Binary(bz2.compress(xml)) - if _VERBOSE: - print '============== calling gui side interaction============' - self._guiServer.interaction(xmlrpclib.Binary(message), arg, info) - if _VERBOSE: - print 'after interaction' - done = True - except: - tp, val, tb = sys.exc_info() - if True or _VERBOSE: - print 'Error contacting GUI server!: ' - try: - traceback.print_exception(tp, val, tb) - except: - print "Exception printing traceback", - tp, val, tb = sys.exc_info() - traceback.print_exception(tp, val, tb) - done = False - # Block while waiting to be called back from the GUI. Eventually, self._wait will - # be set false by a function on this side. Seems pretty lame--I'm surprised it works. - self.waitForRPC() - - - def waitForRPC(self): - self._wait = True - while self._wait : - try: - if _VERBOSE: - print "+++ in harness wait for rpc, before handle_request" - self._server.handle_request() - if _VERBOSE: - print "+++ in harness wait for rpc, after handle_request" - except: - if _VERBOSE: - tp, val, tb = sys.exc_info() - print "Got waitForRpc exception : ", repr(tp), ": ", val - #time.sleep(0.1) - - def set_step(self): - self._adb.set_step() - self._wait = False - return "" - - def set_continue(self): - self._adb.set_continue() - self._wait = False - return "" - - def set_next(self): - self._adb.set_next(self._currentFrame) - self._wait = False - return "" - - def set_return(self): - self._adb.set_return(self._currentFrame) - self._wait = False - return "" - -if __name__ == '__main__': - try: - harness = DebuggerHarness() - harness.run() - harness.do_exit(kill=True) - except SystemExit: - print "Exiting..." - except: - tp, val, tb = sys.exc_info() - traceback.print_exception(tp, val, tb)