10 from Carbon
import Evt
11 from Carbon
import Lists
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
68 from Carbon
import Menu
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, 64, 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, 24, 0, 16), self
.reason
)
169 bottom
.srctitle
= W
.TextBox((12, 44, 0, 16))
170 bottom
.buttons
= buttons
= W
.Group((12, 0, 0, 20))
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, 60, 16), "Step", self
.do_step
)
177 buttons
.stepinbutton
= W
.Button((249, 0, 60, 16), "Step in", self
.do_stepin
)
178 buttons
.stepoutbutton
= W
.Button((317, 0, 60, 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
, 'rU')
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
, 'rU')
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 data
= data
.replace('\n', '\r')
373 self
.w
.panes
.bottom
.src
.source
.set(data
, filename
)
375 self
.w
.panes
.bottom
.srctitle
.set('Source: ' + filename
+ ((lineno
> 0) and (' (line %d)' % lineno
) or ' '))
376 self
.goto_line(lineno
)
378 self
.showvars((frame
, lineno
))
380 def showvars(self
, (frame
, lineno
)):
381 if frame
.f_locals
is not frame
.f_globals
:
382 locals = frame
.f_locals
384 locals = {'Same as Globals':''}
386 for key
, value
in locals.items():
387 # empty key is magic for Python 1.4; '.' is magic for 1.5...
388 if not key
or key
[0] <> '.':
389 filteredlocals
[key
] = value
390 self
.w
.panes
.browserpanes
.locals.browser
.set(filteredlocals
)
391 self
.w
.panes
.browserpanes
.globals.browser
.set(frame
.f_globals
)
393 def showstack(self
, stackindex
):
395 for frame
, lineno
in self
.stack
[1:]:
396 filename
= frame
.f_code
.co_filename
398 filename
= _filenames
[filename
]
400 if filename
[:1] + filename
[-1:] <> '<>':
401 filename
= os
.path
.basename(filename
)
402 _filenames
[frame
.f_code
.co_filename
] = filename
403 funcname
= frame
.f_code
.co_name
405 funcname
= '<toplevel>'
406 stack
.append(filename
+ ': ' + funcname
)
407 if stack
<> self
.laststack
:
408 self
.w
.panes
.browserpanes
.stacklist
.stack
.set(stack
)
409 self
.laststack
= stack
410 sel
= [stackindex
- 1]
411 self
.w
.panes
.browserpanes
.stacklist
.stack
.setselection(sel
)
412 self
.laststacksel
= sel
414 def goto_line(self
, lineno
):
416 self
.w
.panes
.bottom
.src
.source
.selectline(lineno
- 1)
418 self
.w
.panes
.bottom
.src
.source
.setselection(0, 0)
422 # def user_call(self, frame, argument_list):
423 # self.reason = 'Calling'
424 # self.interaction(frame, None)
426 def user_line(self
, frame
):
427 # This function is called when we stop or break at this line
428 self
.reason
= 'Stopped'
429 self
.interaction(frame
, None)
431 def user_return(self
, frame
, return_value
):
432 # This function is called when a return trap is set here
433 fname
= frame
.f_code
.co_name
435 self
.reason
= 'Returning from %s()' % frame
.f_code
.co_name
436 frame
.f_locals
['__return__'] = return_value
437 elif frame
.f_back
is self
.botframe
:
440 self
.reason
= 'Returning'
441 self
.interaction(frame
, None, 1)
443 def user_exception(self
, frame
, (exc_type
, exc_value
, exc_traceback
)):
444 # This function is called when we stop or break at this line
445 self
.reason
= self
.formatexception(exc_type
, exc_value
)
446 self
.interaction(frame
, exc_traceback
)
448 def formatexception(self
, exc_type
, exc_value
):
449 if exc_type
== SyntaxError:
451 value
, (filename
, lineno
, charno
, line
) = exc_value
455 return str(exc_type
) + ': ' + str(value
)
456 if type(exc_type
) == types
.ClassType
:
457 nice
= exc_type
.__name
__
460 value
= str(exc_value
)
461 if exc_value
and value
:
462 nice
= nice
+ ": " + value
470 def setup(self
, f
, t
, isreturning
= 0):
472 self
.stack
, self
.curindex
= self
.get_stack(f
, t
)
473 self
.curframe
= self
.stack
[self
.curindex
- isreturning
][0]
475 def interaction(self
, frame
, traceback
, isreturning
= 0):
476 saveport
= Qd
.GetPort()
479 self
.setup(frame
, traceback
, isreturning
)
480 self
.setstate('stopped')
481 stackindex
= self
.curindex
483 if frame
.f_back
is not self
.botframe
:
484 stackindex
= stackindex
- 1
485 self
.showstack(stackindex
)
486 self
.showframe(stackindex
)
487 self
.w
.parent
.debugger_mainloop()
494 def trace_dispatch(self
, frame
, event
, arg
, TickCount
= Evt
.TickCount
):
495 if TickCount() - self
.tracingmonitortime
> 15:
496 self
.tracingmonitortime
= TickCount()
497 self
.w
.panes
.bottom
.tracingmonitor
.toggle()
500 if hasattr(MacOS
, 'EnableAppswitch'):
501 MacOS
.EnableAppswitch(0)
503 # returning None is not enough, a former BdbQuit exception
504 # might have been eaten by the print statement
507 return self
.dispatch_line(frame
)
509 return self
.dispatch_call(frame
, arg
)
510 if event
== 'return':
511 return self
.dispatch_return(frame
, arg
)
512 if event
== 'exception':
513 return self
.dispatch_exception(frame
, arg
)
514 print 'bdb.Bdb.dispatch: unknown debugging event:', repr(event
)
515 return self
.trace_dispatch
517 if hasattr(MacOS
, 'EnableAppswitch'):
518 MacOS
.EnableAppswitch(-1)
519 except KeyboardInterrupt:
521 return self
.trace_dispatch
523 if self
.continuewithoutdebugger
:
524 self
.clear_tracefuncs()
529 print 'XXX Exception during debugger interaction.', \
530 self
.formatexception(sys
.exc_type
, sys
.exc_value
)
532 traceback
.print_exc()
533 return self
.trace_dispatch
535 def dispatch_call(self
, frame
, arg
):
536 if not self
.tracemagic
and \
537 frame
.f_code
.co_name
[:2] == '__' == frame
.f_code
.co_name
[-2:] and \
538 frame
.f_code
.co_name
<> '__init__':
540 if self
.botframe
is None:
541 # First call of dispatch since reset()
542 self
.botframe
= frame
.f_back
# xxx !!! added f_back
543 return self
.trace_dispatch
544 if not (self
.stop_here(frame
) or self
.break_anywhere(frame
)):
545 # No need to trace this function
547 self
.user_call(frame
, arg
)
550 return self
.trace_dispatch
552 def set_continue(self
):
553 # Don't stop except at breakpoints or when finished
554 self
.stopframe
= self
.botframe
555 self
.returnframe
= None
557 # unlike in bdb/pdb, there's a chance that breakpoints change
558 # *while* a program (this program ;-) is running. It's actually quite likely.
559 # So we don't delete frame.f_trace until the bottom frame if there are no breakpoints.
561 def set_break(self
, filename
, lineno
):
562 if not self
.breaks
.has_key(filename
):
563 self
.breaks
[filename
] = []
564 list = self
.breaks
[filename
]
566 return 'There is already a breakpoint there!'
568 list.sort() # I want to keep them neatly sorted; easier for drawing
569 if hasattr(bdb
, "Breakpoint"):
571 bp
= bdb
.Breakpoint(filename
, lineno
, 0, None)
572 self
.update_breaks(filename
)
574 def clear_break(self
, filename
, lineno
):
575 bdb
.Bdb
.clear_break(self
, filename
, lineno
)
576 self
.update_breaks(filename
)
578 def clear_all_file_breaks(self
, filename
):
579 bdb
.Bdb
.clear_all_file_breaks(self
, filename
)
580 self
.update_breaks(filename
)
582 def clear_all_breaks(self
):
583 bdb
.Bdb
.clear_all_breaks(self
)
584 for editors
in self
.editors
.values():
585 for editor
in editors
:
586 editor
.drawbreakpoints()
590 def toggle_break(self
, filename
, lineno
):
591 if self
.get_break(filename
, lineno
):
592 self
.clear_break(filename
, lineno
)
594 self
.set_break(filename
, lineno
)
596 def clear_breaks_above(self
, filename
, above
):
597 if not self
.breaks
.has_key(filename
):
598 return 'There are no breakpoints in that file!'
599 for lineno
in self
.breaks
[filename
][:]:
601 self
.breaks
[filename
].remove(lineno
)
602 if not self
.breaks
[filename
]:
603 del self
.breaks
[filename
]
607 def update_breaks(self
, filename
):
608 if self
.breaksviewer
:
609 self
.breaksviewer
.update()
610 if self
.editors
.has_key(filename
):
611 for editor
in self
.editors
[filename
]:
612 if editor
._debugger
: # XXX
613 editor
.drawbreakpoints()
615 print 'xxx dead editor!'
617 def update_allbreaks(self
):
618 if self
.breaksviewer
:
619 self
.breaksviewer
.update()
620 for filename
in self
.breaks
.keys():
621 if self
.editors
.has_key(filename
):
622 for editor
in self
.editors
[filename
]:
623 if editor
._debugger
: # XXX
624 editor
.drawbreakpoints()
626 print 'xxx dead editor!'
628 def register_editor(self
, editor
, filename
):
631 if not self
.editors
.has_key(filename
):
632 self
.editors
[filename
] = [editor
]
633 elif editor
not in self
.editors
[filename
]:
634 self
.editors
[filename
].append(editor
)
636 def unregister_editor(self
, editor
, filename
):
640 self
.editors
[filename
].remove(editor
)
641 if not self
.editors
[filename
]:
642 del self
.editors
[filename
]
643 # if this was an untitled window, clear the breaks.
644 if filename
[:1] == '<' and filename
[-1:] == '>' and \
645 self
.breaks
.has_key(filename
):
646 self
.clear_all_file_breaks(filename
)
647 except (KeyError, ValueError):
651 class SourceViewer(W
.PyEditor
):
653 def __init__(self
, *args
, **kwargs
):
654 apply(W
.PyEditor
.__init
__, (self
,) + args
, kwargs
)
655 self
.bind('<click>', self
.clickintercept
)
657 def clickintercept(self
, point
, modifiers
):
658 if self
._parentwindow
._currentwidget
<> self
and not self
.pt_in_breaks(point
):
659 self
._parentwindow
.xxx___select(self
)
662 def _getviewrect(self
):
663 l
, t
, r
, b
= self
._bounds
665 return (l
+ 12, t
+ 2, r
- 1, b
- 2)
667 return (l
+ 5, t
+ 2, r
- 1, b
- 2)
669 def select(self
, onoff
, isclick
= 0):
670 if W
.SelectableWidget
.select(self
, onoff
):
674 # self.ted.WEActivate()
676 # self.ted.WEDeactivate()
677 self
.drawselframe(onoff
)
679 def drawselframe(self
, onoff
):
683 class BreakpointsViewer
:
685 def __init__(self
, debugger
):
686 self
.debugger
= debugger
687 self
.w
= W
.Window((300, 250), 'Breakpoints', minsize
= (200, 200))
688 self
.w
.panes
= W
.HorizontalPanes((8, 8, -8, -32), (0.3, 0.7))
689 self
.w
.panes
.files
= W
.List(None, callback
= self
.filehit
) #, flags = Lists.lOnlyOne)
690 self
.w
.panes
.gr
= W
.Group(None)
691 self
.w
.panes
.gr
.breaks
= W
.List((0, 0, -130, 0), callback
= self
.linehit
) #, flags = Lists.lOnlyOne)
692 self
.w
.panes
.gr
.openbutton
= W
.Button((-80, 4, 0, 16), 'View\xc9', self
.openbuttonhit
)
693 self
.w
.panes
.gr
.deletebutton
= W
.Button((-80, 28, 0, 16), 'Delete', self
.deletebuttonhit
)
695 self
.w
.bind('<close>', self
.close
)
696 self
.w
.bind('backspace', self
.w
.panes
.gr
.deletebutton
.push
)
700 self
.w
.panes
.gr
.openbutton
.enable(0)
701 self
.w
.panes
.gr
.deletebutton
.enable(0)
704 def deletebuttonhit(self
):
705 if self
.w
._currentwidget
== self
.w
.panes
.files
:
711 def del_number(self
):
712 if self
.curfile
is None:
714 sel
= self
.w
.panes
.gr
.breaks
.getselectedobjects()
716 self
.debugger
.clear_break(self
.curfile
, lineno
)
718 def del_filename(self
):
719 sel
= self
.w
.panes
.files
.getselectedobjects()
721 self
.debugger
.clear_all_file_breaks(filename
)
722 self
.debugger
.update_allbreaks()
725 files
= self
.debugger
.breaks
.keys()
727 self
.w
.panes
.files
.set(files
)
730 self
.debugger
.breaksviewer
= None
734 sel
= self
.w
.panes
.files
.getselectedobjects()
736 self
.w
.panes
.files
.setselectedobjects(sel
)
737 sel
= self
.w
.panes
.files
.getselection()
738 if len(sel
) == 0 and self
.curfile
:
739 self
.w
.panes
.files
.setselectedobjects([self
.curfile
])
745 def selectfile(self
, file):
746 self
.w
.panes
.files
.setselectedobjects([file])
749 def openbuttonhit(self
):
752 def filehit(self
, isdbl
):
753 sel
= self
.w
.panes
.files
.getselectedobjects()
757 if filename
== self
.curfile
:
758 linesel
= self
.w
.panes
.gr
.breaks
.getselectedobjects()
761 elif self
.w
.panes
.gr
.breaks
:
762 lineno
= self
.w
.panes
.gr
.breaks
[0]
763 editor
= self
.w
._parentwindow
.parent
.openscript(filename
, lineno
)
764 editor
.showbreakpoints(1)
768 filebreaks
= self
.debugger
.breaks
[file][:]
769 if self
.curfile
== file:
770 linesel
= self
.w
.panes
.gr
.breaks
.getselectedobjects()
771 self
.w
.panes
.gr
.breaks
.set(filebreaks
)
772 if self
.curfile
== file:
773 self
.w
.panes
.gr
.breaks
.setselectedobjects(linesel
)
778 self
.w
.panes
.gr
.breaks
.set([])
781 def linehit(self
, isdbl
):
783 files
= self
.w
.panes
.files
.getselectedobjects()
787 linenos
= self
.w
.panes
.gr
.breaks
.getselectedobjects()
791 editor
= self
.w
._parentwindow
.parent
.openscript(filename
, lineno
)
792 editor
.showbreakpoints(1)
795 def checkbuttons(self
):
796 if self
.w
.panes
.files
.getselection():
797 self
.w
.panes
.gr
.openbutton
.enable(1)
798 self
.w
._parentwindow
.setdefaultbutton(self
.w
.panes
.gr
.openbutton
)
799 if self
.w
._currentwidget
== self
.w
.panes
.files
:
800 if self
.w
.panes
.files
.getselection():
801 self
.w
.panes
.gr
.deletebutton
.enable(1)
803 self
.w
.panes
.gr
.deletebutton
.enable(0)
805 if self
.w
.panes
.gr
.breaks
.getselection():
806 self
.w
.panes
.gr
.deletebutton
.enable(1)
808 self
.w
.panes
.gr
.deletebutton
.enable(0)
810 self
.w
.panes
.gr
.openbutton
.enable(0)
811 self
.w
.panes
.gr
.deletebutton
.enable(0)
814 class TracingMonitor(W
.Widget
):
816 def __init__(self
, *args
, **kwargs
):
817 apply(W
.Widget
.__init
__, (self
,) + args
, kwargs
)
821 if hasattr(self
, "_parentwindow") and self
._parentwindow
is not None:
822 self
.state
= self
.state
% 2 + 1
829 if self
._parentwindow
:
836 def draw(self
, visRgn
= None):
838 Qd
.PaintOval(self
._bounds
)
840 Qd
.EraseOval(self
._bounds
)
845 def postmortem(exc_type
, exc_value
, tb
):
847 d
.postmortem(exc_type
, exc_value
, tb
)
849 def start(bottomframe
= None):
858 frame
= sys
.exc_traceback
.tb_frame
.f_back
861 def startfrombottom():
863 d
.start(_getbottomframe(), 1)
872 d
.set_continue_without_debugger()
874 def _getbottomframe():
879 frame
= sys
.exc_traceback
.tb_frame
881 if frame
.f_code
.co_name
== 'mainloop' or frame
.f_back
is None:
890 raise W
.AlertError
, "Can't debug in \"Optimize bytecode\" mode.\r(see \"Default startup options\" in EditPythonPreferences)"
892 if _debugger
is None:
893 _debugger
= Debugger()