25 class Debugger(bdb
.Bdb
):
27 def __init__(self
, title
= 'Debugger'):
28 bdb
.Bdb
.__init
__(self
)
31 self
.breaksviewer
= None
34 self
.tracingmonitortime
= Evt
.TickCount()
37 prefs
= W
.getapplication().getprefs()
39 for file, breaks
in prefs
.debugger
.breaks
.items():
41 self
.set_break(file, b
)
42 self
.bounds
, self
.horpanes
, self
.verpanes
= prefs
.debugger
.windowsettings
43 self
.tracemagic
= prefs
.debugger
.tracemagic
46 self
.horpanes
= (0.4, 0.6)
47 self
.verpanes
= (0.3, 0.35, 0.35)
48 self
.bounds
= (600, 400)
50 self
.laststacksel
= None
52 def canonic(self
, filename
):
53 # override: the provided canonic() method breaks our
54 # file-less Untitled windows
58 self
.currentframe
= None
61 self
.reason
= 'Not running'
62 self
.continuewithoutdebugger
= 0
66 def start(self
, bottomframe
= None, running
= 0):
67 W
.getapplication().DebuggerQuit
= bdb
.BdbQuit
71 self
.setupwidgets(self
.title
)
73 if not self
.w
.parent
.debugger_quitting
:
75 raise W
.AlertError
, 'There is another debugger session busy.'
77 self
.botframe
= bottomframe
80 self
.reason
= 'Running\xc9'
81 self
.setstate('running')
84 self
.reason
= 'stopped'
85 self
.setstate('stopped')
86 sys
.settrace(self
.trace_dispatch
)
94 def set_continue_without_debugger(self
):
97 self
.clear_tracefuncs()
98 self
.continuewithoutdebugger
= 1
99 if hasattr(self
, "w") and self
.w
.parent
:
103 def clear_tracefuncs(self
):
108 frame
= sys
.exc_traceback
.tb_frame
109 while frame
is not None:
113 def postmortem(self
, exc_type
, exc_value
, traceback
):
115 self
.setupwidgets(self
.title
)
117 if not self
.w
.parent
.debugger_quitting
:
118 raise W
.AlertError
, 'There is another debugger session busy.'
121 self
.botframe
= traceback
.tb_frame
122 while traceback
.tb_next
<> None:
123 traceback
= traceback
.tb_next
124 frame
= traceback
.tb_frame
128 self
.w
.panes
.bottom
.buttons
.killbutton
.enable(1)
129 self
.reason
= '(dead) ' + self
.formatexception(exc_type
, exc_value
)
131 self
.setup(frame
, traceback
)
132 self
.setstate('dead')
133 self
.showstack(self
.curindex
)
134 self
.showframe(self
.curindex
)
136 def setupwidgets(self
, title
):
137 self
.w
= w
= W
.Window(self
.bounds
, title
, minsize
= (500, 300))
139 w
.panes
= W
.HorizontalPanes((8, 4, -8, -8), self
.horpanes
)
141 w
.panes
.browserpanes
= browserpanes
= W
.VerticalPanes(None, self
.verpanes
)
143 browserpanes
.stacklist
= W
.Group(None)
144 browserpanes
.stacklist
.title
= W
.TextBox((4, 0, 0, 12), 'Stack')
145 browserpanes
.stacklist
.stack
= W
.List((0, 16, 0, 0), callback
= self
.do_stack
, flags
= Lists
.lOnlyOne
)
147 browserpanes
.locals = W
.Group(None)
148 browserpanes
.locals.title
= W
.TextBox((4, 0, 0, 12), 'Local variables')
149 browserpanes
.locals.browser
= PyBrowser
.BrowserWidget((0, 16, 0, 0))
151 browserpanes
.globals = W
.Group(None)
152 browserpanes
.globals.title
= W
.TextBox((4, 0, 0, 12), 'Global variables')
153 browserpanes
.globals.browser
= PyBrowser
.BrowserWidget((0, 16, 0, 0))
155 w
.panes
.bottom
= bottom
= W
.Group(None)
156 bottom
.src
= src
= W
.Group((0, 52, 0, 0))
157 source
= SourceViewer((1, 1, -15, -15), readonly
= 1, debugger
= self
)
158 src
.optionsmenu
= W
.PopupMenu((-16, 0, 16, 16), [])
159 src
.optionsmenu
.bind('<click>', self
.makeoptionsmenu
)
161 src
._barx
= W
.Scrollbar((0, -16, -15, 16), source
.hscroll
, max = 32767)
162 src
._bary
= W
.Scrollbar((-16, 15, 16, -15), source
.vscroll
, max = 32767)
164 src
.frame
= W
.Frame((0, 0, -15, -15))
166 bottom
.tracingmonitor
= TracingMonitor((0, 23, 6, 6))
167 bottom
.state
= W
.TextBox((12, 20, 0, 16), self
.reason
)
169 bottom
.srctitle
= W
.TextBox((12, 36, 0, 14))
170 bottom
.buttons
= buttons
= W
.Group((12, 0, 0, 16))
172 buttons
.runbutton
= W
.Button((0, 0, 50, 16), "Run", self
.do_run
)
173 buttons
.stopbutton
= W
.Button((58, 0, 50, 16), "Stop", self
.do_stop
)
174 buttons
.killbutton
= W
.Button((116, 0, 50, 16), "Kill", self
.do_kill
)
175 buttons
.line
= W
.VerticalLine((173, 0, 0, 0))
176 buttons
.stepbutton
= W
.Button((181, 0, 50, 16), "Step", self
.do_step
)
177 buttons
.stepinbutton
= W
.Button((239, 0, 50, 16), "Step in", self
.do_stepin
)
178 buttons
.stepoutbutton
= W
.Button((297, 0, 50, 16), "Step out", self
.do_stepout
)
180 w
.bind('cmdr', buttons
.runbutton
.push
)
181 w
.bind('cmd.', buttons
.stopbutton
.push
)
182 w
.bind('cmdk', buttons
.killbutton
.push
)
183 w
.bind('cmds', buttons
.stepbutton
.push
)
184 w
.bind('cmdt', buttons
.stepinbutton
.push
)
185 w
.bind('cmdu', buttons
.stepoutbutton
.push
)
187 w
.bind('<close>', self
.close
)
190 w
.xxx___select(w
.panes
.bottom
.src
.source
)
192 def makeoptionsmenu(self
):
193 options
= [('Clear breakpoints', self
.w
.panes
.bottom
.src
.source
.clearbreakpoints
),
194 ('Clear all breakpoints', self
.clear_all_breaks
),
195 ('Edit breakpoints\xc9', self
.edit_breaks
), '-',
197 'Disable __magic__ tracing' or 'Enable __magic__ tracing', self
.togglemagic
)]
198 self
.w
.panes
.bottom
.src
.optionsmenu
.set(options
)
200 def edit_breaks(self
):
201 if self
.breaksviewer
:
202 self
.breaksviewer
.select()
204 self
.breaksviewer
= BreakpointsViewer(self
)
206 def togglemagic(self
):
207 self
.tracemagic
= not self
.tracemagic
209 def setstate(self
, state
):
210 self
.w
.panes
.bottom
.tracingmonitor
.reset()
211 self
.w
.panes
.bottom
.state
.set(self
.reason
)
212 buttons
= self
.w
.panes
.bottom
.buttons
213 if state
== 'stopped':
214 buttons
.runbutton
.enable(1)
215 buttons
.stopbutton
.enable(0)
216 buttons
.killbutton
.enable(1)
217 buttons
.stepbutton
.enable(1)
218 buttons
.stepinbutton
.enable(1)
219 buttons
.stepoutbutton
.enable(1)
220 elif state
== 'running':
221 buttons
.runbutton
.enable(0)
222 buttons
.stopbutton
.enable(1)
223 buttons
.killbutton
.enable(1)
224 buttons
.stepbutton
.enable(0)
225 buttons
.stepinbutton
.enable(0)
226 buttons
.stepoutbutton
.enable(0)
227 elif state
== 'idle':
228 buttons
.runbutton
.enable(0)
229 buttons
.stopbutton
.enable(0)
230 buttons
.killbutton
.enable(0)
231 buttons
.stepbutton
.enable(0)
232 buttons
.stepinbutton
.enable(0)
233 buttons
.stepoutbutton
.enable(0)
234 elif state
== 'dead':
235 buttons
.runbutton
.enable(0)
236 buttons
.stopbutton
.enable(0)
237 buttons
.killbutton
.enable(1)
238 buttons
.stepbutton
.enable(0)
239 buttons
.stepinbutton
.enable(0)
240 buttons
.stepoutbutton
.enable(0)
242 print 'unknown state:', state
244 def resetwidgets(self
):
246 self
.w
.panes
.bottom
.srctitle
.set('')
247 self
.w
.panes
.bottom
.src
.source
.set('')
248 self
.w
.panes
.browserpanes
.stacklist
.stack
.set([])
249 self
.w
.panes
.browserpanes
.locals.browser
.set({})
250 self
.w
.panes
.browserpanes
.globals.browser
.set({})
251 self
.setstate('idle')
260 self
.unregister_editor(self
.w
.panes
.bottom
.src
.source
,
261 self
.w
.panes
.bottom
.src
.source
.file)
262 self
.horpanes
= self
.w
.panes
.getpanesizes()
263 self
.verpanes
= self
.w
.panes
.browserpanes
.getpanesizes()
264 self
.bounds
= self
.w
.getbounds()
265 prefs
= W
.getapplication().getprefs()
266 prefs
.debugger
.breaks
= self
.breaks
267 prefs
.debugger
.windowsettings
= self
.bounds
, self
.horpanes
, self
.verpanes
268 prefs
.debugger
.tracemagic
= self
.tracemagic
271 # stack list callback
273 def do_stack(self
, isdbl
):
274 sel
= self
.w
.panes
.browserpanes
.stacklist
.stack
.getselection()
277 frame
, lineno
= self
.stack
[sel
[0] + 1]
278 filename
= frame
.f_code
.co_filename
279 editor
= self
.w
._parentwindow
.parent
.openscript(filename
, lineno
)
280 if self
.breaks
.has_key(filename
):
281 editor
.showbreakpoints(1)
283 if sel
and sel
<> self
.laststacksel
:
284 self
.showframe(sel
[0] + 1)
285 self
.laststacksel
= sel
287 def geteditor(self
, filename
):
288 if filename
[:1] == '<' and filename
[-1:] == '>':
289 editor
= W
.getapplication().getscript(filename
[1:-1])
291 editor
= W
.getapplication().getscript(filename
)
311 self
.set_next(self
.curframe
)
319 def do_stepout(self
):
321 self
.set_return(self
.curframe
)
326 self
.reason
= 'Running\xc9'
327 self
.setstate('running')
328 #self.w.panes.bottom.src.source.set('')
329 #self.w.panes.browserpanes.stacklist.stack.set([])
330 #self.w.panes.browserpanes.locals.browser.set({})
331 #self.w.panes.browserpanes.globals.browser.set({})
333 def exit_mainloop(self
):
334 self
.w
.parent
.debugger_quitting
= 1
338 def showframe(self
, stackindex
):
339 (frame
, lineno
) = self
.stack
[stackindex
]
341 filename
= frame
.f_code
.co_filename
342 if filename
<> self
.file:
343 editor
= self
.geteditor(filename
)
345 self
.w
.panes
.bottom
.src
.source
.set(editor
.get(), filename
)
348 f
= open(filename
, 'rb')
352 if filename
[-3:] == '.py':
354 modname
= os
.path
.basename(filename
)[:-3]
356 f
, filename
, (suff
, mode
, dummy
) = imp
.find_module(modname
)
358 self
.w
.panes
.bottom
.src
.source
.set("can't find file")
362 if f
and suff
== '.py':
363 f
= open(filename
, 'rb')
366 self
.w
.panes
.bottom
.src
.source
.set(data
, filename
)
368 self
.w
.panes
.bottom
.src
.source
.set("can't find file")
370 self
.w
.panes
.bottom
.src
.source
.set("can't find file")
372 self
.w
.panes
.bottom
.src
.source
.set(data
, filename
)
374 self
.w
.panes
.bottom
.srctitle
.set('Source: ' + filename
+ ((lineno
> 0) and (' (line %d)' % lineno
) or ' '))
375 self
.goto_line(lineno
)
377 self
.showvars((frame
, lineno
))
379 def showvars(self
, (frame
, lineno
)):
380 if frame
.f_locals
is not frame
.f_globals
:
381 locals = frame
.f_locals
383 locals = {'Same as Globals':''}
385 for key
, value
in locals.items():
386 # empty key is magic for Python 1.4; '.' is magic for 1.5...
387 if not key
or key
[0] <> '.':
388 filteredlocals
[key
] = value
389 self
.w
.panes
.browserpanes
.locals.browser
.set(filteredlocals
)
390 self
.w
.panes
.browserpanes
.globals.browser
.set(frame
.f_globals
)
392 def showstack(self
, stackindex
):
394 for frame
, lineno
in self
.stack
[1:]:
395 filename
= frame
.f_code
.co_filename
397 filename
= _filenames
[filename
]
399 if filename
[:1] + filename
[-1:] <> '<>':
400 filename
= os
.path
.basename(filename
)
401 _filenames
[frame
.f_code
.co_filename
] = filename
402 funcname
= frame
.f_code
.co_name
404 funcname
= '<toplevel>'
405 stack
.append(filename
+ ': ' + funcname
)
406 if stack
<> self
.laststack
:
407 self
.w
.panes
.browserpanes
.stacklist
.stack
.set(stack
)
408 self
.laststack
= stack
409 sel
= [stackindex
- 1]
410 self
.w
.panes
.browserpanes
.stacklist
.stack
.setselection(sel
)
411 self
.laststacksel
= sel
413 def goto_line(self
, lineno
):
415 self
.w
.panes
.bottom
.src
.source
.selectline(lineno
- 1)
417 self
.w
.panes
.bottom
.src
.source
.setselection(0, 0)
421 # def user_call(self, frame, argument_list):
422 # self.reason = 'Calling'
423 # self.interaction(frame, None)
425 def user_line(self
, frame
):
426 # This function is called when we stop or break at this line
427 self
.reason
= 'Stopped'
428 self
.interaction(frame
, None)
430 def user_return(self
, frame
, return_value
):
431 # This function is called when a return trap is set here
432 fname
= frame
.f_code
.co_name
434 self
.reason
= 'Returning from %s()' % frame
.f_code
.co_name
435 frame
.f_locals
['__return__'] = return_value
436 elif frame
.f_back
is self
.botframe
:
439 self
.reason
= 'Returning'
440 self
.interaction(frame
, None, 1)
442 def user_exception(self
, frame
, (exc_type
, exc_value
, exc_traceback
)):
443 # This function is called when we stop or break at this line
444 self
.reason
= self
.formatexception(exc_type
, exc_value
)
445 self
.interaction(frame
, exc_traceback
)
447 def formatexception(self
, exc_type
, exc_value
):
448 if exc_type
== SyntaxError:
450 value
, (filename
, lineno
, charno
, line
) = exc_value
454 return str(exc_type
) + ': ' + str(value
)
455 if type(exc_type
) == types
.ClassType
:
456 nice
= exc_type
.__name
__
459 value
= str(exc_value
)
460 if exc_value
and value
:
461 nice
= nice
+ ": " + value
469 def setup(self
, f
, t
, isreturning
= 0):
471 self
.stack
, self
.curindex
= self
.get_stack(f
, t
)
472 self
.curframe
= self
.stack
[self
.curindex
- isreturning
][0]
474 def interaction(self
, frame
, traceback
, isreturning
= 0):
475 saveport
= Qd
.GetPort()
478 self
.setup(frame
, traceback
, isreturning
)
479 self
.setstate('stopped')
480 stackindex
= self
.curindex
482 if frame
.f_back
is not self
.botframe
:
483 stackindex
= stackindex
- 1
484 self
.showstack(stackindex
)
485 self
.showframe(stackindex
)
486 self
.w
.parent
.debugger_mainloop()
493 def trace_dispatch(self
, frame
, event
, arg
, TickCount
= Evt
.TickCount
):
494 if TickCount() - self
.tracingmonitortime
> 15:
495 self
.tracingmonitortime
= TickCount()
496 self
.w
.panes
.bottom
.tracingmonitor
.toggle()
499 MacOS
.EnableAppswitch(0)
501 # returning None is not enough, a former BdbQuit exception
502 # might have been eaten by the print statement
505 return self
.dispatch_line(frame
)
507 return self
.dispatch_call(frame
, arg
)
508 if event
== 'return':
509 return self
.dispatch_return(frame
, arg
)
510 if event
== 'exception':
511 return self
.dispatch_exception(frame
, arg
)
512 print 'bdb.Bdb.dispatch: unknown debugging event:', `event`
513 return self
.trace_dispatch
515 MacOS
.EnableAppswitch(-1)
516 except KeyboardInterrupt:
518 return self
.trace_dispatch
520 if self
.continuewithoutdebugger
:
521 self
.clear_tracefuncs()
526 print 'XXX Exception during debugger interaction.', \
527 self
.formatexception(sys
.exc_type
, sys
.exc_value
)
529 traceback
.print_exc()
530 return self
.trace_dispatch
532 def dispatch_call(self
, frame
, arg
):
533 if not self
.tracemagic
and \
534 frame
.f_code
.co_name
[:2] == '__' == frame
.f_code
.co_name
[-2:] and \
535 frame
.f_code
.co_name
<> '__init__':
537 if self
.botframe
is None:
538 # First call of dispatch since reset()
539 self
.botframe
= frame
.f_back
# xxx !!! added f_back
540 return self
.trace_dispatch
541 if not (self
.stop_here(frame
) or self
.break_anywhere(frame
)):
542 # No need to trace this function
544 self
.user_call(frame
, arg
)
547 return self
.trace_dispatch
549 def set_continue(self
):
550 # Don't stop except at breakpoints or when finished
551 self
.stopframe
= self
.botframe
552 self
.returnframe
= None
554 # unlike in bdb/pdb, there's a chance that breakpoints change
555 # *while* a program (this program ;-) is running. It's actually quite likely.
556 # So we don't delete frame.f_trace until the bottom frame if there are no breakpoints.
558 def set_break(self
, filename
, lineno
):
559 if not self
.breaks
.has_key(filename
):
560 self
.breaks
[filename
] = []
561 list = self
.breaks
[filename
]
563 return 'There is already a breakpoint there!'
565 list.sort() # I want to keep them neatly sorted; easier for drawing
566 if hasattr(bdb
, "Breakpoint"):
568 bp
= bdb
.Breakpoint(filename
, lineno
, 0, None)
569 self
.update_breaks(filename
)
571 def clear_break(self
, filename
, lineno
):
572 bdb
.Bdb
.clear_break(self
, filename
, lineno
)
573 self
.update_breaks(filename
)
575 def clear_all_file_breaks(self
, filename
):
576 bdb
.Bdb
.clear_all_file_breaks(self
, filename
)
577 self
.update_breaks(filename
)
579 def clear_all_breaks(self
):
580 bdb
.Bdb
.clear_all_breaks(self
)
581 for editors
in self
.editors
.values():
582 for editor
in editors
:
583 editor
.drawbreakpoints()
587 def toggle_break(self
, filename
, lineno
):
588 if self
.get_break(filename
, lineno
):
589 self
.clear_break(filename
, lineno
)
591 self
.set_break(filename
, lineno
)
593 def clear_breaks_above(self
, filename
, above
):
594 if not self
.breaks
.has_key(filename
):
595 return 'There are no breakpoints in that file!'
596 for lineno
in self
.breaks
[filename
][:]:
598 self
.breaks
[filename
].remove(lineno
)
599 if not self
.breaks
[filename
]:
600 del self
.breaks
[filename
]
604 def update_breaks(self
, filename
):
605 if self
.breaksviewer
:
606 self
.breaksviewer
.update()
607 if self
.editors
.has_key(filename
):
608 for editor
in self
.editors
[filename
]:
609 if editor
._debugger
: # XXX
610 editor
.drawbreakpoints()
612 print 'xxx dead editor!'
614 def update_allbreaks(self
):
615 if self
.breaksviewer
:
616 self
.breaksviewer
.update()
617 for filename
in self
.breaks
.keys():
618 if self
.editors
.has_key(filename
):
619 for editor
in self
.editors
[filename
]:
620 if editor
._debugger
: # XXX
621 editor
.drawbreakpoints()
623 print 'xxx dead editor!'
625 def register_editor(self
, editor
, filename
):
628 if not self
.editors
.has_key(filename
):
629 self
.editors
[filename
] = [editor
]
630 elif editor
not in self
.editors
[filename
]:
631 self
.editors
[filename
].append(editor
)
633 def unregister_editor(self
, editor
, filename
):
637 self
.editors
[filename
].remove(editor
)
638 if not self
.editors
[filename
]:
639 del self
.editors
[filename
]
640 # if this was an untitled window, clear the breaks.
641 if filename
[:1] == '<' and filename
[-1:] == '>' and \
642 self
.breaks
.has_key(filename
):
643 self
.clear_all_file_breaks(filename
)
644 except (KeyError, ValueError):
648 class SourceViewer(W
.PyEditor
):
650 def __init__(self
, *args
, **kwargs
):
651 apply(W
.PyEditor
.__init
__, (self
,) + args
, kwargs
)
652 self
.bind('<click>', self
.clickintercept
)
654 def clickintercept(self
, point
, modifiers
):
655 if self
._parentwindow
._currentwidget
<> self
and not self
.pt_in_breaks(point
):
656 self
._parentwindow
.xxx___select(self
)
659 def _getviewrect(self
):
660 l
, t
, r
, b
= self
._bounds
662 return (l
+ 12, t
+ 2, r
- 1, b
- 2)
664 return (l
+ 5, t
+ 2, r
- 1, b
- 2)
666 def select(self
, onoff
, isclick
= 0):
667 if W
.SelectableWidget
.select(self
, onoff
):
671 # self.ted.WEActivate()
673 # self.ted.WEDeactivate()
674 self
.drawselframe(onoff
)
676 def drawselframe(self
, onoff
):
680 class BreakpointsViewer
:
682 def __init__(self
, debugger
):
683 self
.debugger
= debugger
685 self
.w
= W
.Window((300, 250), 'Breakpoints', minsize
= (200, 200))
686 self
.w
.panes
= W
.HorizontalPanes((8, 8, -8, -32), (0.3, 0.7))
687 self
.w
.panes
.files
= W
.List(None, callback
= self
.filehit
) #, flags = Lists.lOnlyOne)
688 self
.w
.panes
.gr
= W
.Group(None)
689 self
.w
.panes
.gr
.breaks
= W
.List((0, 0, -130, 0), callback
= self
.linehit
) #, flags = Lists.lOnlyOne)
690 self
.w
.panes
.gr
.openbutton
= W
.Button((-80, 4, 0, 16), 'View\xc9', self
.openbuttonhit
)
691 self
.w
.panes
.gr
.deletebutton
= W
.Button((-80, 28, 0, 16), 'Delete', self
.deletebuttonhit
)
693 self
.w
.bind('<close>', self
.close
)
694 self
.w
.bind('backspace', self
.w
.panes
.gr
.deletebutton
.push
)
698 self
.w
.panes
.gr
.openbutton
.enable(0)
699 self
.w
.panes
.gr
.deletebutton
.enable(0)
702 def deletebuttonhit(self
):
703 if self
.w
._currentwidget
== self
.w
.panes
.files
:
709 def del_number(self
):
710 if self
.curfile
is None:
712 sel
= self
.w
.panes
.gr
.breaks
.getselectedobjects()
714 self
.debugger
.clear_break(self
.curfile
, lineno
)
716 def del_filename(self
):
717 sel
= self
.w
.panes
.files
.getselectedobjects()
719 self
.debugger
.clear_all_file_breaks(filename
)
720 self
.debugger
.update_allbreaks()
723 files
= self
.debugger
.breaks
.keys()
725 self
.w
.panes
.files
.set(files
)
728 self
.debugger
.breaksviewer
= None
732 sel
= self
.w
.panes
.files
.getselectedobjects()
734 self
.w
.panes
.files
.setselectedobjects(sel
)
735 sel
= self
.w
.panes
.files
.getselection()
736 if len(sel
) == 0 and self
.curfile
:
737 self
.w
.panes
.files
.setselectedobjects([self
.curfile
])
743 def selectfile(self
, file):
744 self
.w
.panes
.files
.setselectedobjects([file])
747 def openbuttonhit(self
):
750 def filehit(self
, isdbl
):
751 sel
= self
.w
.panes
.files
.getselectedobjects()
755 if filename
== self
.curfile
:
756 linesel
= self
.w
.panes
.gr
.breaks
.getselectedobjects()
759 elif self
.w
.panes
.gr
.breaks
:
760 lineno
= self
.w
.panes
.gr
.breaks
[0]
761 editor
= self
.w
._parentwindow
.parent
.openscript(filename
, lineno
)
762 editor
.showbreakpoints(1)
766 filebreaks
= self
.debugger
.breaks
[file][:]
767 if self
.curfile
== file:
768 linesel
= self
.w
.panes
.gr
.breaks
.getselectedobjects()
769 self
.w
.panes
.gr
.breaks
.set(filebreaks
)
770 if self
.curfile
== file:
771 self
.w
.panes
.gr
.breaks
.setselectedobjects(linesel
)
776 self
.w
.panes
.gr
.breaks
.set([])
779 def linehit(self
, isdbl
):
781 files
= self
.w
.panes
.files
.getselectedobjects()
785 linenos
= self
.w
.panes
.gr
.breaks
.getselectedobjects()
789 editor
= self
.w
._parentwindow
.parent
.openscript(filename
, lineno
)
790 editor
.showbreakpoints(1)
793 def checkbuttons(self
):
794 if self
.w
.panes
.files
.getselection():
795 self
.w
.panes
.gr
.openbutton
.enable(1)
796 self
.w
._parentwindow
.setdefaultbutton(self
.w
.panes
.gr
.openbutton
)
797 if self
.w
._currentwidget
== self
.w
.panes
.files
:
798 if self
.w
.panes
.files
.getselection():
799 self
.w
.panes
.gr
.deletebutton
.enable(1)
801 self
.w
.panes
.gr
.deletebutton
.enable(0)
803 if self
.w
.panes
.gr
.breaks
.getselection():
804 self
.w
.panes
.gr
.deletebutton
.enable(1)
806 self
.w
.panes
.gr
.deletebutton
.enable(0)
808 self
.w
.panes
.gr
.openbutton
.enable(0)
809 self
.w
.panes
.gr
.deletebutton
.enable(0)
812 class TracingMonitor(W
.Widget
):
814 def __init__(self
, *args
, **kwargs
):
815 apply(W
.Widget
.__init
__, (self
,) + args
, kwargs
)
819 if hasattr(self
, "_parentwindow") and self
._parentwindow
is not None:
820 self
.state
= self
.state
% 2 + 1
827 if self
._parentwindow
:
834 def draw(self
, visRgn
= None):
836 Qd
.PaintOval(self
._bounds
)
838 Qd
.EraseOval(self
._bounds
)
843 def postmortem(exc_type
, exc_value
, tb
):
845 d
.postmortem(exc_type
, exc_value
, tb
)
847 def start(bottomframe
= None):
856 frame
= sys
.exc_traceback
.tb_frame
.f_back
859 def startfrombottom():
861 d
.start(_getbottomframe(), 1)
870 d
.set_continue_without_debugger()
872 def _getbottomframe():
877 frame
= sys
.exc_traceback
.tb_frame
879 if frame
.f_code
.co_name
== 'mainloop' or frame
.f_back
is None:
888 raise W
.AlertError
, "Can't debug in \"Optimize bytecode\" mode.\r(see \"Default startup options\" in EditPythonPreferences)"
890 if _debugger
is None:
891 _debugger
= Debugger()