def __init__(self, editor, filename=None, slave_mode=1): wx.Frame.__init__(self, editor, -1, _('Debugger'), style=wx.DEFAULT_FRAME_STYLE | wx.CLIP_CHILDREN|Preferences.childFrameStyle) self.winConfOption = 'debugger' self.loadDims() self.editor = editor self.running = 0 self.slave_mode = slave_mode if filename: self.setDebugFile(filename) else: self.filename = '' self.SetIcon(IS.load('Images/Icons/Debug.ico')) self.viewsImgLst = wx.ImageList(16, 16) self.viewsImgLst.Add(IS.load('Images/Debug/Stack.png')) self.viewsImgLst.Add(IS.load('Images/Debug/Breakpoints.png')) self.viewsImgLst.Add(IS.load('Images/Debug/Watches.png')) self.viewsImgLst.Add(IS.load('Images/Debug/Locals.png')) self.viewsImgLst.Add(IS.load('Images/Debug/Globals.png')) self.viewsImgLst.Add(IS.load('Images/Debug/Output.png')) self.invalidatePanes() self.sb = DebugStatusBar(self) self.SetStatusBar(self.sb) self.toolbar = wx.ToolBar(self, -1, style=wx.TB_HORIZONTAL | wx.NO_BORDER|flatTools) self.SetToolBar(self.toolbar) self.runId = Utils.AddToolButtonBmpIS(self, self.toolbar, 'Images/Debug/Debug.png', _('Debug/Continue - %s')%keyDefs['Debug'][2], self.OnDebug) #, runs in debugger, stops at breaks and exceptions' self.runFullSpdId = Utils.AddToolButtonBmpIS(self, self.toolbar, 'Images/Debug/DebugFullSpeed.png', _('Debug/Continue full speed'), self.OnDebugFullSpeed) #'stops only at hard (code) breaks and exceptions' self.stepId = Utils.AddToolButtonBmpIS(self, self.toolbar, 'Images/Debug/Step.png', _('Step - %s')%keyDefs['DebugStep'][2], self.OnStep) self.overId = Utils.AddToolButtonBmpIS(self, self.toolbar, 'Images/Debug/Over.png', _('Over - %s')%keyDefs['DebugOver'][2], self.OnOver) self.outId = Utils.AddToolButtonBmpIS(self, self.toolbar, 'Images/Debug/Out.png', _('Out - %s')%keyDefs['DebugOut'][2], self.OnOut) self.jumpId = -1 if sys.version_info[:2] >= (2, 3): self.jumpId = Utils.AddToolButtonBmpIS(self, self.toolbar, 'Images/Debug/Jump.png', _('Jump to line'), self.OnJump) self.pauseId = Utils.AddToolButtonBmpIS(self, self.toolbar, 'Images/Debug/Pause.png', _('Pause'), self.OnPause) self.stopId = Utils.AddToolButtonBmpIS(self, self.toolbar, 'Images/Debug/Stop.png', _('Stop'), self.OnStop) self.toolbar.AddSeparator() self.sourceTraceId = Utils.AddToolButtonBmpIS(self, self.toolbar, 'Images/Debug/SourceTrace-Off.png', _('Trace in source'), self.OnSourceTrace, '1') self.debugBrowseId = Utils.AddToolButtonBmpIS(self, self.toolbar, 'Images/Debug/DebugBrowse.png', _('Debug browsing'), self.OnDebugBrowse, '1') if Preferences.psPythonShell == 'Shell': self.shellNamespaceId = Utils.AddToolButtonBmpIS(self, self.toolbar, 'Images/Debug/ShellDebug.png', _('Eval in shell'), self.OnDebugNamespace, '1') else: self.shellNamespaceId = -1 self.toolbar.AddSeparator() self.pathMappingsId = Utils.AddToolButtonBmpIS(self, self.toolbar, 'Images/Debug/PathMapping.png', _('Edit client/server path mappings...'), self.OnPathMappings) self.splitOrientId = Utils.AddToolButtonBmpIS(self, self.toolbar, 'Images/Debug/SplitOrient.png', _('Toggle split orientation'), self.OnToggleSplitOrient) self.SetAcceleratorTable(wx.AcceleratorTable( [ (keyDefs['Debug'][0], keyDefs['Debug'][1], self.runId), (keyDefs['DebugStep'][0], keyDefs['DebugStep'][1], self.stepId), (keyDefs['DebugOver'][0], keyDefs['DebugOver'][1], self.overId), (keyDefs['DebugOut'][0], keyDefs['DebugOut'][1], self.outId) ] )) self.toolbar.Realize() self.toolbar.ToggleTool(self.sourceTraceId, True) self.toolbar.ToggleTool(self.debugBrowseId, False) self.splitter = wx.SplitterWindow(self, -1, style=wx.SP_NOBORDER|Preferences.splitterStyle) (stackImgIdx, breaksImgIdx, watchesImgIdx, localsImgIdx, globalsImgIdx) = range(5) # Create a Notebook self.nbTop = wx.Notebook(self.splitter, wxID_TOPPAGECHANGED) self.nbTop.SetImageList(self.viewsImgLst) self.stackView = StackViewCtrl(self.nbTop, None, self) self.nbTop.AddPage(self.stackView, _('Stack'), imageId=stackImgIdx) self.breakpts = BreakViewCtrl(self.nbTop, self) self.nbTop.AddPage(self.breakpts, _('Breakpoints'), imageId=breaksImgIdx) # Create a Notebook self.nbBottom = wx.Notebook(self.splitter, wxID_PAGECHANGED, style=wx.CLIP_CHILDREN) self.nbBottom.Bind(wx.EVT_NOTEBOOK_PAGE_CHANGED, self.OnPageChange, id=wxID_PAGECHANGED) self.nbBottom.SetImageList(self.viewsImgLst) self.watches = WatchViewCtrl(self.nbBottom, self.viewsImgLst, self) self.nbBottom.AddPage(self.watches, _('Watches'), imageId=watchesImgIdx) self.locs = NamespaceViewCtrl(self.nbBottom, self, 1, 'local') self.nbBottom.AddPage(self.locs, _('Locals'), imageId=localsImgIdx) self.globs = NamespaceViewCtrl( self.nbBottom, self, 0, 'global') self.nbBottom.AddPage(self.globs, _('Globals'), imageId=globalsImgIdx) self.splitter.SetMinimumPaneSize(40) self.splitter.SplitHorizontally(self.nbTop, self.nbBottom) self.splitter.SetSashPosition(175) self.splitter.SetSplitMode(wx.SPLIT_HORIZONTAL) self.mlc = 0 self.frame = None self.lastStepView = None self.lastStepLineno = -1 self.stepping_enabled = 1 self.setParams([]) self.setServerClientPaths([]) self.Bind(EVT_DEBUGGER_OK, self.OnDebuggerOk, id=self.GetId()) self.Bind(EVT_DEBUGGER_EXC, self.OnDebuggerException, id=self.GetId()) self.Bind(EVT_DEBUGGER_STOPPED, self.OnDebuggerStopped, id=self.GetId()) # used to indicate when the debugger start, # would be better if there was a start event in addition to the OK event self._pid = None self._erroutFrm = self.editor.erroutFrm self.stream_timer = wx.PyTimer(self.OnStreamTimer) self.stream_timer.Start(100) self.Bind(wx.EVT_MENU_HIGHLIGHT_ALL, self.OnToolOver) self.Bind(wx.EVT_CLOSE, self.OnCloseWindow)
def __init__(self, editor, filename=None, slave_mode=1): wx.Frame.__init__(self, editor, -1, _('Debugger'), style=wx.DEFAULT_FRAME_STYLE | wx.CLIP_CHILDREN | Preferences.childFrameStyle) self.winConfOption = 'debugger' self.loadDims() self.editor = editor self.running = 0 self.slave_mode = slave_mode if filename: self.setDebugFile(filename) else: self.filename = '' self.SetIcon(IS.load('Images/Icons/Debug.ico')) self.viewsImgLst = wx.ImageList(16, 16) self.viewsImgLst.Add(IS.load('Images/Debug/Stack.png')) self.viewsImgLst.Add(IS.load('Images/Debug/Breakpoints.png')) self.viewsImgLst.Add(IS.load('Images/Debug/Watches.png')) self.viewsImgLst.Add(IS.load('Images/Debug/Locals.png')) self.viewsImgLst.Add(IS.load('Images/Debug/Globals.png')) self.viewsImgLst.Add(IS.load('Images/Debug/Output.png')) self.invalidatePanes() self.sb = DebugStatusBar(self) self.SetStatusBar(self.sb) self.toolbar = wx.ToolBar(self, -1, style=wx.TB_HORIZONTAL | wx.NO_BORDER | flatTools) self.SetToolBar(self.toolbar) self.runId = Utils.AddToolButtonBmpIS( self, self.toolbar, 'Images/Debug/Debug.png', _('Debug/Continue - %s') % keyDefs['Debug'][2], self.OnDebug) #, runs in debugger, stops at breaks and exceptions' self.runFullSpdId = Utils.AddToolButtonBmpIS( self, self.toolbar, 'Images/Debug/DebugFullSpeed.png', _('Debug/Continue full speed'), self.OnDebugFullSpeed ) #'stops only at hard (code) breaks and exceptions' self.stepId = Utils.AddToolButtonBmpIS( self, self.toolbar, 'Images/Debug/Step.png', _('Step - %s') % keyDefs['DebugStep'][2], self.OnStep) self.overId = Utils.AddToolButtonBmpIS( self, self.toolbar, 'Images/Debug/Over.png', _('Over - %s') % keyDefs['DebugOver'][2], self.OnOver) self.outId = Utils.AddToolButtonBmpIS( self, self.toolbar, 'Images/Debug/Out.png', _('Out - %s') % keyDefs['DebugOut'][2], self.OnOut) self.jumpId = -1 if sys.version_info[:2] >= (2, 3): self.jumpId = Utils.AddToolButtonBmpIS(self, self.toolbar, 'Images/Debug/Jump.png', _('Jump to line'), self.OnJump) self.pauseId = Utils.AddToolButtonBmpIS(self, self.toolbar, 'Images/Debug/Pause.png', _('Pause'), self.OnPause) self.stopId = Utils.AddToolButtonBmpIS(self, self.toolbar, 'Images/Debug/Stop.png', _('Stop'), self.OnStop) self.toolbar.AddSeparator() self.sourceTraceId = Utils.AddToolButtonBmpIS( self, self.toolbar, 'Images/Debug/SourceTrace-Off.png', _('Trace in source'), self.OnSourceTrace, '1') self.debugBrowseId = Utils.AddToolButtonBmpIS( self, self.toolbar, 'Images/Debug/DebugBrowse.png', _('Debug browsing'), self.OnDebugBrowse, '1') if Preferences.psPythonShell == 'Shell': self.shellNamespaceId = Utils.AddToolButtonBmpIS( self, self.toolbar, 'Images/Debug/ShellDebug.png', _('Eval in shell'), self.OnDebugNamespace, '1') else: self.shellNamespaceId = -1 self.toolbar.AddSeparator() self.pathMappingsId = Utils.AddToolButtonBmpIS( self, self.toolbar, 'Images/Debug/PathMapping.png', _('Edit client/server path mappings...'), self.OnPathMappings) self.splitOrientId = Utils.AddToolButtonBmpIS( self, self.toolbar, 'Images/Debug/SplitOrient.png', _('Toggle split orientation'), self.OnToggleSplitOrient) self.SetAcceleratorTable( wx.AcceleratorTable([ (keyDefs['Debug'][0], keyDefs['Debug'][1], self.runId), (keyDefs['DebugStep'][0], keyDefs['DebugStep'][1], self.stepId), (keyDefs['DebugOver'][0], keyDefs['DebugOver'][1], self.overId), (keyDefs['DebugOut'][0], keyDefs['DebugOut'][1], self.outId) ])) self.toolbar.Realize() self.toolbar.ToggleTool(self.sourceTraceId, True) self.toolbar.ToggleTool(self.debugBrowseId, False) self.splitter = wx.SplitterWindow(self, -1, style=wx.SP_NOBORDER | Preferences.splitterStyle) (stackImgIdx, breaksImgIdx, watchesImgIdx, localsImgIdx, globalsImgIdx) = range(5) # Create a Notebook self.nbTop = wx.Notebook(self.splitter, wxID_TOPPAGECHANGED) self.nbTop.SetImageList(self.viewsImgLst) self.stackView = StackViewCtrl(self.nbTop, None, self) self.nbTop.AddPage(self.stackView, _('Stack'), imageId=stackImgIdx) self.breakpts = BreakViewCtrl(self.nbTop, self) self.nbTop.AddPage(self.breakpts, _('Breakpoints'), imageId=breaksImgIdx) # Create a Notebook self.nbBottom = wx.Notebook(self.splitter, wxID_PAGECHANGED, style=wx.CLIP_CHILDREN) self.nbBottom.Bind(wx.EVT_NOTEBOOK_PAGE_CHANGED, self.OnPageChange, id=wxID_PAGECHANGED) self.nbBottom.SetImageList(self.viewsImgLst) self.watches = WatchViewCtrl(self.nbBottom, self.viewsImgLst, self) self.nbBottom.AddPage(self.watches, _('Watches'), imageId=watchesImgIdx) self.locs = NamespaceViewCtrl(self.nbBottom, self, 1, 'local') self.nbBottom.AddPage(self.locs, _('Locals'), imageId=localsImgIdx) self.globs = NamespaceViewCtrl(self.nbBottom, self, 0, 'global') self.nbBottom.AddPage(self.globs, _('Globals'), imageId=globalsImgIdx) self.splitter.SetMinimumPaneSize(40) self.splitter.SplitHorizontally(self.nbTop, self.nbBottom) self.splitter.SetSashPosition(175) self.splitter.SetSplitMode(wx.SPLIT_HORIZONTAL) self.mlc = 0 self.frame = None self.lastStepView = None self.lastStepLineno = -1 self.stepping_enabled = 1 self.setParams([]) self.setServerClientPaths([]) self.Bind(EVT_DEBUGGER_OK, self.OnDebuggerOk, id=self.GetId()) self.Bind(EVT_DEBUGGER_EXC, self.OnDebuggerException, id=self.GetId()) self.Bind(EVT_DEBUGGER_STOPPED, self.OnDebuggerStopped, id=self.GetId()) # used to indicate when the debugger start, # would be better if there was a start event in addition to the OK event self._pid = None self._erroutFrm = self.editor.erroutFrm self.stream_timer = wx.PyTimer(self.OnStreamTimer) self.stream_timer.Start(100) self.Bind(wx.EVT_MENU_HIGHLIGHT_ALL, self.OnToolOver) self.Bind(wx.EVT_CLOSE, self.OnCloseWindow)
class DebuggerFrame(wx.Frame, Utils.FrameRestorerMixin): debug_client = None _destroyed = 0 _closing = 0 def __init__(self, editor, filename=None, slave_mode=1): wx.Frame.__init__(self, editor, -1, _('Debugger'), style=wx.DEFAULT_FRAME_STYLE | wx.CLIP_CHILDREN|Preferences.childFrameStyle) self.winConfOption = 'debugger' self.loadDims() self.editor = editor self.running = 0 self.slave_mode = slave_mode if filename: self.setDebugFile(filename) else: self.filename = '' self.SetIcon(IS.load('Images/Icons/Debug.ico')) self.viewsImgLst = wx.ImageList(16, 16) self.viewsImgLst.Add(IS.load('Images/Debug/Stack.png')) self.viewsImgLst.Add(IS.load('Images/Debug/Breakpoints.png')) self.viewsImgLst.Add(IS.load('Images/Debug/Watches.png')) self.viewsImgLst.Add(IS.load('Images/Debug/Locals.png')) self.viewsImgLst.Add(IS.load('Images/Debug/Globals.png')) self.viewsImgLst.Add(IS.load('Images/Debug/Output.png')) self.invalidatePanes() self.sb = DebugStatusBar(self) self.SetStatusBar(self.sb) self.toolbar = wx.ToolBar(self, -1, style=wx.TB_HORIZONTAL | wx.NO_BORDER|flatTools) self.SetToolBar(self.toolbar) self.runId = Utils.AddToolButtonBmpIS(self, self.toolbar, 'Images/Debug/Debug.png', _('Debug/Continue - %s')%keyDefs['Debug'][2], self.OnDebug) #, runs in debugger, stops at breaks and exceptions' self.runFullSpdId = Utils.AddToolButtonBmpIS(self, self.toolbar, 'Images/Debug/DebugFullSpeed.png', _('Debug/Continue full speed'), self.OnDebugFullSpeed) #'stops only at hard (code) breaks and exceptions' self.stepId = Utils.AddToolButtonBmpIS(self, self.toolbar, 'Images/Debug/Step.png', _('Step - %s')%keyDefs['DebugStep'][2], self.OnStep) self.overId = Utils.AddToolButtonBmpIS(self, self.toolbar, 'Images/Debug/Over.png', _('Over - %s')%keyDefs['DebugOver'][2], self.OnOver) self.outId = Utils.AddToolButtonBmpIS(self, self.toolbar, 'Images/Debug/Out.png', _('Out - %s')%keyDefs['DebugOut'][2], self.OnOut) self.jumpId = -1 if sys.version_info[:2] >= (2, 3): self.jumpId = Utils.AddToolButtonBmpIS(self, self.toolbar, 'Images/Debug/Jump.png', _('Jump to line'), self.OnJump) self.pauseId = Utils.AddToolButtonBmpIS(self, self.toolbar, 'Images/Debug/Pause.png', _('Pause'), self.OnPause) self.stopId = Utils.AddToolButtonBmpIS(self, self.toolbar, 'Images/Debug/Stop.png', _('Stop'), self.OnStop) self.toolbar.AddSeparator() self.sourceTraceId = Utils.AddToolButtonBmpIS(self, self.toolbar, 'Images/Debug/SourceTrace-Off.png', _('Trace in source'), self.OnSourceTrace, '1') self.debugBrowseId = Utils.AddToolButtonBmpIS(self, self.toolbar, 'Images/Debug/DebugBrowse.png', _('Debug browsing'), self.OnDebugBrowse, '1') if Preferences.psPythonShell == 'Shell': self.shellNamespaceId = Utils.AddToolButtonBmpIS(self, self.toolbar, 'Images/Debug/ShellDebug.png', _('Eval in shell'), self.OnDebugNamespace, '1') else: self.shellNamespaceId = -1 self.toolbar.AddSeparator() self.pathMappingsId = Utils.AddToolButtonBmpIS(self, self.toolbar, 'Images/Debug/PathMapping.png', _('Edit client/server path mappings...'), self.OnPathMappings) self.splitOrientId = Utils.AddToolButtonBmpIS(self, self.toolbar, 'Images/Debug/SplitOrient.png', _('Toggle split orientation'), self.OnToggleSplitOrient) self.SetAcceleratorTable(wx.AcceleratorTable( [ (keyDefs['Debug'][0], keyDefs['Debug'][1], self.runId), (keyDefs['DebugStep'][0], keyDefs['DebugStep'][1], self.stepId), (keyDefs['DebugOver'][0], keyDefs['DebugOver'][1], self.overId), (keyDefs['DebugOut'][0], keyDefs['DebugOut'][1], self.outId) ] )) self.toolbar.Realize() self.toolbar.ToggleTool(self.sourceTraceId, True) self.toolbar.ToggleTool(self.debugBrowseId, False) self.splitter = wx.SplitterWindow(self, -1, style=wx.SP_NOBORDER|Preferences.splitterStyle) (stackImgIdx, breaksImgIdx, watchesImgIdx, localsImgIdx, globalsImgIdx) = range(5) # Create a Notebook self.nbTop = wx.Notebook(self.splitter, wxID_TOPPAGECHANGED) self.nbTop.SetImageList(self.viewsImgLst) self.stackView = StackViewCtrl(self.nbTop, None, self) self.nbTop.AddPage(self.stackView, _('Stack'), imageId=stackImgIdx) self.breakpts = BreakViewCtrl(self.nbTop, self) self.nbTop.AddPage(self.breakpts, _('Breakpoints'), imageId=breaksImgIdx) # Create a Notebook self.nbBottom = wx.Notebook(self.splitter, wxID_PAGECHANGED, style=wx.CLIP_CHILDREN) self.nbBottom.Bind(wx.EVT_NOTEBOOK_PAGE_CHANGED, self.OnPageChange, id=wxID_PAGECHANGED) self.nbBottom.SetImageList(self.viewsImgLst) self.watches = WatchViewCtrl(self.nbBottom, self.viewsImgLst, self) self.nbBottom.AddPage(self.watches, _('Watches'), imageId=watchesImgIdx) self.locs = NamespaceViewCtrl(self.nbBottom, self, 1, 'local') self.nbBottom.AddPage(self.locs, _('Locals'), imageId=localsImgIdx) self.globs = NamespaceViewCtrl( self.nbBottom, self, 0, 'global') self.nbBottom.AddPage(self.globs, _('Globals'), imageId=globalsImgIdx) self.splitter.SetMinimumPaneSize(40) self.splitter.SplitHorizontally(self.nbTop, self.nbBottom) self.splitter.SetSashPosition(175) self.splitter.SetSplitMode(wx.SPLIT_HORIZONTAL) self.mlc = 0 self.frame = None self.lastStepView = None self.lastStepLineno = -1 self.stepping_enabled = 1 self.setParams([]) self.setServerClientPaths([]) self.Bind(EVT_DEBUGGER_OK, self.OnDebuggerOk, id=self.GetId()) self.Bind(EVT_DEBUGGER_EXC, self.OnDebuggerException, id=self.GetId()) self.Bind(EVT_DEBUGGER_STOPPED, self.OnDebuggerStopped, id=self.GetId()) # used to indicate when the debugger start, # would be better if there was a start event in addition to the OK event self._pid = None self._erroutFrm = self.editor.erroutFrm self.stream_timer = wx.PyTimer(self.OnStreamTimer) self.stream_timer.Start(100) self.Bind(wx.EVT_MENU_HIGHLIGHT_ALL, self.OnToolOver) self.Bind(wx.EVT_CLOSE, self.OnCloseWindow) def destroy(self): if self._destroyed: return self._destroyed = 1 self.breakpts.destroy() self.watches.destroy() self.locs.destroy() self.globs.destroy() self.sb.stateCols = None if self.stream_timer is not None: self.stream_timer.Stop() self.stream_timer = None def setDefaultDimensions(self): self.SetDimensions(0, Preferences.underPalette, Preferences.inspWidth, Preferences.bottomHeight) _sashes_inited = 0 def initSashes(self): if not self._sashes_inited: s = self.GetSize() if s.x /float(s.y) > 1: mode = wx.SPLIT_HORIZONTAL else: mode = wx.SPLIT_VERTICAL self.splitter.SetSplitMode(mode) self.OnToggleSplitOrient() self._sashes_inited = 1 def add_watch(self, name, local): self.watches.add_watch(name, local) self.nbBottom.SetSelection(0) self.invalidatePanes() self.updateSelectedPane() def OnPageChange(self, event): sel = event.GetSelection() if sel >= 0: self.updateSelectedPane(sel) event.Skip() def invalidatePanes(self): self.updated_panes = [0, 0, 0] def updateSelectedPane(self, pageno=-1, do_request=1, force=0): if pageno < 0: pageno = self.nbBottom.GetSelection() if not self.updated_panes[pageno] or force: frameno = self.stackView.getSelection() if pageno == 0: self.watches.showLoading() if do_request: self.requestWatches(frameno) else: if pageno==1: self.locs.showLoading() else: self.globs.showLoading() if do_request: self.requestDict((pageno==1), frameno) def requestWatches(self, frameno): ws = self.watches.watches exprs = [] for name, local in ws: exprs.append({'name':name, 'local':local}) if exprs: self.invokeInDebugger( 'evaluateWatches', (exprs, frameno), 'receiveWatches') else: # No exprs, so no request is necessary. self.watches.load_dict(None) self.updated_panes[0] = 1 def receiveWatches(self, status): frameno = status['frameno'] if frameno == self.stackView.getSelection(): self.updated_panes[0] = 1 self.watches.load_dict(status['watches']) else: # Re-request. self.updateSelectedPane() def requestDict(self, locs, frameno): self.invokeInDebugger( 'getSafeDict', (locs, frameno), 'receiveDict') def receiveDict(self, status): frameno = status['frameno'] if frameno == self.stackView.getSelection(): if status.has_key('locals'): self.updated_panes[1] = 1 self.locs.load_dict(status['locals']) if status.has_key('globals'): self.updated_panes[2] = 1 self.globs.load_dict(status['globals']) else: # Re-request. self.updateSelectedPane() def requestWatchSubobjects(self, name, local, pos): self.invokeInDebugger( 'getWatchSubobjects', (name, self.stackView.getSelection()), 'receiveWatchSubobjects', (name, local, pos)) def receiveWatchSubobjects(self, subnames, name, local, pos): for subname in subnames: self.watches.add_watch('%s.%s' % (name, subname), local, pos) pos = pos + 1 self.nbBottom.SetSelection(0) self.invalidatePanes() self.updateSelectedPane() def requestVarValue(self, name): self.invokeInDebugger( 'pprintVarValue', (name, self.stackView.getSelection()), 'receiveVarValue') def receiveVarValue(self, val): if val: self.editor.setStatus(val) def getVarValue(self, name): if not name.strip(): return None self._hasReceivedVal = 0 self._receivedVal = None self.invokeInDebugger( 'pprintVarValue', (name, self.stackView.getSelection()), 'receiveVarValue2') # XXX I'm not comfortable with this... try: while not self._hasReceivedVal: wx.Yield() return self._receivedVal finally: del self._hasReceivedVal del self._receivedVal def receiveVarValue2(self, val): self._receivedVal = val self._hasReceivedVal = 1 def valueToOutput(self, name): val = self.getVarValue(name) self.editor.erroutFrm.outputTC.SetValue('') self.editor.erroutFrm.appendToOutput(val) #--------------------------------------------------------------------------- def setParams(self, params): self.params = params def setDebugFile(self, filename): self.filename = filename title = '%s - %s' % (os.path.basename(filename), filename) self.setTitleInfo(title) def setTitleInfo(self, info): pidinfo = '' if self.debug_client: pid = self.debug_client.getProcessId() if pid: pidinfo = '(%s) ' % pid title = _('Debugger %s- %s') % (pidinfo, info) self.SetTitle(title) def setDebugClient(self, client=None): if client is None: from ChildProcessClient import ChildProcessClient client = ChildProcessClient(self, Preferences.debugServerArgs) self.debug_client = client def setServerClientPaths(self, paths): self.serverClientPaths = paths def invokeInDebugger(self, m_name, m_args=(), r_name=None, r_args=()): """ Invokes a method asynchronously in the debugger, possibly expecting a debugger event to be generated when finished. """ self.debug_client.invokeOnServer(m_name, m_args, r_name, r_args) def killDebugger(self): if self._destroyed: return self.running = 0 if self.debug_client: try: self.debug_client.kill() except: print _('Error on killing debugger: %s: %s')%sys.exc_info()[:2] self.clearViews() def OnDebuggerStopped(self, event): """Called when a debugger process stops.""" show_dialog = 0 if self.running: show_dialog = 1 self.killDebugger() if self._closing: # Close the window. self.destroy() self.Destroy() elif show_dialog: wx.MessageBox(_('The debugger process stopped prematurely.'), _('Debugger stopped'), wx.OK | wx.ICON_EXCLAMATION | wx.CENTRE) if self._pid: self._erroutFrm.processFinished(self._pid) self._pid = None def OnStreamTimer(self, event=None): if self.stream_timer: self.updateErrOutWindow() def updateErrOutWindow(self): if self.debug_client: info = self.debug_client.pollStreams() if info and self.editor: stdout_text, stderr_text = info if stdout_text: self.editor.erroutFrm.appendToOutput(stdout_text) if stderr_text: self.editor.erroutFrm.appendToErrors(stderr_text) def OnDebuggerOk(self, event): if self._destroyed: return if self._pid is None and self.debug_client: self._pid = self.debug_client.getProcessId() script = os.path.basename(self.filename) intp = os.path.basename(self.debug_client.pyIntpPath) if intp: self._erroutFrm.processStarted(intp, self._pid, script, 'Debug') self.restoreDebugger() self.enableStepping() receiver_name = event.GetReceiverName() if receiver_name is not None: rcv = getattr(self, receiver_name) rcv( *( (event.GetResult(),) + event.GetReceiverArgs()) ) def OnDebuggerException(self, event): if self._destroyed: return self.enableStepping() t, v = event.GetExc() if isinstance(v, EmptyResponseError): if not self.debug_client or not self.debug_client.isAlive(): # If the debugger was killed, this exception is normal. return self.restoreDebugger() if hasattr(t, '__name__'): t = t.__name__ msg = '%s: %s.' % (t, v) confirm = wx.MessageBox(_('%s\n\nStop debugger?')%msg, _('Debugger Communication Exception'), wx.YES_NO | wx.YES_DEFAULT | wx.ICON_EXCLAMATION | wx.CENTRE) == wx.YES if confirm: self.killDebugger() def runProcess(self, autocont=0): self.running = 1 self.sb.updateState(_('Waiting...'), 'busy') brks = bplist.getBreakpointList() for brk in brks: brk['filename'] = self.clientFNToServerFN(brk['filename']) if self.slave_mode: # Work with a child process. add_paths = simplifyPathList(pyPath) add_paths = map(self.clientFNToServerFN, add_paths) filename = self.clientFNToServerFN(self.filename) self.invokeInDebugger( 'runFileAndRequestStatus', (filename, self.params or [], autocont, add_paths, brks), 'receiveDebuggerStatus') else: # Work with a peer or remote process. self.invokeInDebugger( 'setupAndRequestStatus', (autocont, brks), 'receiveDebuggerStatus') # InProcessClient TODO: setup the execution environment # the way it used to be done. def proceedAndRequestStatus(self, command, temp_breakpoint=None, args=()): # Non-blocking. self.sb.updateState(_('Running...'), 'busy') if not temp_breakpoint: temp_breakpoint = 0 self.invokeInDebugger('proceedAndRequestStatus', (command, temp_breakpoint, args), 'receiveDebuggerStatus') def clientFNToServerFN(self, filename): """Converts a filename on the client to a filename on the server. Currently just turns file URLs into paths. If you want to be able to set breakpoints when running the client in a different environment from the server, you'll need to expand this. """ # XXX should we .fncache this? Files changing names are undefined # XXX during the lifetime of the debugger from Explorers.Explorer import splitURI, getTransport from Explorers.ExplorerNodes import all_transports prot, category, filepath, filename = splitURI(filename) if prot == 'zope': node = getTransport(prot, category, filepath, all_transports) if node: props = node.properties return 'zopedebug://%s:%s/%s/%s'%(props['host'], props['httpport'], filepath, node.metatype) else: raise Exception(_('No Zope connection for: %s')%filename) elif prot == 'zopedebug': raise Exception(_('"zopedebug" is a server filename protocol')) else: #if prot == 'file': if self.serverClientPaths: normFilepath = os.path.normcase(filepath) for serverPath, clientPath in self.serverClientPaths: normClientPath = os.path.normcase(clientPath) if normFilepath.startswith(normClientPath): return serverPath+normFilepath[len(normClientPath):] return filepath def serverFNToClientFN(self, filename): """Converts a filename on the server to a filename on the client. Currently just generates URLs. If you want to be able to set breakpoints when running the client in a different environment from the server, you'll need to expand this. """ from Explorers.Explorer import splitURI if self.serverClientPaths: normFilepath = os.path.normcase(filename) for serverPath, clientPath in self.serverClientPaths: normServerPath = os.path.normcase(serverPath) if normFilepath.startswith(normServerPath): return splitURI(clientPath+normFilepath[len(normServerPath):])[3] return splitURI(filename)[3] def deleteBreakpoints(self, filename, lineno): fn = self.clientFNToServerFN(filename) self.invokeInDebugger('clearBreakpoints', (fn, lineno)) self.breakpts.refreshList() def adjustBreakpoints(self, filename, lineno, delta): fn = self.clientFNToServerFN(filename) self.invokeInDebugger('adjustBreakpoints', (fn, lineno, delta)) self.breakpts.refreshList() def setBreakpoint(self, filename, lineno, tmp): fn = self.clientFNToServerFN(filename) self.invokeInDebugger('addBreakpoint', (fn, lineno, tmp)) self.breakpts.refreshList() def requestDebuggerStatus(self): self.sb.updateState('Waiting...', 'busy') self.invokeInDebugger('getStatusSummary', (), 'receiveDebuggerStatus') def receiveDebuggerStatus(self, info): self.updateErrOutWindow() self.setDebugFile(self.filename) # Determine the current lineno, filename, and # funcname from the stack. # Update call stack stack = info['stack'] # Translate server filenames to client filenames. for frame in stack: frame['client_filename'] = ( self.serverFNToClientFN(frame['filename'])) # Determine the current lineno, filename, and # funcname from the stack. if stack: bottom = stack[-1] filename = bottom['client_filename'] funcname = bottom['funcname'] lineno = bottom['lineno'] base = os.path.basename(filename) else: filename = funcname = lineno = base = '' # Show running status. self.running = info['running'] if self.running: message = "%s:%s" % (base, lineno) if funcname != "?": message = "%s: %s()" % (message, funcname) else: message = _('Finished.') self.sb.updateInstructionPtr(message) # Show exception information. exc_type = info.get('exc_type', None) exc_value = info.get('exc_value', None) if exc_type is not None: m1 = exc_type if exc_value is not None: try: m1 = "%s: %s" % (m1, str(exc_value)) except: m1 = 'internal error' self.sb.updateState(m1) else: self.sb.updateState(_('Ready.'), 'info') # Load the stack view. sv = self.stackView if sv: i = info['frame_stack_len'] sv.load_stack(stack, i) sv.selectCurrentEntry() # Update breakpoints view with stats. breaks = info['breaks'] for item in breaks: item['client_filename'] = self.serverFNToClientFN( item['filename']) self.breakpts.updateBreakpointStats(breaks) self.breakpts.refreshList() # If at a breakpoint, display status. if bplist.hasBreakpoint(filename, lineno): bplist.clearTemporaryBreakpoints(filename, lineno) self.sb.updateState(_('Breakpoint.'), 'break') self.breakpts.selectBreakpoint(filename, lineno) self.selectSourceLine(filename, lineno) # All info in watches, locals, and globals panes is now invalid. self.invalidatePanes() # Update the currently selected pane. self.updateSelectedPane() # Receive stream data even if the user isn't looking. self.updateErrOutWindow() self.restoreDebugger() self.refreshTools() def restoreDebugger(self): if self.editor: if self.editor.palette.IsShown(): if self.editor.palette.IsIconized(): self.editor.palette.restore() self.editor.restore() elif self.editor.IsIconized(): self.editor.restore() def clearStepPos(self): if self.lastStepView is not None: if hasattr(self.lastStepView, 'clearStepPos'): self.lastStepView.clearStepPos(self.lastStepLineno) self.lastStepView = None def getEditorSourceView(self, filename): if self.editor.modules.has_key(filename): return self.editor.modules[filename].model.getSourceView() else: return None def selectSourceLine(self, filename, lineno): if self.isSourceTracing(): self.clearStepPos() if not filename: return #self.editor.SetFocus() try: self.editor.openOrGotoModule(filename) except Exception, err: self.editor.setStatus( _('Debugger: Failed to open file %s')%filename, 'Error') else: model = self.editor.getActiveModulePage().model view = model.getSourceView() if view is not None: view.focus(False) #view.selectLine(lineno - 1) view.GotoLine(lineno - 1) if hasattr(view, 'setStepPos'): view.setStepPos(lineno - 1) else: view.selectLine(lineno - 1) self.lastStepView = view self.lastStepLineno = lineno - 1
class DebuggerFrame(wx.Frame, Utils.FrameRestorerMixin): debug_client = None _destroyed = 0 _closing = 0 def __init__(self, editor, filename=None, slave_mode=1): wx.Frame.__init__(self, editor, -1, _('Debugger'), style=wx.DEFAULT_FRAME_STYLE | wx.CLIP_CHILDREN | Preferences.childFrameStyle) self.winConfOption = 'debugger' self.loadDims() self.editor = editor self.running = 0 self.slave_mode = slave_mode if filename: self.setDebugFile(filename) else: self.filename = '' self.SetIcon(IS.load('Images/Icons/Debug.ico')) self.viewsImgLst = wx.ImageList(16, 16) self.viewsImgLst.Add(IS.load('Images/Debug/Stack.png')) self.viewsImgLst.Add(IS.load('Images/Debug/Breakpoints.png')) self.viewsImgLst.Add(IS.load('Images/Debug/Watches.png')) self.viewsImgLst.Add(IS.load('Images/Debug/Locals.png')) self.viewsImgLst.Add(IS.load('Images/Debug/Globals.png')) self.viewsImgLst.Add(IS.load('Images/Debug/Output.png')) self.invalidatePanes() self.sb = DebugStatusBar(self) self.SetStatusBar(self.sb) self.toolbar = wx.ToolBar(self, -1, style=wx.TB_HORIZONTAL | wx.NO_BORDER | flatTools) self.SetToolBar(self.toolbar) self.runId = Utils.AddToolButtonBmpIS( self, self.toolbar, 'Images/Debug/Debug.png', _('Debug/Continue - %s') % keyDefs['Debug'][2], self.OnDebug) #, runs in debugger, stops at breaks and exceptions' self.runFullSpdId = Utils.AddToolButtonBmpIS( self, self.toolbar, 'Images/Debug/DebugFullSpeed.png', _('Debug/Continue full speed'), self.OnDebugFullSpeed ) #'stops only at hard (code) breaks and exceptions' self.stepId = Utils.AddToolButtonBmpIS( self, self.toolbar, 'Images/Debug/Step.png', _('Step - %s') % keyDefs['DebugStep'][2], self.OnStep) self.overId = Utils.AddToolButtonBmpIS( self, self.toolbar, 'Images/Debug/Over.png', _('Over - %s') % keyDefs['DebugOver'][2], self.OnOver) self.outId = Utils.AddToolButtonBmpIS( self, self.toolbar, 'Images/Debug/Out.png', _('Out - %s') % keyDefs['DebugOut'][2], self.OnOut) self.jumpId = -1 if sys.version_info[:2] >= (2, 3): self.jumpId = Utils.AddToolButtonBmpIS(self, self.toolbar, 'Images/Debug/Jump.png', _('Jump to line'), self.OnJump) self.pauseId = Utils.AddToolButtonBmpIS(self, self.toolbar, 'Images/Debug/Pause.png', _('Pause'), self.OnPause) self.stopId = Utils.AddToolButtonBmpIS(self, self.toolbar, 'Images/Debug/Stop.png', _('Stop'), self.OnStop) self.toolbar.AddSeparator() self.sourceTraceId = Utils.AddToolButtonBmpIS( self, self.toolbar, 'Images/Debug/SourceTrace-Off.png', _('Trace in source'), self.OnSourceTrace, '1') self.debugBrowseId = Utils.AddToolButtonBmpIS( self, self.toolbar, 'Images/Debug/DebugBrowse.png', _('Debug browsing'), self.OnDebugBrowse, '1') if Preferences.psPythonShell == 'Shell': self.shellNamespaceId = Utils.AddToolButtonBmpIS( self, self.toolbar, 'Images/Debug/ShellDebug.png', _('Eval in shell'), self.OnDebugNamespace, '1') else: self.shellNamespaceId = -1 self.toolbar.AddSeparator() self.pathMappingsId = Utils.AddToolButtonBmpIS( self, self.toolbar, 'Images/Debug/PathMapping.png', _('Edit client/server path mappings...'), self.OnPathMappings) self.splitOrientId = Utils.AddToolButtonBmpIS( self, self.toolbar, 'Images/Debug/SplitOrient.png', _('Toggle split orientation'), self.OnToggleSplitOrient) self.SetAcceleratorTable( wx.AcceleratorTable([ (keyDefs['Debug'][0], keyDefs['Debug'][1], self.runId), (keyDefs['DebugStep'][0], keyDefs['DebugStep'][1], self.stepId), (keyDefs['DebugOver'][0], keyDefs['DebugOver'][1], self.overId), (keyDefs['DebugOut'][0], keyDefs['DebugOut'][1], self.outId) ])) self.toolbar.Realize() self.toolbar.ToggleTool(self.sourceTraceId, True) self.toolbar.ToggleTool(self.debugBrowseId, False) self.splitter = wx.SplitterWindow(self, -1, style=wx.SP_NOBORDER | Preferences.splitterStyle) (stackImgIdx, breaksImgIdx, watchesImgIdx, localsImgIdx, globalsImgIdx) = range(5) # Create a Notebook self.nbTop = wx.Notebook(self.splitter, wxID_TOPPAGECHANGED) self.nbTop.SetImageList(self.viewsImgLst) self.stackView = StackViewCtrl(self.nbTop, None, self) self.nbTop.AddPage(self.stackView, _('Stack'), imageId=stackImgIdx) self.breakpts = BreakViewCtrl(self.nbTop, self) self.nbTop.AddPage(self.breakpts, _('Breakpoints'), imageId=breaksImgIdx) # Create a Notebook self.nbBottom = wx.Notebook(self.splitter, wxID_PAGECHANGED, style=wx.CLIP_CHILDREN) self.nbBottom.Bind(wx.EVT_NOTEBOOK_PAGE_CHANGED, self.OnPageChange, id=wxID_PAGECHANGED) self.nbBottom.SetImageList(self.viewsImgLst) self.watches = WatchViewCtrl(self.nbBottom, self.viewsImgLst, self) self.nbBottom.AddPage(self.watches, _('Watches'), imageId=watchesImgIdx) self.locs = NamespaceViewCtrl(self.nbBottom, self, 1, 'local') self.nbBottom.AddPage(self.locs, _('Locals'), imageId=localsImgIdx) self.globs = NamespaceViewCtrl(self.nbBottom, self, 0, 'global') self.nbBottom.AddPage(self.globs, _('Globals'), imageId=globalsImgIdx) self.splitter.SetMinimumPaneSize(40) self.splitter.SplitHorizontally(self.nbTop, self.nbBottom) self.splitter.SetSashPosition(175) self.splitter.SetSplitMode(wx.SPLIT_HORIZONTAL) self.mlc = 0 self.frame = None self.lastStepView = None self.lastStepLineno = -1 self.stepping_enabled = 1 self.setParams([]) self.setServerClientPaths([]) self.Bind(EVT_DEBUGGER_OK, self.OnDebuggerOk, id=self.GetId()) self.Bind(EVT_DEBUGGER_EXC, self.OnDebuggerException, id=self.GetId()) self.Bind(EVT_DEBUGGER_STOPPED, self.OnDebuggerStopped, id=self.GetId()) # used to indicate when the debugger start, # would be better if there was a start event in addition to the OK event self._pid = None self._erroutFrm = self.editor.erroutFrm self.stream_timer = wx.PyTimer(self.OnStreamTimer) self.stream_timer.Start(100) self.Bind(wx.EVT_MENU_HIGHLIGHT_ALL, self.OnToolOver) self.Bind(wx.EVT_CLOSE, self.OnCloseWindow) def destroy(self): if self._destroyed: return self._destroyed = 1 self.breakpts.destroy() self.watches.destroy() self.locs.destroy() self.globs.destroy() self.sb.stateCols = None if self.stream_timer is not None: self.stream_timer.Stop() self.stream_timer = None def setDefaultDimensions(self): self.SetDimensions(0, Preferences.underPalette, Preferences.inspWidth, Preferences.bottomHeight) _sashes_inited = 0 def initSashes(self): if not self._sashes_inited: s = self.GetSize() if s.x / float(s.y) > 1: mode = wx.SPLIT_HORIZONTAL else: mode = wx.SPLIT_VERTICAL self.splitter.SetSplitMode(mode) self.OnToggleSplitOrient() self._sashes_inited = 1 def add_watch(self, name, local): self.watches.add_watch(name, local) self.nbBottom.SetSelection(0) self.invalidatePanes() self.updateSelectedPane() def OnPageChange(self, event): sel = event.GetSelection() if sel >= 0: self.updateSelectedPane(sel) event.Skip() def invalidatePanes(self): self.updated_panes = [0, 0, 0] def updateSelectedPane(self, pageno=-1, do_request=1, force=0): if pageno < 0: pageno = self.nbBottom.GetSelection() if not self.updated_panes[pageno] or force: frameno = self.stackView.getSelection() if pageno == 0: self.watches.showLoading() if do_request: self.requestWatches(frameno) else: if pageno == 1: self.locs.showLoading() else: self.globs.showLoading() if do_request: self.requestDict((pageno == 1), frameno) def requestWatches(self, frameno): ws = self.watches.watches exprs = [] for name, local in ws: exprs.append({'name': name, 'local': local}) if exprs: self.invokeInDebugger('evaluateWatches', (exprs, frameno), 'receiveWatches') else: # No exprs, so no request is necessary. self.watches.load_dict(None) self.updated_panes[0] = 1 def receiveWatches(self, status): frameno = status['frameno'] if frameno == self.stackView.getSelection(): self.updated_panes[0] = 1 self.watches.load_dict(status['watches']) else: # Re-request. self.updateSelectedPane() def requestDict(self, locs, frameno): self.invokeInDebugger('getSafeDict', (locs, frameno), 'receiveDict') def receiveDict(self, status): frameno = status['frameno'] if frameno == self.stackView.getSelection(): if status.has_key('locals'): self.updated_panes[1] = 1 self.locs.load_dict(status['locals']) if status.has_key('globals'): self.updated_panes[2] = 1 self.globs.load_dict(status['globals']) else: # Re-request. self.updateSelectedPane() def requestWatchSubobjects(self, name, local, pos): self.invokeInDebugger('getWatchSubobjects', (name, self.stackView.getSelection()), 'receiveWatchSubobjects', (name, local, pos)) def receiveWatchSubobjects(self, subnames, name, local, pos): for subname in subnames: self.watches.add_watch('%s.%s' % (name, subname), local, pos) pos = pos + 1 self.nbBottom.SetSelection(0) self.invalidatePanes() self.updateSelectedPane() def requestVarValue(self, name): self.invokeInDebugger('pprintVarValue', (name, self.stackView.getSelection()), 'receiveVarValue') def receiveVarValue(self, val): if val: self.editor.setStatus(val) def getVarValue(self, name): if not name.strip(): return None self._hasReceivedVal = 0 self._receivedVal = None self.invokeInDebugger('pprintVarValue', (name, self.stackView.getSelection()), 'receiveVarValue2') # XXX I'm not comfortable with this... try: while not self._hasReceivedVal: wx.Yield() return self._receivedVal finally: del self._hasReceivedVal del self._receivedVal def receiveVarValue2(self, val): self._receivedVal = val self._hasReceivedVal = 1 def valueToOutput(self, name): val = self.getVarValue(name) self.editor.erroutFrm.outputTC.SetValue('') self.editor.erroutFrm.appendToOutput(val) #--------------------------------------------------------------------------- def setParams(self, params): self.params = params def setDebugFile(self, filename): self.filename = filename title = '%s - %s' % (os.path.basename(filename), filename) self.setTitleInfo(title) def setTitleInfo(self, info): pidinfo = '' if self.debug_client: pid = self.debug_client.getProcessId() if pid: pidinfo = '(%s) ' % pid title = _('Debugger %s- %s') % (pidinfo, info) self.SetTitle(title) def setDebugClient(self, client=None): if client is None: from ChildProcessClient import ChildProcessClient client = ChildProcessClient(self, Preferences.debugServerArgs) self.debug_client = client def setServerClientPaths(self, paths): self.serverClientPaths = paths def invokeInDebugger(self, m_name, m_args=(), r_name=None, r_args=()): """ Invokes a method asynchronously in the debugger, possibly expecting a debugger event to be generated when finished. """ self.debug_client.invokeOnServer(m_name, m_args, r_name, r_args) def killDebugger(self): if self._destroyed: return self.running = 0 if self.debug_client: try: self.debug_client.kill() except: print _( 'Error on killing debugger: %s: %s') % sys.exc_info()[:2] self.clearViews() def OnDebuggerStopped(self, event): """Called when a debugger process stops.""" show_dialog = 0 if self.running: show_dialog = 1 self.killDebugger() if self._closing: # Close the window. self.destroy() self.Destroy() elif show_dialog: wx.MessageBox(_('The debugger process stopped prematurely.'), _('Debugger stopped'), wx.OK | wx.ICON_EXCLAMATION | wx.CENTRE) if self._pid: self._erroutFrm.processFinished(self._pid) self._pid = None def OnStreamTimer(self, event=None): if self.stream_timer: self.updateErrOutWindow() def updateErrOutWindow(self): if self.debug_client: info = self.debug_client.pollStreams() if info and self.editor: stdout_text, stderr_text = info if stdout_text: self.editor.erroutFrm.appendToOutput(stdout_text) if stderr_text: self.editor.erroutFrm.appendToErrors(stderr_text) def OnDebuggerOk(self, event): if self._destroyed: return if self._pid is None and self.debug_client: self._pid = self.debug_client.getProcessId() script = os.path.basename(self.filename) intp = os.path.basename(self.debug_client.pyIntpPath) if intp: self._erroutFrm.processStarted(intp, self._pid, script, 'Debug') self.restoreDebugger() self.enableStepping() receiver_name = event.GetReceiverName() if receiver_name is not None: rcv = getattr(self, receiver_name) rcv(*((event.GetResult(), ) + event.GetReceiverArgs())) def OnDebuggerException(self, event): if self._destroyed: return self.enableStepping() t, v = event.GetExc() if isinstance(v, EmptyResponseError): if not self.debug_client or not self.debug_client.isAlive(): # If the debugger was killed, this exception is normal. return self.restoreDebugger() if hasattr(t, '__name__'): t = t.__name__ msg = '%s: %s.' % (t, v) confirm = wx.MessageBox( _('%s\n\nStop debugger?') % msg, _('Debugger Communication Exception'), wx.YES_NO | wx.YES_DEFAULT | wx.ICON_EXCLAMATION | wx.CENTRE) == wx.YES if confirm: self.killDebugger() def runProcess(self, autocont=0): self.running = 1 self.sb.updateState(_('Waiting...'), 'busy') brks = bplist.getBreakpointList() for brk in brks: brk['filename'] = self.clientFNToServerFN(brk['filename']) if self.slave_mode: # Work with a child process. add_paths = simplifyPathList(pyPath) add_paths = map(self.clientFNToServerFN, add_paths) filename = self.clientFNToServerFN(self.filename) self.invokeInDebugger( 'runFileAndRequestStatus', (filename, self.params or [], autocont, add_paths, brks), 'receiveDebuggerStatus') else: # Work with a peer or remote process. self.invokeInDebugger('setupAndRequestStatus', (autocont, brks), 'receiveDebuggerStatus') # InProcessClient TODO: setup the execution environment # the way it used to be done. def proceedAndRequestStatus(self, command, temp_breakpoint=None, args=()): # Non-blocking. self.sb.updateState(_('Running...'), 'busy') if not temp_breakpoint: temp_breakpoint = 0 self.invokeInDebugger('proceedAndRequestStatus', (command, temp_breakpoint, args), 'receiveDebuggerStatus') def clientFNToServerFN(self, filename): """Converts a filename on the client to a filename on the server. Currently just turns file URLs into paths. If you want to be able to set breakpoints when running the client in a different environment from the server, you'll need to expand this. """ # XXX should we .fncache this? Files changing names are undefined # XXX during the lifetime of the debugger from Explorers.Explorer import splitURI, getTransport from Explorers.ExplorerNodes import all_transports prot, category, filepath, filename = splitURI(filename) if prot == 'zope': node = getTransport(prot, category, filepath, all_transports) if node: props = node.properties return 'zopedebug://%s:%s/%s/%s' % ( props['host'], props['httpport'], filepath, node.metatype) else: raise Exception(_('No Zope connection for: %s') % filename) elif prot == 'zopedebug': raise Exception(_('"zopedebug" is a server filename protocol')) else: #if prot == 'file': if self.serverClientPaths: normFilepath = os.path.normcase(filepath) for serverPath, clientPath in self.serverClientPaths: normClientPath = os.path.normcase(clientPath) if normFilepath.startswith(normClientPath): return serverPath + normFilepath[len(normClientPath):] return filepath def serverFNToClientFN(self, filename): """Converts a filename on the server to a filename on the client. Currently just generates URLs. If you want to be able to set breakpoints when running the client in a different environment from the server, you'll need to expand this. """ from Explorers.Explorer import splitURI if self.serverClientPaths: normFilepath = os.path.normcase(filename) for serverPath, clientPath in self.serverClientPaths: normServerPath = os.path.normcase(serverPath) if normFilepath.startswith(normServerPath): return splitURI(clientPath + normFilepath[len(normServerPath):])[3] return splitURI(filename)[3] def deleteBreakpoints(self, filename, lineno): fn = self.clientFNToServerFN(filename) self.invokeInDebugger('clearBreakpoints', (fn, lineno)) self.breakpts.refreshList() def adjustBreakpoints(self, filename, lineno, delta): fn = self.clientFNToServerFN(filename) self.invokeInDebugger('adjustBreakpoints', (fn, lineno, delta)) self.breakpts.refreshList() def setBreakpoint(self, filename, lineno, tmp): fn = self.clientFNToServerFN(filename) self.invokeInDebugger('addBreakpoint', (fn, lineno, tmp)) self.breakpts.refreshList() def requestDebuggerStatus(self): self.sb.updateState('Waiting...', 'busy') self.invokeInDebugger('getStatusSummary', (), 'receiveDebuggerStatus') def receiveDebuggerStatus(self, info): self.updateErrOutWindow() self.setDebugFile(self.filename) # Determine the current lineno, filename, and # funcname from the stack. # Update call stack stack = info['stack'] # Translate server filenames to client filenames. for frame in stack: frame['client_filename'] = (self.serverFNToClientFN( frame['filename'])) # Determine the current lineno, filename, and # funcname from the stack. if stack: bottom = stack[-1] filename = bottom['client_filename'] funcname = bottom['funcname'] lineno = bottom['lineno'] base = os.path.basename(filename) else: filename = funcname = lineno = base = '' # Show running status. self.running = info['running'] if self.running: message = "%s:%s" % (base, lineno) if funcname != "?": message = "%s: %s()" % (message, funcname) else: message = _('Finished.') self.sb.updateInstructionPtr(message) # Show exception information. exc_type = info.get('exc_type', None) exc_value = info.get('exc_value', None) if exc_type is not None: m1 = exc_type if exc_value is not None: try: m1 = "%s: %s" % (m1, str(exc_value)) except: m1 = 'internal error' self.sb.updateState(m1) else: self.sb.updateState(_('Ready.'), 'info') # Load the stack view. sv = self.stackView if sv: i = info['frame_stack_len'] sv.load_stack(stack, i) sv.selectCurrentEntry() # Update breakpoints view with stats. breaks = info['breaks'] for item in breaks: item['client_filename'] = self.serverFNToClientFN(item['filename']) self.breakpts.updateBreakpointStats(breaks) self.breakpts.refreshList() # If at a breakpoint, display status. if bplist.hasBreakpoint(filename, lineno): bplist.clearTemporaryBreakpoints(filename, lineno) self.sb.updateState(_('Breakpoint.'), 'break') self.breakpts.selectBreakpoint(filename, lineno) self.selectSourceLine(filename, lineno) # All info in watches, locals, and globals panes is now invalid. self.invalidatePanes() # Update the currently selected pane. self.updateSelectedPane() # Receive stream data even if the user isn't looking. self.updateErrOutWindow() self.restoreDebugger() self.refreshTools() def restoreDebugger(self): if self.editor: if self.editor.palette.IsShown(): if self.editor.palette.IsIconized(): self.editor.palette.restore() self.editor.restore() elif self.editor.IsIconized(): self.editor.restore() def clearStepPos(self): if self.lastStepView is not None: if hasattr(self.lastStepView, 'clearStepPos'): self.lastStepView.clearStepPos(self.lastStepLineno) self.lastStepView = None def getEditorSourceView(self, filename): if self.editor.modules.has_key(filename): return self.editor.modules[filename].model.getSourceView() else: return None def selectSourceLine(self, filename, lineno): if self.isSourceTracing(): self.clearStepPos() if not filename: return #self.editor.SetFocus() try: self.editor.openOrGotoModule(filename) except Exception, err: self.editor.setStatus( _('Debugger: Failed to open file %s') % filename, 'Error') else: model = self.editor.getActiveModulePage().model view = model.getSourceView() if view is not None: view.focus(False) #view.selectLine(lineno - 1) view.GotoLine(lineno - 1) if hasattr(view, 'setStepPos'): view.setStepPos(lineno - 1) else: view.selectLine(lineno - 1) self.lastStepView = view self.lastStepLineno = lineno - 1