]>
Commit | Line | Data |
---|---|---|
1f780e48 RD |
1 | #---------------------------------------------------------------------------- |
2 | # Name: DebuggerService.py | |
3 | # Purpose: Debugger Service for Python. | |
4 | # | |
5 | # Author: Matt Fryer | |
6 | # | |
7 | # Created: 12/9/04 | |
8 | # CVS-ID: $Id$ | |
9 | # Copyright: (c) 2004-2005 ActiveGrid, Inc. | |
10 | # License: wxWindows License | |
11 | #---------------------------------------------------------------------------- | |
12 | ||
13 | import wx | |
14 | import wx.lib.intctrl | |
15 | import wx.lib.docview | |
16 | import wx.lib.dialogs | |
17 | import wx.gizmos | |
18 | import wx._core | |
19 | import wx.lib.pydocview | |
20 | import Service | |
21 | import STCTextEditor | |
22 | import CodeEditor | |
23 | import PythonEditor | |
24 | from IDE import ACTIVEGRID_BASE_IDE | |
25 | if not ACTIVEGRID_BASE_IDE: | |
26 | import ProcessModelEditor | |
27 | import wx.lib.scrolledpanel as scrolled | |
28 | import sys | |
29 | import time | |
30 | import SimpleXMLRPCServer | |
31 | import xmlrpclib | |
32 | import os | |
33 | import threading | |
1f780e48 RD |
34 | import Queue |
35 | import SocketServer | |
36 | import ProjectEditor | |
37 | import types | |
38 | from xml.dom.minidom import parse, parseString | |
39 | import bz2 | |
40 | import pickle | |
41 | import DebuggerHarness | |
42 | import traceback | |
43 | import StringIO | |
44 | if wx.Platform == '__WXMSW__': | |
b792147d RD |
45 | try: |
46 | import win32api | |
47 | _PYWIN32_INSTALLED = True | |
48 | except ImportError: | |
49 | _PYWIN32_INSTALLED = False | |
1f780e48 RD |
50 | _WINDOWS = True |
51 | else: | |
52 | _WINDOWS = False | |
b792147d RD |
53 | |
54 | if not _WINDOWS or _PYWIN32_INSTALLED: | |
55 | import process | |
56 | ||
1f780e48 RD |
57 | _ = wx.GetTranslation |
58 | ||
59 | _VERBOSE = False | |
60 | _WATCHES_ON = False | |
61 | ||
62 | # Class to read from stdout or stderr and write the result to a text control. | |
63 | # Args: file=file-like object | |
64 | # callback_function= function that takes a single argument, the line of text | |
65 | # read. | |
66 | class OutputReaderThread(threading.Thread): | |
67 | def __init__(self, file, callback_function, callbackOnExit=None, accumulate=True): | |
68 | threading.Thread.__init__(self) | |
69 | self._file = file | |
70 | self._callback_function = callback_function | |
71 | self._keepGoing = True | |
72 | self._lineCount = 0 | |
73 | self._accumulate = accumulate | |
74 | self._callbackOnExit = callbackOnExit | |
75 | ||
76 | def run(self): | |
77 | file = self._file | |
78 | start = time.time() | |
79 | output = "" | |
80 | while self._keepGoing: | |
81 | try: | |
82 | # This could block--how to handle that? | |
83 | text = file.readline() | |
84 | if text == '' or text == None: | |
85 | self._keepGoing = False | |
86 | elif not self._accumulate: | |
87 | self._callback_function(text) | |
88 | else: | |
89 | # Should use a buffer? StringIO? | |
90 | output += text | |
91 | # Seems as though the read blocks if we got an error, so, to be | |
92 | # sure that at least some of the exception gets printed, always | |
93 | # send the first hundred lines back as they come in. | |
94 | if self._lineCount < 100: | |
95 | self._callback_function(output) | |
96 | self._lineCount += 1 | |
97 | output = "" | |
98 | elif time.time() - start > 0.25: | |
99 | try: | |
100 | self._callback_function(output) | |
101 | except wx._core.PyDeadObjectError: | |
102 | # GUI was killed while we were blocked. | |
103 | self._keepGoing = False | |
104 | start = time.time() | |
105 | output = "" | |
6f1a3f9c RD |
106 | except TypeError: |
107 | pass | |
1f780e48 RD |
108 | except: |
109 | tp, val, tb = sys.exc_info() | |
110 | print "Exception in OutputReaderThread.run():", tp, val | |
111 | self._keepGoing = False | |
112 | if self._callbackOnExit: | |
113 | try: | |
114 | self._callbackOnExit() | |
115 | except wx._core.PyDeadObjectError: | |
116 | pass | |
117 | if _VERBOSE: print "Exiting OutputReaderThread" | |
118 | ||
119 | def AskToStop(self): | |
120 | self._keepGoing = False | |
121 | ||
122 | import wx.lib.newevent | |
123 | (UpdateTextEvent, EVT_UPDATE_STDTEXT) = wx.lib.newevent.NewEvent() | |
124 | (UpdateErrorEvent, EVT_UPDATE_ERRTEXT) = wx.lib.newevent.NewEvent() | |
125 | ||
126 | class Executor: | |
127 | ||
128 | def GetPythonExecutablePath(): | |
129 | config = wx.ConfigBase_Get() | |
130 | path = config.Read("ActiveGridPythonLocation") | |
131 | if path: | |
132 | return path | |
133 | wx.MessageBox(_("To proceed I need to know the location of the python.exe you would like to use.\nTo set this, go to Tools-->Options and use the 'Python' tab to enter a value.\n"), _("Python Executable Location Unknown")) | |
134 | return None | |
135 | GetPythonExecutablePath = staticmethod(GetPythonExecutablePath) | |
136 | ||
137 | def __init__(self, fileName, wxComponent, arg1=None, arg2=None, arg3=None, arg4=None, arg5=None, arg6=None, arg7=None, arg8=None, arg9=None, callbackOnExit=None): | |
138 | self._fileName = fileName | |
139 | self._stdOutCallback = self.OutCall | |
140 | self._stdErrCallback = self.ErrCall | |
141 | self._callbackOnExit = callbackOnExit | |
142 | self._wxComponent = wxComponent | |
143 | path = Executor.GetPythonExecutablePath() | |
144 | self._cmd = '"' + path + '" -u \"' + fileName + '\"' | |
145 | #Better way to do this? Quotes needed for windows file paths. | |
146 | if(arg1 != None): | |
147 | self._cmd += ' \"' + arg1 + '\"' | |
148 | if(arg2 != None): | |
149 | self._cmd += ' \"' + arg2 + '\"' | |
150 | if(arg3 != None): | |
151 | self._cmd += ' \"' + arg3 + '\"' | |
152 | if(arg4 != None): | |
153 | self._cmd += ' \"' + arg4 + '\"' | |
154 | if(arg5 != None): | |
155 | self._cmd += ' \"' + arg5 + '\"' | |
156 | if(arg6 != None): | |
157 | self._cmd += ' \"' + arg6 + '\"' | |
158 | if(arg7 != None): | |
159 | self._cmd += ' \"' + arg7 + '\"' | |
160 | if(arg8 != None): | |
161 | self._cmd += ' \"' + arg8 + '\"' | |
162 | if(arg9 != None): | |
163 | self._cmd += ' \"' + arg9 + '\"' | |
164 | ||
165 | self._stdOutReader = None | |
166 | self._stdErrReader = None | |
167 | self._process = None | |
6f1a3f9c | 168 | DebuggerService.executors.append(self) |
1f780e48 RD |
169 | |
170 | def OutCall(self, text): | |
171 | evt = UpdateTextEvent(value = text) | |
172 | wx.PostEvent(self._wxComponent, evt) | |
173 | ||
174 | def ErrCall(self, text): | |
175 | evt = UpdateErrorEvent(value = text) | |
176 | wx.PostEvent(self._wxComponent, evt) | |
177 | ||
178 | def Execute(self, arguments, startIn=None, environment=None): | |
179 | if not startIn: | |
180 | startIn = str(os.getcwd()) | |
181 | startIn = os.path.abspath(startIn) | |
182 | command = self._cmd + ' ' + arguments | |
183 | #stdinput = process.IOBuffer() | |
184 | #self._process = process.ProcessProxy(command, mode='b', cwd=startIn, stdin=stdinput) | |
185 | self._process = process.ProcessOpen(command, mode='b', cwd=startIn, env=environment) | |
186 | # Kick off threads to read stdout and stderr and write them | |
187 | # to our text control. | |
188 | self._stdOutReader = OutputReaderThread(self._process.stdout, self._stdOutCallback, callbackOnExit=self._callbackOnExit) | |
189 | self._stdOutReader.start() | |
190 | self._stdErrReader = OutputReaderThread(self._process.stderr, self._stdErrCallback, accumulate=False) | |
191 | self._stdErrReader.start() | |
192 | ||
193 | ||
194 | def DoStopExecution(self): | |
195 | if(self._process != None): | |
196 | self._process.kill() | |
197 | self._process.close() | |
198 | self._process = None | |
199 | if(self._stdOutReader != None): | |
200 | self._stdOutReader.AskToStop() | |
201 | if(self._stdErrReader != None): | |
202 | self._stdErrReader.AskToStop() | |
6f1a3f9c | 203 | DebuggerService.executors.remove(self) |
1f780e48 RD |
204 | |
205 | class RunCommandUI(wx.Panel): | |
206 | ||
207 | def __init__(self, parent, id, fileName): | |
208 | wx.Panel.__init__(self, parent, id) | |
209 | self._noteBook = parent | |
210 | ||
211 | self.KILL_PROCESS_ID = wx.NewId() | |
212 | self.CLOSE_TAB_ID = wx.NewId() | |
213 | ||
214 | self.Bind(wx.EVT_END_PROCESS, self.OnProcessEnded) | |
215 | ||
216 | # GUI Initialization follows | |
217 | sizer = wx.BoxSizer(wx.HORIZONTAL) | |
218 | self._tb = tb = wx.ToolBar(self, -1, wx.DefaultPosition, (30,1000), wx.TB_VERTICAL| wx.TB_FLAT, "Runner" ) | |
219 | tb.SetToolBitmapSize((16,16)) | |
220 | sizer.Add(tb, 0, wx.EXPAND |wx.ALIGN_LEFT|wx.ALL, 1) | |
221 | ||
222 | close_bmp = getCloseBitmap() | |
223 | tb.AddSimpleTool( self.CLOSE_TAB_ID, close_bmp, _('Close Window')) | |
224 | wx.EVT_TOOL(self, self.CLOSE_TAB_ID, self.OnToolClicked) | |
225 | ||
226 | stop_bmp = getStopBitmap() | |
227 | tb.AddSimpleTool(self.KILL_PROCESS_ID, stop_bmp, _("Stop the Run.")) | |
228 | wx.EVT_TOOL(self, self.KILL_PROCESS_ID, self.OnToolClicked) | |
229 | ||
230 | tb.Realize() | |
231 | self._textCtrl = STCTextEditor.TextCtrl(self, wx.NewId()) #id) | |
232 | sizer.Add(self._textCtrl, 1, wx.ALIGN_LEFT|wx.ALL|wx.EXPAND, 1) | |
233 | self._textCtrl.SetViewLineNumbers(False) | |
234 | self._textCtrl.SetReadOnly(True) | |
235 | if wx.Platform == '__WXMSW__': | |
236 | font = "Courier New" | |
237 | else: | |
238 | font = "Courier" | |
239 | self._textCtrl.SetFont(wx.Font(9, wx.DEFAULT, wx.NORMAL, wx.NORMAL, faceName = font)) | |
240 | self._textCtrl.SetFontColor(wx.BLACK) | |
241 | self._textCtrl.StyleClearAll() | |
242 | ||
243 | #Disabling for now...may interfere with file open. wx.stc.EVT_STC_DOUBLECLICK(self._textCtrl, self._textCtrl.GetId(), self.OnDoubleClick) | |
244 | ||
245 | self.SetSizer(sizer) | |
246 | sizer.Fit(self) | |
247 | ||
248 | # Executor initialization | |
249 | self._executor = Executor(fileName, self, callbackOnExit=self.ExecutorFinished) | |
250 | self.Bind(EVT_UPDATE_STDTEXT, self.AppendText) | |
251 | self.Bind(EVT_UPDATE_ERRTEXT, self.AppendErrorText) | |
252 | ||
253 | def __del__(self): | |
254 | self._executor.DoStopExecution() | |
255 | ||
256 | def Execute(self, initialArgs, startIn, environment): | |
257 | self._executor.Execute(initialArgs, startIn, environment) | |
258 | ||
259 | def ExecutorFinished(self): | |
260 | self._tb.EnableTool(self.KILL_PROCESS_ID, False) | |
261 | nb = self.GetParent() | |
262 | for i in range(0,nb.GetPageCount()): | |
263 | if self == nb.GetPage(i): | |
264 | text = nb.GetPageText(i) | |
265 | newText = text.replace("Running", "Finished") | |
266 | nb.SetPageText(i, newText) | |
267 | break | |
268 | ||
269 | def StopExecution(self): | |
270 | self.Unbind(EVT_UPDATE_STDTEXT) | |
271 | self.Unbind(EVT_UPDATE_ERRTEXT) | |
272 | self._executor.DoStopExecution() | |
273 | ||
274 | def AppendText(self, event): | |
275 | self._textCtrl.SetReadOnly(False) | |
276 | self._textCtrl.AddText(event.value) | |
277 | self._textCtrl.ScrollToLine(self._textCtrl.GetLineCount()) | |
278 | self._textCtrl.SetReadOnly(True) | |
279 | ||
280 | def AppendErrorText(self, event): | |
281 | self._textCtrl.SetReadOnly(False) | |
282 | self._textCtrl.SetFontColor(wx.RED) | |
283 | self._textCtrl.StyleClearAll() | |
284 | self._textCtrl.AddText(event.value) | |
285 | self._textCtrl.ScrollToLine(self._textCtrl.GetLineCount()) | |
286 | self._textCtrl.SetFontColor(wx.BLACK) | |
287 | self._textCtrl.StyleClearAll() | |
288 | self._textCtrl.SetReadOnly(True) | |
289 | ||
290 | #------------------------------------------------------------------------------ | |
291 | # Event handling | |
292 | #----------------------------------------------------------------------------- | |
293 | ||
294 | def OnToolClicked(self, event): | |
295 | id = event.GetId() | |
296 | ||
297 | if id == self.KILL_PROCESS_ID: | |
298 | self._executor.DoStopExecution() | |
299 | ||
300 | elif id == self.CLOSE_TAB_ID: | |
301 | self._executor.DoStopExecution() | |
302 | index = self._noteBook.GetSelection() | |
303 | self._noteBook.GetPage(index).Show(False) | |
304 | self._noteBook.RemovePage(index) | |
305 | ||
306 | def OnDoubleClick(self, event): | |
307 | # Looking for a stack trace line. | |
308 | lineText, pos = self._textCtrl.GetCurLine() | |
309 | fileBegin = lineText.find("File \"") | |
310 | fileEnd = lineText.find("\", line ") | |
311 | lineEnd = lineText.find(", in ") | |
312 | if lineText == "\n" or fileBegin == -1 or fileEnd == -1 or lineEnd == -1: | |
313 | # Check the line before the one that was clicked on | |
314 | lineNumber = self._textCtrl.GetCurrentLine() | |
315 | if(lineNumber == 0): | |
316 | return | |
317 | lineText = self._textCtrl.GetLine(lineNumber - 1) | |
318 | fileBegin = lineText.find("File \"") | |
319 | fileEnd = lineText.find("\", line ") | |
320 | lineEnd = lineText.find(", in ") | |
321 | if lineText == "\n" or fileBegin == -1 or fileEnd == -1 or lineEnd == -1: | |
322 | return | |
323 | ||
324 | filename = lineText[fileBegin + 6:fileEnd] | |
325 | lineNum = int(lineText[fileEnd + 8:lineEnd]) | |
326 | ||
327 | foundView = None | |
328 | openDocs = wx.GetApp().GetDocumentManager().GetDocuments() | |
329 | for openDoc in openDocs: | |
330 | if openDoc.GetFilename() == filename: | |
331 | foundView = openDoc.GetFirstView() | |
332 | break | |
333 | ||
334 | if not foundView: | |
335 | doc = wx.GetApp().GetDocumentManager().CreateDocument(filename, wx.lib.docview.DOC_SILENT) | |
336 | foundView = doc.GetFirstView() | |
337 | ||
338 | if foundView: | |
339 | foundView.GetFrame().SetFocus() | |
340 | foundView.Activate() | |
341 | foundView.GotoLine(lineNum) | |
342 | startPos = foundView.PositionFromLine(lineNum) | |
343 | ||
344 | # FACTOR THIS INTO DocManager | |
345 | openDocs = wx.GetApp().GetDocumentManager().GetDocuments() | |
346 | for openDoc in openDocs: | |
347 | if(isinstance(openDoc.GetFirstView(), CodeEditor.CodeView)): | |
348 | openDoc.GetFirstView().GetCtrl().ClearCurrentLineMarkers() | |
349 | ||
350 | foundView.GetCtrl().MarkerAdd(lineNum -1, CodeEditor.CodeCtrl.CURRENT_LINE_MARKER_NUM) | |
351 | ||
352 | def OnProcessEnded(self, evt): | |
353 | self._executor.DoStopExecution() | |
354 | ||
355 | DEFAULT_PORT = 32032 | |
356 | DEFAULT_HOST = 'localhost' | |
357 | PORT_COUNT = 21 | |
358 | ||
359 | class DebugCommandUI(wx.Panel): | |
360 | debuggerPortList = None | |
361 | debuggers = [] | |
362 | ||
363 | def NotifyDebuggersOfBreakpointChange(): | |
364 | for debugger in DebugCommandUI.debuggers: | |
365 | debugger.BreakPointChange() | |
366 | ||
367 | NotifyDebuggersOfBreakpointChange = staticmethod(NotifyDebuggersOfBreakpointChange) | |
368 | ||
369 | def DebuggerRunning(): | |
370 | for debugger in DebugCommandUI.debuggers: | |
371 | if debugger._executor: | |
372 | return True | |
373 | return False | |
374 | DebuggerRunning = staticmethod(DebuggerRunning) | |
375 | ||
376 | def ShutdownAllDebuggers(): | |
377 | for debugger in DebugCommandUI.debuggers: | |
6f1a3f9c | 378 | debugger.StopExecution(None) |
1f780e48 RD |
379 | |
380 | ShutdownAllDebuggers = staticmethod(ShutdownAllDebuggers) | |
6f1a3f9c | 381 | |
1f780e48 RD |
382 | def GetAvailablePort(): |
383 | for index in range( 0, len(DebugCommandUI.debuggerPortList)): | |
384 | port = DebugCommandUI.debuggerPortList[index] | |
385 | if DebugCommandUI.PortAvailable(port): | |
386 | DebugCommandUI.debuggerPortList.pop(index) | |
387 | return port | |
388 | wx.MessageBox(_("Out of ports for debugging! Please restart the application builder.\nIf that does not work, check for and remove running instances of python."), _("Out of Ports")) | |
389 | assert False, "Out of ports for debugger." | |
390 | ||
391 | GetAvailablePort = staticmethod(GetAvailablePort) | |
392 | ||
393 | def ReturnPortToPool(port): | |
394 | config = wx.ConfigBase_Get() | |
395 | startingPort = config.ReadInt("DebuggerStartingPort", DEFAULT_PORT) | |
396 | if port in range(startingPort, startingPort + PORT_COUNT): | |
397 | DebugCommandUI.debuggerPortList.append(port) | |
398 | ||
399 | ReturnPortToPool = staticmethod(ReturnPortToPool) | |
400 | ||
401 | def PortAvailable(port): | |
402 | config = wx.ConfigBase_Get() | |
403 | hostname = config.Read("DebuggerHostName", DEFAULT_HOST) | |
404 | try: | |
405 | server = AGXMLRPCServer((hostname, port)) | |
406 | server.server_close() | |
407 | if _VERBOSE: print "Port ", str(port), " available." | |
408 | return True | |
409 | except: | |
410 | tp,val,tb = sys.exc_info() | |
411 | if _VERBOSE: traceback.print_exception(tp, val, tb) | |
412 | if _VERBOSE: print "Port ", str(port), " unavailable." | |
413 | return False | |
414 | ||
415 | PortAvailable = staticmethod(PortAvailable) | |
416 | ||
417 | def NewPortRange(): | |
418 | config = wx.ConfigBase_Get() | |
419 | startingPort = config.ReadInt("DebuggerStartingPort", DEFAULT_PORT) | |
420 | DebugCommandUI.debuggerPortList = range(startingPort, startingPort + PORT_COUNT) | |
421 | NewPortRange = staticmethod(NewPortRange) | |
422 | ||
423 | def __init__(self, parent, id, command, service): | |
424 | # Check for ports before creating the panel. | |
425 | if not DebugCommandUI.debuggerPortList: | |
426 | DebugCommandUI.NewPortRange() | |
427 | self._debuggerPort = str(DebugCommandUI.GetAvailablePort()) | |
428 | self._guiPort = str(DebugCommandUI.GetAvailablePort()) | |
429 | self._debuggerBreakPort = str(DebugCommandUI.GetAvailablePort()) | |
430 | ||
431 | wx.Panel.__init__(self, parent, id) | |
432 | ||
433 | self._parentNoteBook = parent | |
434 | self._command = command | |
1f780e48 RD |
435 | self._service = service |
436 | self._executor = None | |
437 | self.STEP_ID = wx.NewId() | |
438 | self.CONTINUE_ID = wx.NewId() | |
439 | self.STEP_OUT_ID = wx.NewId() | |
440 | self.NEXT_ID = wx.NewId() | |
441 | self.KILL_PROCESS_ID = wx.NewId() | |
442 | self.CLOSE_WINDOW_ID = wx.NewId() | |
443 | self.BREAK_INTO_DEBUGGER_ID = wx.NewId() | |
444 | self.CLEAR_ID = wx.NewId() | |
445 | self.ADD_WATCH_ID = wx.NewId() | |
446 | sizer = wx.BoxSizer(wx.VERTICAL) | |
447 | self._tb = tb = wx.ToolBar(self, -1, wx.DefaultPosition, (1000,30), wx.TB_HORIZONTAL| wx.NO_BORDER| wx.TB_FLAT| wx.TB_TEXT, "Debugger" ) | |
448 | sizer.Add(tb, 0, wx.EXPAND |wx.ALIGN_LEFT|wx.ALL, 1) | |
449 | tb.SetToolBitmapSize((16,16)) | |
450 | ||
451 | close_bmp = getCloseBitmap() | |
452 | tb.AddSimpleTool( self.CLOSE_WINDOW_ID, close_bmp, _('Close Window')) | |
453 | wx.EVT_TOOL(self, self.CLOSE_WINDOW_ID, self.StopAndRemoveUI) | |
454 | ||
455 | stop_bmp = getStopBitmap() | |
456 | tb.AddSimpleTool( self.KILL_PROCESS_ID, stop_bmp, _("Stop Debugging")) | |
457 | wx.EVT_TOOL(self, self.KILL_PROCESS_ID, self.StopExecution) | |
458 | ||
459 | tb.AddSeparator() | |
460 | ||
461 | break_bmp = getBreakBitmap() | |
462 | tb.AddSimpleTool( self.BREAK_INTO_DEBUGGER_ID, break_bmp, _("Break into Debugger")) | |
463 | wx.EVT_TOOL(self, self.BREAK_INTO_DEBUGGER_ID, self.BreakExecution) | |
464 | ||
465 | tb.AddSeparator() | |
466 | ||
467 | continue_bmp = getContinueBitmap() | |
468 | tb.AddSimpleTool( self.CONTINUE_ID, continue_bmp, _("Continue Execution")) | |
469 | wx.EVT_TOOL(self, self.CONTINUE_ID, self.OnContinue) | |
470 | ||
471 | tb.AddSeparator() | |
472 | ||
473 | next_bmp = getNextBitmap() | |
474 | tb.AddSimpleTool( self.NEXT_ID, next_bmp, _("Step to next line")) | |
475 | wx.EVT_TOOL(self, self.NEXT_ID, self.OnNext) | |
476 | ||
477 | step_bmp = getStepInBitmap() | |
478 | tb.AddSimpleTool( self.STEP_ID, step_bmp, _("Step in")) | |
479 | wx.EVT_TOOL(self, self.STEP_ID, self.OnSingleStep) | |
480 | ||
481 | stepOut_bmp = getStepReturnBitmap() | |
482 | tb.AddSimpleTool(self.STEP_OUT_ID, stepOut_bmp, _("Stop at function return")) | |
483 | wx.EVT_TOOL(self, self.STEP_OUT_ID, self.OnStepOut) | |
484 | ||
485 | tb.AddSeparator() | |
486 | if _WATCHES_ON: | |
487 | watch_bmp = getAddWatchBitmap() | |
488 | tb.AddSimpleTool(self.ADD_WATCH_ID, watch_bmp, _("Add a watch")) | |
489 | wx.EVT_TOOL(self, self.ADD_WATCH_ID, self.OnAddWatch) | |
490 | tb.AddSeparator() | |
491 | ||
492 | clear_bmp = getClearOutputBitmap() | |
493 | tb.AddSimpleTool(self.CLEAR_ID, clear_bmp, _("Clear output pane")) | |
494 | wx.EVT_TOOL(self, self.CLEAR_ID, self.OnClearOutput) | |
495 | ||
1f780e48 RD |
496 | self.framesTab = None |
497 | self.DisableWhileDebuggerRunning() | |
6f1a3f9c RD |
498 | self.framesTab = self.MakeFramesUI(self, wx.NewId(), None) |
499 | sizer.Add(self.framesTab, 1, wx.ALIGN_LEFT|wx.ALL|wx.EXPAND, 1) | |
1f780e48 RD |
500 | self._statusBar = wx.StatusBar( self, -1) |
501 | self._statusBar.SetFieldsCount(1) | |
502 | sizer.Add(self._statusBar, 0, wx.EXPAND |wx.ALIGN_LEFT|wx.ALL, 1) | |
503 | ||
504 | self.SetStatusText("Starting debug...") | |
505 | ||
506 | self.SetSizer(sizer) | |
6f1a3f9c | 507 | tb.Realize() |
1f780e48 RD |
508 | sizer.Fit(self) |
509 | config = wx.ConfigBase_Get() | |
510 | self._debuggerHost = self._guiHost = config.Read("DebuggerHostName", DEFAULT_HOST) | |
511 | url = 'http://' + self._debuggerHost + ':' + self._debuggerPort + '/' | |
512 | self._breakURL = 'http://' + self._debuggerHost + ':' + self._debuggerBreakPort + '/' | |
513 | self._callback = DebuggerCallback(self._guiHost, self._guiPort, url, self._breakURL, self) | |
514 | if DebuggerHarness.__file__.find('library.zip') > 0: | |
515 | try: | |
516 | fname = DebuggerHarness.__file__ | |
517 | parts = fname.split('library.zip') | |
518 | path = os.path.join(parts[0],'activegrid', 'tool', 'DebuggerHarness.py') | |
519 | except: | |
520 | tp, val, tb = sys.exc_info() | |
521 | traceback.print_exception(tp, val, tb) | |
522 | ||
523 | else: | |
524 | print "Starting debugger on these ports: %s, %s, %s" % (str(self._debuggerPort) , str(self._guiPort) , str(self._debuggerBreakPort)) | |
525 | path = DebuggerService.ExpandPath(DebuggerHarness.__file__) | |
526 | self._executor = Executor(path, self, self._debuggerHost, \ | |
527 | self._debuggerPort, self._debuggerBreakPort, self._guiHost, self._guiPort, self._command, callbackOnExit=self.ExecutorFinished) | |
528 | ||
529 | self.Bind(EVT_UPDATE_STDTEXT, self.AppendText) | |
530 | self.Bind(EVT_UPDATE_ERRTEXT, self.AppendErrorText) | |
531 | DebugCommandUI.debuggers.append(self) | |
532 | self._stopped = False | |
533 | ||
534 | def OnSingleStep(self, event): | |
535 | self._callback.SingleStep() | |
536 | ||
537 | def OnContinue(self, event): | |
538 | self._callback.Continue() | |
539 | ||
540 | def OnStepOut(self, event): | |
541 | self._callback.Return() | |
542 | ||
543 | def OnNext(self, event): | |
544 | self._callback.Next() | |
545 | ||
546 | def BreakPointChange(self): | |
547 | if not self._stopped: | |
548 | self._callback.pushBreakpoints() | |
6f1a3f9c | 549 | self.framesTab.PopulateBPList() |
1f780e48 RD |
550 | |
551 | def __del__(self): | |
552 | if self in DebugCommandUI.debuggers: | |
553 | DebugCommandUI.debuggers.remove(self) | |
554 | ||
1f780e48 RD |
555 | |
556 | def DisableWhileDebuggerRunning(self): | |
557 | self._tb.EnableTool(self.STEP_ID, False) | |
558 | self._tb.EnableTool(self.CONTINUE_ID, False) | |
559 | self._tb.EnableTool(self.STEP_OUT_ID, False) | |
560 | self._tb.EnableTool(self.NEXT_ID, False) | |
561 | self._tb.EnableTool(self.BREAK_INTO_DEBUGGER_ID, True) | |
562 | if _WATCHES_ON: | |
563 | self._tb.EnableTool(self.ADD_WATCH_ID, False) | |
564 | openDocs = wx.GetApp().GetDocumentManager().GetDocuments() | |
565 | for openDoc in openDocs: | |
566 | if(isinstance(openDoc.GetFirstView(), CodeEditor.CodeView)): | |
567 | openDoc.GetFirstView().GetCtrl().ClearCurrentLineMarkers() | |
568 | if self.framesTab: | |
569 | self.framesTab.ClearWhileRunning() | |
1f780e48 RD |
570 | |
571 | def EnableWhileDebuggerStopped(self): | |
572 | self._tb.EnableTool(self.STEP_ID, True) | |
573 | self._tb.EnableTool(self.CONTINUE_ID, True) | |
574 | self._tb.EnableTool(self.STEP_OUT_ID, True) | |
575 | self._tb.EnableTool(self.NEXT_ID, True) | |
576 | if _WATCHES_ON: | |
577 | self._tb.EnableTool(self.ADD_WATCH_ID, True) | |
578 | self._tb.EnableTool(self.BREAK_INTO_DEBUGGER_ID, False) | |
1f780e48 RD |
579 | |
580 | def ExecutorFinished(self): | |
581 | if _VERBOSE: print "In ExectorFinished" | |
582 | try: | |
583 | self.DisableAfterStop() | |
584 | except wx._core.PyDeadObjectError: | |
585 | pass | |
586 | try: | |
587 | nb = self.GetParent() | |
588 | for i in range(0, nb.GetPageCount()): | |
589 | if self == nb.GetPage(i): | |
590 | text = nb.GetPageText(i) | |
591 | newText = text.replace("Debugging", "Finished") | |
592 | nb.SetPageText(i, newText) | |
593 | if _VERBOSE: print "In ExectorFinished, changed tab title." | |
594 | break | |
595 | except: | |
596 | if _VERBOSE: print "In ExectorFinished, got exception" | |
597 | ||
598 | def DisableAfterStop(self): | |
599 | self.DisableWhileDebuggerRunning() | |
600 | self._tb.EnableTool(self.BREAK_INTO_DEBUGGER_ID, False) | |
601 | self._tb.EnableTool(self.KILL_PROCESS_ID, False) | |
602 | ||
603 | def SynchCurrentLine(self, filename, lineNum): | |
604 | # FACTOR THIS INTO DocManager | |
605 | self.DeleteCurrentLineMarkers() | |
606 | ||
607 | # Filename will be <string> if we're in a bit of code that was executed from | |
608 | # a string (rather than a file). I haven't been able to get the original string | |
609 | # for display. | |
610 | if filename == '<string>': | |
611 | return | |
612 | foundView = None | |
613 | openDocs = wx.GetApp().GetDocumentManager().GetDocuments() | |
614 | for openDoc in openDocs: | |
615 | # This ugliness to prevent comparison failing because the drive letter | |
616 | # gets lowercased occasionally. Don't know why that happens or why it | |
617 | # only happens occasionally. | |
618 | if DebuggerService.ComparePaths(openDoc.GetFilename(),filename): | |
619 | foundView = openDoc.GetFirstView() | |
620 | break | |
621 | ||
622 | if not foundView: | |
623 | if _VERBOSE: | |
624 | print "filename=", filename | |
625 | doc = wx.GetApp().GetDocumentManager().CreateDocument(DebuggerService.ExpandPath(filename), wx.lib.docview.DOC_SILENT) | |
626 | foundView = doc.GetFirstView() | |
627 | ||
628 | if foundView: | |
629 | foundView.GetFrame().SetFocus() | |
630 | foundView.Activate() | |
631 | foundView.GotoLine(lineNum) | |
632 | startPos = foundView.PositionFromLine(lineNum) | |
633 | ||
634 | foundView.GetCtrl().MarkerAdd(lineNum -1, CodeEditor.CodeCtrl.CURRENT_LINE_MARKER_NUM) | |
635 | ||
636 | def DeleteCurrentLineMarkers(self): | |
637 | openDocs = wx.GetApp().GetDocumentManager().GetDocuments() | |
638 | for openDoc in openDocs: | |
639 | if(isinstance(openDoc.GetFirstView(), CodeEditor.CodeView)): | |
640 | openDoc.GetFirstView().GetCtrl().ClearCurrentLineMarkers() | |
641 | ||
642 | def LoadFramesListXML(self, framesXML): | |
643 | self.framesTab.LoadFramesListXML(framesXML) | |
644 | ||
645 | def SetStatusText(self, text): | |
646 | self._statusBar.SetStatusText(text,0) | |
647 | ||
648 | def Execute(self, initialArgs, startIn, environment): | |
649 | self._callback.start() | |
650 | self._executor.Execute(initialArgs, startIn, environment) | |
651 | self._callback.waitForRPC() | |
652 | ||
653 | def BreakExecution(self, event): | |
654 | self._callback.BreakExecution() | |
655 | ||
656 | ||
657 | def StopExecution(self, event): | |
658 | self._stopped = True | |
659 | self.DisableAfterStop() | |
660 | try: | |
661 | self._callback.ServerClose() | |
662 | except: | |
663 | pass | |
664 | try: | |
665 | if self._executor: | |
666 | self._executor.DoStopExecution() | |
667 | self._executor = None | |
668 | except: | |
669 | pass | |
670 | self.DeleteCurrentLineMarkers() | |
671 | DebugCommandUI.ReturnPortToPool(self._debuggerPort) | |
672 | DebugCommandUI.ReturnPortToPool(self._guiPort) | |
673 | DebugCommandUI.ReturnPortToPool(self._debuggerBreakPort) | |
674 | ||
675 | def StopAndRemoveUI(self, event): | |
676 | self.StopExecution(None) | |
677 | if self in DebugCommandUI.debuggers: | |
678 | DebugCommandUI.debuggers.remove(self) | |
679 | index = self._parentNoteBook.GetSelection() | |
680 | self._parentNoteBook.GetPage(index).Show(False) | |
6f1a3f9c | 681 | self._parentNoteBook.RemovePage(index) |
1f780e48 RD |
682 | |
683 | def OnAddWatch(self, event): | |
684 | if self.framesTab: | |
685 | self.framesTab.OnWatch(event) | |
6f1a3f9c RD |
686 | |
687 | def MakeFramesUI(self, parent, id, debugger): | |
1f780e48 RD |
688 | panel = FramesUI(parent, id, self) |
689 | return panel | |
690 | ||
1f780e48 | 691 | def AppendText(self, event): |
6f1a3f9c | 692 | self.framesTab.AppendText(event.value) |
1f780e48 RD |
693 | |
694 | def AppendErrorText(self, event): | |
6f1a3f9c RD |
695 | self.framesTab.AppendErrorText(event.value) |
696 | ||
697 | def OnClearOutput(self, event): | |
698 | self.framesTab.ClearOutput() | |
699 | ||
700 | def SwitchToOutputTab(self): | |
701 | self.framesTab.SwitchToOutputTab() | |
1f780e48 RD |
702 | |
703 | class BreakpointsUI(wx.Panel): | |
704 | def __init__(self, parent, id, ui): | |
705 | wx.Panel.__init__(self, parent, id) | |
706 | self._ui = ui | |
707 | self.currentItem = None | |
708 | self.clearBPID = wx.NewId() | |
709 | self.Bind(wx.EVT_MENU, self.ClearBreakPoint, id=self.clearBPID) | |
710 | self.syncLineID = wx.NewId() | |
711 | self.Bind(wx.EVT_MENU, self.SyncBPLine, id=self.syncLineID) | |
1f780e48 RD |
712 | sizer = wx.BoxSizer(wx.VERTICAL) |
713 | p1 = self | |
714 | self._bpListCtrl = wx.ListCtrl(p1, -1, pos=wx.DefaultPosition, size=(1000,1000), style=wx.LC_REPORT) | |
715 | sizer.Add(self._bpListCtrl, 1, wx.ALIGN_LEFT|wx.ALL|wx.EXPAND, 1) | |
716 | self._bpListCtrl.InsertColumn(0, "File") | |
717 | self._bpListCtrl.InsertColumn(1, "Line") | |
718 | self._bpListCtrl.InsertColumn(2, "Path") | |
719 | self._bpListCtrl.SetColumnWidth(0, 150) | |
720 | self._bpListCtrl.SetColumnWidth(1, 50) | |
721 | self._bpListCtrl.SetColumnWidth(2, 450) | |
722 | self._bpListCtrl.Bind(wx.EVT_LIST_ITEM_RIGHT_CLICK, self.OnListRightClick) | |
723 | self.Bind(wx.EVT_LIST_ITEM_SELECTED, self.ListItemSelected, self._bpListCtrl) | |
724 | self.Bind(wx.EVT_LIST_ITEM_DESELECTED, self.ListItemDeselected, self._bpListCtrl) | |
6f1a3f9c RD |
725 | |
726 | def OnLeftDoubleClick(event): | |
727 | self.SyncBPLine(event) | |
728 | ||
729 | wx.EVT_LEFT_DCLICK(self._bpListCtrl, OnLeftDoubleClick) | |
1f780e48 RD |
730 | |
731 | self.PopulateBPList() | |
732 | ||
733 | p1.SetSizer(sizer) | |
734 | sizer.Fit(p1) | |
735 | p1.Layout() | |
736 | ||
737 | def PopulateBPList(self): | |
738 | list = self._bpListCtrl | |
739 | list.DeleteAllItems() | |
740 | ||
741 | bps = wx.GetApp().GetService(DebuggerService).GetMasterBreakpointDict() | |
742 | index = 0 | |
743 | for fileName in bps.keys(): | |
744 | shortFile = os.path.basename(fileName) | |
745 | lines = bps[fileName] | |
746 | if lines: | |
747 | for line in lines: | |
748 | list.InsertStringItem(index, shortFile) | |
749 | list.SetStringItem(index, 1, str(line)) | |
750 | list.SetStringItem(index, 2, fileName) | |
751 | ||
752 | def OnListRightClick(self, event): | |
753 | menu = wx.Menu() | |
754 | item = wx.MenuItem(menu, self.clearBPID, "Clear Breakpoint") | |
755 | menu.AppendItem(item) | |
756 | item = wx.MenuItem(menu, self.syncLineID, "Goto Source Line") | |
757 | menu.AppendItem(item) | |
758 | self.PopupMenu(menu, event.GetPosition()) | |
759 | menu.Destroy() | |
760 | ||
761 | def SyncBPLine(self, event): | |
762 | if self.currentItem != -1: | |
763 | list = self._bpListCtrl | |
764 | fileName = list.GetItem(self.currentItem, 2).GetText() | |
765 | lineNumber = list.GetItem(self.currentItem, 1).GetText() | |
766 | self._ui.SynchCurrentLine( fileName, int(lineNumber) ) | |
767 | ||
768 | def ClearBreakPoint(self, event): | |
769 | if self.currentItem >= 0: | |
770 | list = self._bpListCtrl | |
771 | fileName = list.GetItem(self.currentItem, 2).GetText() | |
772 | lineNumber = list.GetItem(self.currentItem, 1).GetText() | |
773 | wx.GetApp().GetService(DebuggerService).OnToggleBreakpoint(None, line=int(lineNumber) -1, fileName=fileName ) | |
774 | ||
775 | def ListItemSelected(self, event): | |
776 | self.currentItem = event.m_itemIndex | |
777 | ||
778 | def ListItemDeselected(self, event): | |
779 | self.currentItem = -1 | |
780 | ||
781 | class Watch: | |
782 | CODE_ALL_FRAMES = 1 | |
783 | CODE_THIS_BLOCK = 2 | |
784 | CODE_THIS_LINE = 4 | |
785 | CODE_RUN_ONCE = 8 | |
786 | ||
787 | def __init__(self, name, command, show_code=CODE_ALL_FRAMES): | |
788 | self._name = name | |
789 | self._command = command | |
790 | self._show_code = show_code | |
791 | ||
792 | class WatchDialog(wx.Dialog): | |
793 | WATCH_ALL_FRAMES = "Watch in all frames" | |
794 | WATCH_THIS_FRAME = "Watch in this frame only" | |
795 | WATCH_ONCE = "Watch once and delete" | |
796 | def __init__(self, parent, title, chain): | |
797 | wx.Dialog.__init__(self, parent, -1, title, style=wx.DEFAULT_DIALOG_STYLE) | |
798 | self._chain = chain | |
799 | self.label_2 = wx.StaticText(self, -1, "Watch Name:") | |
800 | self._watchNameTextCtrl = wx.TextCtrl(self, -1, "") | |
801 | self.label_3 = wx.StaticText(self, -1, "eval(", style=wx.ALIGN_RIGHT) | |
802 | self._watchValueTextCtrl = wx.TextCtrl(self, -1, "") | |
803 | self.label_4 = wx.StaticText(self, -1, ",frame.f_globals, frame.f_locals)") | |
804 | 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) | |
805 | ||
806 | self._okButton = wx.Button(self, wx.ID_OK, "OK", size=(75,-1)) | |
807 | self._okButton.SetDefault() | |
808 | self._okButton.SetHelpText(_("The OK button completes the dialog")) | |
809 | def OnOkClick(event): | |
810 | if self._watchNameTextCtrl.GetValue() == "": | |
811 | wx.MessageBox(_("You must enter a name for the watch."), _("Add Watch")) | |
812 | return | |
813 | if self._watchValueTextCtrl.GetValue() == "": | |
814 | wx.MessageBox(_("You must enter some code to run for the watch."), _("Add Watch")) | |
815 | return | |
816 | self.EndModal(wx.ID_OK) | |
817 | self.Bind(wx.EVT_BUTTON, OnOkClick, self._okButton) | |
818 | ||
819 | self._cancelButton = wx.Button(self, wx.ID_CANCEL, _("Cancel"), size=(75,-1)) | |
820 | self._cancelButton.SetHelpText(_("The Cancel button cancels the dialog.")) | |
821 | ||
822 | self.__set_properties() | |
823 | self.__do_layout() | |
824 | ||
825 | def GetSettings(self): | |
826 | return self._watchNameTextCtrl.GetValue(), self._watchValueTextCtrl.GetValue(), self.GetSendFrame(), self.GetRunOnce() | |
827 | ||
828 | def GetSendFrame(self): | |
829 | return (WatchDialog.WATCH_ALL_FRAMES != self.radio_box_1.GetStringSelection()) | |
830 | ||
831 | def GetRunOnce(self): | |
832 | return (WatchDialog.WATCH_ONCE == self.radio_box_1.GetStringSelection()) | |
833 | ||
834 | def __set_properties(self): | |
835 | self.SetTitle("Add a Watch") | |
836 | #self.SetSize((400, 250)) | |
837 | self.radio_box_1.SetSelection(0) | |
838 | ||
839 | def __do_layout(self): | |
840 | sizer_1 = wx.BoxSizer(wx.VERTICAL) | |
841 | grid_sizer_4 = wx.FlexGridSizer(1, 3, 5, 5) | |
842 | grid_sizer_2 = wx.FlexGridSizer(1, 2, 5, 5) | |
843 | grid_sizer_2.Add(self.label_2, 0, wx.ALIGN_CENTER_VERTICAL|wx.FIXED_MINSIZE, 0) | |
844 | grid_sizer_2.Add(self._watchNameTextCtrl, 0, wx.EXPAND, 0) | |
845 | grid_sizer_2.AddGrowableCol(1) | |
846 | sizer_1.Add(grid_sizer_2, 1, wx.EXPAND, 0) | |
847 | grid_sizer_4.Add(self.label_3, 0, wx.ALIGN_CENTER_VERTICAL|wx.FIXED_MINSIZE, 0) | |
848 | grid_sizer_4.Add(self._watchValueTextCtrl, 0, wx.EXPAND, 0) | |
849 | grid_sizer_4.AddGrowableCol(1) | |
850 | grid_sizer_4.Add(self.label_4, 0, wx.ALIGN_CENTER_VERTICAL|wx.FIXED_MINSIZE, 0) | |
851 | sizer_1.Add(grid_sizer_4, 0, wx.EXPAND, 0) | |
852 | sizer_1.Add(self.radio_box_1, 0, wx.EXPAND, 0) | |
853 | ||
854 | box = wx.BoxSizer(wx.HORIZONTAL) | |
855 | box.Add(self._okButton, 0, wx.ALIGN_RIGHT|wx.ALL, 5) | |
856 | box.Add(self._cancelButton, 0, wx.ALIGN_RIGHT|wx.ALL, 5) | |
857 | sizer_1.Add(box, 1, wx.EXPAND, 0) | |
858 | self.SetAutoLayout(True) | |
859 | self.SetSizer(sizer_1) | |
860 | self.Layout() | |
861 | ||
862 | class FramesUI(wx.SplitterWindow): | |
863 | def __init__(self, parent, id, ui): | |
864 | wx.SplitterWindow.__init__(self, parent, id, style = wx.SP_3D) | |
865 | self._ui = ui | |
1f780e48 | 866 | self._p1 = p1 = wx.ScrolledWindow(self, -1) |
1f780e48 | 867 | |
6f1a3f9c RD |
868 | sizer = wx.BoxSizer(wx.HORIZONTAL) |
869 | framesLabel = wx.StaticText(self, -1, "Stack Frame:") | |
870 | sizer.Add(framesLabel, 0, flag=wx.ALIGN_CENTER_VERTICAL|wx.ALIGN_LEFT|wx.LEFT, border=2) | |
871 | ||
872 | self._framesChoiceCtrl = wx.Choice(p1, -1, choices=[" "]) | |
873 | sizer.Add(self._framesChoiceCtrl, 1, wx.ALIGN_LEFT|wx.ALL|wx.EXPAND, 1) | |
874 | self._framesChoiceCtrl.Bind(wx.EVT_LIST_ITEM_RIGHT_CLICK, self.OnListRightClick) | |
875 | self.Bind(wx.EVT_CHOICE, self.ListItemSelected, self._framesChoiceCtrl) | |
1f780e48 RD |
876 | |
877 | sizer2 = wx.BoxSizer(wx.VERTICAL) | |
6f1a3f9c RD |
878 | p1.SetSizer(sizer2) |
879 | ||
880 | self._treeCtrl = wx.gizmos.TreeListCtrl(p1, -1, style=wx.TR_DEFAULT_STYLE| wx.TR_FULL_ROW_HIGHLIGHT) | |
1f780e48 | 881 | self._treeCtrl.Bind(wx.EVT_TREE_ITEM_RIGHT_CLICK, self.OnRightClick) |
6f1a3f9c RD |
882 | sizer2.Add(sizer, 0, wx.ALIGN_LEFT|wx.ALL|wx.EXPAND, 1) |
883 | sizer2.Add(self._treeCtrl,1, wx.ALIGN_LEFT|wx.ALL|wx.EXPAND, 1) | |
1f780e48 RD |
884 | tree = self._treeCtrl |
885 | tree.AddColumn("Thing") | |
886 | tree.AddColumn("Value") | |
887 | tree.SetMainColumn(0) # the one with the tree in it... | |
888 | tree.SetColumnWidth(0, 175) | |
889 | tree.SetColumnWidth(1, 355) | |
890 | self._root = tree.AddRoot("Frame") | |
891 | tree.SetItemText(self._root, "", 1) | |
6f1a3f9c RD |
892 | tree.Bind(wx.EVT_TREE_ITEM_EXPANDING, self.IntrospectCallback) |
893 | ||
894 | self._p2 = p2 = wx.Window(self, -1) | |
895 | sizer3 = wx.BoxSizer(wx.HORIZONTAL) | |
896 | p2.SetSizer(sizer3) | |
897 | p2.Bind(wx.EVT_SIZE, self.OnSize) | |
898 | self._notebook = wx.Notebook(p2, -1, size=(20,20)) | |
899 | self._notebook.Hide() | |
900 | sizer3.Add(self._notebook, 1, wx.ALIGN_LEFT|wx.ALL|wx.EXPAND, 1) | |
901 | self.consoleTab = self.MakeConsoleTab(self._notebook, wx.NewId()) | |
902 | #self.inspectConsoleTab = self.MakeInspectConsoleTab(self._notebook, wx.NewId()) | |
903 | self.breakPointsTab = self.MakeBreakPointsTab(self._notebook, wx.NewId()) | |
904 | self._notebook.AddPage(self.consoleTab, "Output") | |
905 | #self._notebook.AddPage(self.inspectConsoleTab, "Interact") | |
906 | self._notebook.AddPage(self.breakPointsTab, "Break Points") | |
1f780e48 RD |
907 | |
908 | self.SetMinimumPaneSize(20) | |
6f1a3f9c | 909 | self.SplitVertically(p1, p2, 550) |
1f780e48 | 910 | self.currentItem = None |
6f1a3f9c RD |
911 | self._notebook.Show(True) |
912 | ||
913 | def PopulateBPList(self): | |
914 | self.breakPointsTab.PopulateBPList() | |
915 | ||
916 | def OnSize(self, event): | |
917 | self._notebook.SetSize(self._p2.GetSize()) | |
918 | ||
919 | def MakeConsoleTab(self, parent, id): | |
920 | panel = wx.Panel(parent, id) | |
921 | sizer = wx.BoxSizer(wx.HORIZONTAL) | |
922 | self._textCtrl = STCTextEditor.TextCtrl(panel, wx.NewId()) | |
923 | sizer.Add(self._textCtrl, 1, wx.ALIGN_LEFT|wx.ALL|wx.EXPAND, 2) | |
924 | self._textCtrl.SetViewLineNumbers(False) | |
925 | self._textCtrl.SetReadOnly(True) | |
926 | if wx.Platform == '__WXMSW__': | |
927 | font = "Courier New" | |
928 | else: | |
929 | font = "Courier" | |
930 | self._textCtrl.SetFont(wx.Font(9, wx.DEFAULT, wx.NORMAL, wx.NORMAL, faceName = font)) | |
931 | self._textCtrl.SetFontColor(wx.BLACK) | |
932 | self._textCtrl.StyleClearAll() | |
933 | panel.SetSizer(sizer) | |
934 | #sizer.Fit(panel) | |
935 | ||
936 | return panel | |
937 | ||
938 | def MakeInspectConsoleTab(self, parent, id): | |
939 | def OnEnterPressed(event): | |
940 | print "Enter text was %s" % event.GetString() | |
941 | def OnText(event): | |
942 | print "Command was %s" % event.GetString() | |
943 | ||
944 | panel = wx.Panel(parent, id) | |
945 | try: | |
946 | sizer = wx.BoxSizer(wx.HORIZONTAL) | |
947 | self._ictextCtrl = wx.TextCtrl(panel, wx.NewId(), style=wx.TE_MULTILINE|wx.TE_RICH|wx.HSCROLL) | |
948 | sizer.Add(self._ictextCtrl, 1, wx.ALIGN_LEFT|wx.ALL|wx.EXPAND, 2) | |
949 | self._ictextCtrl.Bind(wx.EVT_TEXT_ENTER, OnEnterPressed) | |
950 | self._ictextCtrl.Bind(wx.EVT_TEXT, OnText) | |
951 | if wx.Platform == '__WXMSW__': | |
952 | font = "Courier New" | |
953 | else: | |
954 | font = "Courier" | |
955 | self._ictextCtrl.SetDefaultStyle(wx.TextAttr(font=wx.Font(9, wx.DEFAULT, wx.NORMAL, wx.NORMAL, faceName = font))) | |
956 | panel.SetSizer(sizer) | |
957 | except: | |
958 | tp, val, tb = sys.exc_info() | |
959 | traceback.print_exception(tp, val, tb) | |
960 | ||
961 | return panel | |
962 | ||
963 | def MakeBreakPointsTab(self, parent, id): | |
964 | panel = BreakpointsUI(parent, id, self._ui) | |
965 | return panel | |
1f780e48 RD |
966 | |
967 | def OnRightClick(self, event): | |
968 | #Refactor this... | |
969 | self._introspectItem = event.GetItem() | |
970 | self._parentChain = self.GetItemChain(event.GetItem()) | |
971 | watchOnly = len(self._parentChain) < 1 | |
972 | if not _WATCHES_ON and watchOnly: | |
973 | return | |
974 | menu = wx.Menu() | |
1f780e48 RD |
975 | if _WATCHES_ON: |
976 | if not hasattr(self, "watchID"): | |
977 | self.watchID = wx.NewId() | |
978 | self.Bind(wx.EVT_MENU, self.OnWatch, id=self.watchID) | |
979 | item = wx.MenuItem(menu, self.watchID, "Create a Watch") | |
980 | menu.AppendItem(item) | |
981 | menu.AppendSeparator() | |
982 | if not watchOnly: | |
983 | if not hasattr(self, "viewID"): | |
984 | self.viewID = wx.NewId() | |
985 | self.Bind(wx.EVT_MENU, self.OnView, id=self.viewID) | |
986 | item = wx.MenuItem(menu, self.viewID, "View in Dialog") | |
987 | menu.AppendItem(item) | |
988 | offset = wx.Point(x=0, y=20) | |
989 | menuSpot = event.GetPoint() + offset | |
990 | self._treeCtrl.PopupMenu(menu, menuSpot) | |
991 | menu.Destroy() | |
992 | self._parentChain = None | |
993 | self._introspectItem = None | |
994 | ||
995 | def GetItemChain(self, item): | |
996 | parentChain = [] | |
997 | if item: | |
998 | if _VERBOSE: print 'Exploding: %s' % self._treeCtrl.GetItemText(item, 0) | |
999 | while item != self._root: | |
1000 | text = self._treeCtrl.GetItemText(item, 0) | |
1001 | if _VERBOSE: print "Appending ", text | |
1002 | parentChain.append(text) | |
1003 | item = self._treeCtrl.GetItemParent(item) | |
1004 | parentChain.reverse() | |
1005 | return parentChain | |
1006 | ||
1007 | def OnView(self, event): | |
1008 | title = self._treeCtrl.GetItemText(self._introspectItem,0) | |
1009 | value = self._treeCtrl.GetItemText(self._introspectItem,1) | |
1010 | dlg = wx.lib.dialogs.ScrolledMessageDialog(self, value, title, style=wx.DD_DEFAULT_STYLE | wx.RESIZE_BORDER) | |
1011 | dlg.Show() | |
1012 | ||
1013 | def OnWatch(self, event): | |
1014 | try: | |
1015 | if hasattr(self, '_parentChain'): | |
1016 | wd = WatchDialog(wx.GetApp().GetTopWindow(), "Add a Watch", self._parentChain) | |
1017 | else: | |
1018 | wd = WatchDialog(wx.GetApp().GetTopWindow(), "Add a Watch", None) | |
1019 | if wd.ShowModal() == wx.ID_OK: | |
1020 | name, text, send_frame, run_once = wd.GetSettings() | |
1021 | if send_frame: | |
1022 | frameNode = self._stack[int(self.currentItem)] | |
1023 | message = frameNode.getAttribute("message") | |
1024 | else: | |
1025 | message = "" | |
1026 | binType = self._ui._callback._debuggerServer.add_watch(name, text, message, run_once) | |
1027 | xmldoc = bz2.decompress(binType.data) | |
1028 | domDoc = parseString(xmldoc) | |
1029 | nodeList = domDoc.getElementsByTagName('watch') | |
1030 | if len(nodeList) == 1: | |
1031 | watchValue = nodeList.item(0).getAttribute("message") | |
1032 | except: | |
1033 | tp, val, tb = sys.exc_info() | |
1034 | traceback.print_exception(tp, val, tb) | |
1035 | ||
1036 | def OnIntrospect(self, event): | |
1037 | wx.GetApp().GetTopWindow().SetCursor(wx.StockCursor(wx.CURSOR_WAIT)) | |
1038 | ||
1039 | try: | |
6f1a3f9c | 1040 | list = self._framesChoiceCtrl |
1f780e48 RD |
1041 | frameNode = self._stack[int(self.currentItem)] |
1042 | message = frameNode.getAttribute("message") | |
1043 | binType = self._ui._callback._debuggerServer.attempt_introspection(message, self._parentChain) | |
1044 | xmldoc = bz2.decompress(binType.data) | |
1f780e48 | 1045 | domDoc = parseString(xmldoc) |
6f1a3f9c | 1046 | #wx.MessageBox(xmldoc, "result of introspection") |
1f780e48 RD |
1047 | nodeList = domDoc.getElementsByTagName('replacement') |
1048 | replacementNode = nodeList.item(0) | |
1049 | if len(replacementNode.childNodes): | |
1050 | thingToWalk = replacementNode.childNodes.item(0) | |
1051 | tree = self._treeCtrl | |
1052 | parent = tree.GetItemParent(self._introspectItem) | |
1053 | treeNode = self.AppendSubTreeFromNode(thingToWalk, thingToWalk.getAttribute('name'), parent, insertBefore=self._introspectItem) | |
6f1a3f9c | 1054 | self._treeCtrl.Expand(treeNode) |
1f780e48 RD |
1055 | tree.Delete(self._introspectItem) |
1056 | except: | |
1057 | tp,val,tb = sys.exc_info() | |
1058 | traceback.print_exception(tp, val, tb) | |
1059 | ||
1060 | wx.GetApp().GetTopWindow().SetCursor(wx.StockCursor(wx.CURSOR_DEFAULT)) | |
1061 | ||
1f780e48 | 1062 | def ClearWhileRunning(self): |
6f1a3f9c RD |
1063 | list = self._framesChoiceCtrl |
1064 | list.Clear() | |
1065 | list.Enable(False) | |
1066 | tree = self._treeCtrl | |
1067 | root = self._root | |
1068 | tree.DeleteChildren(root) | |
1069 | ||
1070 | #tree.Hide() | |
1f780e48 RD |
1071 | |
1072 | def OnListRightClick(self, event): | |
1073 | if not hasattr(self, "syncFrameID"): | |
1074 | self.syncFrameID = wx.NewId() | |
1075 | self.Bind(wx.EVT_MENU, self.OnSyncFrame, id=self.syncFrameID) | |
1076 | menu = wx.Menu() | |
1077 | item = wx.MenuItem(menu, self.syncFrameID, "Goto Source Line") | |
1078 | menu.AppendItem(item) | |
1079 | self.PopupMenu(menu, event.GetPosition()) | |
1080 | menu.Destroy() | |
1081 | ||
1082 | def OnSyncFrame(self, event): | |
6f1a3f9c | 1083 | list = self._framesChoiceCtrl |
1f780e48 RD |
1084 | frameNode = self._stack[int(self.currentItem)] |
1085 | file = frameNode.getAttribute("file") | |
1086 | line = frameNode.getAttribute("line") | |
1087 | self._ui.SynchCurrentLine( file, int(line) ) | |
1088 | ||
1089 | def LoadFramesListXML(self, framesXML): | |
1090 | wx.GetApp().GetTopWindow().SetCursor(wx.StockCursor(wx.CURSOR_WAIT)) | |
1091 | try: | |
1092 | domDoc = parseString(framesXML) | |
6f1a3f9c RD |
1093 | list = self._framesChoiceCtrl |
1094 | list.Clear() | |
1f780e48 RD |
1095 | self._stack = [] |
1096 | nodeList = domDoc.getElementsByTagName('frame') | |
1097 | frame_count = -1 | |
1098 | for index in range(0, nodeList.length): | |
1099 | frameNode = nodeList.item(index) | |
1100 | message = frameNode.getAttribute("message") | |
6f1a3f9c | 1101 | list.Append(message) |
1f780e48 RD |
1102 | self._stack.append(frameNode) |
1103 | frame_count += 1 | |
6f1a3f9c RD |
1104 | index = len(self._stack) - 1 |
1105 | list.SetSelection(index) | |
1106 | node = self._stack[index] | |
1107 | self.currentItem = index | |
1108 | self.PopulateTreeFromFrameNode(node) | |
1109 | self.OnSyncFrame(None) | |
1110 | ||
1f780e48 RD |
1111 | self._p1.FitInside() |
1112 | frameNode = nodeList.item(index) | |
1113 | file = frameNode.getAttribute("file") | |
1114 | line = frameNode.getAttribute("line") | |
1115 | self._ui.SynchCurrentLine( file, int(line) ) | |
1116 | except: | |
1117 | tp,val,tb=sys.exc_info() | |
1118 | traceback.print_exception(tp, val, tb) | |
1119 | ||
1120 | wx.GetApp().GetTopWindow().SetCursor(wx.StockCursor(wx.CURSOR_DEFAULT)) | |
1121 | ||
1f780e48 RD |
1122 | |
1123 | def ListItemSelected(self, event): | |
6f1a3f9c RD |
1124 | message = event.GetString() |
1125 | index = 0 | |
1126 | for node in self._stack: | |
1127 | if node.getAttribute("message") == message: | |
1128 | self.currentItem = index | |
1129 | self.PopulateTreeFromFrameNode(node) | |
1130 | self.OnSyncFrame(None) | |
1131 | return | |
1132 | index = index + 1 | |
1133 | ||
1f780e48 | 1134 | def PopulateTreeFromFrameNode(self, frameNode): |
6f1a3f9c RD |
1135 | list = self._framesChoiceCtrl |
1136 | list.Enable(True) | |
1f780e48 | 1137 | tree = self._treeCtrl |
6f1a3f9c | 1138 | #tree.Show(True) |
1f780e48 RD |
1139 | root = self._root |
1140 | tree.DeleteChildren(root) | |
1141 | children = frameNode.childNodes | |
1142 | firstChild = None | |
1143 | for index in range(0, children.length): | |
1144 | subNode = children.item(index) | |
1145 | treeNode = self.AppendSubTreeFromNode(subNode, subNode.getAttribute('name'), root) | |
1146 | if not firstChild: | |
1147 | firstChild = treeNode | |
1148 | tree.Expand(root) | |
1149 | tree.Expand(firstChild) | |
1150 | self._p2.FitInside() | |
6f1a3f9c RD |
1151 | |
1152 | def IntrospectCallback(self, event): | |
1153 | tree = self._treeCtrl | |
1154 | item = event.GetItem() | |
1155 | if _VERBOSE: | |
1156 | print "In introspectCallback item is %s, pydata is %s" % (event.GetItem(), tree.GetPyData(item)) | |
1157 | if tree.GetPyData(item) != "Introspect": | |
1158 | event.Skip() | |
1159 | return | |
1160 | self._introspectItem = item | |
1161 | self._parentChain = self.GetItemChain(item) | |
1162 | self.OnIntrospect(event) | |
1163 | event.Skip() | |
1f780e48 RD |
1164 | |
1165 | def AppendSubTreeFromNode(self, node, name, parent, insertBefore=None): | |
1166 | tree = self._treeCtrl | |
1167 | if insertBefore != None: | |
1168 | treeNode = tree.InsertItem(parent, insertBefore, name) | |
1169 | else: | |
1170 | treeNode = tree.AppendItem(parent, name) | |
1171 | children = node.childNodes | |
6f1a3f9c RD |
1172 | intro = node.getAttribute('intro') |
1173 | ||
1174 | if intro == "True": | |
1175 | tree.SetItemHasChildren(treeNode, True) | |
1176 | tree.SetPyData(treeNode, "Introspect") | |
1177 | if node.getAttribute("value"): | |
1f780e48 RD |
1178 | tree.SetItemText(treeNode, self.StripOuterSingleQuotes(node.getAttribute("value")), 1) |
1179 | for index in range(0, children.length): | |
1180 | subNode = children.item(index) | |
1181 | if self.HasChildren(subNode): | |
1182 | self.AppendSubTreeFromNode(subNode, subNode.getAttribute("name"), treeNode) | |
1183 | else: | |
1184 | name = subNode.getAttribute("name") | |
1185 | value = self.StripOuterSingleQuotes(subNode.getAttribute("value")) | |
1186 | n = tree.AppendItem(treeNode, name) | |
1187 | tree.SetItemText(n, value, 1) | |
6f1a3f9c RD |
1188 | intro = subNode.getAttribute('intro') |
1189 | if intro == "True": | |
1190 | tree.SetItemHasChildren(n, True) | |
1191 | tree.SetPyData(n, "Introspect") | |
1192 | ||
1f780e48 RD |
1193 | return treeNode |
1194 | ||
1195 | def StripOuterSingleQuotes(self, string): | |
1196 | if string.startswith("'") and string.endswith("'"): | |
6f1a3f9c RD |
1197 | retval = string[1:-1] |
1198 | elif string.startswith("\"") and string.endswith("\""): | |
1199 | retval = string[1:-1] | |
1f780e48 | 1200 | else: |
6f1a3f9c RD |
1201 | retval = string |
1202 | if retval.startswith("u'") and retval.endswith("'"): | |
1203 | retval = retval[1:] | |
1204 | return retval | |
1f780e48 RD |
1205 | |
1206 | def HasChildren(self, node): | |
1207 | try: | |
1208 | return node.childNodes.length > 0 | |
1209 | except: | |
1210 | tp,val,tb=sys.exc_info() | |
1211 | return False | |
6f1a3f9c RD |
1212 | |
1213 | def AppendText(self, text): | |
1214 | self._textCtrl.SetReadOnly(False) | |
1215 | self._textCtrl.AddText(text) | |
1216 | self._textCtrl.ScrollToLine(self._textCtrl.GetLineCount()) | |
1217 | self._textCtrl.SetReadOnly(True) | |
1218 | ||
1219 | def AppendErrorText(self, text): | |
1220 | self._textCtrl.SetReadOnly(False) | |
1221 | self._textCtrl.SetFontColor(wx.RED) | |
1222 | self._textCtrl.StyleClearAll() | |
1223 | self._textCtrl.AddText(text) | |
1224 | self._textCtrl.ScrollToLine(self._textCtrl.GetLineCount()) | |
1225 | self._textCtrl.SetFontColor(wx.BLACK) | |
1226 | self._textCtrl.StyleClearAll() | |
1227 | self._textCtrl.SetReadOnly(True) | |
1228 | ||
1229 | def ClearOutput(self, event): | |
1230 | self._textCtrl.SetReadOnly(False) | |
1231 | self._textCtrl.ClearAll() | |
1232 | self._textCtrl.SetReadOnly(True) | |
1233 | ||
1234 | def SwitchToOutputTab(self): | |
1235 | self._notebook.SetSelection(0) | |
1236 | ||
1f780e48 RD |
1237 | class DebuggerView(Service.ServiceView): |
1238 | ||
1239 | #---------------------------------------------------------------------------- | |
1240 | # Overridden methods | |
1241 | #---------------------------------------------------------------------------- | |
1242 | ||
1243 | def __init__(self, service): | |
1244 | Service.ServiceView.__init__(self, service) | |
1245 | ||
1246 | def _CreateControl(self, parent, id): | |
1247 | return None | |
1248 | ||
1249 | #------------------------------------------------------------------------------ | |
1250 | # Event handling | |
1251 | #----------------------------------------------------------------------------- | |
1252 | ||
1253 | def OnToolClicked(self, event): | |
1254 | self.GetFrame().ProcessEvent(event) | |
1255 | ||
1256 | #------------------------------------------------------------------------------ | |
1257 | # Class methods | |
1258 | #----------------------------------------------------------------------------- | |
1259 | ||
1260 | class Interaction: | |
1261 | def __init__(self, message, framesXML, info=None, quit=False): | |
1262 | self._framesXML = framesXML | |
1263 | self._message = message | |
1264 | self._info = info | |
1265 | self._quit = quit | |
1266 | ||
1267 | def getFramesXML(self): | |
1268 | return self._framesXML | |
1269 | ||
1270 | def getMessage(self): | |
1271 | return self._message | |
1272 | ||
1273 | def getInfo(self): | |
1274 | return self._info | |
1275 | ||
1276 | def getQuit(self): | |
1277 | return self._quit | |
1278 | ||
1279 | class AGXMLRPCServer(SimpleXMLRPCServer.SimpleXMLRPCServer): | |
1280 | def __init__(self, address, logRequests=0): | |
1281 | SimpleXMLRPCServer.SimpleXMLRPCServer.__init__(self, address, logRequests=logRequests) | |
1282 | ||
1283 | class RequestHandlerThread(threading.Thread): | |
1284 | def __init__(self, queue, address): | |
1285 | threading.Thread.__init__(self) | |
1286 | self._keepGoing = True | |
1287 | self._queue = queue | |
1288 | self._address = address | |
1289 | self._server = AGXMLRPCServer(self._address,logRequests=0) | |
1290 | self._server.register_function(self.interaction) | |
1291 | self._server.register_function(self.quit) | |
1292 | self._server.register_function(self.dummyOperation) | |
1293 | if _VERBOSE: print "RequestHandlerThread on fileno %s" % str(self._server.fileno()) | |
1294 | ||
1295 | def run(self): | |
1296 | while self._keepGoing: | |
1297 | try: | |
1298 | self._server.handle_request() | |
1299 | except: | |
1300 | tp, val, tb = sys.exc_info() | |
1301 | traceback.print_exception(tp, val, tb) | |
1302 | self._keepGoing = False | |
1303 | if _VERBOSE: print "Exiting Request Handler Thread." | |
1304 | ||
1305 | def interaction(self, message, frameXML, info): | |
1306 | if _VERBOSE: print "In RequestHandlerThread.interaction -- adding to queue" | |
1307 | interaction = Interaction(message, frameXML, info) | |
1308 | self._queue.put(interaction) | |
1309 | return "" | |
1310 | ||
1311 | def quit(self): | |
1312 | interaction = Interaction(None, None, info=None, quit=True) | |
1313 | self._queue.put(interaction) | |
1314 | return "" | |
1315 | ||
1316 | def dummyOperation(self): | |
1317 | return "" | |
1318 | ||
1319 | def AskToStop(self): | |
1320 | self._keepGoing = False | |
1321 | if type(self._server) is not types.NoneType: | |
1322 | try: | |
1323 | # This is a really ugly way to make sure this thread isn't blocked in | |
1324 | # handle_request. | |
1325 | url = 'http://' + self._address[0] + ':' + str(self._address[1]) + '/' | |
1326 | tempServer = xmlrpclib.ServerProxy(url, allow_none=1) | |
1327 | tempServer.dummyOperation() | |
1328 | except: | |
1329 | tp, val, tb = sys.exc_info() | |
1330 | traceback.print_exception(tp, val, tb) | |
1331 | self._server.server_close() | |
1332 | ||
1333 | ||
1334 | class RequestBreakThread(threading.Thread): | |
1335 | def __init__(self, server, interrupt=False, pushBreakpoints=False, breakDict=None, kill=False): | |
1336 | threading.Thread.__init__(self) | |
1337 | self._server = server | |
1338 | ||
1339 | self._interrupt = interrupt | |
1340 | self._pushBreakpoints = pushBreakpoints | |
1341 | self._breakDict = breakDict | |
1342 | self._kill = kill | |
1343 | ||
1344 | def run(self): | |
1345 | try: | |
1346 | if _VERBOSE: print "RequestBreakThread, before call" | |
1347 | if self._interrupt: | |
1348 | self._server.break_requested() | |
1349 | if self._pushBreakpoints: | |
1350 | self._server.update_breakpoints(xmlrpclib.Binary(pickle.dumps(self._breakDict))) | |
1351 | if self._kill: | |
1352 | try: | |
1353 | self._server.die() | |
1354 | except: | |
1355 | pass | |
1356 | if _VERBOSE: print "RequestBreakThread, after call" | |
1357 | except: | |
1358 | tp,val,tb = sys.exc_info() | |
1359 | traceback.print_exception(tp, val, tb) | |
1360 | ||
1361 | class DebuggerOperationThread(threading.Thread): | |
1362 | def __init__(self, function): | |
1363 | threading.Thread.__init__(self) | |
1364 | self._function = function | |
1365 | ||
1366 | def run(self): | |
1367 | if _VERBOSE: print "In DOT, before call" | |
1368 | try: | |
1369 | self._function() | |
1370 | except: | |
1371 | tp,val,tb = sys.exc_info() | |
1372 | traceback.print_exception(tp, val, tb) | |
1373 | if _VERBOSE: print "In DOT, after call" | |
1374 | ||
1375 | class DebuggerCallback: | |
1376 | ||
1377 | def __init__(self, host, port, debugger_url, break_url, debuggerUI): | |
1378 | if _VERBOSE: print "+++++++ Creating server on port, ", str(port) | |
1379 | ||
1380 | self._queue = Queue.Queue(50) | |
1381 | self._host = host | |
1382 | self._port = int(port) | |
1383 | threading._VERBOSE = _VERBOSE | |
1384 | self._serverHandlerThread = RequestHandlerThread(self._queue, (self._host, self._port)) | |
1385 | ||
1386 | self._debugger_url = debugger_url | |
1387 | self._debuggerServer = None | |
1388 | self._waiting = False | |
1389 | self._service = wx.GetApp().GetService(DebuggerService) | |
1390 | self._debuggerUI = debuggerUI | |
1391 | self._break_url = break_url | |
1392 | self._breakServer = None | |
1393 | self._firstInteraction = True | |
1394 | self._pendingBreak = False | |
1395 | ||
1396 | def start(self): | |
1397 | self._serverHandlerThread.start() | |
1398 | ||
1399 | def ServerClose(self): | |
1400 | rbt = RequestBreakThread(self._breakServer, kill=True) | |
1401 | rbt.start() | |
1402 | self.setWaiting(False) | |
1403 | if self._serverHandlerThread: | |
1404 | self._serverHandlerThread.AskToStop() | |
1405 | self._serverHandlerThread = None | |
1406 | ||
1407 | def BreakExecution(self): | |
1408 | rbt = RequestBreakThread(self._breakServer, interrupt=True) | |
1409 | rbt.start() | |
1410 | ||
1411 | def SingleStep(self): | |
1412 | self._debuggerUI.DisableWhileDebuggerRunning() | |
1413 | #dot = DebuggerOperationThread(self._debuggerServer.set_step) | |
1414 | #dot.start() | |
1415 | self._debuggerServer.set_step() # Figure out where to set allowNone | |
1416 | self.waitForRPC() | |
1417 | ||
1418 | def Next(self): | |
1419 | self._debuggerUI.DisableWhileDebuggerRunning() | |
1420 | #dot = DebuggerOperationThread(self._debuggerServer.set_next) | |
1421 | #dot.start() | |
1422 | self._debuggerServer.set_next() | |
1423 | self.waitForRPC() | |
1424 | ||
1425 | def Continue(self): | |
1426 | self._debuggerUI.DisableWhileDebuggerRunning() | |
1427 | #dot = DebuggerOperationThread(self._debuggerServer.set_continue) | |
1428 | #dot.start() | |
1429 | self._debuggerServer.set_continue() | |
1430 | self.waitForRPC() | |
1431 | ||
1432 | def Return(self): | |
1433 | self._debuggerUI.DisableWhileDebuggerRunning() | |
1434 | #dot = DebuggerOperationThread(self._debuggerServer.set_return) | |
1435 | #dot.start() | |
1436 | self._debuggerServer.set_return() | |
1437 | self.waitForRPC() | |
1438 | ||
1439 | def setWaiting(self, value): | |
1440 | self._waiting = value | |
1441 | ||
1442 | def getWaiting(self): | |
1443 | return self._waiting | |
1444 | ||
1445 | def readQueue(self): | |
1446 | if self._queue.qsize(): | |
1447 | try: | |
1448 | item = self._queue.get_nowait() | |
1449 | if item.getQuit(): | |
1450 | self.interaction(None, None, None, True) | |
1451 | else: | |
1452 | data = bz2.decompress(item.getFramesXML().data) | |
1453 | self.interaction(item.getMessage().data, data, item.getInfo(), False) | |
1454 | except Queue.Empty: | |
1455 | pass | |
1456 | ||
1457 | def pushBreakpoints(self): | |
1458 | rbt = RequestBreakThread(self._breakServer, pushBreakpoints=True, breakDict=self._service.GetMasterBreakpointDict()) | |
1459 | rbt.start() | |
1460 | ||
1461 | ||
1462 | def waitForRPC(self): | |
1463 | self.setWaiting(True) | |
1464 | while self.getWaiting(): | |
1465 | try: | |
1466 | self.readQueue() | |
1467 | import time | |
1468 | time.sleep(0.02) | |
1469 | except: | |
1470 | tp, val, tb = sys.exc_info() | |
1471 | traceback.print_exception(tp, val, tb) | |
1472 | wx.GetApp().Yield(True) | |
1473 | if _VERBOSE: print "Exiting waitForRPC." | |
1474 | ||
1475 | def interaction(self, message, frameXML, info, quit): | |
1476 | ||
1477 | #This method should be hit as the debugger starts. | |
1478 | if self._firstInteraction: | |
1479 | self._firstInteraction = False | |
1480 | self._debuggerServer = xmlrpclib.ServerProxy(self._debugger_url, allow_none=1) | |
1481 | self._breakServer = xmlrpclib.ServerProxy(self._break_url, allow_none=1) | |
1482 | self.pushBreakpoints() | |
1483 | self.setWaiting(False) | |
1484 | if _VERBOSE: print "+"*40 | |
1485 | if(quit): | |
1486 | self._debuggerUI.StopExecution(None) | |
1487 | return "" | |
1488 | if(info != ""): | |
1489 | if _VERBOSE: print "Hit interaction with exception" | |
1490 | #self._debuggerUI.StopExecution(None) | |
1491 | #self._debuggerUI.SetStatusText("Got exception: " + str(info)) | |
1492 | self._debuggerUI.SwitchToOutputTab() | |
1493 | else: | |
1494 | if _VERBOSE: print "Hit interaction no exception" | |
1495 | self._debuggerUI.SetStatusText(message) | |
1496 | self._debuggerUI.LoadFramesListXML(frameXML) | |
1497 | self._debuggerUI.EnableWhileDebuggerStopped() | |
1498 | if _VERBOSE: print "+"*40 | |
1499 | ||
1500 | class DebuggerService(Service.Service): | |
6f1a3f9c | 1501 | executors = [] |
1f780e48 RD |
1502 | |
1503 | #---------------------------------------------------------------------------- | |
1504 | # Constants | |
1505 | #---------------------------------------------------------------------------- | |
1506 | TOGGLE_BREAKPOINT_ID = wx.NewId() | |
1507 | CLEAR_ALL_BREAKPOINTS = wx.NewId() | |
1508 | RUN_ID = wx.NewId() | |
1509 | DEBUG_ID = wx.NewId() | |
bbf7159c | 1510 | DEBUG_WEBSERVER_ID = wx.NewId() |
1f780e48 | 1511 | |
6f1a3f9c RD |
1512 | def KillAllRunningProcesses(): |
1513 | execs = DebuggerService.executors | |
1514 | for executor in execs: | |
1515 | executor.DoStopExecution() | |
1516 | KillAllRunningProcesses = staticmethod(KillAllRunningProcesses) | |
1517 | ||
1f780e48 RD |
1518 | def ComparePaths(first, second): |
1519 | one = DebuggerService.ExpandPath(first) | |
1520 | two = DebuggerService.ExpandPath(second) | |
1521 | if _WINDOWS: | |
1522 | return one.lower() == two.lower() | |
1523 | else: | |
1524 | return one == two | |
1525 | ComparePaths = staticmethod(ComparePaths) | |
1526 | ||
1527 | # Make sure we're using an expanded path on windows. | |
1528 | def ExpandPath(path): | |
1529 | if _WINDOWS: | |
1530 | try: | |
1531 | return win32api.GetLongPathName(path) | |
1532 | except: | |
1533 | print "Cannot get long path for %s" % path | |
1534 | ||
1535 | return path | |
1536 | ||
1537 | ExpandPath = staticmethod(ExpandPath) | |
1538 | ||
1539 | #---------------------------------------------------------------------------- | |
1540 | # Overridden methods | |
1541 | #---------------------------------------------------------------------------- | |
1542 | ||
1543 | def __init__(self, serviceName, embeddedWindowLocation = wx.lib.pydocview.EMBEDDED_WINDOW_LEFT): | |
1544 | Service.Service.__init__(self, serviceName, embeddedWindowLocation) | |
1545 | self.BREAKPOINT_DICT_STRING = "MasterBreakpointDict" | |
1546 | config = wx.ConfigBase_Get() | |
1547 | pickledbps = config.Read(self.BREAKPOINT_DICT_STRING) | |
1548 | if pickledbps: | |
1549 | try: | |
1550 | self._masterBPDict = pickle.loads(pickledbps.encode('ascii')) | |
1551 | except: | |
1552 | tp, val, tb = sys.exc_info() | |
1553 | traceback.print_exception(tp,val,tb) | |
1554 | self._masterBPDict = {} | |
1555 | else: | |
1556 | self._masterBPDict = {} | |
1557 | ||
1558 | def OnCloseFrame(self, event): | |
1559 | # IS THIS THE RIGHT PLACE? | |
1560 | try: | |
1561 | config = wx.ConfigBase_Get() | |
1562 | config.Write(self.BREAKPOINT_DICT_STRING, pickle.dumps(self._masterBPDict)) | |
1563 | except: | |
1564 | tp,val,tb = sys.exc_info() | |
1565 | traceback.print_exception(tp, val, tb) | |
1566 | return True | |
1567 | ||
1568 | def _CreateView(self): | |
1569 | return DebuggerView(self) | |
1570 | ||
1571 | ||
1572 | #---------------------------------------------------------------------------- | |
1573 | # Service specific methods | |
1574 | #---------------------------------------------------------------------------- | |
1575 | ||
1576 | def InstallControls(self, frame, menuBar = None, toolBar = None, statusBar = None, document = None): | |
1577 | #Service.Service.InstallControls(self, frame, menuBar, toolBar, statusBar, document) | |
1578 | ||
1579 | config = wx.ConfigBase_Get() | |
1580 | ||
1581 | debuggerMenu = wx.Menu() | |
1582 | if not menuBar.FindItemById(DebuggerService.CLEAR_ALL_BREAKPOINTS): | |
1583 | ||
1584 | debuggerMenu.Append(DebuggerService.RUN_ID, _("&Run...\tCtrl+R"), _("Runs a file")) | |
1585 | wx.EVT_MENU(frame, DebuggerService.RUN_ID, frame.ProcessEvent) | |
1586 | wx.EVT_UPDATE_UI(frame, DebuggerService.RUN_ID, frame.ProcessUpdateUIEvent) | |
1587 | ||
1588 | debuggerMenu.Append(DebuggerService.DEBUG_ID, _("&Debug...\tCtrl+D"), _("Debugs a file")) | |
1589 | wx.EVT_MENU(frame, DebuggerService.DEBUG_ID, frame.ProcessEvent) | |
1590 | wx.EVT_UPDATE_UI(frame, DebuggerService.DEBUG_ID, frame.ProcessUpdateUIEvent) | |
1591 | ||
bbf7159c RD |
1592 | if not ACTIVEGRID_BASE_IDE: |
1593 | debuggerMenu.AppendSeparator() | |
1594 | debuggerMenu.Append(DebuggerService.DEBUG_WEBSERVER_ID, _("Debug Internal Web Server"), _("Debugs the internal webservier")) | |
1595 | wx.EVT_MENU(frame, DebuggerService.DEBUG_WEBSERVER_ID, frame.ProcessEvent) | |
1596 | wx.EVT_UPDATE_UI(frame, DebuggerService.DEBUG_WEBSERVER_ID, frame.ProcessUpdateUIEvent) | |
1597 | ||
1f780e48 RD |
1598 | debuggerMenu.AppendSeparator() |
1599 | ||
1600 | debuggerMenu.Append(DebuggerService.TOGGLE_BREAKPOINT_ID, _("&Toggle Breakpoint...\tCtrl+B"), _("Toggle a breakpoint")) | |
1601 | wx.EVT_MENU(frame, DebuggerService.TOGGLE_BREAKPOINT_ID, self.ProcessEvent) | |
1602 | wx.EVT_UPDATE_UI(frame, DebuggerService.TOGGLE_BREAKPOINT_ID, self.ProcessUpdateUIEvent) | |
1603 | ||
1604 | debuggerMenu.Append(DebuggerService.CLEAR_ALL_BREAKPOINTS, _("&Clear All Breakpoints"), _("Clear All Breakpoints")) | |
1605 | wx.EVT_MENU(frame, DebuggerService.CLEAR_ALL_BREAKPOINTS, self.ProcessEvent) | |
1606 | wx.EVT_UPDATE_UI(frame, DebuggerService.CLEAR_ALL_BREAKPOINTS, self.ProcessUpdateUIEvent) | |
1607 | ||
1608 | ||
1609 | viewMenuIndex = menuBar.FindMenu(_("&Project")) | |
1610 | menuBar.Insert(viewMenuIndex + 1, debuggerMenu, _("&Run")) | |
1611 | ||
1612 | return True | |
1613 | ||
1614 | ||
1615 | ||
1616 | #---------------------------------------------------------------------------- | |
1617 | # Event Processing Methods | |
1618 | #---------------------------------------------------------------------------- | |
1619 | ||
1620 | def ProcessEventBeforeWindows(self, event): | |
1621 | return False | |
1622 | ||
1623 | ||
1624 | def ProcessEvent(self, event): | |
1625 | if Service.Service.ProcessEvent(self, event): | |
1626 | return True | |
1627 | ||
1628 | an_id = event.GetId() | |
1629 | if an_id == DebuggerService.TOGGLE_BREAKPOINT_ID: | |
1630 | self.OnToggleBreakpoint(event) | |
1631 | return True | |
1632 | elif an_id == DebuggerService.CLEAR_ALL_BREAKPOINTS: | |
1633 | self.ClearAllBreakpoints() | |
1634 | return True | |
1635 | elif an_id == DebuggerService.RUN_ID: | |
1636 | self.OnRunProject(event) | |
1637 | return True | |
1638 | elif an_id == DebuggerService.DEBUG_ID: | |
1639 | self.OnDebugProject(event) | |
1640 | return True | |
bbf7159c RD |
1641 | elif an_id == DebuggerService.DEBUG_WEBSERVER_ID: |
1642 | self.OnDebugWebServer(event) | |
1643 | return True | |
1f780e48 RD |
1644 | return False |
1645 | ||
1646 | def ProcessUpdateUIEvent(self, event): | |
1647 | if Service.Service.ProcessUpdateUIEvent(self, event): | |
1648 | return True | |
1649 | ||
1650 | an_id = event.GetId() | |
1651 | if an_id == DebuggerService.TOGGLE_BREAKPOINT_ID: | |
1652 | currentView = self.GetDocumentManager().GetCurrentView() | |
1653 | event.Enable(isinstance(currentView, PythonEditor.PythonView)) | |
1654 | return True | |
1655 | elif an_id == DebuggerService.CLEAR_ALL_BREAKPOINTS: | |
1656 | event.Enable(self.HasBreakpointsSet()) | |
1657 | return True | |
b792147d RD |
1658 | elif (an_id == DebuggerService.RUN_ID |
1659 | or an_id == DebuggerService.DEBUG_ID): | |
1f780e48 RD |
1660 | event.Enable(self.HasAnyFiles()) |
1661 | return True | |
1662 | else: | |
1663 | return False | |
1664 | ||
1665 | #---------------------------------------------------------------------------- | |
1666 | # Class Methods | |
1667 | #---------------------------------------------------------------------------- | |
1668 | ||
1669 | def OnDebugProject(self, event): | |
b792147d RD |
1670 | if _WINDOWS and not _PYWIN32_INSTALLED: |
1671 | wx.MessageBox(_("Python for Windows extensions (pywin32) is required to debug on Windows machines. Please go to http://sourceforge.net/projects/pywin32/, download and install pywin32.")) | |
1672 | return | |
1f780e48 RD |
1673 | if not Executor.GetPythonExecutablePath(): |
1674 | return | |
1675 | if DebugCommandUI.DebuggerRunning(): | |
1676 | wx.MessageBox(_("A debugger is already running. Please shut down the other debugger first."), _("Debugger Running")) | |
1677 | return | |
1678 | self.ShowWindow(True) | |
1679 | projectService = wx.GetApp().GetService(ProjectEditor.ProjectService) | |
1680 | project = projectService.GetView().GetDocument() | |
bbf7159c RD |
1681 | try: |
1682 | dlg = CommandPropertiesDialog(self.GetView().GetFrame(), 'Debug Python File', projectService, None, pythonOnly=True, okButtonName="Debug", debugging=True) | |
1683 | except: | |
1684 | return | |
1f780e48 RD |
1685 | if dlg.ShowModal() == wx.ID_OK: |
1686 | fileToDebug, initialArgs, startIn, isPython, environment = dlg.GetSettings() | |
1687 | dlg.Destroy() | |
1688 | else: | |
1689 | dlg.Destroy() | |
1690 | return | |
1691 | self.PromptToSaveFiles() | |
1692 | ||
1693 | shortFile = os.path.basename(fileToDebug) | |
1694 | fileToDebug = DebuggerService.ExpandPath(fileToDebug) | |
1695 | try: | |
1696 | page = DebugCommandUI(Service.ServiceView.bottomTab, -1, str(fileToDebug), self) | |
1697 | count = Service.ServiceView.bottomTab.GetPageCount() | |
bbf7159c | 1698 | Service.ServiceView.bottomTab.AddPage(page, _("Debugging: ") + shortFile) |
1f780e48 RD |
1699 | Service.ServiceView.bottomTab.SetSelection(count) |
1700 | page.Execute(initialArgs, startIn, environment) | |
1701 | except: | |
1702 | pass | |
bbf7159c RD |
1703 | |
1704 | def OnDebugWebServer(self, event): | |
6f1a3f9c RD |
1705 | if _WINDOWS and not _PYWIN32_INSTALLED: |
1706 | wx.MessageBox(_("Python for Windows extensions (pywin32) is required to debug on Windows machines. Please go to http://sourceforge.net/projects/pywin32/, download and install pywin32.")) | |
1707 | return | |
1708 | if not Executor.GetPythonExecutablePath(): | |
1709 | return | |
1710 | if DebugCommandUI.DebuggerRunning(): | |
1711 | wx.MessageBox(_("A debugger is already running. Please shut down the other debugger first."), _("Debugger Running")) | |
1712 | return | |
bbf7159c RD |
1713 | import WebServerService |
1714 | wsService = wx.GetApp().GetService(WebServerService.WebServerService) | |
1715 | fileName, args = wsService.StopAndPrepareToDebug() | |
1716 | try: | |
1717 | page = DebugCommandUI(Service.ServiceView.bottomTab, -1, str(fileName), self) | |
1718 | count = Service.ServiceView.bottomTab.GetPageCount() | |
1719 | Service.ServiceView.bottomTab.AddPage(page, _("Debugging: Internal WebServer")) | |
1720 | Service.ServiceView.bottomTab.SetSelection(count) | |
1721 | page.Execute(args, startIn=os.getcwd(), environment=os.environ) | |
1722 | except: | |
1723 | pass | |
1724 | ||
1725 | ||
1f780e48 RD |
1726 | def HasAnyFiles(self): |
1727 | docs = wx.GetApp().GetDocumentManager().GetDocuments() | |
1728 | return len(docs) > 0 | |
1729 | ||
1730 | def PromptToSaveFiles(self, running=True): | |
1731 | filesModified = False | |
1732 | docs = wx.GetApp().GetDocumentManager().GetDocuments() | |
1733 | for doc in docs: | |
1734 | if doc.IsModified(): | |
1735 | filesModified = True | |
1736 | break | |
1737 | if filesModified: | |
1738 | frame = self.GetView().GetFrame() | |
1739 | if running: | |
1740 | yesNoMsg = wx.MessageDialog(frame, | |
1741 | _("Files have been modified.\nWould you like to save all files before running?"), | |
1742 | _("Run"), | |
b792147d | 1743 | wx.YES_NO|wx.ICON_QUESTION |
1f780e48 RD |
1744 | ) |
1745 | else: | |
1746 | yesNoMsg = wx.MessageDialog(frame, | |
1747 | _("Files have been modified.\nWould you like to save all files before debugging?"), | |
1748 | _("Debug"), | |
b792147d | 1749 | wx.YES_NO|wx.ICON_QUESTION |
1f780e48 RD |
1750 | ) |
1751 | if yesNoMsg.ShowModal() == wx.ID_YES: | |
1752 | docs = wx.GetApp().GetDocumentManager().GetDocuments() | |
1753 | for doc in docs: | |
1754 | doc.Save() | |
1755 | ||
1756 | def OnExit(self): | |
1757 | DebugCommandUI.ShutdownAllDebuggers() | |
1758 | ||
1759 | def OnRunProject(self, event): | |
b792147d RD |
1760 | if _WINDOWS and not _PYWIN32_INSTALLED: |
1761 | wx.MessageBox(_("Python for Windows extensions (pywin32) is required to run on Windows machines. Please go to http://sourceforge.net/projects/pywin32/, download and install pywin32.")) | |
1762 | return | |
1f780e48 RD |
1763 | if not Executor.GetPythonExecutablePath(): |
1764 | return | |
1765 | projectService = wx.GetApp().GetService(ProjectEditor.ProjectService) | |
1766 | project = projectService.GetView().GetDocument() | |
bbf7159c RD |
1767 | try: |
1768 | dlg = CommandPropertiesDialog(self.GetView().GetFrame(), 'Run', projectService, None) | |
1769 | except: | |
1770 | return | |
1f780e48 RD |
1771 | if dlg.ShowModal() == wx.ID_OK: |
1772 | fileToRun, initialArgs, startIn, isPython, environment = dlg.GetSettings() | |
1773 | ||
1774 | ||
1775 | dlg.Destroy() | |
1776 | else: | |
1777 | dlg.Destroy() | |
1778 | return | |
1779 | self.PromptToSaveFiles() | |
1780 | # This will need to change when we can run more than .py and .bpel files. | |
1781 | if not isPython: | |
1782 | projectService.RunProcessModel(fileToRun) | |
1783 | return | |
1784 | ||
1785 | self.ShowWindow(True) | |
1786 | shortFile = os.path.basename(fileToRun) | |
1787 | page = RunCommandUI(Service.ServiceView.bottomTab, -1, str(fileToRun)) | |
1788 | count = Service.ServiceView.bottomTab.GetPageCount() | |
1789 | Service.ServiceView.bottomTab.AddPage(page, "Running: " + shortFile) | |
1790 | Service.ServiceView.bottomTab.SetSelection(count) | |
1791 | page.Execute(initialArgs, startIn, environment) | |
1792 | ||
1793 | def OnToggleBreakpoint(self, event, line=-1, fileName=None): | |
1794 | if not fileName: | |
1795 | view = wx.GetApp().GetDocumentManager().GetCurrentView() | |
1796 | # Test to make sure we aren't the project view. | |
1797 | if not hasattr(view, 'MarkerExists'): | |
1798 | return | |
1799 | fileName = wx.GetApp().GetDocumentManager().GetCurrentDocument().GetFilename() | |
1800 | if line < 0: | |
1801 | line = view.GetCtrl().GetCurrentLine() | |
1802 | if self.BreakpointSet(fileName, line + 1): | |
1803 | self.ClearBreak(fileName, line + 1) | |
1804 | else: | |
1805 | self.SetBreak(fileName, line + 1) | |
1806 | # Now refresh all the markers icons in all the open views. | |
1807 | self.ClearAllBreakpointMarkers() | |
1808 | self.SetAllBreakpointMarkers() | |
1809 | ||
1810 | def SilentToggleBreakpoint(self, fileName, line): | |
1811 | found = False | |
1812 | for lineNumber in self.GetBreakpointList(fileName): | |
1813 | if int(lineNumber) == int(line): | |
1814 | found = True | |
1815 | break | |
1816 | if found: | |
1817 | self.SetBreak(fileName, line) | |
1818 | else: | |
1819 | self.ClearBreak(fileName, line) | |
1820 | ||
1821 | def SetBreak(self, fileName, line): | |
1822 | expandedName = DebuggerService.ExpandPath(fileName) | |
1823 | if not self._masterBPDict.has_key(expandedName): | |
1824 | self._masterBPDict[expandedName] = [line] | |
1825 | else: | |
1826 | self._masterBPDict[expandedName] += [line] | |
1827 | # If we're already debugging, pass this bp off to the DebuggerCallback | |
1828 | self.NotifyDebuggersOfBreakpointChange() | |
1829 | ||
1830 | def NotifyDebuggersOfBreakpointChange(self): | |
1831 | DebugCommandUI.NotifyDebuggersOfBreakpointChange() | |
1832 | ||
1833 | def GetBreakpointList(self, fileName): | |
1834 | expandedName = DebuggerService.ExpandPath(fileName) | |
1835 | if not self._masterBPDict.has_key(expandedName): | |
1836 | return [] | |
1837 | else: | |
1838 | return self._masterBPDict[expandedName] | |
1839 | ||
1840 | def BreakpointSet(self, fileName, line): | |
1841 | expandedName = DebuggerService.ExpandPath(fileName) | |
1842 | if not self._masterBPDict.has_key(expandedName): | |
1843 | return False | |
1844 | else: | |
1845 | newList = [] | |
1846 | for number in self._masterBPDict[expandedName]: | |
1847 | if(int(number) == int(line)): | |
1848 | return True | |
1849 | return False | |
1850 | ||
1851 | def ClearBreak(self, fileName, line): | |
1852 | expandedName = DebuggerService.ExpandPath(fileName) | |
1853 | if not self._masterBPDict.has_key(expandedName): | |
1854 | print "In ClearBreak: no key" | |
1855 | return | |
1856 | else: | |
1857 | newList = [] | |
1858 | for number in self._masterBPDict[expandedName]: | |
1859 | if(int(number) != int(line)): | |
1860 | newList.append(number) | |
1861 | self._masterBPDict[expandedName] = newList | |
1862 | self.NotifyDebuggersOfBreakpointChange() | |
1863 | ||
1864 | def HasBreakpointsSet(self): | |
1865 | for key, value in self._masterBPDict.items(): | |
1866 | if len(value) > 0: | |
1867 | return True | |
1868 | return False | |
1869 | ||
1870 | def ClearAllBreakpoints(self): | |
1871 | self._masterBPDict = {} | |
1872 | self.NotifyDebuggersOfBreakpointChange() | |
1873 | self.ClearAllBreakpointMarkers() | |
1874 | ||
1875 | def ClearAllBreakpointMarkers(self): | |
1876 | openDocs = wx.GetApp().GetDocumentManager().GetDocuments() | |
1877 | for openDoc in openDocs: | |
1878 | if(isinstance(openDoc.GetFirstView(), CodeEditor.CodeView)): | |
1879 | openDoc.GetFirstView().MarkerDeleteAll(CodeEditor.CodeCtrl.BREAKPOINT_MARKER_NUM) | |
1880 | ||
1881 | def GetMasterBreakpointDict(self): | |
1882 | return self._masterBPDict | |
1883 | ||
1884 | def SetAllBreakpointMarkers(self): | |
1885 | openDocs = wx.GetApp().GetDocumentManager().GetDocuments() | |
1886 | for openDoc in openDocs: | |
1887 | if(isinstance(openDoc.GetFirstView(), CodeEditor.CodeView)): | |
1888 | self.SetCurrentBreakpointMarkers(openDoc.GetFirstView()) | |
1889 | ||
1890 | def SetCurrentBreakpointMarkers(self, view): | |
1891 | if isinstance(view, CodeEditor.CodeView) and hasattr(view, 'GetDocument'): | |
1892 | view.MarkerDeleteAll(CodeEditor.CodeCtrl.BREAKPOINT_MARKER_NUM) | |
1893 | for linenum in self.GetBreakpointList(view.GetDocument().GetFilename()): | |
1894 | view.MarkerAdd(lineNum=int(linenum) - 1, marker_index=CodeEditor.CodeCtrl.BREAKPOINT_MARKER_NUM) | |
1895 | ||
1896 | class DebuggerOptionsPanel(wx.Panel): | |
1897 | ||
1898 | ||
1899 | def __init__(self, parent, id): | |
1900 | wx.Panel.__init__(self, parent, id) | |
1901 | SPACE = 10 | |
1902 | config = wx.ConfigBase_Get() | |
1903 | localHostStaticText = wx.StaticText(self, -1, _("Local Host Name:")) | |
1904 | self._LocalHostTextCtrl = wx.TextCtrl(self, -1, config.Read("DebuggerHostName", DEFAULT_HOST), size = (150, -1)) | |
1905 | portNumberStaticText = wx.StaticText(self, -1, _("Port Range:")) | |
1906 | dashStaticText = wx.StaticText(self, -1, _("through to")) | |
1907 | startingPort=config.ReadInt("DebuggerStartingPort", DEFAULT_PORT) | |
1908 | self._PortNumberTextCtrl = wx.lib.intctrl.IntCtrl(self, -1, startingPort, size = (50, -1)) | |
1909 | self._PortNumberTextCtrl.SetMin(1)#What are real values? | |
1910 | self._PortNumberTextCtrl.SetMax(65514) #What are real values? | |
1911 | self.Bind(wx.lib.intctrl.EVT_INT, self.MinPortChange, self._PortNumberTextCtrl) | |
1912 | ||
1913 | self._EndPortNumberTextCtrl = wx.lib.intctrl.IntCtrl(self, -1, startingPort + PORT_COUNT, size = (50, -1)) | |
1914 | self._EndPortNumberTextCtrl.SetMin(22)#What are real values? | |
1915 | self._EndPortNumberTextCtrl.SetMax(65535)#What are real values? | |
1916 | self._EndPortNumberTextCtrl.Enable( False ) | |
1917 | debuggerPanelBorderSizer = wx.BoxSizer(wx.VERTICAL) | |
1918 | debuggerPanelSizer = wx.GridBagSizer(hgap = 5, vgap = 5) | |
1919 | debuggerPanelSizer.Add( localHostStaticText, (0,0), flag=wx.ALIGN_CENTER_VERTICAL|wx.ALIGN_LEFT) | |
1920 | debuggerPanelSizer.Add( self._LocalHostTextCtrl, (0,1), (1,3), flag=wx.EXPAND|wx.ALIGN_CENTER) | |
1921 | debuggerPanelSizer.Add( portNumberStaticText, (1,0), flag=wx.ALIGN_LEFT|wx.ALIGN_CENTER_VERTICAL) | |
1922 | debuggerPanelSizer.Add( self._PortNumberTextCtrl, (1,1), flag=wx.ALIGN_CENTER) | |
1923 | debuggerPanelSizer.Add( dashStaticText, (1,2), flag=wx.ALIGN_CENTER) | |
1924 | debuggerPanelSizer.Add( self._EndPortNumberTextCtrl, (1,3), flag=wx.ALIGN_CENTER) | |
1925 | FLUSH_PORTS_ID = wx.NewId() | |
1926 | self._flushPortsButton = wx.Button(self, FLUSH_PORTS_ID, "Reset Port List") | |
1927 | wx.EVT_BUTTON(parent, FLUSH_PORTS_ID, self.FlushPorts) | |
1928 | debuggerPanelSizer.Add(self._flushPortsButton, (2,2), (1,2), flag=wx.ALIGN_RIGHT) | |
1929 | ||
1930 | debuggerPanelBorderSizer.Add(debuggerPanelSizer, 0, wx.ALL, SPACE) | |
1931 | self.SetSizer(debuggerPanelBorderSizer) | |
1932 | self.Layout() | |
1933 | parent.AddPage(self, _("Debugger")) | |
1934 | ||
1935 | def FlushPorts(self, event): | |
1936 | if self._PortNumberTextCtrl.IsInBounds(): | |
1937 | config = wx.ConfigBase_Get() | |
1938 | config.WriteInt("DebuggerStartingPort", self._PortNumberTextCtrl.GetValue()) | |
1939 | DebugCommandUI.NewPortRange() | |
1940 | else: | |
1941 | wx.MessageBox(_("The starting port is not valid. Please change the value and try again.", "Invalid Starting Port Number")) | |
1942 | ||
1943 | def MinPortChange(self, event): | |
1944 | self._EndPortNumberTextCtrl.Enable( True ) | |
1945 | self._EndPortNumberTextCtrl.SetValue( self._PortNumberTextCtrl.GetValue() + PORT_COUNT) | |
1946 | self._EndPortNumberTextCtrl.Enable( False ) | |
1947 | ||
1948 | def OnOK(self, optionsDialog): | |
1949 | config = wx.ConfigBase_Get() | |
1950 | config.Write("DebuggerHostName", self._LocalHostTextCtrl.GetValue()) | |
1951 | if self._PortNumberTextCtrl.IsInBounds(): | |
1952 | config.WriteInt("DebuggerStartingPort", self._PortNumberTextCtrl.GetValue()) | |
1953 | ||
1954 | class CommandPropertiesDialog(wx.Dialog): | |
1955 | ||
1956 | def __init__(self, parent, title, projectService, currentProjectDocument, pythonOnly=False, okButtonName="Run", debugging=False): | |
1f780e48 RD |
1957 | self._projService = projectService |
1958 | self._pmext = None | |
1959 | self._pyext = None | |
1960 | for template in self._projService.GetDocumentManager().GetTemplates(): | |
1961 | if not ACTIVEGRID_BASE_IDE and template.GetDocumentType() == ProcessModelEditor.ProcessModelDocument: | |
1962 | self._pmext = template.GetDefaultExtension() | |
1963 | if template.GetDocumentType() == PythonEditor.PythonDocument: | |
1964 | self._pyext = template.GetDefaultExtension() | |
1965 | self._pythonOnly = pythonOnly | |
1f780e48 | 1966 | self._currentProj = currentProjectDocument |
bbf7159c RD |
1967 | self._projectNameList, self._projectDocumentList, selectedIndex = self.GetProjectList() |
1968 | if not self._projectNameList: | |
1969 | wx.MessageBox(_("To run or debug you must have an open runnable file or project containing runnable files. Use File->Open to open the file you wish to run or debug."), _("Nothing to Run")) | |
1970 | raise BadBadBad | |
1971 | if _WINDOWS: | |
1972 | wx.Dialog.__init__(self, parent, -1, title) | |
1973 | else: | |
1974 | wx.Dialog.__init__(self, parent, -1, title, size=(390,270)) | |
1975 | ||
1f780e48 RD |
1976 | projStaticText = wx.StaticText(self, -1, _("Project:")) |
1977 | fileStaticText = wx.StaticText(self, -1, _("File:")) | |
1978 | argsStaticText = wx.StaticText(self, -1, _("Arguments:")) | |
1979 | startInStaticText = wx.StaticText(self, -1, _("Start in:")) | |
1980 | pythonPathStaticText = wx.StaticText(self, -1, _("PYTHONPATH:")) | |
1981 | postpendStaticText = _("Postpend win32api path") | |
1982 | cpPanelBorderSizer = wx.BoxSizer(wx.VERTICAL) | |
1f780e48 RD |
1983 | self._projList = wx.Choice(self, -1, (200,-1), choices=self._projectNameList) |
1984 | self.Bind(wx.EVT_CHOICE, self.EvtListBox, self._projList) | |
1985 | HALF_SPACE = 5 | |
1986 | flexGridSizer = wx.FlexGridSizer(cols = 3, vgap = 10, hgap = 10) | |
1987 | ||
1988 | flexGridSizer.Add(projStaticText, 0, flag=wx.ALIGN_CENTER_VERTICAL|wx.ALIGN_LEFT) | |
1989 | flexGridSizer.Add(self._projList, 1, flag=wx.EXPAND) | |
1990 | flexGridSizer.Add(wx.StaticText(parent, -1, ""), 0) | |
1991 | ||
1992 | flexGridSizer.Add(fileStaticText, 0, flag=wx.ALIGN_CENTER_VERTICAL|wx.ALIGN_LEFT) | |
1993 | self._fileList = wx.Choice(self, -1, (200,-1)) | |
1994 | self.Bind(wx.EVT_CHOICE, self.OnFileSelected, self._fileList) | |
1995 | flexGridSizer.Add(self._fileList, 1, flag=wx.EXPAND) | |
1996 | flexGridSizer.Add(wx.StaticText(parent, -1, ""), 0) | |
1997 | ||
1998 | config = wx.ConfigBase_Get() | |
1999 | self._lastArguments = config.Read("LastRunArguments") | |
2000 | self._argsEntry = wx.TextCtrl(self, -1, str(self._lastArguments)) | |
2001 | self._argsEntry.SetToolTipString(str(self._lastArguments)) | |
1f780e48 RD |
2002 | |
2003 | flexGridSizer.Add(argsStaticText, 0, flag=wx.ALIGN_CENTER_VERTICAL|wx.ALIGN_LEFT) | |
2004 | flexGridSizer.Add(self._argsEntry, 1, flag=wx.EXPAND) | |
2005 | flexGridSizer.Add(wx.StaticText(parent, -1, ""), 0) | |
2006 | ||
2007 | flexGridSizer.Add(startInStaticText, 0, flag=wx.ALIGN_CENTER_VERTICAL|wx.ALIGN_LEFT) | |
2008 | self._lastStartIn = config.Read("LastRunStartIn") | |
2009 | if not self._lastStartIn: | |
2010 | self._lastStartIn = str(os.getcwd()) | |
2011 | self._startEntry = wx.TextCtrl(self, -1, self._lastStartIn) | |
2012 | self._startEntry.SetToolTipString(self._lastStartIn) | |
2013 | def TextChanged2(event): | |
2014 | self._startEntry.SetToolTipString(event.GetString()) | |
2015 | self.Bind(wx.EVT_TEXT, TextChanged2, self._startEntry) | |
2016 | ||
2017 | flexGridSizer.Add(self._startEntry, 1, wx.EXPAND) | |
b792147d | 2018 | self._findDir = wx.Button(self, -1, _("Browse...")) |
1f780e48 RD |
2019 | self.Bind(wx.EVT_BUTTON, self.OnFindDirClick, self._findDir) |
2020 | flexGridSizer.Add(self._findDir, 0, wx.RIGHT, 10) | |
2021 | ||
2022 | flexGridSizer.Add(pythonPathStaticText, 0, flag=wx.ALIGN_CENTER_VERTICAL|wx.ALIGN_LEFT) | |
2023 | if os.environ.has_key('PYTHONPATH'): | |
2024 | startval = os.environ['PYTHONPATH'] | |
2025 | else: | |
2026 | startval = "" | |
2027 | self._lastPythonPath = config.Read("LastPythonPath", startval) | |
2028 | self._pythonPathEntry = wx.TextCtrl(self, -1, self._lastPythonPath) | |
2029 | self._pythonPathEntry.SetToolTipString(self._lastPythonPath) | |
2030 | flexGridSizer.Add(self._pythonPathEntry, 1, wx.EXPAND) | |
2031 | flexGridSizer.Add(wx.StaticText(parent, -1, ""), 0) | |
2032 | flexGridSizer.Add(wx.StaticText(parent, -1, ""), 0) | |
2033 | if debugging: | |
2034 | self._postpendCheckBox = wx.CheckBox(self, -1, postpendStaticText) | |
2035 | checked = bool(config.ReadInt("PythonPathPostpend", 1)) | |
2036 | self._postpendCheckBox.SetValue(checked) | |
2037 | flexGridSizer.Add(self._postpendCheckBox, 1, wx.EXPAND) | |
2038 | flexGridSizer.Add(wx.StaticText(parent, -1, ""), 0) | |
2039 | cpPanelBorderSizer.Add(flexGridSizer, 0, wx.ALL, 10) | |
2040 | ||
2041 | box = wx.BoxSizer(wx.HORIZONTAL) | |
b792147d | 2042 | self._okButton = wx.Button(self, wx.ID_OK, okButtonName) |
1f780e48 RD |
2043 | self._okButton.SetDefault() |
2044 | self._okButton.SetHelpText(_("The ") + okButtonName + _(" button completes the dialog")) | |
2045 | box.Add(self._okButton, 0, wx.ALIGN_RIGHT|wx.ALL, 5) | |
2046 | self.Bind(wx.EVT_BUTTON, self.OnOKClick, self._okButton) | |
b792147d | 2047 | btn = wx.Button(self, wx.ID_CANCEL, _("Cancel")) |
1f780e48 RD |
2048 | btn.SetHelpText(_("The Cancel button cancels the dialog.")) |
2049 | box.Add(btn, 0, wx.ALIGN_RIGHT|wx.ALL, 5) | |
2050 | cpPanelBorderSizer.Add(box, 0, wx.ALIGN_RIGHT|wx.BOTTOM, 5) | |
2051 | ||
2052 | self.SetSizer(cpPanelBorderSizer) | |
2053 | if _WINDOWS: | |
2054 | self.GetSizer().Fit(self) | |
2055 | ||
2056 | self.Layout() | |
2057 | ||
2058 | # Set up selections based on last values used. | |
2059 | self._fileNameList = None | |
2060 | self._selectedFileIndex = 0 | |
2061 | lastProject = config.Read("LastRunProject") | |
2062 | lastFile = config.Read("LastRunFile") | |
2063 | ||
2064 | if lastProject in self._projectNameList: | |
2065 | selectedIndex = self._projectNameList.index(lastProject) | |
2066 | elif selectedIndex < 0: | |
2067 | selectedIndex = 0 | |
2068 | self._projList.Select(selectedIndex) | |
2069 | self._selectedProjectIndex = selectedIndex | |
2070 | self._selectedProjectDocument = self._projectDocumentList[selectedIndex] | |
2071 | self.PopulateFileList(self._selectedProjectDocument, lastFile) | |
2072 | ||
2073 | def OnOKClick(self, event): | |
2074 | startIn = self._startEntry.GetValue() | |
2075 | fileToRun = self._fileList.GetStringSelection() | |
2076 | if not fileToRun: | |
2077 | wx.MessageBox(_("You must select a file to proceed. Note that not all projects have files that can be run or debugged.")) | |
2078 | return | |
2079 | isPython = fileToRun.endswith(self._pyext) | |
2080 | if isPython and not os.path.exists(startIn): | |
2081 | wx.MessageBox(_("Starting directory does not exist. Please change this value.")) | |
2082 | return | |
2083 | config = wx.ConfigBase_Get() | |
2084 | config.Write("LastRunProject", self._projectNameList[self._selectedProjectIndex]) | |
2085 | config.Write("LastRunFile", fileToRun) | |
2086 | # Don't update the arguments or starting directory unless we're runing python. | |
2087 | if isPython: | |
2088 | config.Write("LastRunArguments", self._argsEntry.GetValue()) | |
2089 | config.Write("LastRunStartIn", self._startEntry.GetValue()) | |
2090 | config.Write("LastPythonPath",self._pythonPathEntry.GetValue()) | |
2091 | if hasattr(self, "_postpendCheckBox"): | |
2092 | config.WriteInt("PythonPathPostpend", int(self._postpendCheckBox.GetValue())) | |
2093 | ||
2094 | self.EndModal(wx.ID_OK) | |
2095 | ||
2096 | def GetSettings(self): | |
2097 | filename = self._fileNameList[self._selectedFileIndex] | |
2098 | args = self._argsEntry.GetValue() | |
2099 | startIn = self._startEntry.GetValue() | |
2100 | isPython = filename.endswith(self._pyext) | |
2101 | env = os.environ | |
2102 | if hasattr(self, "_postpendCheckBox"): | |
2103 | postpend = self._postpendCheckBox.GetValue() | |
2104 | else: | |
2105 | postpend = False | |
2106 | if postpend: | |
2107 | env['PYTHONPATH'] = self._pythonPathEntry.GetValue() + os.pathsep + os.path.join(os.getcwd(), "3rdparty", "pywin32") | |
2108 | else: | |
2109 | env['PYTHONPATH'] = self._pythonPathEntry.GetValue() | |
2110 | ||
2111 | return filename, args, startIn, isPython, env | |
2112 | ||
2113 | def OnFileSelected(self, event): | |
2114 | self._selectedFileIndex = self._fileList.GetSelection() | |
2115 | self.EnableForFileType(event.GetString()) | |
2116 | ||
2117 | def EnableForFileType(self, fileName): | |
2118 | show = fileName.endswith(self._pyext) | |
2119 | self._startEntry.Enable(show) | |
2120 | self._findDir.Enable(show) | |
2121 | self._argsEntry.Enable(show) | |
2122 | ||
2123 | if not show: | |
2124 | self._lastStartIn = self._startEntry.GetValue() | |
2125 | self._startEntry.SetValue("") | |
2126 | self._lastArguments = self._argsEntry.GetValue() | |
2127 | self._argsEntry.SetValue("") | |
2128 | else: | |
2129 | self._startEntry.SetValue(self._lastStartIn) | |
2130 | self._argsEntry.SetValue(self._lastArguments) | |
2131 | ||
2132 | ||
2133 | ||
2134 | def OnFindDirClick(self, event): | |
2135 | dlg = wx.DirDialog(self, "Choose a starting directory:", self._startEntry.GetValue(), | |
2136 | style=wx.DD_DEFAULT_STYLE|wx.DD_NEW_DIR_BUTTON) | |
2137 | ||
2138 | if dlg.ShowModal() == wx.ID_OK: | |
2139 | self._startEntry.SetValue(dlg.GetPath()) | |
2140 | ||
2141 | dlg.Destroy() | |
2142 | ||
2143 | def EvtListBox(self, event): | |
2144 | if event.GetString(): | |
2145 | index = self._projectNameList.index(event.GetString()) | |
2146 | self._selectedProjectDocument = self._projectDocumentList[index] | |
2147 | self._selectedProjectIndex = index | |
2148 | self.PopulateFileList(self._selectedProjectDocument) | |
2149 | ||
2150 | def FilterFileList(self, list): | |
2151 | if self._pythonOnly: | |
2152 | files = filter(lambda f: f.endswith(self._pyext), list) | |
2153 | else: | |
2154 | files = filter(lambda f: (self._pmext and f.endswith(self._pmext)) or f.endswith(self._pyext), list) | |
2155 | return files | |
2156 | ||
2157 | def PopulateFileList(self, project, shortNameToSelect=None): | |
2158 | self._fileNameList = self.FilterFileList(project.GetFiles()[:]) | |
2159 | self._fileList.Clear() | |
2160 | if not self._fileNameList: | |
2161 | return | |
2162 | self._fileNameList.sort(lambda a, b: cmp(os.path.basename(a).lower(), os.path.basename(b).lower())) | |
2163 | strings = map(lambda file: os.path.basename(file), self._fileNameList) | |
2164 | for index in range(0, len(strings)): | |
2165 | if shortNameToSelect == strings[index]: | |
2166 | self._selectedFileIndex = index | |
2167 | break | |
2168 | self._fileList.Hide() | |
2169 | self._fileList.AppendItems(strings) | |
2170 | self._fileList.Show() | |
2171 | if self._selectedFileIndex not in range(0, len(strings)) : self._selectedFileIndex = 0 | |
2172 | self._fileList.SetSelection(self._selectedFileIndex) | |
2173 | self.EnableForFileType(strings[self._selectedFileIndex]) | |
2174 | ||
2175 | def GetProjectList(self): | |
2176 | docList = [] | |
2177 | nameList = [] | |
2178 | found = False | |
2179 | index = -1 | |
2180 | count = 0 | |
2181 | for document in self._projService.GetDocumentManager().GetDocuments(): | |
2182 | if document.GetDocumentTemplate().GetDocumentType() == ProjectEditor.ProjectDocument and len(document.GetFiles()): | |
2183 | docList.append(document) | |
2184 | nameList.append(os.path.basename(document.GetFilename())) | |
2185 | if document == self._currentProj: | |
2186 | found = True | |
2187 | index = count | |
2188 | count += 1 | |
bbf7159c RD |
2189 | #Check for open files not in any of these projects and add them to a default project |
2190 | def AlreadyInProject(fileName): | |
2191 | for projectDocument in docList: | |
2192 | if projectDocument.IsFileInProject(fileName): | |
2193 | return True | |
2194 | return False | |
2195 | ||
2196 | unprojectedFiles = [] | |
2197 | for document in self._projService.GetDocumentManager().GetDocuments(): | |
2198 | if not ACTIVEGRID_BASE_IDE and type(document) == ProcessModelEditor.ProcessModelDocument: | |
2199 | if not AlreadyInProject(document.GetFilename()): | |
2200 | unprojectedFiles.append(document.GetFilename()) | |
2201 | if type(document) == PythonEditor.PythonDocument: | |
2202 | if not AlreadyInProject(document.GetFilename()): | |
2203 | unprojectedFiles.append(document.GetFilename()) | |
2204 | ||
2205 | if unprojectedFiles: | |
2206 | unprojProj = ProjectEditor.ProjectDocument() | |
2207 | unprojProj.SetFilename(_("Not in any Project")) | |
2208 | unprojProj.AddFiles(unprojectedFiles) | |
2209 | docList.append(unprojProj) | |
2210 | nameList.append(_("Not in any Project")) | |
2211 | ||
1f780e48 | 2212 | return nameList, docList, index |
bbf7159c RD |
2213 | |
2214 | ||
1f780e48 RD |
2215 | #---------------------------------------------------------------------- |
2216 | from wx import ImageFromStream, BitmapFromImage | |
1f780e48 | 2217 | import cStringIO |
bbf7159c | 2218 | |
1f780e48 RD |
2219 | #---------------------------------------------------------------------- |
2220 | def getBreakData(): | |
2221 | return \ | |
b792147d RD |
2222 | '\x89PNG\r\n\x1a\n\x00\x00\x00\rIHDR\x00\x00\x00\x10\x00\x00\x00\x10\x08\x02\ |
2223 | \x00\x00\x00\x90\x91h6\x00\x00\x00\x03sBIT\x08\x08\x08\xdb\xe1O\xe0\x00\x00\ | |
2224 | \x00\x85IDAT(\x91\xbd\x92A\x16\x03!\x08CI\xdf\xdc\x0b\x8e\xe6\xd1\xe0d\xe9\ | |
2225 | \x82\xd6\xc7(\x9di7\xfd\xab<\x14\x13Q\xb8\xbb\xfc\xc2\xe3\xd3\x82\x99\xb9\ | |
2226 | \xe9\xaeq\xe1`f)HF\xc4\x8dC2\x06\xbf\x8a4\xcf\x1e\x03K\xe5h\x1bH\x02\x98\xc7\ | |
2227 | \x03\x98\xa9z\x07\x00%\xd6\xa9\xd27\x90\xac\xbbk\xe5\x15I\xcdD$\xdc\xa7\xceT\ | |
2228 | 5a\xce\xf3\xe4\xa0\xaa\x8bO\x12\x11\xabC\xcb\x9c}\xd57\xef\xb0\xf3\xb7\x86p\ | |
2229 | \x97\xf7\xb5\xaa\xde\xb9\xfa|-O\xbdjN\x9b\xf8\x06A\xcb\x00\x00\x00\x00IEND\ | |
2230 | \xaeB`\x82' | |
1f780e48 RD |
2231 | |
2232 | def getBreakBitmap(): | |
2233 | return BitmapFromImage(getBreakImage()) | |
2234 | ||
2235 | def getBreakImage(): | |
2236 | stream = cStringIO.StringIO(getBreakData()) | |
2237 | return ImageFromStream(stream) | |
2238 | ||
2239 | def getBreakIcon(): | |
bbf7159c | 2240 | return wx.IconFromBitmap(getBreakBitmap()) |
1f780e48 RD |
2241 | |
2242 | #---------------------------------------------------------------------- | |
2243 | def getClearOutputData(): | |
2244 | return \ | |
2245 | '\x89PNG\r\n\x1a\n\x00\x00\x00\rIHDR\x00\x00\x00\x10\x00\x00\x00\x10\x08\x06\ | |
2246 | \x00\x00\x00\x1f\xf3\xffa\x00\x00\x00\x04sBIT\x08\x08\x08\x08|\x08d\x88\x00\ | |
2247 | \x00\x00\xb4IDAT8\x8d\xa5\x92\xdd\r\x03!\x0c\x83\xbf\xa0n\xd4\x9d\xda5\xb81\ | |
2248 | \xbaS\xbb\x12\xee\x03?\xe5\x08\xe5N\xba\xbc Db\xec\xd8p\xb1l\xb8\xa7\x83\xfe\ | |
2249 | \xb0\x02H\x92F\xc0_\xa3\x99$\x99\x99\xedznc\xe36\x81\x88\x98"\xb2\x02\xa2\ | |
2250 | \x1e\xc4Q\x9aUD\x161\xcd\xde\x1c\x83\x15\x084)\x8d\xc5)\x06\xab\xaaZ\x92\xee\ | |
2251 | \xce\x11W\xdbGD\x0cIT\x06\xe7\x00\xdeY\xfe\xcc\x89\x06\xf0\xf2\x99\x00\xe0\ | |
2252 | \x91\x7f\xab\x83\xed\xa4\xc8\xafK\x0c\xcf\x92\x83\x99\x8d\xe3p\xef\xe4\xa1\ | |
2253 | \x0b\xe57j\xc8:\x06\t\x08\x87.H\xb2n\xa8\xc9\xa9\x12vQ\xfeG"\xe3\xacw\x00\ | |
2254 | \x10$M\xd3\x86_\xf0\xe5\xfc\xb4\xfa\x02\xcb\x13j\x10\xc5\xd7\x92D\x00\x00\ | |
2255 | \x00\x00IEND\xaeB`\x82' | |
2256 | ||
2257 | def getClearOutputBitmap(): | |
2258 | return BitmapFromImage(getClearOutputImage()) | |
2259 | ||
2260 | def getClearOutputImage(): | |
2261 | stream = cStringIO.StringIO(getClearOutputData()) | |
2262 | return ImageFromStream(stream) | |
2263 | ||
2264 | def getClearOutputIcon(): | |
bbf7159c | 2265 | return wx.IconFromBitmap(getClearOutputBitmap()) |
1f780e48 RD |
2266 | |
2267 | #---------------------------------------------------------------------- | |
2268 | def getCloseData(): | |
2269 | return \ | |
b792147d RD |
2270 | '\x89PNG\r\n\x1a\n\x00\x00\x00\rIHDR\x00\x00\x00\x10\x00\x00\x00\x10\x08\x02\ |
2271 | \x00\x00\x00\x90\x91h6\x00\x00\x00\x03sBIT\x08\x08\x08\xdb\xe1O\xe0\x00\x00\ | |
2272 | \x00\xedIDAT(\x91\xa5\x90!\xae\x840\x10\x86g_\xd6"*kz\x82j\xb0h\x1c\t\' x\ | |
2273 | \x92Z\xc2\x05\x10\x95\x18\x0e\x00\x02M\x82 \xe1\nMF#jz\x80\xea&+\x9a\x10\x96\ | |
2274 | \xdd}\xfb\xc8\x1b\xd7?\xdf\x97\xfe3\xb7u]\xe1\xca\xfc\\\xa2\xff- \xe24M\xc7\ | |
2275 | \xc49wJ\xee\xc7G]\xd7\x8c1\xc6\x18\xe7\xdc\'B\x08k\xed1y\xfaa\x1cG\xad\xb5\ | |
2276 | \x94\x12\x11\x9dsy\x9e+\xa5\x84\x10;\r\x00\xb7\xd3\x95\x8c1UU\x05A\x00\x00\ | |
2277 | \xd6\xda,\xcb\x92$\xf9\xb8\x03\x00PJ\x85\x10Zk\xa5\xd4+\xfdF\x00\x80\xae\xeb\ | |
2278 | \x08!\x84\x90y\x9e\x11\xf1\x8bP\x96\xa5\xef\xdd\xb6\xad\xb5VJ\xf9\x9b\xe0\ | |
2279 | \xe9\xa6i8\xe7\xbe\xdb\xb6mi\x9a\x0e\xc3\xf0F\x88\xe3\x18\x00\xfa\xbe\x0f\ | |
2280 | \xc3\xd0\'\x9c\xf3eY\xa2(*\x8ab\xc7\x9e\xaed\x8c\xa1\x94\xben\xf5\xb1\xd2W\ | |
2281 | \xfa,\xfce.\x0b\x0f\xb8\x96e\x90gS\xe0v\x00\x00\x00\x00IEND\xaeB`\x82' | |
1f780e48 RD |
2282 | |
2283 | def getCloseBitmap(): | |
2284 | return BitmapFromImage(getCloseImage()) | |
2285 | ||
2286 | def getCloseImage(): | |
2287 | stream = cStringIO.StringIO(getCloseData()) | |
2288 | return ImageFromStream(stream) | |
2289 | ||
2290 | def getCloseIcon(): | |
bbf7159c | 2291 | return wx.IconFromBitmap(getCloseBitmap()) |
1f780e48 RD |
2292 | |
2293 | #---------------------------------------------------------------------- | |
2294 | def getContinueData(): | |
2295 | return \ | |
2296 | '\x89PNG\r\n\x1a\n\x00\x00\x00\rIHDR\x00\x00\x00\x10\x00\x00\x00\x10\x08\x06\ | |
2297 | \x00\x00\x00\x1f\xf3\xffa\x00\x00\x00\x04sBIT\x08\x08\x08\x08|\x08d\x88\x00\ | |
2298 | \x00\x00\x9eIDAT8\x8d\xbd\x92\xd1\r\x83@\x0cC\xed\x8a\x11X\xac\x1b\xddF,\xd6\ | |
2299 | \x11\x90\xdc\x0f\x9a\x93s)\x14Z\xa9\x91\x10\n\x97\xbc\xd89\x80?\x84\x1a\xa4\ | |
2300 | \x83\xfc\x1c$\x1e)7\xdf<Y0\xaf\x0b\xe6\xf5\x1d\xa1\xb5\x13C\x03 !\xaa\xfd\ | |
2301 | \xed\n:mr\xc0\x1d\x8f\xc9\x9a!\t$\xe5\xd3I\xe2\xe5B$\x99\x00[\x01\xe8\xc5\ | |
2302 | \xd9G\xfaN`\xd8\x81I\xed\x8c\xb19\x94\x8d\xcbL\x00;t\xcf\x9fwPh\xdb\x0e\xe8\ | |
2303 | \xd3,\x17\x8b\xc7\x9d\xbb>\x8a \xec5\x94\tc\xc4\x12\xab\x94\xeb\x7fkWr\xc9B%\ | |
2304 | \xfc\xd2\xfcM<\x01\xf6tn\x12O3c\xe6\x00\x00\x00\x00IEND\xaeB`\x82' | |
2305 | ||
2306 | def getContinueBitmap(): | |
2307 | return BitmapFromImage(getContinueImage()) | |
2308 | ||
2309 | def getContinueImage(): | |
2310 | stream = cStringIO.StringIO(getContinueData()) | |
2311 | return ImageFromStream(stream) | |
2312 | ||
2313 | def getContinueIcon(): | |
bbf7159c | 2314 | return wx.IconFromBitmap(getContinueBitmap()) |
1f780e48 RD |
2315 | |
2316 | #---------------------------------------------------------------------- | |
2317 | def getNextData(): | |
2318 | return \ | |
2319 | '\x89PNG\r\n\x1a\n\x00\x00\x00\rIHDR\x00\x00\x00\x10\x00\x00\x00\x10\x08\x06\ | |
2320 | \x00\x00\x00\x1f\xf3\xffa\x00\x00\x00\x04sBIT\x08\x08\x08\x08|\x08d\x88\x00\ | |
2321 | \x00\x00\x8eIDAT8\x8d\xa5SA\x12\xc4 \x08K\xb0\xff\xde\xe9\xbf\xb7\xa6\x87\ | |
2322 | \x1d:\xba\xa2tZn(\x84`"i\x05obk\x13\xd5CmN+\xcc\x00l\xd6\x0c\x00\xf5\xf8\x0e\ | |
2323 | gK\x06\x00 \xa5=k\x00\x00\xb0\xb2]\xd4?5f\xb1\xdb\xaf\xc6\xa2\xcb\xa8\xf0?\ | |
2324 | \x1c\x98\xae\x82\xbf\x81\xa4\x8eA\x16\xe1\n\xd1\xa4\x19\xb3\xe9\n\xce\xe8\ | |
2325 | \xf1\n\x9eg^\x18\x18\x90\xec<\x11\xf9#\x04XMZ\x19\xaac@+\x94\xd4\x99)SeP\xa1\ | |
2326 | )\xd6\x1dI\xe7*\xdc\xf4\x03\xdf~\xe7\x13T^Q?:X\x19d\x00\x00\x00\x00IEND\xaeB\ | |
2327 | `\x82' | |
2328 | ||
2329 | def getNextBitmap(): | |
2330 | return BitmapFromImage(getNextImage()) | |
2331 | ||
2332 | def getNextImage(): | |
2333 | stream = cStringIO.StringIO(getNextData()) | |
2334 | return ImageFromStream(stream) | |
2335 | ||
2336 | def getNextIcon(): | |
bbf7159c | 2337 | return wx.IconFromBitmap(getNextBitmap()) |
1f780e48 RD |
2338 | |
2339 | #---------------------------------------------------------------------- | |
2340 | def getStepInData(): | |
2341 | return \ | |
2342 | '\x89PNG\r\n\x1a\n\x00\x00\x00\rIHDR\x00\x00\x00\x10\x00\x00\x00\x10\x08\x06\ | |
2343 | \x00\x00\x00\x1f\xf3\xffa\x00\x00\x00\x04sBIT\x08\x08\x08\x08|\x08d\x88\x00\ | |
2344 | \x00\x00\x87IDAT8\x8d\xadSA\x12\x84 \x0ck\x8a\xffv\xfc\xb74{X\xeb0P@\x07s\ | |
2345 | \x84\xa4$\x01\x00M\xb2\x02]R\x8b\xc86\xda\xdc\xedd\xb4~\xe8\x86\xc6\x01-\x93\ | |
2346 | \x96\xd9#\xf6\x06\xc3;p1I\xd1\x14\x0b#|\x17aF\xec\r\xeeF\xa0eB\xd34\xca\xd0A\ | |
2347 | ]j\x84\xa6\x03\x00""\xb7\xb0tRZ\xf7x\xb7\x83\x91]\xcb\x7fa\xd9\x89\x0fC\xfd\ | |
2348 | \x94\x9d|9\x99^k\x13\xa1 \xb3\x16\x0f#\xd4\x88N~\x14\xe1-\x96\x7f\xe3\x0f\ | |
2349 | \x11\x91UC\x0cX\'\x1e\x00\x00\x00\x00IEND\xaeB`\x82' | |
2350 | ||
2351 | def getStepInBitmap(): | |
2352 | return BitmapFromImage(getStepInImage()) | |
2353 | ||
2354 | def getStepInImage(): | |
2355 | stream = cStringIO.StringIO(getStepInData()) | |
2356 | return ImageFromStream(stream) | |
2357 | ||
2358 | def getStepInIcon(): | |
bbf7159c | 2359 | return wx.IconFromBitmap(getStepInBitmap()) |
1f780e48 RD |
2360 | |
2361 | #---------------------------------------------------------------------- | |
2362 | def getStopData(): | |
2363 | return \ | |
2364 | "\x89PNG\r\n\x1a\n\x00\x00\x00\rIHDR\x00\x00\x00\x10\x00\x00\x00\x10\x08\x06\ | |
2365 | \x00\x00\x00\x1f\xf3\xffa\x00\x00\x00\x04sBIT\x08\x08\x08\x08|\x08d\x88\x00\ | |
2366 | \x00\x00FIDAT8\x8d\xed\x91\xc1\t\xc00\x0c\x03O!\x0b\xa9\xfb\xef\xa6\xfcB\xa1\ | |
2367 | N\t\xf4Wr\xa0\x8f\xb1\x0f\x81\xe1\x97\xe4-\xb6}_V%\xc8\xc2, \t\x92\xe6]\xfbZ\ | |
2368 | \xf7\x08\xa0W\xc3\xea5\xdb\rl_IX\xe5\xf0d\x00\xfa\x8d#\x7f\xc4\xf7'\xab\x00\ | |
2369 | \x00\x00\x00IEND\xaeB`\x82" | |
2370 | ||
2371 | def getStopBitmap(): | |
2372 | return BitmapFromImage(getStopImage()) | |
2373 | ||
2374 | def getStopImage(): | |
2375 | stream = cStringIO.StringIO(getStopData()) | |
2376 | return ImageFromStream(stream) | |
2377 | ||
2378 | def getStopIcon(): | |
bbf7159c | 2379 | return wx.IconFromBitmap(getStopBitmap()) |
1f780e48 RD |
2380 | |
2381 | #---------------------------------------------------------------------- | |
2382 | def getStepReturnData(): | |
2383 | return \ | |
2384 | "\x89PNG\r\n\x1a\n\x00\x00\x00\rIHDR\x00\x00\x00\x10\x00\x00\x00\x10\x08\x06\ | |
2385 | \x00\x00\x00\x1f\xf3\xffa\x00\x00\x00\x04sBIT\x08\x08\x08\x08|\x08d\x88\x00\ | |
2386 | \x00\x00\x8dIDAT8\x8d\xa5S\xd1\x0e\xc4 \x08\xa3\xb0\xff\xbe\xdc\x7fO\xba'6\ | |
2387 | \xf1\xf44\xb3O$Phk\x04\xd4d\x07\xba\xc5\x16\x91#\nza\xdb\x84\x1a\xa2\xfe\xf8\ | |
2388 | \x99\xfa_=p+\xe8\x91ED\xbc<\xa4 \xb4\x0b\x01\xb5{\x01\xf9\xbbG-\x13\x87\x16f\ | |
2389 | \x84\xbf\x16V\xb0l\x01@\no\x86\xae\x82Q\xa8=\xa4\x0c\x80\xe70\xbd\x10jh\xbd\ | |
2390 | \x07R\x06#\xc9^N\xb6\xde\x03)\x83\x18\xaeU\x90\x9c>a\xb2P\r\xb3&/Y\xa8\xd1^^\ | |
2391 | \xb6\xf0\x16\xdb\xbf\xf1\x02\x81\xa5TK\x1d\x07\xde\x92\x00\x00\x00\x00IEND\ | |
2392 | \xaeB`\x82" | |
2393 | ||
2394 | def getStepReturnBitmap(): | |
2395 | return BitmapFromImage(getStepReturnImage()) | |
2396 | ||
2397 | def getStepReturnImage(): | |
2398 | stream = cStringIO.StringIO(getStepReturnData()) | |
2399 | return ImageFromStream(stream) | |
2400 | ||
2401 | def getStepReturnIcon(): | |
bbf7159c | 2402 | return wx.IconFromBitmap(getStepReturnBitmap()) |
1f780e48 | 2403 | |
bbf7159c | 2404 | #---------------------------------------------------------------------- |
1f780e48 RD |
2405 | def getAddWatchData(): |
2406 | return \ | |
2407 | '\x89PNG\r\n\x1a\n\x00\x00\x00\rIHDR\x00\x00\x00\x10\x00\x00\x00\x10\x08\x06\ | |
2408 | \x00\x00\x00\x1f\xf3\xffa\x00\x00\x00\x04sBIT\x08\x08\x08\x08|\x08d\x88\x00\ | |
2409 | \x00\x00\x85IDAT8\x8dc`\x18h\xc0\x88.\xd0\xc0\xf0\xff?*\x9f\x11C\rN\x80\xae\ | |
2410 | \x19\x97\x18\xd1\x9a\x896\x84\x18[p\xa9aA\xe6\xfc7f\xc0P\xc4x\x163\x9cp\x1a0\ | |
2411 | \xeb,!w\x100 \x1dK\xac\x10\r\x08\x05".yFL\x85\x8c\x18b\xa8|Ty\xa2\x13\x92\'\ | |
2412 | \xc3\xe4\xff\x9f\x18\x1e3\xb82t\xa2\x88\x13\xedg.\x06aa&\x06VV\x7f\x86\xb9\ | |
2413 | \xcfU\x19\xbc\xb0\xba\x86h\xe0\xc8\xd0\xfc\xbf\x80\xe1>q)\x94\xe6\x00\x00\ | |
2414 | \x85\x923_\xd22\xa4\xcd\x00\x00\x00\x00IEND\xaeB`\x82' | |
2415 | ||
2416 | def getAddWatchBitmap(): | |
2417 | return BitmapFromImage(getAddWatchImage()) | |
2418 | ||
2419 | def getAddWatchImage(): | |
2420 | stream = cStringIO.StringIO(getAddWatchData()) | |
2421 | return ImageFromStream(stream) | |
2422 | ||
2423 | def getAddWatchIcon(): | |
bbf7159c | 2424 | return wx.IconFromBitmap(getAddWatchBitmap()) |