1 # Window-interface-independent part of twit
24 class DebuggerStuff(bdb
.Bdb
):
26 def __init__(self
, parent
):
27 bdb
.Bdb
.__init
__(self
)
29 self
.exception_info
= (None, None)
30 self
.reason
= 'Not running'
31 self
.icon
= ICON_NORMAL
44 def run(self
, cmd
, locals, globals):
45 self
.reason
= 'Running'
46 bdb
.Bdb
.run(self
, cmd
, locals, globals)
47 print 'RETURN from run'
48 self
.reason
= 'Not running'
50 def setup(self
, f
, t
):
52 self
.stack
, self
.curindex
= self
.get_stack(f
, t
)
53 self
.curframe
= self
.stack
[self
.curindex
][0]
55 def interaction(self
, frame
, traceback
):
56 self
.setup(frame
, traceback
)
57 self
.parent
.interact()
58 self
.exception_info
= (None, None)
60 # def user_call(self, frame, argument_list):
61 # self.reason = 'Calling'
62 # self.icon = ICON_CALL
63 # self.interaction(frame, None)
65 def user_line(self
, frame
):
66 self
.reason
= 'Stopped'
67 self
.icon
= ICON_NORMAL
68 self
.interaction(frame
, None)
70 def user_return(self
, frame
, return_value
):
71 self
.reason
= 'Returning'
72 self
.icon
= ICON_RETURN
73 self
.interaction(frame
, None)
75 def user_exception(self
, frame
, (exc_type
, exc_value
, exc_traceback
)):
76 self
.reason
= 'Exception occurred'
78 self
.parent
.setstate('tb')
79 self
.exception_info
= (exc_type
, exc_value
)
80 self
.interaction(frame
, exc_traceback
)
82 def getexception(self
):
83 tp
, value
= self
.exception_info
84 if tp
<> None and type(tp
) <> type(''):
86 if value
<> None and type(value
) <> type(''):
90 def getstacktrace(self
):
91 names
, locations
= [], []
92 for frame
, lineno
in self
.stack
:
93 name
= frame
.f_code
.co_name
97 name
= "<not a function>"
103 lineno
= getframelineno(frame
)
105 modname
= getframemodname(frame
)
106 if not modname
: modname
= "<unknown>"
108 locations
.append("%s:%d" % (modname
, lineno
))
109 return names
, locations
111 def getframe(self
, number
):
112 if number
< 0 or number
>= len(self
.stack
):
114 return self
.stack
[number
][0]
116 def getframevars(self
, number
, show_complex
=1, show_system
=1):
117 frame
= self
.getframe(number
)
120 return getvarsfromdict(frame
.f_locals
, show_complex
, show_system
)
122 def getframevar(self
, number
, var
):
123 frame
= self
.getframe(number
)
124 return frame
.f_locals
[var
]
126 def getframefilepos(self
, frameno
):
127 if frameno
== None or frameno
< 0 or frameno
>= len(self
.stack
):
128 return None, None, None
129 frame
, line
= self
.stack
[frameno
]
131 line
= getframelineno(frame
)
132 modname
= getframemodname(frame
)
133 filename
= frame
.f_code
.co_filename
134 return filename
, modname
, line
136 def getprogramstate(self
):
140 """Base code for the application"""
142 def mi_init(self
, sessiontype
, arg
):
143 self
.dbg
= DebuggerStuff(self
)
144 self
.run_dialog
= self
.new_stack_browser(self
)
145 self
.run_dialog
.open()
146 self
.module_dialog
= None
147 self
.initial_cmd
= None
148 self
.cur_string_name
= None
149 if sessiontype
== 'tb':
150 while arg
.tb_next
<> None:
152 self
.dbg
.setup(arg
.tb_frame
, arg
)
153 self
.run_dialog
.setup()
154 elif sessiontype
== 'run':
155 self
.initial_cmd
= arg
157 def breaks_changed(self
, filename
):
158 self
.run_dialog
.breaks_changed(filename
)
159 if self
.module_dialog
:
160 self
.module_dialog
.breaks_changed(filename
)
162 def to_debugger(self
):
163 cmd
= self
.initial_cmd
164 self
.initial_cmd
= None
167 apply(self
.dbg
.run
, cmd
)
168 self
.setstate('none')
170 self
.run_dialog
.update_views()
171 if self
.module_dialog
:
172 self
.module_dialog
.update_views()
175 # Interact with user. First, display correct info
177 self
.run_dialog
.update_views()
178 if self
.module_dialog
:
179 self
.module_dialog
.update_views()
181 # Next, go into mainloop
184 # Finally (before we start the debuggee again) show state
186 self
.run_dialog
.show_it_running()
192 cmd
= self
.AskString('Statement to execute:')
195 def runfile(self
, path
):
196 dir, file = os
.path
.split(path
)
199 except os
.error
, arg
:
200 self
.Message("%s: %s"%(dir, arg
))
202 ns
= {'__name__':'__main__', '__file__':path
}
203 cmd
= "execfile('%s')"%file
204 self
.runstring(cmd
, ns
, ns
)
206 def runstring(self
, cmd
, globals={}, locals={}):
207 self
.cur_string_name
= '<string: "%s">'%cmd
209 cmd
= compile(cmd
, self
.cur_string_name
, 'exec')
210 except SyntaxError, arg
:
211 self
.Message('Syntax error: %s'%`arg`
)
213 self
.initial_cmd
= (cmd
, globals, locals)
217 self
.dbg
.set_continue()
220 def step(self
, frame
):
221 self
.dbg
.set_next(frame
)
228 def step_out(self
, frame
):
229 self
.dbg
.set_return(frame
)
239 def browse(self
, module
):
240 if not self
.module_dialog
:
241 self
.module_dialog
= self
.new_module_browser(self
)
242 self
.module_dialog
.open(module
)
244 self
.module_dialog
.focus(module
)
246 def browse_var(self
, var
):
247 b
= self
.new_var_browser(self
, var
)
250 """Base code for stack browser"""
252 """Setup initial data structures"""
253 self
.cur_stackitem
= None
254 self
.cur_source
= None
255 self
.cur_modname
= None
257 self
.show_complex
= 1
261 # create_items(self) should create self.modules, self.vars and self.source
264 self
.parent
.SetWatch()
265 """Fill the various widgets with values"""
266 name
, value
= self
.parent
.dbg
.getexception()
267 self
.setexception(name
, value
)
268 self
.setprogramstate(self
.parent
.dbg
.getprogramstate())
270 names
, locations
= self
.parent
.dbg
.getstacktrace()
271 self
.stack_setcontent(names
, locations
)
272 self
.cur_stackitem
= len(names
)-1
273 self
.stack_select(self
.cur_stackitem
)
276 def setup_frame(self
):
277 """Setup frame-dependent widget data"""
278 self
.parent
.SetWatch()
279 self
.cont_varnames
, self
.cont_varvalues
= \
280 self
.parent
.dbg
.getframevars(self
.cur_stackitem
,
281 self
.show_complex
, self
.show_system
)
283 self
.set_var_buttons()
286 if self
.cur_stackitem
== None:
287 self
.cur_source
= None
288 self
.cur_modname
= None
290 msg
= "No stackframe selected"
292 self
.cur_source
, self
.cur_modname
, optnextline
= \
293 self
.parent
.dbg
.getframefilepos(self
.cur_stackitem
)
295 self
.cur_line
= optnextline
296 if self
.cur_source
== '<string>':
297 self
.cur_source
= None
298 msg
= "Executing from unknown <string>"
299 elif type(self
.cur_source
) == types
.StringType
and \
300 self
.cur_source
[:8] == '<string:':
301 msg
= "Executing from "+self
.cur_source
302 self
.cur_source
= None
305 if not self
.cur_line
:
306 self
.source_setline(1, ICON_ZERO
)
308 self
.source_setline(self
.cur_line
, self
.parent
.dbg
.icon
)
309 self
.breaks_changed(self
.cur_source
)
312 self
.parent
.SetCursor()
314 # setsource(msg) should display cur_source+content, or msg if None
316 def show_it_running(self
):
317 self
.setprogramstate("Running")
319 def update_views(self
):
322 def click_stack(self
, number
, *dummy
):
323 if number
== self
.cur_stackitem
: return
324 self
.cur_stackitem
= number
325 self
.stack_select(self
.cur_stackitem
)
328 def click_var(self
, var
, *dummy
):
329 v
= self
.parent
.dbg
.getframevar(self
.cur_stackitem
, var
)
330 self
.parent
.browse_var(v
)
332 def click_source(self
, lineno
, inborder
):
334 self
.source_select(lineno
)
335 self
.cur_line
= lineno
336 if lineno
== None or not self
.cur_source
or not inborder
:
338 if self
.parent
.dbg
.get_break(self
.cur_source
, lineno
):
339 self
.parent
.dbg
.clear_break(self
.cur_source
, lineno
)
341 self
.parent
.dbg
.set_break(self
.cur_source
, lineno
)
342 self
.parent
.breaks_changed(self
.cur_source
)
344 def breaks_changed(self
, filename
):
345 if filename
== self
.cur_source
:
346 list = self
.parent
.dbg
.get_file_breaks(filename
)
347 self
.source_setbreaks(list)
349 def click_quit(self
):
355 def click_continue(self
):
358 def click_step(self
):
359 if self
.cur_stackitem
<> None:
360 frame
= self
.parent
.dbg
.getframe(self
.cur_stackitem
)
361 self
.parent
.step(frame
)
363 self
.parent
.step_in()
365 def click_step_in(self
):
366 self
.parent
.step_in()
368 def click_step_out(self
):
369 if self
.cur_stackitem
<> None:
370 frame
= self
.parent
.dbg
.getframe(self
.cur_stackitem
)
371 self
.parent
.step_out(frame
)
373 self
.parent
.step_in()
375 def click_kill(self
):
378 def click_browse(self
):
379 self
.parent
.browse(self
.cur_modname
)
381 def click_edit(self
):
386 self
.parent
.edit(self
.cur_source
, lino
)
389 """Base code for a module-browser"""
391 def mi_open(self
, module
):
392 """Setup initial data structures"""
393 self
.cur_module
= module
394 self
.cur_source
= None
396 self
.cont_modules
= []
397 self
.value_windows
= []
400 # create_items(self) should create self.modules, self.vars and self.source
403 """Fill the various widgets with values"""
404 self
.parent
.SetWatch()
405 modnames
= getmodulenames()
406 if not self
.cur_module
in modnames
:
407 self
.cur_module
= None
408 if modnames
<> self
.cont_modules
:
409 self
.cont_modules
= modnames
410 self
.setmodulenames()
412 self
.module_select(self
.cont_modules
.index(self
.cur_module
))
414 self
.module_select(None)
417 def setup_module(self
):
418 """Setup module-dependent widget data"""
419 self
.parent
.SetWatch()
420 if not self
.cur_module
:
421 self
.cont_varnames
= []
422 self
.cont_varvalues
= []
424 self
.cont_varnames
, self
.cont_varvalues
= getmodulevars(self
.cur_module
)
428 if not self
.cur_module
:
429 self
.cur_source
= None
430 msg
= "No module selected"
432 m
= sys
.modules
[self
.cur_module
]
434 self
.cur_source
= m
.__file
__
435 except AttributeError:
436 self
.cur_source
= None
437 msg
= "Not a python module"
440 self
.source_select(self
.cur_line
)
441 self
.breaks_changed(self
.cur_source
)
443 self
.parent
.SetCursor()
445 # setsource(msg) should display cur_source+content, or msg if None
447 def update_views(self
):
450 def click_module(self
, module
, *dummy
):
451 if not module
or module
== self
.cur_module
: return
454 def focus(self
, module
):
455 self
.cur_module
= module
458 def click_var(self
, var
, *dummy
):
460 m
= sys
.modules
[self
.cur_module
]
462 self
.parent
.browse_var(dict[var
])
464 def click_source(self
, lineno
, inborder
):
466 self
.source_select(lineno
)
467 self
.cur_lineno
= lineno
468 if lineno
== None or not self
.cur_source
or not inborder
:
470 if self
.parent
.dbg
.get_break(self
.cur_source
, lineno
):
471 self
.parent
.dbg
.clear_break(self
.cur_source
, lineno
)
473 self
.parent
.dbg
.set_break(self
.cur_source
, lineno
)
474 self
.parent
.breaks_changed(self
.cur_source
)
476 def breaks_changed(self
, filename
):
477 if filename
== self
.cur_source
:
478 list = self
.parent
.dbg
.get_file_breaks(filename
)
479 self
.source_setbreaks(list)
481 def click_edit(self
):
482 lino
= self
.cur_lineno
486 self
.parent
.edit(self
.cur_source
, lino
)
489 def getmodulenames():
490 """Return a list of all current modules, sorted"""
491 list = sys
.modules
.keys()[:]
495 def getmodulevars(name
):
496 """For given module return lists with names and values"""
497 m
= sys
.modules
[name
]
500 except AttributeError:
502 return getvarsfromdict(dict)
504 def getvarsfromdict(dict, show_complex
=1, show_system
=1):
505 allnames
= dict.keys()[:]
510 if not type(dict[n
]) in SIMPLE_TYPES
:
513 if n
[:2] == '__' and n
[-2:] == '__':
524 if t
== types
.FunctionType
: return '<function>'
525 if t
== types
.ClassType
: return '<class>'
528 def getframelineno(frame
):
529 """Given a frame return the line number"""
530 return getcodelineno(frame
.f_code
)
532 def getfunclineno(func
):
533 """Given a function return the line number"""
534 return getcodelineno(func
.func_code
)
536 def getcodelineno(cobj
):
537 """Given a code object return the line number"""
540 if ord(code
[0]) == 127: # SET_LINENO instruction
541 lineno
= ord(code
[1]) |
(ord(code
[2]) << 8)
544 def getframemodname(frame
):
545 """Given a frame return the module name"""
546 globals = frame
.f_globals
547 if globals.has_key('__name__'):
548 return globals['__name__']