| 
									
										
										
										
											1999-01-30 22:39:17 +00:00
										 |  |  | import sys | 
					
						
							|  |  |  | import bdb | 
					
						
							|  |  |  | import types | 
					
						
							|  |  |  | import os | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | import W | 
					
						
							|  |  |  | import WASTEconst | 
					
						
							|  |  |  | import PyBrowser | 
					
						
							| 
									
										
										
										
											2001-08-25 12:15:04 +00:00
										 |  |  | from Carbon import Qd | 
					
						
							|  |  |  | from Carbon import Evt | 
					
						
							|  |  |  | from Carbon import Lists | 
					
						
							| 
									
										
										
										
											1999-01-30 22:39:17 +00:00
										 |  |  | import MacOS | 
					
						
							|  |  |  | _filenames = {} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | SIMPLE_TYPES = ( | 
					
						
							|  |  |  | 	types.NoneType, | 
					
						
							|  |  |  | 	types.IntType, | 
					
						
							|  |  |  | 	types.LongType, | 
					
						
							|  |  |  | 	types.FloatType, | 
					
						
							|  |  |  | 	types.ComplexType, | 
					
						
							|  |  |  | 	types.StringType | 
					
						
							|  |  |  | ) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | class Debugger(bdb.Bdb): | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	def __init__(self, title = 'Debugger'): | 
					
						
							|  |  |  | 		bdb.Bdb.__init__(self) | 
					
						
							|  |  |  | 		self.closed = 1 | 
					
						
							|  |  |  | 		self.title = title | 
					
						
							|  |  |  | 		self.breaksviewer = None | 
					
						
							|  |  |  | 		self.reset() | 
					
						
							|  |  |  | 		self.tracing = 0 | 
					
						
							|  |  |  | 		self.tracingmonitortime = Evt.TickCount() | 
					
						
							|  |  |  | 		self.editors = {} | 
					
						
							|  |  |  | 		 | 
					
						
							|  |  |  | 		prefs = W.getapplication().getprefs() | 
					
						
							|  |  |  | 		if prefs.debugger: | 
					
						
							|  |  |  | 			for file, breaks in prefs.debugger.breaks.items(): | 
					
						
							|  |  |  | 				for b in breaks: | 
					
						
							|  |  |  | 					self.set_break(file, b) | 
					
						
							|  |  |  | 			self.bounds, self.horpanes, self.verpanes = prefs.debugger.windowsettings | 
					
						
							|  |  |  | 			self.tracemagic = prefs.debugger.tracemagic | 
					
						
							|  |  |  | 		else: | 
					
						
							|  |  |  | 			self.breaks = {} | 
					
						
							|  |  |  | 			self.horpanes = (0.4, 0.6) | 
					
						
							|  |  |  | 			self.verpanes = (0.3, 0.35, 0.35) | 
					
						
							|  |  |  | 			self.bounds = (600, 400) | 
					
						
							|  |  |  | 			self.tracemagic = 0 | 
					
						
							|  |  |  | 		self.laststacksel = None | 
					
						
							|  |  |  | 	 | 
					
						
							| 
									
										
										
										
											2001-06-20 19:57:55 +00:00
										 |  |  | 	def canonic(self, filename): | 
					
						
							|  |  |  | 		# override: the provided canonic() method breaks our | 
					
						
							|  |  |  | 		# file-less Untitled windows | 
					
						
							|  |  |  | 		return filename | 
					
						
							|  |  |  | 	 | 
					
						
							| 
									
										
										
										
											1999-01-30 22:39:17 +00:00
										 |  |  | 	def reset(self): | 
					
						
							|  |  |  | 		self.currentframe = None | 
					
						
							|  |  |  | 		self.file = None | 
					
						
							|  |  |  | 		self.laststack = None | 
					
						
							|  |  |  | 		self.reason = 'Not running' | 
					
						
							|  |  |  | 		self.continuewithoutdebugger = 0 | 
					
						
							|  |  |  | 		bdb.Bdb.reset(self) | 
					
						
							|  |  |  | 		self.forget() | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	def start(self, bottomframe = None, running = 0): | 
					
						
							|  |  |  | 		W.getapplication().DebuggerQuit = bdb.BdbQuit | 
					
						
							| 
									
										
										
										
											2001-08-25 12:15:04 +00:00
										 |  |  | 		from Carbon import Menu | 
					
						
							| 
									
										
										
										
											1999-01-30 22:39:17 +00:00
										 |  |  | 		Menu.HiliteMenu(0) | 
					
						
							|  |  |  | 		if self.closed: | 
					
						
							|  |  |  | 			self.setupwidgets(self.title) | 
					
						
							|  |  |  | 			self.closed = 0 | 
					
						
							|  |  |  | 		if not self.w.parent.debugger_quitting: | 
					
						
							|  |  |  | 			self.w.select() | 
					
						
							|  |  |  | 			raise W.AlertError, 'There is another debugger session busy.' | 
					
						
							|  |  |  | 		self.reset() | 
					
						
							|  |  |  | 		self.botframe = bottomframe | 
					
						
							|  |  |  | 		if running: | 
					
						
							|  |  |  | 			self.set_continue() | 
					
						
							| 
									
										
										
										
											2001-06-19 21:37:33 +00:00
										 |  |  | 			self.reason = 'Running\xc9' | 
					
						
							| 
									
										
										
										
											1999-01-30 22:39:17 +00:00
										 |  |  | 			self.setstate('running') | 
					
						
							|  |  |  | 		else: | 
					
						
							|  |  |  | 			self.set_step() | 
					
						
							|  |  |  | 			self.reason = 'stopped' | 
					
						
							|  |  |  | 			self.setstate('stopped') | 
					
						
							|  |  |  | 		sys.settrace(self.trace_dispatch) | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	def stop(self): | 
					
						
							|  |  |  | 		self.set_quit() | 
					
						
							|  |  |  | 		if self.w.parent: | 
					
						
							|  |  |  | 			self.exit_mainloop() | 
					
						
							|  |  |  | 			self.resetwidgets() | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	def set_continue_without_debugger(self): | 
					
						
							|  |  |  | 		sys.settrace(None) | 
					
						
							|  |  |  | 		self.set_quit() | 
					
						
							|  |  |  | 		self.clear_tracefuncs() | 
					
						
							|  |  |  | 		self.continuewithoutdebugger = 1 | 
					
						
							| 
									
										
										
										
											1999-09-26 12:11:50 +00:00
										 |  |  | 		if hasattr(self, "w") and self.w.parent: | 
					
						
							| 
									
										
										
										
											1999-01-30 22:39:17 +00:00
										 |  |  | 			self.exit_mainloop() | 
					
						
							|  |  |  | 			self.resetwidgets() | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	def clear_tracefuncs(self): | 
					
						
							|  |  |  | 		try: | 
					
						
							|  |  |  | 			raise 'spam' | 
					
						
							|  |  |  | 		except: | 
					
						
							|  |  |  | 			pass | 
					
						
							|  |  |  | 		frame = sys.exc_traceback.tb_frame | 
					
						
							|  |  |  | 		while frame is not None: | 
					
						
							|  |  |  | 			del frame.f_trace | 
					
						
							|  |  |  | 			frame = frame.f_back | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	def postmortem(self, exc_type, exc_value, traceback): | 
					
						
							|  |  |  | 		if self.closed: | 
					
						
							|  |  |  | 			self.setupwidgets(self.title) | 
					
						
							|  |  |  | 			self.closed = 0 | 
					
						
							|  |  |  | 		if not self.w.parent.debugger_quitting: | 
					
						
							|  |  |  | 			raise W.AlertError, 'There is another debugger session busy.' | 
					
						
							|  |  |  | 		self.reset() | 
					
						
							|  |  |  | 		if traceback: | 
					
						
							|  |  |  | 			self.botframe = traceback.tb_frame | 
					
						
							|  |  |  | 			while traceback.tb_next <> None: | 
					
						
							|  |  |  | 				traceback = traceback.tb_next | 
					
						
							|  |  |  | 			frame = traceback.tb_frame | 
					
						
							|  |  |  | 		else: | 
					
						
							|  |  |  | 			self.botframe = None | 
					
						
							|  |  |  | 			frame = None | 
					
						
							|  |  |  | 		self.w.panes.bottom.buttons.killbutton.enable(1) | 
					
						
							|  |  |  | 		self.reason = '(dead) ' + self.formatexception(exc_type, exc_value) | 
					
						
							|  |  |  | 		self.w.select() | 
					
						
							|  |  |  | 		self.setup(frame, traceback) | 
					
						
							|  |  |  | 		self.setstate('dead') | 
					
						
							|  |  |  | 		self.showstack(self.curindex) | 
					
						
							|  |  |  | 		self.showframe(self.curindex) | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	def setupwidgets(self, title): | 
					
						
							|  |  |  | 		self.w = w = W.Window(self.bounds, title, minsize = (500, 300)) | 
					
						
							|  |  |  | 		 | 
					
						
							|  |  |  | 		w.panes = W.HorizontalPanes((8, 4, -8, -8), self.horpanes) | 
					
						
							|  |  |  | 		 | 
					
						
							|  |  |  | 		w.panes.browserpanes = browserpanes = W.VerticalPanes(None, self.verpanes) | 
					
						
							|  |  |  | 		 | 
					
						
							|  |  |  | 		browserpanes.stacklist = W.Group(None) | 
					
						
							|  |  |  | 		browserpanes.stacklist.title = W.TextBox((4, 0, 0, 12), 'Stack') | 
					
						
							|  |  |  | 		browserpanes.stacklist.stack = W.List((0, 16, 0, 0), callback = self.do_stack, flags = Lists.lOnlyOne) | 
					
						
							|  |  |  | 		 | 
					
						
							|  |  |  | 		browserpanes.locals = W.Group(None) | 
					
						
							|  |  |  | 		browserpanes.locals.title = W.TextBox((4, 0, 0, 12), 'Local variables') | 
					
						
							|  |  |  | 		browserpanes.locals.browser = PyBrowser.BrowserWidget((0, 16, 0, 0)) | 
					
						
							|  |  |  | 		 | 
					
						
							|  |  |  | 		browserpanes.globals = W.Group(None) | 
					
						
							|  |  |  | 		browserpanes.globals.title = W.TextBox((4, 0, 0, 12), 'Global variables') | 
					
						
							|  |  |  | 		browserpanes.globals.browser = PyBrowser.BrowserWidget((0, 16, 0, 0)) | 
					
						
							|  |  |  | 		 | 
					
						
							|  |  |  | 		w.panes.bottom = bottom = W.Group(None) | 
					
						
							|  |  |  | 		bottom.src = src = W.Group((0, 52, 0, 0)) | 
					
						
							|  |  |  | 		source = SourceViewer((1, 1, -15, -15), readonly = 1, debugger = self) | 
					
						
							|  |  |  | 		src.optionsmenu = W.PopupMenu((-16, 0, 16, 16), []) | 
					
						
							|  |  |  | 		src.optionsmenu.bind('<click>', self.makeoptionsmenu) | 
					
						
							|  |  |  | 		 | 
					
						
							|  |  |  | 		src._barx = W.Scrollbar((0, -16, -15, 16), source.hscroll, max = 32767) | 
					
						
							|  |  |  | 		src._bary = W.Scrollbar((-16, 15, 16, -15), source.vscroll, max = 32767) | 
					
						
							|  |  |  | 		src.source = source | 
					
						
							|  |  |  | 		src.frame = W.Frame((0, 0, -15, -15)) | 
					
						
							|  |  |  | 		 | 
					
						
							|  |  |  | 		bottom.tracingmonitor = TracingMonitor((0, 23, 6, 6)) | 
					
						
							|  |  |  | 		bottom.state = W.TextBox((12, 20, 0, 16), self.reason) | 
					
						
							|  |  |  | 		 | 
					
						
							|  |  |  | 		bottom.srctitle = W.TextBox((12, 36, 0, 14)) | 
					
						
							|  |  |  | 		bottom.buttons = buttons = W.Group((12, 0, 0, 16)) | 
					
						
							|  |  |  | 		 | 
					
						
							|  |  |  | 		buttons.runbutton = W.Button((0, 0, 50, 16), "Run", self.do_run) | 
					
						
							|  |  |  | 		buttons.stopbutton = W.Button((58, 0, 50, 16), "Stop", self.do_stop) | 
					
						
							|  |  |  | 		buttons.killbutton = W.Button((116, 0, 50, 16), "Kill", self.do_kill) | 
					
						
							|  |  |  | 		buttons.line = W.VerticalLine((173, 0, 0, 0)) | 
					
						
							|  |  |  | 		buttons.stepbutton = W.Button((181, 0, 50, 16), "Step", self.do_step) | 
					
						
							|  |  |  | 		buttons.stepinbutton = W.Button((239, 0, 50, 16), "Step in", self.do_stepin) | 
					
						
							|  |  |  | 		buttons.stepoutbutton = W.Button((297, 0, 50, 16), "Step out", self.do_stepout) | 
					
						
							|  |  |  | 		 | 
					
						
							|  |  |  | 		w.bind('cmdr', buttons.runbutton.push) | 
					
						
							|  |  |  | 		w.bind('cmd.', buttons.stopbutton.push) | 
					
						
							|  |  |  | 		w.bind('cmdk', buttons.killbutton.push) | 
					
						
							|  |  |  | 		w.bind('cmds', buttons.stepbutton.push) | 
					
						
							|  |  |  | 		w.bind('cmdt', buttons.stepinbutton.push) | 
					
						
							|  |  |  | 		w.bind('cmdu', buttons.stepoutbutton.push) | 
					
						
							|  |  |  | 		 | 
					
						
							|  |  |  | 		w.bind('<close>', self.close) | 
					
						
							|  |  |  | 		 | 
					
						
							|  |  |  | 		w.open() | 
					
						
							|  |  |  | 		w.xxx___select(w.panes.bottom.src.source) | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	def makeoptionsmenu(self): | 
					
						
							|  |  |  | 		options = [('Clear breakpoints', self.w.panes.bottom.src.source.clearbreakpoints),  | 
					
						
							|  |  |  | 				('Clear all breakpoints', self.clear_all_breaks), | 
					
						
							| 
									
										
										
										
											2001-06-19 21:37:33 +00:00
										 |  |  | 				('Edit breakpoints\xc9', self.edit_breaks), '-', | 
					
						
							| 
									
										
										
										
											1999-01-30 22:39:17 +00:00
										 |  |  | 				(self.tracemagic and  | 
					
						
							|  |  |  | 					'Disable __magic__ tracing' or 'Enable __magic__ tracing', self.togglemagic)] | 
					
						
							|  |  |  | 		self.w.panes.bottom.src.optionsmenu.set(options) | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	def edit_breaks(self): | 
					
						
							|  |  |  | 		if self.breaksviewer: | 
					
						
							|  |  |  | 			self.breaksviewer.select() | 
					
						
							|  |  |  | 		else: | 
					
						
							|  |  |  | 			self.breaksviewer = BreakpointsViewer(self) | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	def togglemagic(self): | 
					
						
							|  |  |  | 		self.tracemagic = not self.tracemagic | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	def setstate(self, state): | 
					
						
							|  |  |  | 		self.w.panes.bottom.tracingmonitor.reset() | 
					
						
							|  |  |  | 		self.w.panes.bottom.state.set(self.reason) | 
					
						
							|  |  |  | 		buttons = self.w.panes.bottom.buttons | 
					
						
							|  |  |  | 		if state == 'stopped': | 
					
						
							|  |  |  | 			buttons.runbutton.enable(1) | 
					
						
							|  |  |  | 			buttons.stopbutton.enable(0) | 
					
						
							|  |  |  | 			buttons.killbutton.enable(1) | 
					
						
							|  |  |  | 			buttons.stepbutton.enable(1) | 
					
						
							|  |  |  | 			buttons.stepinbutton.enable(1) | 
					
						
							|  |  |  | 			buttons.stepoutbutton.enable(1) | 
					
						
							|  |  |  | 		elif state == 'running': | 
					
						
							|  |  |  | 			buttons.runbutton.enable(0) | 
					
						
							|  |  |  | 			buttons.stopbutton.enable(1) | 
					
						
							|  |  |  | 			buttons.killbutton.enable(1) | 
					
						
							|  |  |  | 			buttons.stepbutton.enable(0) | 
					
						
							|  |  |  | 			buttons.stepinbutton.enable(0) | 
					
						
							|  |  |  | 			buttons.stepoutbutton.enable(0) | 
					
						
							|  |  |  | 		elif state == 'idle': | 
					
						
							|  |  |  | 			buttons.runbutton.enable(0) | 
					
						
							|  |  |  | 			buttons.stopbutton.enable(0) | 
					
						
							|  |  |  | 			buttons.killbutton.enable(0) | 
					
						
							|  |  |  | 			buttons.stepbutton.enable(0) | 
					
						
							|  |  |  | 			buttons.stepinbutton.enable(0) | 
					
						
							|  |  |  | 			buttons.stepoutbutton.enable(0) | 
					
						
							|  |  |  | 		elif state == 'dead': | 
					
						
							|  |  |  | 			buttons.runbutton.enable(0) | 
					
						
							|  |  |  | 			buttons.stopbutton.enable(0) | 
					
						
							|  |  |  | 			buttons.killbutton.enable(1) | 
					
						
							|  |  |  | 			buttons.stepbutton.enable(0) | 
					
						
							|  |  |  | 			buttons.stepinbutton.enable(0) | 
					
						
							|  |  |  | 			buttons.stepoutbutton.enable(0) | 
					
						
							|  |  |  | 		else: | 
					
						
							|  |  |  | 			print 'unknown state:', state | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	def resetwidgets(self): | 
					
						
							|  |  |  | 		self.reason = '' | 
					
						
							|  |  |  | 		self.w.panes.bottom.srctitle.set('') | 
					
						
							|  |  |  | 		self.w.panes.bottom.src.source.set('') | 
					
						
							|  |  |  | 		self.w.panes.browserpanes.stacklist.stack.set([]) | 
					
						
							|  |  |  | 		self.w.panes.browserpanes.locals.browser.set({}) | 
					
						
							|  |  |  | 		self.w.panes.browserpanes.globals.browser.set({}) | 
					
						
							|  |  |  | 		self.setstate('idle') | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	# W callbacks | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	def close(self): | 
					
						
							|  |  |  | 		self.set_quit() | 
					
						
							|  |  |  | 		self.exit_mainloop() | 
					
						
							|  |  |  | 		self.closed = 1 | 
					
						
							|  |  |  | 		 | 
					
						
							|  |  |  | 		self.unregister_editor(self.w.panes.bottom.src.source,  | 
					
						
							|  |  |  | 				self.w.panes.bottom.src.source.file) | 
					
						
							|  |  |  | 		self.horpanes = self.w.panes.getpanesizes() | 
					
						
							|  |  |  | 		self.verpanes = self.w.panes.browserpanes.getpanesizes() | 
					
						
							|  |  |  | 		self.bounds = self.w.getbounds() | 
					
						
							|  |  |  | 		prefs = W.getapplication().getprefs() | 
					
						
							|  |  |  | 		prefs.debugger.breaks = self.breaks | 
					
						
							|  |  |  | 		prefs.debugger.windowsettings = self.bounds, self.horpanes, self.verpanes | 
					
						
							|  |  |  | 		prefs.debugger.tracemagic = self.tracemagic | 
					
						
							|  |  |  | 		prefs.save() | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	# stack list callback | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	def do_stack(self, isdbl): | 
					
						
							|  |  |  | 		sel = self.w.panes.browserpanes.stacklist.stack.getselection() | 
					
						
							|  |  |  | 		if isdbl: | 
					
						
							|  |  |  | 			if sel: | 
					
						
							|  |  |  | 				frame, lineno = self.stack[sel[0] + 1] | 
					
						
							|  |  |  | 				filename = frame.f_code.co_filename | 
					
						
							|  |  |  | 				editor = self.w._parentwindow.parent.openscript(filename, lineno) | 
					
						
							|  |  |  | 				if self.breaks.has_key(filename): | 
					
						
							|  |  |  | 					editor.showbreakpoints(1) | 
					
						
							|  |  |  | 		else: | 
					
						
							|  |  |  | 			if sel and sel <> self.laststacksel: | 
					
						
							|  |  |  | 				self.showframe(sel[0] + 1) | 
					
						
							|  |  |  | 			self.laststacksel = sel | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	def geteditor(self, filename): | 
					
						
							|  |  |  | 		if filename[:1] == '<' and filename[-1:] == '>': | 
					
						
							|  |  |  | 			editor = W.getapplication().getscript(filename[1:-1]) | 
					
						
							|  |  |  | 		else: | 
					
						
							|  |  |  | 			editor = W.getapplication().getscript(filename) | 
					
						
							|  |  |  | 		return editor | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	# button callbacks | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	def do_run(self): | 
					
						
							|  |  |  | 		self.running() | 
					
						
							|  |  |  | 		self.set_continue() | 
					
						
							|  |  |  | 		self.exit_mainloop() | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	def do_stop(self): | 
					
						
							|  |  |  | 		self.set_step() | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	def do_kill(self): | 
					
						
							|  |  |  | 		self.set_quit() | 
					
						
							|  |  |  | 		self.exit_mainloop() | 
					
						
							|  |  |  | 		self.resetwidgets() | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	def do_step(self): | 
					
						
							|  |  |  | 		self.running() | 
					
						
							|  |  |  | 		self.set_next(self.curframe) | 
					
						
							|  |  |  | 		self.exit_mainloop() | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	def do_stepin(self): | 
					
						
							|  |  |  | 		self.running() | 
					
						
							|  |  |  | 		self.set_step() | 
					
						
							|  |  |  | 		self.exit_mainloop() | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	def do_stepout(self): | 
					
						
							|  |  |  | 		self.running() | 
					
						
							|  |  |  | 		self.set_return(self.curframe) | 
					
						
							|  |  |  | 		self.exit_mainloop() | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	def running(self): | 
					
						
							|  |  |  | 		W.SetCursor('watch') | 
					
						
							| 
									
										
										
										
											2001-06-19 21:37:33 +00:00
										 |  |  | 		self.reason = 'Running\xc9' | 
					
						
							| 
									
										
										
										
											1999-01-30 22:39:17 +00:00
										 |  |  | 		self.setstate('running') | 
					
						
							|  |  |  | 		#self.w.panes.bottom.src.source.set('') | 
					
						
							|  |  |  | 		#self.w.panes.browserpanes.stacklist.stack.set([]) | 
					
						
							|  |  |  | 		#self.w.panes.browserpanes.locals.browser.set({}) | 
					
						
							|  |  |  | 		#self.w.panes.browserpanes.globals.browser.set({}) | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	def exit_mainloop(self): | 
					
						
							|  |  |  | 		self.w.parent.debugger_quitting = 1 | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	# | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	def showframe(self, stackindex): | 
					
						
							|  |  |  | 		(frame, lineno) = self.stack[stackindex] | 
					
						
							|  |  |  | 		W.SetCursor('watch') | 
					
						
							|  |  |  | 		filename = frame.f_code.co_filename | 
					
						
							|  |  |  | 		if filename <> self.file: | 
					
						
							|  |  |  | 			editor = self.geteditor(filename) | 
					
						
							|  |  |  | 			if editor: | 
					
						
							|  |  |  | 				self.w.panes.bottom.src.source.set(editor.get(), filename) | 
					
						
							|  |  |  | 			else: | 
					
						
							|  |  |  | 				try: | 
					
						
							|  |  |  | 					f = open(filename, 'rb') | 
					
						
							|  |  |  | 					data = f.read() | 
					
						
							|  |  |  | 					f.close() | 
					
						
							|  |  |  | 				except IOError: | 
					
						
							|  |  |  | 					if filename[-3:] == '.py': | 
					
						
							|  |  |  | 						import imp | 
					
						
							|  |  |  | 						modname = os.path.basename(filename)[:-3] | 
					
						
							|  |  |  | 						try: | 
					
						
							|  |  |  | 							f, filename, (suff, mode, dummy) = imp.find_module(modname) | 
					
						
							|  |  |  | 						except ImportError: | 
					
						
							| 
									
										
										
										
											2001-06-19 21:37:33 +00:00
										 |  |  | 							self.w.panes.bottom.src.source.set("can't find file") | 
					
						
							| 
									
										
										
										
											1999-01-30 22:39:17 +00:00
										 |  |  | 						else: | 
					
						
							|  |  |  | 							if f: | 
					
						
							|  |  |  | 								f.close() | 
					
						
							|  |  |  | 							if f and suff == '.py': | 
					
						
							|  |  |  | 								f = open(filename, 'rb') | 
					
						
							|  |  |  | 								data = f.read() | 
					
						
							|  |  |  | 								f.close() | 
					
						
							|  |  |  | 								self.w.panes.bottom.src.source.set(data, filename) | 
					
						
							|  |  |  | 							else: | 
					
						
							| 
									
										
										
										
											2001-06-19 21:37:33 +00:00
										 |  |  | 								self.w.panes.bottom.src.source.set("can't find file") | 
					
						
							| 
									
										
										
										
											1999-01-30 22:39:17 +00:00
										 |  |  | 					else: | 
					
						
							| 
									
										
										
										
											2001-06-19 21:37:33 +00:00
										 |  |  | 						self.w.panes.bottom.src.source.set("can't find file") | 
					
						
							| 
									
										
										
										
											1999-01-30 22:39:17 +00:00
										 |  |  | 				else: | 
					
						
							|  |  |  | 					self.w.panes.bottom.src.source.set(data, filename) | 
					
						
							|  |  |  | 			self.file = filename | 
					
						
							|  |  |  | 		self.w.panes.bottom.srctitle.set('Source: ' + filename + ((lineno > 0) and (' (line %d)' % lineno) or ' ')) | 
					
						
							|  |  |  | 		self.goto_line(lineno) | 
					
						
							|  |  |  | 		self.lineno = lineno | 
					
						
							|  |  |  | 		self.showvars((frame, lineno)) | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	def showvars(self, (frame, lineno)): | 
					
						
							|  |  |  | 		if frame.f_locals is not frame.f_globals: | 
					
						
							|  |  |  | 			locals = frame.f_locals | 
					
						
							|  |  |  | 		else: | 
					
						
							|  |  |  | 			locals = {'Same as Globals':''} | 
					
						
							|  |  |  | 		filteredlocals = {} | 
					
						
							|  |  |  | 		for key, value in locals.items(): | 
					
						
							|  |  |  | 			# empty key is magic for Python 1.4; '.' is magic for 1.5... | 
					
						
							|  |  |  | 			if not key or key[0] <> '.': | 
					
						
							|  |  |  | 				filteredlocals[key] = value | 
					
						
							|  |  |  | 		self.w.panes.browserpanes.locals.browser.set(filteredlocals) | 
					
						
							|  |  |  | 		self.w.panes.browserpanes.globals.browser.set(frame.f_globals) | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	def showstack(self, stackindex): | 
					
						
							|  |  |  | 		stack = [] | 
					
						
							|  |  |  | 		for frame, lineno in self.stack[1:]: | 
					
						
							|  |  |  | 			filename = frame.f_code.co_filename | 
					
						
							|  |  |  | 			try: | 
					
						
							|  |  |  | 				filename = _filenames[filename] | 
					
						
							|  |  |  | 			except KeyError: | 
					
						
							|  |  |  | 				if filename[:1] + filename[-1:] <> '<>': | 
					
						
							|  |  |  | 					filename = os.path.basename(filename) | 
					
						
							|  |  |  | 				_filenames[frame.f_code.co_filename] = filename | 
					
						
							|  |  |  | 			funcname = frame.f_code.co_name | 
					
						
							|  |  |  | 			if funcname == '?': | 
					
						
							|  |  |  | 				funcname = '<toplevel>' | 
					
						
							|  |  |  | 			stack.append(filename + ': ' + funcname) | 
					
						
							|  |  |  | 		if stack <> self.laststack: | 
					
						
							|  |  |  | 			self.w.panes.browserpanes.stacklist.stack.set(stack) | 
					
						
							|  |  |  | 			self.laststack = stack | 
					
						
							|  |  |  | 		sel = [stackindex - 1] | 
					
						
							|  |  |  | 		self.w.panes.browserpanes.stacklist.stack.setselection(sel) | 
					
						
							|  |  |  | 		self.laststacksel = sel | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	def goto_line(self, lineno): | 
					
						
							|  |  |  | 		if lineno > 0: | 
					
						
							|  |  |  | 			self.w.panes.bottom.src.source.selectline(lineno - 1) | 
					
						
							|  |  |  | 		else: | 
					
						
							|  |  |  | 			self.w.panes.bottom.src.source.setselection(0, 0) | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	# bdb entry points | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | #	def user_call(self, frame, argument_list): | 
					
						
							|  |  |  | #		self.reason = 'Calling' | 
					
						
							|  |  |  | #		self.interaction(frame, None) | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	def user_line(self, frame): | 
					
						
							|  |  |  | 		# This function is called when we stop or break at this line | 
					
						
							|  |  |  | 		self.reason = 'Stopped' | 
					
						
							|  |  |  | 		self.interaction(frame, None) | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	def user_return(self, frame, return_value): | 
					
						
							|  |  |  | 		# This function is called when a return trap is set here | 
					
						
							|  |  |  | 		fname = frame.f_code.co_name | 
					
						
							|  |  |  | 		if fname <> '?': | 
					
						
							|  |  |  | 			self.reason = 'Returning from %s()' % frame.f_code.co_name | 
					
						
							|  |  |  | 			frame.f_locals['__return__'] = return_value | 
					
						
							|  |  |  | 		elif frame.f_back is self.botframe: | 
					
						
							|  |  |  | 			self.reason = 'Done' | 
					
						
							|  |  |  | 		else: | 
					
						
							|  |  |  | 			self.reason = 'Returning' | 
					
						
							|  |  |  | 		self.interaction(frame, None, 1) | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	def user_exception(self, frame, (exc_type, exc_value, exc_traceback)): | 
					
						
							|  |  |  | 		# This function is called when we stop or break at this line | 
					
						
							|  |  |  | 		self.reason = self.formatexception(exc_type, exc_value) | 
					
						
							|  |  |  | 		self.interaction(frame, exc_traceback) | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	def formatexception(self, exc_type, exc_value): | 
					
						
							|  |  |  | 		if exc_type == SyntaxError: | 
					
						
							|  |  |  | 			try: | 
					
						
							|  |  |  | 				value, (filename, lineno, charno, line) = exc_value | 
					
						
							|  |  |  | 			except: | 
					
						
							|  |  |  | 				pass | 
					
						
							|  |  |  | 			else: | 
					
						
							|  |  |  | 				return str(exc_type) + ': ' + str(value) | 
					
						
							|  |  |  | 		if type(exc_type) == types.ClassType: | 
					
						
							|  |  |  | 			nice = exc_type.__name__ | 
					
						
							|  |  |  | 		else: | 
					
						
							|  |  |  | 			nice = str(exc_type) | 
					
						
							|  |  |  | 		value = str(exc_value) | 
					
						
							|  |  |  | 		if exc_value and value: | 
					
						
							|  |  |  | 			nice = nice + ": " + value | 
					
						
							|  |  |  | 		return nice | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	def forget(self): | 
					
						
							|  |  |  | 		self.stack = [] | 
					
						
							|  |  |  | 		self.curindex = 0 | 
					
						
							|  |  |  | 		self.curframe = None | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	def setup(self, f, t, isreturning = 0): | 
					
						
							|  |  |  | 		self.forget() | 
					
						
							|  |  |  | 		self.stack, self.curindex = self.get_stack(f, t) | 
					
						
							|  |  |  | 		self.curframe = self.stack[self.curindex - isreturning][0] | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	def interaction(self, frame, traceback, isreturning = 0): | 
					
						
							|  |  |  | 		saveport = Qd.GetPort() | 
					
						
							|  |  |  | 		self.w.select() | 
					
						
							|  |  |  | 		try: | 
					
						
							|  |  |  | 			self.setup(frame, traceback, isreturning) | 
					
						
							|  |  |  | 			self.setstate('stopped') | 
					
						
							|  |  |  | 			stackindex = self.curindex | 
					
						
							|  |  |  | 			if isreturning: | 
					
						
							|  |  |  | 				if frame.f_back is not self.botframe: | 
					
						
							|  |  |  | 					stackindex = stackindex - 1 | 
					
						
							|  |  |  | 			self.showstack(stackindex) | 
					
						
							|  |  |  | 			self.showframe(stackindex) | 
					
						
							|  |  |  | 			self.w.parent.debugger_mainloop() | 
					
						
							|  |  |  | 			self.forget() | 
					
						
							|  |  |  | 		finally: | 
					
						
							|  |  |  | 			Qd.SetPort(saveport) | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	# bdb customization | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	def trace_dispatch(self, frame, event, arg, TickCount = Evt.TickCount): | 
					
						
							|  |  |  | 		if TickCount() - self.tracingmonitortime > 15: | 
					
						
							|  |  |  | 			self.tracingmonitortime = TickCount() | 
					
						
							|  |  |  | 			self.w.panes.bottom.tracingmonitor.toggle() | 
					
						
							|  |  |  | 		try: | 
					
						
							|  |  |  | 			try: | 
					
						
							|  |  |  | 				MacOS.EnableAppswitch(0) | 
					
						
							|  |  |  | 				if self.quitting: | 
					
						
							|  |  |  | 					# returning None is not enough, a former BdbQuit exception | 
					
						
							|  |  |  | 					# might have been eaten by the print statement | 
					
						
							|  |  |  | 					raise bdb.BdbQuit | 
					
						
							|  |  |  | 				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 'bdb.Bdb.dispatch: unknown debugging event:', `event` | 
					
						
							|  |  |  | 				return self.trace_dispatch | 
					
						
							|  |  |  | 			finally: | 
					
						
							|  |  |  | 				MacOS.EnableAppswitch(-1) | 
					
						
							|  |  |  | 		except KeyboardInterrupt: | 
					
						
							|  |  |  | 			self.set_step() | 
					
						
							|  |  |  | 			return self.trace_dispatch | 
					
						
							|  |  |  | 		except bdb.BdbQuit: | 
					
						
							|  |  |  | 			if self.continuewithoutdebugger: | 
					
						
							|  |  |  | 				self.clear_tracefuncs() | 
					
						
							|  |  |  | 				return | 
					
						
							|  |  |  | 			else: | 
					
						
							|  |  |  | 				raise bdb.BdbQuit | 
					
						
							|  |  |  | 		except: | 
					
						
							|  |  |  | 			print 'XXX Exception during debugger interaction.', \ | 
					
						
							|  |  |  | 					self.formatexception(sys.exc_type, sys.exc_value) | 
					
						
							|  |  |  | 			import traceback | 
					
						
							|  |  |  | 			traceback.print_exc() | 
					
						
							|  |  |  | 			return self.trace_dispatch | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	def dispatch_call(self, frame, arg): | 
					
						
							|  |  |  | 		if not self.tracemagic and \ | 
					
						
							|  |  |  | 				frame.f_code.co_name[:2] == '__' == frame.f_code.co_name[-2:] and \ | 
					
						
							|  |  |  | 				frame.f_code.co_name <> '__init__': | 
					
						
							|  |  |  | 			return | 
					
						
							|  |  |  | 		if self.botframe is None: | 
					
						
							|  |  |  | 			# First call of dispatch since reset() | 
					
						
							|  |  |  | 			self.botframe = frame.f_back	# xxx !!! added f_back | 
					
						
							|  |  |  | 			return self.trace_dispatch | 
					
						
							|  |  |  | 		if not (self.stop_here(frame) or self.break_anywhere(frame)): | 
					
						
							|  |  |  | 			# No need to trace this function | 
					
						
							|  |  |  | 			return # None | 
					
						
							|  |  |  | 		self.user_call(frame, arg) | 
					
						
							|  |  |  | 		if self.quitting: | 
					
						
							|  |  |  | 			raise bdb.BdbQuit | 
					
						
							|  |  |  | 		return self.trace_dispatch | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	def set_continue(self): | 
					
						
							|  |  |  | 		# Don't stop except at breakpoints or when finished | 
					
						
							|  |  |  | 		self.stopframe = self.botframe | 
					
						
							|  |  |  | 		self.returnframe = None | 
					
						
							|  |  |  | 		self.quitting = 0 | 
					
						
							|  |  |  | 		# unlike in bdb/pdb, there's a chance that breakpoints change  | 
					
						
							|  |  |  | 		# *while* a program (this program ;-) is running. It's actually quite likely. | 
					
						
							|  |  |  | 		# So we don't delete frame.f_trace until the bottom frame if there are no breakpoints. | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	def set_break(self, filename, lineno): | 
					
						
							|  |  |  | 		if not self.breaks.has_key(filename): | 
					
						
							|  |  |  | 			self.breaks[filename] = [] | 
					
						
							|  |  |  | 		list = self.breaks[filename] | 
					
						
							|  |  |  | 		if lineno in list: | 
					
						
							|  |  |  | 			return 'There is already a breakpoint there!' | 
					
						
							|  |  |  | 		list.append(lineno) | 
					
						
							|  |  |  | 		list.sort()	# I want to keep them neatly sorted; easier for drawing | 
					
						
							|  |  |  | 		if hasattr(bdb, "Breakpoint"): | 
					
						
							|  |  |  | 			# 1.5.2b1 specific | 
					
						
							|  |  |  | 			bp = bdb.Breakpoint(filename, lineno, 0, None) | 
					
						
							|  |  |  | 		self.update_breaks(filename) | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	def clear_break(self, filename, lineno): | 
					
						
							|  |  |  | 		bdb.Bdb.clear_break(self, filename, lineno) | 
					
						
							|  |  |  | 		self.update_breaks(filename) | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	def clear_all_file_breaks(self, filename): | 
					
						
							|  |  |  | 		bdb.Bdb.clear_all_file_breaks(self, filename) | 
					
						
							|  |  |  | 		self.update_breaks(filename) | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	def clear_all_breaks(self): | 
					
						
							|  |  |  | 		bdb.Bdb.clear_all_breaks(self) | 
					
						
							|  |  |  | 		for editors in self.editors.values(): | 
					
						
							|  |  |  | 			for editor in editors: | 
					
						
							|  |  |  | 				editor.drawbreakpoints() | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	# special | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	def toggle_break(self, filename, lineno): | 
					
						
							|  |  |  | 		if self.get_break(filename, lineno): | 
					
						
							|  |  |  | 			self.clear_break(filename, lineno) | 
					
						
							|  |  |  | 		else: | 
					
						
							|  |  |  | 			self.set_break(filename, lineno) | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	def clear_breaks_above(self, filename, above): | 
					
						
							|  |  |  | 		if not self.breaks.has_key(filename): | 
					
						
							|  |  |  | 			return 'There are no breakpoints in that file!' | 
					
						
							|  |  |  | 		for lineno in self.breaks[filename][:]: | 
					
						
							|  |  |  | 			if lineno > above: | 
					
						
							|  |  |  | 				self.breaks[filename].remove(lineno) | 
					
						
							|  |  |  | 		if not self.breaks[filename]: | 
					
						
							|  |  |  | 			del self.breaks[filename] | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	# editor stuff | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	def update_breaks(self, filename): | 
					
						
							|  |  |  | 		if self.breaksviewer: | 
					
						
							|  |  |  | 			self.breaksviewer.update() | 
					
						
							|  |  |  | 		if self.editors.has_key(filename): | 
					
						
							|  |  |  | 			for editor in self.editors[filename]: | 
					
						
							|  |  |  | 				if editor._debugger:	# XXX | 
					
						
							|  |  |  | 					editor.drawbreakpoints() | 
					
						
							|  |  |  | 				else: | 
					
						
							|  |  |  | 					print 'xxx dead editor!' | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	def update_allbreaks(self): | 
					
						
							|  |  |  | 		if self.breaksviewer: | 
					
						
							|  |  |  | 			self.breaksviewer.update() | 
					
						
							|  |  |  | 		for filename in self.breaks.keys(): | 
					
						
							|  |  |  | 			if self.editors.has_key(filename): | 
					
						
							|  |  |  | 				for editor in self.editors[filename]: | 
					
						
							|  |  |  | 					if editor._debugger:	# XXX | 
					
						
							|  |  |  | 						editor.drawbreakpoints() | 
					
						
							|  |  |  | 					else: | 
					
						
							|  |  |  | 						print 'xxx dead editor!' | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	def register_editor(self, editor, filename): | 
					
						
							|  |  |  | 		if not filename: | 
					
						
							|  |  |  | 			return | 
					
						
							|  |  |  | 		if not self.editors.has_key(filename): | 
					
						
							|  |  |  | 			self.editors[filename] = [editor] | 
					
						
							|  |  |  | 		elif editor not in self.editors[filename]: | 
					
						
							|  |  |  | 			self.editors[filename].append(editor) | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	def unregister_editor(self, editor, filename): | 
					
						
							|  |  |  | 		if not filename: | 
					
						
							|  |  |  | 			return | 
					
						
							|  |  |  | 		try: | 
					
						
							|  |  |  | 			self.editors[filename].remove(editor) | 
					
						
							|  |  |  | 			if not self.editors[filename]: | 
					
						
							|  |  |  | 				del self.editors[filename] | 
					
						
							|  |  |  | 				# if this was an untitled window, clear the breaks. | 
					
						
							|  |  |  | 				if filename[:1] == '<' and filename[-1:] == '>' and \ | 
					
						
							|  |  |  | 						self.breaks.has_key(filename): | 
					
						
							|  |  |  | 					self.clear_all_file_breaks(filename) | 
					
						
							|  |  |  | 		except (KeyError, ValueError): | 
					
						
							|  |  |  | 			pass | 
					
						
							|  |  |  | 		 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | class SourceViewer(W.PyEditor): | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	def __init__(self, *args, **kwargs): | 
					
						
							|  |  |  | 		apply(W.PyEditor.__init__, (self,) + args, kwargs) | 
					
						
							|  |  |  | 		self.bind('<click>', self.clickintercept) | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	def clickintercept(self, point, modifiers): | 
					
						
							|  |  |  | 		if self._parentwindow._currentwidget <> self and not self.pt_in_breaks(point): | 
					
						
							|  |  |  | 			self._parentwindow.xxx___select(self) | 
					
						
							|  |  |  | 			return 1 | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	def _getviewrect(self): | 
					
						
							|  |  |  | 		l, t, r, b = self._bounds | 
					
						
							|  |  |  | 		if self._debugger: | 
					
						
							|  |  |  | 			return (l + 12, t + 2, r - 1, b - 2) | 
					
						
							|  |  |  | 		else: | 
					
						
							|  |  |  | 			return (l + 5, t + 2, r - 1, b - 2) | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	def select(self, onoff, isclick = 0): | 
					
						
							|  |  |  | 		if W.SelectableWidget.select(self, onoff): | 
					
						
							|  |  |  | 			return | 
					
						
							|  |  |  | 		self.SetPort() | 
					
						
							|  |  |  | 		#if onoff: | 
					
						
							|  |  |  | 		#	self.ted.WEActivate() | 
					
						
							|  |  |  | 		#else: | 
					
						
							|  |  |  | 		#	self.ted.WEDeactivate() | 
					
						
							|  |  |  | 		self.drawselframe(onoff) | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	def drawselframe(self, onoff): | 
					
						
							|  |  |  | 		pass | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | class BreakpointsViewer: | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	def __init__(self, debugger): | 
					
						
							|  |  |  | 		self.debugger = debugger | 
					
						
							|  |  |  | 		import Lists | 
					
						
							|  |  |  | 		self.w = W.Window((300, 250), 'Breakpoints', minsize = (200, 200)) | 
					
						
							|  |  |  | 		self.w.panes = W.HorizontalPanes((8, 8, -8, -32), (0.3, 0.7)) | 
					
						
							|  |  |  | 		self.w.panes.files = W.List(None, callback = self.filehit)		#, flags = Lists.lOnlyOne) | 
					
						
							|  |  |  | 		self.w.panes.gr = W.Group(None) | 
					
						
							|  |  |  | 		self.w.panes.gr.breaks = W.List((0, 0, -130, 0), callback = self.linehit)	#, flags = Lists.lOnlyOne) | 
					
						
							| 
									
										
										
										
											2001-06-19 21:37:33 +00:00
										 |  |  | 		self.w.panes.gr.openbutton = W.Button((-80, 4, 0, 16), 'View\xc9', self.openbuttonhit) | 
					
						
							| 
									
										
										
										
											1999-01-30 22:39:17 +00:00
										 |  |  | 		self.w.panes.gr.deletebutton = W.Button((-80, 28, 0, 16), 'Delete', self.deletebuttonhit) | 
					
						
							|  |  |  | 		 | 
					
						
							|  |  |  | 		self.w.bind('<close>', self.close) | 
					
						
							|  |  |  | 		self.w.bind('backspace', self.w.panes.gr.deletebutton.push) | 
					
						
							|  |  |  | 		 | 
					
						
							|  |  |  | 		self.setup() | 
					
						
							|  |  |  | 		self.w.open() | 
					
						
							|  |  |  | 		self.w.panes.gr.openbutton.enable(0) | 
					
						
							|  |  |  | 		self.w.panes.gr.deletebutton.enable(0) | 
					
						
							|  |  |  | 		self.curfile = None | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	def deletebuttonhit(self): | 
					
						
							|  |  |  | 		if self.w._currentwidget == self.w.panes.files: | 
					
						
							|  |  |  | 			self.del_filename() | 
					
						
							|  |  |  | 		else: | 
					
						
							|  |  |  | 			self.del_number() | 
					
						
							|  |  |  | 		self.checkbuttons() | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	def del_number(self): | 
					
						
							|  |  |  | 		if self.curfile is None: | 
					
						
							|  |  |  | 			return | 
					
						
							|  |  |  | 		sel = self.w.panes.gr.breaks.getselectedobjects() | 
					
						
							|  |  |  | 		for lineno in sel: | 
					
						
							|  |  |  | 			self.debugger.clear_break(self.curfile, lineno) | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	def del_filename(self): | 
					
						
							|  |  |  | 		sel = self.w.panes.files.getselectedobjects() | 
					
						
							|  |  |  | 		for filename in sel: | 
					
						
							|  |  |  | 			self.debugger.clear_all_file_breaks(filename) | 
					
						
							|  |  |  | 		self.debugger.update_allbreaks() | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	def setup(self): | 
					
						
							|  |  |  | 		files = self.debugger.breaks.keys() | 
					
						
							|  |  |  | 		files.sort() | 
					
						
							|  |  |  | 		self.w.panes.files.set(files) | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	def close(self): | 
					
						
							|  |  |  | 		self.debugger.breaksviewer = None | 
					
						
							|  |  |  | 		self.debugger = None | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	def update(self): | 
					
						
							|  |  |  | 		sel = self.w.panes.files.getselectedobjects() | 
					
						
							|  |  |  | 		self.setup() | 
					
						
							|  |  |  | 		self.w.panes.files.setselectedobjects(sel) | 
					
						
							|  |  |  | 		sel = self.w.panes.files.getselection() | 
					
						
							|  |  |  | 		if len(sel) == 0 and self.curfile: | 
					
						
							|  |  |  | 			self.w.panes.files.setselectedobjects([self.curfile]) | 
					
						
							|  |  |  | 		self.filehit(0) | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	def select(self): | 
					
						
							|  |  |  | 		self.w.select() | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	def selectfile(self, file): | 
					
						
							|  |  |  | 		self.w.panes.files.setselectedobjects([file]) | 
					
						
							|  |  |  | 		self.filehit(0)			 | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	def openbuttonhit(self): | 
					
						
							|  |  |  | 		self.filehit(1) | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	def filehit(self, isdbl): | 
					
						
							|  |  |  | 		sel = self.w.panes.files.getselectedobjects() | 
					
						
							|  |  |  | 		if isdbl: | 
					
						
							|  |  |  | 			for filename in sel: | 
					
						
							|  |  |  | 				lineno = None | 
					
						
							|  |  |  | 				if filename == self.curfile: | 
					
						
							|  |  |  | 					linesel = self.w.panes.gr.breaks.getselectedobjects() | 
					
						
							|  |  |  | 					if linesel: | 
					
						
							|  |  |  | 						lineno = linesel[-1] | 
					
						
							|  |  |  | 					elif self.w.panes.gr.breaks: | 
					
						
							|  |  |  | 						lineno = self.w.panes.gr.breaks[0] | 
					
						
							|  |  |  | 				editor = self.w._parentwindow.parent.openscript(filename, lineno) | 
					
						
							|  |  |  | 				editor.showbreakpoints(1) | 
					
						
							|  |  |  | 			return | 
					
						
							|  |  |  | 		if len(sel) == 1: | 
					
						
							|  |  |  | 			file = sel[0] | 
					
						
							|  |  |  | 			filebreaks = self.debugger.breaks[file][:] | 
					
						
							|  |  |  | 			if self.curfile == file: | 
					
						
							|  |  |  | 				linesel = self.w.panes.gr.breaks.getselectedobjects() | 
					
						
							|  |  |  | 			self.w.panes.gr.breaks.set(filebreaks) | 
					
						
							|  |  |  | 			if self.curfile == file: | 
					
						
							|  |  |  | 				self.w.panes.gr.breaks.setselectedobjects(linesel) | 
					
						
							|  |  |  | 			self.curfile = file | 
					
						
							|  |  |  | 		else: | 
					
						
							|  |  |  | 			if len(sel) <> 0: | 
					
						
							|  |  |  | 				self.curfile = None | 
					
						
							|  |  |  | 			self.w.panes.gr.breaks.set([]) | 
					
						
							|  |  |  | 		self.checkbuttons() | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	def linehit(self, isdbl): | 
					
						
							|  |  |  | 		if isdbl: | 
					
						
							|  |  |  | 			files = self.w.panes.files.getselectedobjects() | 
					
						
							|  |  |  | 			if len(files) <> 1: | 
					
						
							|  |  |  | 				return | 
					
						
							|  |  |  | 			filename = files[0] | 
					
						
							|  |  |  | 			linenos = self.w.panes.gr.breaks.getselectedobjects() | 
					
						
							|  |  |  | 			if not linenos: | 
					
						
							|  |  |  | 				return | 
					
						
							|  |  |  | 			lineno = linenos[-1] | 
					
						
							|  |  |  | 			editor = self.w._parentwindow.parent.openscript(filename, lineno) | 
					
						
							|  |  |  | 			editor.showbreakpoints(1) | 
					
						
							|  |  |  | 		self.checkbuttons() | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	def checkbuttons(self): | 
					
						
							|  |  |  | 		if self.w.panes.files.getselection(): | 
					
						
							|  |  |  | 			self.w.panes.gr.openbutton.enable(1) | 
					
						
							|  |  |  | 			self.w._parentwindow.setdefaultbutton(self.w.panes.gr.openbutton) | 
					
						
							|  |  |  | 			if self.w._currentwidget == self.w.panes.files: | 
					
						
							|  |  |  | 				if self.w.panes.files.getselection(): | 
					
						
							|  |  |  | 					self.w.panes.gr.deletebutton.enable(1) | 
					
						
							|  |  |  | 				else: | 
					
						
							|  |  |  | 					self.w.panes.gr.deletebutton.enable(0) | 
					
						
							|  |  |  | 			else: | 
					
						
							|  |  |  | 				if self.w.panes.gr.breaks.getselection(): | 
					
						
							|  |  |  | 					self.w.panes.gr.deletebutton.enable(1) | 
					
						
							|  |  |  | 				else: | 
					
						
							|  |  |  | 					self.w.panes.gr.deletebutton.enable(0) | 
					
						
							|  |  |  | 		else: | 
					
						
							|  |  |  | 			self.w.panes.gr.openbutton.enable(0) | 
					
						
							|  |  |  | 			self.w.panes.gr.deletebutton.enable(0) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | class TracingMonitor(W.Widget): | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	def __init__(self, *args, **kwargs): | 
					
						
							|  |  |  | 		apply(W.Widget.__init__, (self,) + args, kwargs) | 
					
						
							|  |  |  | 		self.state = 0 | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	def toggle(self): | 
					
						
							|  |  |  | 		if hasattr(self, "_parentwindow") and self._parentwindow is not None: | 
					
						
							|  |  |  | 			self.state = self.state % 2 + 1 | 
					
						
							|  |  |  | 			port = Qd.GetPort() | 
					
						
							|  |  |  | 			self.SetPort() | 
					
						
							|  |  |  | 			self.draw() | 
					
						
							|  |  |  | 			Qd.SetPort(port) | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	def reset(self): | 
					
						
							|  |  |  | 		if self._parentwindow: | 
					
						
							|  |  |  | 			self.state = 0 | 
					
						
							|  |  |  | 			port = Qd.GetPort() | 
					
						
							|  |  |  | 			self.SetPort() | 
					
						
							|  |  |  | 			self.draw() | 
					
						
							|  |  |  | 			Qd.SetPort(port) | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	def draw(self, visRgn = None): | 
					
						
							|  |  |  | 		if self.state == 2: | 
					
						
							|  |  |  | 			Qd.PaintOval(self._bounds) | 
					
						
							|  |  |  | 		else: | 
					
						
							|  |  |  | 			Qd.EraseOval(self._bounds) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | # convenience funcs | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | def postmortem(exc_type, exc_value, tb): | 
					
						
							|  |  |  | 	d = getdebugger() | 
					
						
							|  |  |  | 	d.postmortem(exc_type, exc_value, tb) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | def start(bottomframe = None): | 
					
						
							|  |  |  | 	d = getdebugger() | 
					
						
							|  |  |  | 	d.start(bottomframe) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | def startfromhere(): | 
					
						
							|  |  |  | 	d = getdebugger() | 
					
						
							|  |  |  | 	try: | 
					
						
							|  |  |  | 		raise 'spam' | 
					
						
							|  |  |  | 	except: | 
					
						
							|  |  |  | 		frame = sys.exc_traceback.tb_frame.f_back | 
					
						
							|  |  |  | 	d.start(frame) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | def startfrombottom(): | 
					
						
							|  |  |  | 	d = getdebugger() | 
					
						
							|  |  |  | 	d.start(_getbottomframe(), 1) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | def stop(): | 
					
						
							|  |  |  | 	d = getdebugger() | 
					
						
							|  |  |  | 	d.stop() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | def cont(): | 
					
						
							|  |  |  | 	sys.settrace(None) | 
					
						
							|  |  |  | 	d = getdebugger() | 
					
						
							|  |  |  | 	d.set_continue_without_debugger() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | def _getbottomframe(): | 
					
						
							|  |  |  | 	try: | 
					
						
							|  |  |  | 		raise 'spam' | 
					
						
							|  |  |  | 	except: | 
					
						
							|  |  |  | 		pass | 
					
						
							|  |  |  | 	frame = sys.exc_traceback.tb_frame | 
					
						
							|  |  |  | 	while 1: | 
					
						
							|  |  |  | 		if frame.f_code.co_name == 'mainloop' or frame.f_back is None: | 
					
						
							|  |  |  | 			break | 
					
						
							|  |  |  | 		frame = frame.f_back | 
					
						
							|  |  |  | 	return frame | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | _debugger = None | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | def getdebugger(): | 
					
						
							|  |  |  | 	if not __debug__: | 
					
						
							| 
									
										
										
										
											2001-06-19 21:37:33 +00:00
										 |  |  | 		raise W.AlertError, "Can't debug in \"Optimize bytecode\" mode.\r(see \"Default startup options\" in EditPythonPreferences)" | 
					
						
							| 
									
										
										
										
											1999-01-30 22:39:17 +00:00
										 |  |  | 	global _debugger | 
					
						
							|  |  |  | 	if _debugger is None: | 
					
						
							|  |  |  | 		_debugger = Debugger() | 
					
						
							|  |  |  | 	return _debugger |