📄 debuggerservice.py
字号:
def LoadPythonFramesList(self, framesXML):
self.framesTab.LoadFramesList(framesXML)
def Execute(self, initialArgs, startIn, environment, onWebServer = False):
self._callback.Start()
self._executor.Execute(initialArgs, startIn, environment)
self._callback.WaitForRPC()
def StopExecution(self, event):
# This is a general comment on shutdown for the running and debugged processes. Basically, the
# current state of this is the result of trial and error coding. The common problems were memory
# access violations and threads that would not exit. Making the OutputReaderThreads daemons seems
# to have side-stepped the hung thread issue. Being very careful not to touch things after calling
# process.py:ProcessOpen.kill() also seems to have fixed the memory access violations, but if there
# were more ugliness discovered I would not be surprised. If anyone has any help/advice, please send
# it on to mfryer@activegrid.com.
if not self._stopped:
self._stopped = True
try:
self.DisableAfterStop()
except wx._core.PyDeadObjectError:
pass
try:
self._callback.ShutdownServer()
except:
tp,val,tb = sys.exc_info()
traceback.print_exception(tp, val, tb)
try:
self.DeleteCurrentLineMarkers()
except:
pass
try:
PythonDebuggerUI.ReturnPortToPool(self._debuggerPort)
PythonDebuggerUI.ReturnPortToPool(self._guiPort)
PythonDebuggerUI.ReturnPortToPool(self._debuggerBreakPort)
except:
pass
try:
if self._executor:
self._executor.DoStopExecution()
self._executor = None
except:
tp,val,tb = sys.exc_info()
traceback.print_exception(tp, val, tb)
def MakeFramesUI(self, parent, id, debugger):
panel = PythonFramesUI(parent, id, self)
return panel
class BreakpointsUI(wx.Panel):
def __init__(self, parent, id, ui):
wx.Panel.__init__(self, parent, id)
self._ui = ui
self.currentItem = None
self.clearBPID = wx.NewId()
self.Bind(wx.EVT_MENU, self.ClearBreakPoint, id=self.clearBPID)
self.syncLineID = wx.NewId()
self.Bind(wx.EVT_MENU, self.SyncBPLine, id=self.syncLineID)
sizer = wx.BoxSizer(wx.VERTICAL)
p1 = self
self._bpListCtrl = wx.ListCtrl(p1, -1, pos=wx.DefaultPosition, size=(1000,1000), style=wx.LC_REPORT)
sizer.Add(self._bpListCtrl, 1, wx.ALIGN_LEFT|wx.ALL|wx.EXPAND, 1)
self._bpListCtrl.InsertColumn(0, "File")
self._bpListCtrl.InsertColumn(1, "Line")
self._bpListCtrl.InsertColumn(2, "Path")
self._bpListCtrl.SetColumnWidth(0, 150)
self._bpListCtrl.SetColumnWidth(1, 50)
self._bpListCtrl.SetColumnWidth(2, 450)
self._bpListCtrl.Bind(wx.EVT_LIST_ITEM_RIGHT_CLICK, self.OnListRightClick)
self.Bind(wx.EVT_LIST_ITEM_SELECTED, self.ListItemSelected, self._bpListCtrl)
self.Bind(wx.EVT_LIST_ITEM_DESELECTED, self.ListItemDeselected, self._bpListCtrl)
def OnLeftDoubleClick(event):
self.SyncBPLine(event)
wx.EVT_LEFT_DCLICK(self._bpListCtrl, OnLeftDoubleClick)
self.PopulateBPList()
p1.SetSizer(sizer)
sizer.Fit(p1)
p1.Layout()
def PopulateBPList(self):
list = self._bpListCtrl
list.DeleteAllItems()
bps = wx.GetApp().GetService(DebuggerService).GetMasterBreakpointDict()
index = 0
for fileName in bps.keys():
shortFile = os.path.basename(fileName)
lines = bps[fileName]
if lines:
for line in lines:
list.InsertStringItem(index, shortFile)
list.SetStringItem(index, 1, str(line))
list.SetStringItem(index, 2, fileName)
def OnListRightClick(self, event):
menu = wx.Menu()
item = wx.MenuItem(menu, self.clearBPID, "Clear Breakpoint")
menu.AppendItem(item)
item = wx.MenuItem(menu, self.syncLineID, "Goto Source Line")
menu.AppendItem(item)
self.PopupMenu(menu, event.GetPosition())
menu.Destroy()
def SyncBPLine(self, event):
if self.currentItem != -1:
list = self._bpListCtrl
fileName = list.GetItem(self.currentItem, 2).GetText()
lineNumber = list.GetItem(self.currentItem, 1).GetText()
self._ui.SynchCurrentLine( fileName, int(lineNumber) , noArrow=True)
def ClearBreakPoint(self, event):
if self.currentItem >= 0:
list = self._bpListCtrl
fileName = list.GetItem(self.currentItem, 2).GetText()
lineNumber = list.GetItem(self.currentItem, 1).GetText()
wx.GetApp().GetService(DebuggerService).OnToggleBreakpoint(None, line=int(lineNumber) -1, fileName=fileName )
def ListItemSelected(self, event):
self.currentItem = event.m_itemIndex
def ListItemDeselected(self, event):
self.currentItem = -1
class Watch:
CODE_ALL_FRAMES = 1
CODE_THIS_BLOCK = 2
CODE_THIS_LINE = 4
CODE_RUN_ONCE = 8
def __init__(self, name, command, show_code=CODE_ALL_FRAMES):
self._name = name
self._command = command
self._show_code = show_code
class WatchDialog(wx.Dialog):
WATCH_ALL_FRAMES = "Watch in all frames"
WATCH_THIS_FRAME = "Watch in this frame only"
WATCH_ONCE = "Watch once and delete"
def __init__(self, parent, title, chain):
wx.Dialog.__init__(self, parent, -1, title, style=wx.DEFAULT_DIALOG_STYLE)
self._chain = chain
self.label_2 = wx.StaticText(self, -1, "Watch Name:")
self._watchNameTextCtrl = wx.TextCtrl(self, -1, "")
self.label_3 = wx.StaticText(self, -1, "eval(", style=wx.ALIGN_RIGHT)
self._watchValueTextCtrl = wx.TextCtrl(self, -1, "")
self.label_4 = wx.StaticText(self, -1, ",frame.f_globals, frame.f_locals)")
self.radio_box_1 = wx.RadioBox(self, -1, "Watch Information", choices=[WatchDialog.WATCH_ALL_FRAMES, WatchDialog.WATCH_THIS_FRAME, WatchDialog.WATCH_ONCE], majorDimension=0, style=wx.RA_SPECIFY_ROWS)
self._okButton = wx.Button(self, wx.ID_OK, "OK")
self._okButton.SetDefault()
self._okButton.SetHelpText(_("The OK button completes the dialog"))
def OnOkClick(event):
if self._watchNameTextCtrl.GetValue() == "":
wx.MessageBox(_("You must enter a name for the watch."), _("Add Watch"))
return
if self._watchValueTextCtrl.GetValue() == "":
wx.MessageBox(_("You must enter some code to run for the watch."), _("Add Watch"))
return
self.EndModal(wx.ID_OK)
self.Bind(wx.EVT_BUTTON, OnOkClick, self._okButton)
self._cancelButton = wx.Button(self, wx.ID_CANCEL, _("Cancel"))
self._cancelButton.SetHelpText(_("The Cancel button cancels the dialog."))
self.__set_properties()
self.__do_layout()
def GetSettings(self):
return self._watchNameTextCtrl.GetValue(), self._watchValueTextCtrl.GetValue(), self.GetSendFrame(), self.GetRunOnce()
def GetSendFrame(self):
return (WatchDialog.WATCH_ALL_FRAMES != self.radio_box_1.GetStringSelection())
def GetRunOnce(self):
return (WatchDialog.WATCH_ONCE == self.radio_box_1.GetStringSelection())
def __set_properties(self):
self.SetTitle("Add a Watch")
#self.SetSize((400, 250))
self.radio_box_1.SetSelection(0)
def __do_layout(self):
sizer_1 = wx.BoxSizer(wx.VERTICAL)
grid_sizer_4 = wx.FlexGridSizer(1, 3, 5, 5)
grid_sizer_2 = wx.FlexGridSizer(1, 2, 5, 5)
grid_sizer_2.Add(self.label_2, 0, wx.ALIGN_CENTER_VERTICAL|wx.FIXED_MINSIZE, 0)
grid_sizer_2.Add(self._watchNameTextCtrl, 0, wx.EXPAND, 0)
grid_sizer_2.AddGrowableCol(1)
sizer_1.Add(grid_sizer_2, 1, wx.EXPAND, 0)
grid_sizer_4.Add(self.label_3, 0, wx.ALIGN_CENTER_VERTICAL|wx.FIXED_MINSIZE, 0)
grid_sizer_4.Add(self._watchValueTextCtrl, 0, wx.EXPAND, 0)
grid_sizer_4.AddGrowableCol(1)
grid_sizer_4.Add(self.label_4, 0, wx.ALIGN_CENTER_VERTICAL|wx.FIXED_MINSIZE, 0)
sizer_1.Add(grid_sizer_4, 0, wx.EXPAND, 0)
sizer_1.Add(self.radio_box_1, 0, wx.EXPAND, 0)
box = wx.BoxSizer(wx.HORIZONTAL)
box.Add(self._okButton, 0, wx.ALIGN_RIGHT|wx.ALL, 5)
box.Add(self._cancelButton, 0, wx.ALIGN_RIGHT|wx.ALL, 5)
sizer_1.Add(box, 1, wx.EXPAND, 0)
self.SetSizer(sizer_1)
self.Layout()
class BaseFramesUI(wx.SplitterWindow):
def __init__(self, parent, id, ui):
wx.SplitterWindow.__init__(self, parent, id, style = wx.SP_3D)
self._ui = ui
self._p1 = p1 = wx.ScrolledWindow(self, -1)
sizer = wx.BoxSizer(wx.HORIZONTAL)
framesLabel = wx.StaticText(self, -1, "Stack Frame:")
sizer.Add(framesLabel, 0, flag=wx.ALIGN_CENTER_VERTICAL|wx.ALIGN_LEFT|wx.LEFT, border=2)
self._framesChoiceCtrl = wx.Choice(p1, -1, choices=[" "])
sizer.Add(self._framesChoiceCtrl, 1, wx.ALIGN_LEFT|wx.ALL|wx.EXPAND, 1)
self._framesChoiceCtrl.Bind(wx.EVT_LIST_ITEM_RIGHT_CLICK, self.OnListRightClick)
self.Bind(wx.EVT_CHOICE, self.ListItemSelected, self._framesChoiceCtrl)
sizer2 = wx.BoxSizer(wx.VERTICAL)
p1.SetSizer(sizer2)
self._treeCtrl = wx.gizmos.TreeListCtrl(p1, -1, style=wx.TR_DEFAULT_STYLE| wx.TR_FULL_ROW_HIGHLIGHT)
self._treeCtrl.Bind(wx.EVT_TREE_ITEM_RIGHT_CLICK, self.OnRightClick)
sizer2.Add(sizer, 0, wx.ALIGN_LEFT|wx.ALL|wx.EXPAND, 1)
sizer2.Add(self._treeCtrl,1, wx.ALIGN_LEFT|wx.ALL|wx.EXPAND, 1)
tree = self._treeCtrl
tree.AddColumn("Thing")
tree.AddColumn("Value")
tree.SetMainColumn(0) # the one with the tree in it...
tree.SetColumnWidth(0, 175)
tree.SetColumnWidth(1, 355)
self._root = tree.AddRoot("Frame")
tree.SetPyData(self._root, "root")
tree.SetItemText(self._root, "", 1)
tree.Bind(wx.EVT_TREE_ITEM_EXPANDING, self.IntrospectCallback)
self._p2 = p2 = wx.Window(self, -1)
sizer3 = wx.BoxSizer(wx.HORIZONTAL)
p2.SetSizer(sizer3)
p2.Bind(wx.EVT_SIZE, self.OnSize)
self._notebook = wx.Notebook(p2, -1, size=(20,20))
self._notebook.Hide()
sizer3.Add(self._notebook, 1, wx.ALIGN_LEFT|wx.ALL|wx.EXPAND, 1)
self.consoleTab = self.MakeConsoleTab(self._notebook, wx.NewId())
self.inspectConsoleTab = self.MakeInspectConsoleTab(self._notebook, wx.NewId())
self.breakPointsTab = self.MakeBreakPointsTab(self._notebook, wx.NewId())
self._notebook.AddPage(self.consoleTab, "Output")
self._notebook.AddPage(self.inspectConsoleTab, "Interact")
self._notebook.AddPage(self.breakPointsTab, "Break Points")
self.SetMinimumPaneSize(20)
self.SplitVertically(p1, p2, 550)
self.currentItem = None
self._notebook.Show(True)
def PopulateBPList(self):
self.breakPointsTab.PopulateBPList()
def OnSize(self, event):
self._notebook.SetSize(self._p2.GetSize())
def OnDoubleClick(self, event):
# Looking for a stack trace line.
lineText, pos = self._textCtrl.GetCurLine()
fileBegin = lineText.find("File \"")
fileEnd = lineText.find("\", line ")
lineEnd = lineText.find(", in ")
if lineText == "\n" or fileBegin == -1 or fileEnd == -1 or lineEnd == -1:
# Check the line before the one that was clicked on
lineNumber = self._textCtrl.GetCurrentLine()
if(lineNumber == 0):
return
lineText = self._textCtrl.GetLine(lineNumber - 1)
fileBegin = lineText.find("File \"")
fileEnd = lineText.find("\", line ")
lineEnd = lineText.find(", in ")
if lineText == "\n" or fileBegin == -1 or fileEnd == -1 or lineEnd == -1:
return
filename = lineText[fileBegin + 6:fileEnd]
lineNum = int(lineText[fileEnd + 8:lineEnd])
foundView = None
openDocs = wx.GetApp().GetDocumentManager().GetDocuments()
for openDoc in openDocs:
if openDoc.GetFilename() == filename:
foundView = openDoc.GetFirstView()
break
if not foundView:
doc = wx.GetApp().GetDocumentManager().CreateDocument(filename, wx.lib.docview.DOC_SILENT)
foundView = doc.GetFirstView()
if foundView:
foundView.GetFrame().SetFocus()
foundView.Activate()
foundView.GotoLine(lineNum)
startPos = foundView.PositionFromLine(lineNum)
lineText = foundView.GetCtrl().GetLine(lineNum - 1)
foundView.SetSelection(startPos, startPos + len(lineText.rstrip("\n")))
import OutlineService
wx.GetApp().GetService(OutlineService.OutlineService).LoadOutline(foundView, position=startPos)
def MakeConsoleTab(self, parent, id):
panel = wx.Panel(parent, id)
sizer = wx.BoxSizer(wx.HORIZONTAL)
self._textCtrl = STCTextEditor.TextCtrl(panel, wx.NewId())
sizer.Add(self._textCtrl, 1, wx.ALIGN_LEFT|wx.ALL|wx.EXPAND, 2)
self._textCtrl.SetViewLineNumbers(False)
self._textCtrl.SetReadOnly(True)
if wx.Platform == '__WXMSW__':
font = "Courier New"
else:
font = "Courier"
self._textCtrl.SetFont(wx.Font(9, wx.DEFAULT, wx.NORMAL, wx.NORMAL, faceName = font))
self._textCtrl.SetFontColor(wx.BLACK)
self._textCtrl.StyleClearAll()
wx.stc.EVT_STC_DOUBLECLICK(self._textCtrl, self._textCtrl.GetId(), self.OnDoubleClick)
panel.SetSizer(sizer)
#sizer.Fit(panel)
return panel
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -