]> git.saurik.com Git - wxWidgets.git/blame - wxPython/samples/ide/activegrid/tool/DebuggerHarness.py
Only freeze the splitter, the children will be automatically frozen too.
[wxWidgets.git] / wxPython / samples / ide / activegrid / tool / DebuggerHarness.py
CommitLineData
1f780e48
RD
1#----------------------------------------------------------------------------
2# Name: DebuggerHarness.py
3# Purpose:
4#
5# Author: Matt Fryer
6#
7# Created: 7/28/04
8# CVS-ID: $Id$
9# Copyright: (c) 2005 ActiveGrid, Inc.
10# License: wxWindows License
11#----------------------------------------------------------------------------
12import bdb
13import sys
14import SimpleXMLRPCServer
15import threading
16import xmlrpclib
17import os
18import types
19import Queue
20import traceback
21import inspect
22from xml.dom.minidom import getDOMImplementation
23import atexit
24import pickle
26ee3a06
RD
25import cStringIO
26import bz2
1f780e48
RD
27
28if sys.platform.startswith("win"):
29 import win32api
30 _WINDOWS = True
31else:
32 _WINDOWS = False
33
34_VERBOSE = False
35_DEBUG_DEBUGGER = False
36
37class Adb(bdb.Bdb):
38
39 def __init__(self, harness, queue):
40 bdb.Bdb.__init__(self)
41 self._harness = harness
42 self._userBreak = False
43 self._queue = queue
44 self._knownCantExpandFiles = {}
45 self._knownExpandedFiles = {}
46
47 def getLongName(self, filename):
48 if not _WINDOWS:
49 return filename
50 if self._knownCantExpandFiles.get(filename):
51 return filename
52 if self._knownExpandedFiles.get(filename):
53 return self._knownExpandedFiles.get(filename)
54 try:
55 newname = win32api.GetLongPathName(filename)
56 self._knownExpandedFiles[filename] = newname
57 return newname
58 except:
59 self._knownCantExpandFiles[filename] = filename
60 return filename
61
62 def canonic(self, orig_filename):
63 if orig_filename == "<" + orig_filename[1:-1] + ">":
64 return orig_filename
65 filename = self.getLongName(orig_filename)
66
67 canonic = self.fncache.get(filename)
68 if not canonic:
69 canonic = os.path.abspath(filename)
70 canonic = os.path.normcase(canonic)
71 self.fncache[filename] = canonic
72 return canonic
73
74
75 # Overriding this so that we continue to trace even if no breakpoints are set.
76 def set_continue(self):
77 self.stopframe = self.botframe
78 self.returnframe = None
79 self.quitting = 0
80
81 def do_clear(self, arg):
82 bdb.Breakpoint.bpbynumber[int(arg)].deleteMe()
83
84 def user_line(self, frame):
85 if self.in_debugger_code(frame):
86 self.set_step()
87 return
88 message = self.__frame2message(frame)
89 self._harness.interaction(message, frame, "")
90
91 def user_call(self, frame, argument_list):
92 if self.in_debugger_code(frame):
93 self.set_step()
94 return
95 if self.stop_here(frame):
96 message = self.__frame2message(frame)
97 self._harness.interaction(message, frame, "")
98
99 def user_return(self, frame, return_value):
100 if self.in_debugger_code(frame):
101 self.set_step()
102 return
103 message = self.__frame2message(frame)
104 self._harness.interaction(message, frame, "")
105
106 def user_exception(self, frame, (exc_type, exc_value, exc_traceback)):
107 frame.f_locals['__exception__'] = exc_type, exc_value
108 if type(exc_type) == type(''):
109 exc_type_name = exc_type
110 else:
111 exc_type_name = exc_type.__name__
26ee3a06 112 message = "Exception occured: " + repr(exc_type_name) + " See locals.__exception__ for details."
1f780e48
RD
113 traceback.print_exception(exc_type, exc_value, exc_traceback)
114 self._harness.interaction(message, frame, message)
115
116 def in_debugger_code(self, frame):
117 if _DEBUG_DEBUGGER: return False
118 message = self.__frame2message(frame)
119 return message.count('DebuggerHarness') > 0
120
121 def frame2message(self, frame):
122 return self.__frame2message(frame)
123
124 def __frame2message(self, frame):
125 code = frame.f_code
126 filename = code.co_filename
127 lineno = frame.f_lineno
128 basename = os.path.basename(filename)
129 message = "%s:%s" % (basename, lineno)
130 if code.co_name != "?":
131 message = "%s: %s()" % (message, code.co_name)
132 return message
133
134 def runFile(self, fileName):
135 self.reset()
136 #global_dict = {}
137 #global_dict['__name__'] = '__main__'
138 try:
139 fileToRun = open(fileName, mode='r')
140 if _VERBOSE: print "Running file ", fileName
141 sys.settrace(self.trace_dispatch)
142 import __main__
143 exec fileToRun in __main__.__dict__,__main__.__dict__
144 except SystemExit:
145 pass
146 except:
147 tp, val, tb = sys.exc_info()
148 traceback.print_exception(tp, val, tb)
149
150 sys.settrace(None)
151 self.quitting = 1
152 #global_dict.clear()
153
154 def trace_dispatch(self, frame, event, arg):
155 if self.quitting:
156 return # None
157 # Check for ui events
158 self.readQueue()
159 if event == 'line':
160 return self.dispatch_line(frame)
161 if event == 'call':
162 return self.dispatch_call(frame, arg)
163 if event == 'return':
164 return self.dispatch_return(frame, arg)
165 if event == 'exception':
166 return self.dispatch_exception(frame, arg)
167 print 'Adb.dispatch: unknown debugging event:', `event`
168 return self.trace_dispatch
169
170 def readQueue(self):
171 while self._queue.qsize():
172 try:
173 item = self._queue.get_nowait()
174 if item.kill():
175 self._harness.do_exit(kill=True)
176 elif item.breakHere():
177 self._userBreak = True
178 elif item.hasBreakpoints():
179 self.set_all_breakpoints(item.getBreakpoints())
180 except Queue.Empty:
181 pass
182
183 def set_all_breakpoints(self, dict):
184 self.clear_all_breaks()
185 for fileName in dict.keys():
186 lineList = dict[fileName]
187 for lineNumber in lineList:
188
189 if _VERBOSE: print "Setting break at line ", str(lineNumber), " in file ", self.canonic(fileName)
190 self.set_break(fileName, int(lineNumber))
191 return ""
192
193 def stop_here(self, frame):
26ee3a06 194 if self._userBreak:
1f780e48
RD
195 return True
196
197
198 # (CT) stopframe may now also be None, see dispatch_call.
199 # (CT) the former test for None is therefore removed from here.
200 if frame is self.stopframe:
201 return True
202 while frame is not None and frame is not self.stopframe:
203 if frame is self.botframe:
204 return True
205 frame = frame.f_back
206 return False
207
208class BreakNotify(object):
209 def __init__(self, bps=None, break_here=False, kill=False):
210 self._bps = bps
211 self._break_here = break_here
212 self._kill = kill
213
214 def breakHere(self):
215 return self._break_here
216
217 def kill(self):
218 return self._kill
219
220 def getBreakpoints(self):
221 return self._bps
222
223 def hasBreakpoints(self):
224 return (self._bps != None)
225
226class AGXMLRPCServer(SimpleXMLRPCServer.SimpleXMLRPCServer):
227 def __init__(self, address, logRequests=0):
228 SimpleXMLRPCServer.SimpleXMLRPCServer.__init__(self, address, logRequests=logRequests)
229
230class BreakListenerThread(threading.Thread):
231 def __init__(self, host, port, queue):
232 threading.Thread.__init__(self)
233 self._host = host
234 self._port = int(port)
235 self._keepGoing = True
236 self._queue = queue
237 self._server = AGXMLRPCServer((self._host, self._port), logRequests=0)
238 self._server.register_function(self.update_breakpoints)
239 self._server.register_function(self.break_requested)
240 self._server.register_function(self.die)
241
242 def break_requested(self):
243 bn = BreakNotify(break_here=True)
244 self._queue.put(bn)
245 return ""
246
247 def update_breakpoints(self, pickled_Binary_bpts):
248 dict = pickle.loads(pickled_Binary_bpts.data)
249 bn = BreakNotify(bps=dict)
250 self._queue.put(bn)
251 return ""
252
253 def die(self):
254 bn = BreakNotify(kill=True)
255 self._queue.put(bn)
256 return ""
257
258 def run(self):
259 while self._keepGoing:
260 try:
261 self._server.handle_request()
262 except:
263 if _VERBOSE:
264 tp, val, tb = sys.exc_info()
265 print "Exception in BreakListenerThread.run():", str(tp), str(val)
266 self._keepGoing = False
267
268 def AskToStop(self):
269 self._keepGoing = False
270 if type(self._server) is not types.NoneType:
271 if _VERBOSE: print "Before calling server close on breakpoint server"
272 self._server.server_close()
273 if _VERBOSE: print "Calling server close on breakpoint server"
26ee3a06 274 self._server = None
1f780e48
RD
275
276
277class DebuggerHarness(object):
278
279 def __init__(self):
280 # Host and port for debugger-side RPC server
281 self._hostname = sys.argv[1]
282 self._portNumber = int(sys.argv[2])
283 # Name the gui proxy object is registered under
284 self._breakPortNumber = int(sys.argv[3])
285 # Host and port where the gui proxy can be found.
286 self._guiHost = sys.argv[4]
287 self._guiPort = int(sys.argv[5])
288 # Command to debug.
289 self._command = sys.argv[6]
290 # Strip out the harness' arguments so that the process we run will see argv as if
291 # it was called directly.
292 sys.argv = sys.argv[6:]
293 self._currentFrame = None
294 self._wait = False
295 # Connect to the gui-side RPC server.
296 self._guiServerUrl = 'http://' + self._guiHost + ':' + str(self._guiPort) + '/'
297 if _VERBOSE: print "Connecting to gui server at ", self._guiServerUrl
298 self._guiServer = xmlrpclib.ServerProxy(self._guiServerUrl,allow_none=1)
299
300 # Start the break listener
301 self._breakQueue = Queue.Queue(50)
302 self._breakListener = BreakListenerThread(self._hostname, self._breakPortNumber, self._breakQueue)
303 self._breakListener.start()
304 # Create the debugger.
305 self._adb = Adb(self, self._breakQueue)
306
307 # Create the debugger-side RPC Server and register functions for remote calls.
308 self._server = AGXMLRPCServer((self._hostname, self._portNumber), logRequests=0)
309 self._server.register_function(self.set_step)
310 self._server.register_function(self.set_continue)
311 self._server.register_function(self.set_next)
312 self._server.register_function(self.set_return)
313 self._server.register_function(self.set_breakpoint)
314 self._server.register_function(self.clear_breakpoint)
315 self._server.register_function(self.set_all_breakpoints)
316 self._server.register_function(self.attempt_introspection)
26ee3a06 317 self._server.register_function(self.execute_in_frame)
1f780e48 318 self._server.register_function(self.add_watch)
26ee3a06 319 self._server.register_function(self.request_frame_document)
1f780e48 320
26ee3a06 321 self.frame_stack = []
1f780e48
RD
322 self.message_frame_dict = {}
323 self.introspection_list = []
324 atexit.register(self.do_exit)
325
326 def run(self):
327 self._adb.runFile(self._command)
328 self.do_exit(kill=True)
329
330
331 def do_exit(self, kill=False):
332 self._adb.set_quit()
333 self._breakListener.AskToStop()
334 self._server.server_close()
335 try:
336 self._guiServer.quit()
337 except:
338 pass
339 if kill:
340 try:
341 sys.exit()
342 except:
343 pass
344
345 def set_breakpoint(self, fileName, lineNo):
346 self._adb.set_break(fileName, lineNo)
347 return ""
348
349 def set_all_breakpoints(self, dict):
350 self._adb.clear_all_breaks()
351 for fileName in dict.keys():
352 lineList = dict[fileName]
353 for lineNumber in lineList:
354 self._adb.set_break(fileName, int(lineNumber))
355 if _VERBOSE: print "Setting break at ", str(lineNumber), " in file ", fileName
356 return ""
357
358 def clear_breakpoint(self, fileName, lineNo):
359 self._adb.clear_break(fileName, lineNo)
360 return ""
361
362 def add_watch(self, name, text, frame_message, run_once):
363 if len(frame_message) > 0:
364 frame = self.message_frame_dict[frame_message]
365 try:
366 item = eval(text, frame.f_globals, frame.f_locals)
367 return self.get_watch_document(item, name)
368 except:
369 tp, val, tb = sys.exc_info()
370 return self.get_exception_document(tp, val, tb)
371 return ""
26ee3a06
RD
372
373 def execute_in_frame(self, frame_message, command):
374 frame = self.message_frame_dict[frame_message]
375 output = cStringIO.StringIO()
376 out = sys.stdout
377 err = sys.stderr
378 sys.stdout = output
379 sys.stderr = output
380 try:
381 exec command in frame.f_globals, frame.f_locals
382 return output.getvalue()
383 sys.stdout = out
384 sys.stderr = err
385 except:
386 sys.stdout = out
387 sys.stderr = err
388
389 tp, val, tb = sys.exc_info()
390 output = cStringIO.StringIO()
391 traceback.print_exception(tp, val, tb, file=output)
392 return output.getvalue()
393
1f780e48
RD
394 def attempt_introspection(self, frame_message, chain):
395 try:
396 frame = self.message_frame_dict[frame_message]
397 if frame:
398 name = chain.pop(0)
399 if name == 'globals':
400 item = frame.f_globals
401 elif name == 'locals':
402 item = frame.f_locals
403
404 for name in chain:
405 item = self.getNextItem(item, name)
406 return self.get_introspection_document(item, name)
407 except:
408 tp, val, tb = sys.exc_info()
409 traceback.print_exception(tp, val, tb)
410 return self.get_empty_introspection_document()
411
412 def getNextItem(self, link, identifier):
413 tp = type(link)
414 if self.isTupleized(identifier):
415 return self.deTupleize(link, identifier)
416 else:
417 if tp == types.DictType or tp == types.DictProxyType:
418 return link[identifier]
419 else:
420 if hasattr(link, identifier):
421 return getattr(link, identifier)
422 if _VERBOSE or True: print "Failed to find link ", identifier, " on thing: ", self.saferepr(link), " of type ", repr(type(link))
423 return None
424
425 def isPrimitive(self, item):
426 tp = type(item)
427 return tp is types.IntType or tp is types.LongType or tp is types.FloatType \
428 or tp is types.BooleanType or tp is types.ComplexType \
429 or tp is types.StringType
430
431 def isTupleized(self, value):
432 return value.count('[')
433
434 def deTupleize(self, link, string1):
435 try:
436 start = string1.find('[')
437 end = string1.find(']')
438 num = int(string1[start+1:end])
439 return link[num]
440 except:
441 tp,val,tb = sys.exc_info()
442 if _VERBOSE: print "Got exception in deTupleize: ", val
443 return None
444
445 def wrapAndCompress(self, stringDoc):
446 import bz2
447 return xmlrpclib.Binary(bz2.compress(stringDoc))
448
449 def get_empty_introspection_document(self):
450 doc = getDOMImplementation().createDocument(None, "replacement", None)
451 return self.wrapAndCompress(doc.toxml())
452
453 def get_watch_document(self, item, identifier):
454 doc = getDOMImplementation().createDocument(None, "watch", None)
455 top_element = doc.documentElement
456 self.addAny(top_element, identifier, item, doc, 2)
457 return self.wrapAndCompress(doc.toxml())
458
459 def get_introspection_document(self, item, identifier):
460 doc = getDOMImplementation().createDocument(None, "replacement", None)
461 top_element = doc.documentElement
462 self.addAny(top_element, identifier, item, doc, 2)
463 return self.wrapAndCompress(doc.toxml())
464
465 def get_exception_document(self, name, tp, val, tb):
466 stack = traceback.format_exception(tp, val, tb)
467 wholeStack = ""
468 for line in stack:
469 wholeStack += line
470 doc = getDOMImplementation().createDocument(None, "watch", None)
471 top_element = doc.documentElement
472 item_node = doc.createElement("dict_nv_element")
473 item_node.setAttribute('value', wholeStack)
474 item_node.setAttribute('name', str(name))
475 top_element.appendChild(item_node)
6f1a3f9c
RD
476
477 cantIntro = [types.FunctionType,
478 types.LambdaType,
479 types.UnicodeType,
480 types.StringType,
481 types.NoneType,
482 types.IntType,
483 types.LongType,
484 types.FloatType,
485 types.BooleanType]
1f780e48
RD
486
487 def addAny(self, top_element, name, item, doc, ply):
488 tp = type(item)
6f1a3f9c
RD
489
490 if tp in DebuggerHarness.cantIntro or ply < 1:
491 self.addNode(top_element,name, item, doc)
1f780e48
RD
492 elif tp is types.TupleType or tp is types.ListType:
493 self.addTupleOrList(top_element, name, item, doc, ply - 1)
494 elif tp is types.DictType or tp is types.DictProxyType:
495 self.addDict(top_element, name, item, doc, ply -1)
496 elif inspect.ismodule(item):
497 self.addModule(top_element, name, item, doc, ply -1)
498 elif inspect.isclass(item) or tp is types.InstanceType:
499 self.addClass(top_element, name, item, doc, ply -1)
1f780e48 500 elif hasattr(item, '__dict__'):
6f1a3f9c 501 self.addDictAttr(top_element, name, item, doc, ply -1)
1f780e48 502 else:
6f1a3f9c
RD
503 self.addNode(top_element,name, item, doc)
504
1f780e48 505
6f1a3f9c
RD
506 def canIntrospect(self, item):
507 tp = type(item)
508 if tp in DebuggerHarness.cantIntro:
509 return False
510 elif tp is types.TupleType or tp is types.ListType:
511 return len(item) > 0
512 elif tp is types.DictType or tp is types.DictProxyType:
513 return len(item) > 0
514 elif inspect.ismodule(item):
515 return True
516 elif inspect.isclass(item) or tp is types.InstanceType:
517 if hasattr(item, '__dict__'):
518 return True
519 elif hasattr(item, '__name__'):
520 return True
521 elif hasattr(item, '__module__'):
522 return True
523 elif hasattr(item, '__doc__'):
524 return True
525 else:
526 return False
527 elif hasattr(item, '__dict__'):
528 return len(item.__dict__) > 0
529 else:
530 return False
531
532 def addNode(self, parent_node, name, item, document):
533 item_node = document.createElement("dict_nv_element")
534 item_node.setAttribute('value', self.saferepr(item))
535 item_node.setAttribute('name', str(name))
536 introVal = str(self.canIntrospect(item))
537 item_node.setAttribute('intro', str(introVal))
538 parent_node.appendChild(item_node)
539
540
1f780e48
RD
541 def addTupleOrList(self, top_node, name, tupple, doc, ply):
542 tupleNode = doc.createElement('tuple')
543 tupleNode.setAttribute('name', str(name))
6f1a3f9c 544 tupleNode.setAttribute('value', self.saferepr(tupple))
1f780e48
RD
545 top_node.appendChild(tupleNode)
546 count = 0
547 for item in tupple:
548 self.addAny(tupleNode, name +'[' + str(count) + ']',item, doc, ply -1)
549 count += 1
550
1f780e48
RD
551 def addDictAttr(self, root_node, name, thing, document, ply):
552 dict_node = document.createElement('thing')
1f780e48 553 dict_node.setAttribute('name', name)
6f1a3f9c 554 dict_node.setAttribute('value', self.saferepr(thing))
1f780e48 555 root_node.appendChild(dict_node)
6f1a3f9c
RD
556 self.addDict(dict_node, '', thing.__dict__, document, ply) # Not decreminting ply
557
558 def addDict(self, root_node, name, dict, document, ply):
559 if name != '':
560 dict_node = document.createElement('dict')
561 dict_node.setAttribute('name', name)
562 dict_node.setAttribute('value', self.saferepr(dict))
563 root_node.appendChild(dict_node)
564 else:
565 dict_node = root_node
1f780e48
RD
566 for key in dict.keys():
567 strkey = str(key)
568 try:
6f1a3f9c
RD
569 value = dict[key]
570 self.addAny(dict_node, strkey, value, document, ply-1)
1f780e48 571 except:
1f780e48 572 if _VERBOSE:
6f1a3f9c 573 tp,val,tb=sys.exc_info()
1f780e48
RD
574 print "Error recovering key: ", str(key), " from node ", str(name), " Val = ", str(val)
575 traceback.print_exception(tp, val, tb)
1f780e48
RD
576
577 def addClass(self, root_node, name, class_item, document, ply):
578 item_node = document.createElement('class')
579 item_node.setAttribute('name', str(name))
6f1a3f9c 580 item_node.setAttribute('value', self.saferepr(class_item))
1f780e48
RD
581 root_node.appendChild(item_node)
582 try:
583 if hasattr(class_item, '__dict__'):
6f1a3f9c 584 self.addDict(item_node, '', class_item.__dict__, document, ply -1)
1f780e48
RD
585 except:
586 tp,val,tb=sys.exc_info()
587 if _VERBOSE:
588 traceback.print_exception(tp, val, tb)
1f780e48
RD
589 try:
590 if hasattr(class_item, '__name__'):
591 self.addAny(item_node,'__name__',class_item.__name__, document, ply -1)
592 except:
593 tp,val,tb=sys.exc_info()
594 if _VERBOSE:
595 traceback.print_exception(tp, val, tb)
1f780e48
RD
596 try:
597 if hasattr(class_item, '__module__'):
598 self.addAny(item_node, '__module__', class_item.__module__, document, ply -1)
599 except:
600 tp,val,tb=sys.exc_info()
601 if _VERBOSE:
602 traceback.print_exception(tp, val, tb)
1f780e48
RD
603 try:
604 if hasattr(class_item, '__doc__'):
605 self.addAny(item_node, '__doc__', class_item.__doc__, document, ply -1)
606 except:
607 tp,val,tb=sys.exc_info()
608 if _VERBOSE:
609 traceback.print_exception(tp, val, tb)
1f780e48
RD
610 try:
611 if hasattr(class_item, '__bases__'):
612 self.addAny(item_node, '__bases__', class_item.__bases__, document, ply -1)
613 except:
614 tp,val,tb=sys.exc_info()
615 if _VERBOSE:
616 traceback.print_exception(tp, val, tb)
1f780e48
RD
617
618 def addModule(self, root_node, name, module_item, document, ply):
619 item_node = document.createElement('module')
620 item_node.setAttribute('name', str(name))
6f1a3f9c 621 item_node.setAttribute('value', self.saferepr(module_item))
1f780e48
RD
622 root_node.appendChild(item_node)
623 try:
624 if hasattr(module_item, '__file__'):
625 self.addAny(item_node, '__file__', module_item.__file__, document, ply -1)
626 except:
627 pass
628 try:
629 if hasattr(module_item, '__doc__'):
630 self.addAny(item_node,'__doc__', module_item.__doc__, document, ply -1)
631 except:
632 pass
633
6f1a3f9c
RD
634
635
636 def getFrameXML(self, base_frame):
6f1a3f9c 637
26ee3a06 638 self.frame_stack = []
6f1a3f9c
RD
639 frame = base_frame
640 while frame is not None:
641 if((frame.f_code.co_filename.count('DebuggerHarness.py') == 0) or _DEBUG_DEBUGGER):
26ee3a06 642 self.frame_stack.append(frame)
6f1a3f9c 643 frame = frame.f_back
26ee3a06 644 self.frame_stack.reverse()
6f1a3f9c 645 self.message_frame_dict = {}
26ee3a06
RD
646 doc = getDOMImplementation().createDocument(None, "stack", None)
647 top_element = doc.documentElement
648 numberFrames = len(self.frame_stack)
649 for index in range(numberFrames):
650 frame = self.frame_stack[index]
651 message = self._adb.frame2message(frame)
652 # We include globals and locals only for the last frame as an optimization for cases
653 # where there are a lot of frames.
654 self.addFrame(frame, top_element, doc, includeContent=(index == numberFrames - 1))
6f1a3f9c
RD
655 return doc.toxml()
656
26ee3a06 657 def addFrame(self, frame, root_element, document, includeContent=False):
6f1a3f9c
RD
658 frameNode = document.createElement('frame')
659 root_element.appendChild(frameNode)
660
661 code = frame.f_code
662 filename = code.co_filename
663 frameNode.setAttribute('file', str(filename))
664 frameNode.setAttribute('line', str(frame.f_lineno))
665 message = self._adb.frame2message(frame)
666 frameNode.setAttribute('message', message)
6f1a3f9c 667 self.message_frame_dict[message] = frame
26ee3a06
RD
668 if includeContent:
669 self.addDict(frameNode, "locals", frame.f_locals, document, 2)
670 self.addNode(frameNode, "globals", frame.f_globals, document)
671
672 def request_frame_document(self, message):
673 frame = self.message_frame_dict[message]
674 doc = getDOMImplementation().createDocument(None, "stack", None)
675 top_element = doc.documentElement
676 if frame:
677 self.addFrame(frame, top_element, doc, includeContent=True)
678 return xmlrpclib.Binary(bz2.compress(doc.toxml()))
679
6f1a3f9c
RD
680 def getRepr(self, varName, globals, locals):
681 try:
682 return repr(eval(varName, globals, locals))
683 except:
684 return 'Error: Could not recover value.'
685
686
687 def saferepr(self, thing):
688 try:
26ee3a06
RD
689 try:
690 return repr(thing)
691 except:
692 return str(type(thing))
6f1a3f9c
RD
693 except:
694 tp, val, tb = sys.exc_info()
26ee3a06 695 #traceback.print_exception(tp, val, tb)
6f1a3f9c
RD
696 return repr(val)
697
1f780e48
RD
698 # The debugger calls this method when it reaches a breakpoint.
699 def interaction(self, message, frame, info):
700 if _VERBOSE:
701 print 'hit debug side interaction'
26ee3a06 702 self._adb._userBreak = False
1f780e48
RD
703
704 self._currentFrame = frame
705 done = False
706 while not done:
707 try:
1f780e48
RD
708 xml = self.getFrameXML(frame)
709 arg = xmlrpclib.Binary(bz2.compress(xml))
710 if _VERBOSE:
711 print '============== calling gui side interaction============'
712 self._guiServer.interaction(xmlrpclib.Binary(message), arg, info)
713 if _VERBOSE:
714 print 'after interaction'
715 done = True
716 except:
717 tp, val, tb = sys.exc_info()
718 if True or _VERBOSE:
719 print 'Error contacting GUI server!: '
720 try:
721 traceback.print_exception(tp, val, tb)
722 except:
723 print "Exception printing traceback",
724 tp, val, tb = sys.exc_info()
725 traceback.print_exception(tp, val, tb)
726 done = False
727 # Block while waiting to be called back from the GUI. Eventually, self._wait will
728 # be set false by a function on this side. Seems pretty lame--I'm surprised it works.
729 self.waitForRPC()
730
731
732 def waitForRPC(self):
733 self._wait = True
734 while self._wait :
735 try:
736 if _VERBOSE:
737 print "+++ in harness wait for rpc, before handle_request"
738 self._server.handle_request()
739 if _VERBOSE:
740 print "+++ in harness wait for rpc, after handle_request"
741 except:
742 if _VERBOSE:
743 tp, val, tb = sys.exc_info()
744 print "Got waitForRpc exception : ", repr(tp), ": ", val
745 #time.sleep(0.1)
746
747 def set_step(self):
748 self._adb.set_step()
749 self._wait = False
750 return ""
751
752 def set_continue(self):
753 self._adb.set_continue()
754 self._wait = False
755 return ""
756
757 def set_next(self):
758 self._adb.set_next(self._currentFrame)
759 self._wait = False
760 return ""
761
762 def set_return(self):
763 self._adb.set_return(self._currentFrame)
764 self._wait = False
765 return ""
766
767if __name__ == '__main__':
768 try:
769 harness = DebuggerHarness()
770 harness.run()
6f1a3f9c 771 harness.do_exit(kill=True)
1f780e48
RD
772 except SystemExit:
773 print "Exiting..."
774 except:
775 tp, val, tb = sys.exc_info()
776 traceback.print_exception(tp, val, tb)