1 #----------------------------------------------------------------------------
2 # Name: DebuggerService.py
3 # Purpose: Debugger Service for Python.
9 # Copyright: (c) 2004-2005 ActiveGrid, Inc.
10 # License: wxWindows License
11 #----------------------------------------------------------------------------
19 import wx
.lib
.pydocview
24 from IDE
import ACTIVEGRID_BASE_IDE
25 if not ACTIVEGRID_BASE_IDE
:
26 import ProcessModelEditor
27 import wx
.lib
.scrolledpanel
as scrolled
30 import SimpleXMLRPCServer
38 from xml
.dom
.minidom
import parse
, parseString
41 import DebuggerHarness
45 if wx
.Platform
== '__WXMSW__':
48 _PYWIN32_INSTALLED
= True
50 _PYWIN32_INSTALLED
= False
55 if not _WINDOWS
or _PYWIN32_INSTALLED
:
63 # Class to read from stdout or stderr and write the result to a text control.
64 # Args: file=file-like object
65 # callback_function= function that takes a single argument, the line of text
67 class OutputReaderThread(threading
.Thread
):
68 def __init__(self
, file, callback_function
, callbackOnExit
=None, accumulate
=True):
69 threading
.Thread
.__init
__(self
)
71 self
._callback
_function
= callback_function
72 self
._keepGoing
= True
74 self
._accumulate
= accumulate
75 self
._callbackOnExit
= callbackOnExit
79 # See comment on DebugCommandUI.StopExecution
80 self
._keepGoing
= False
86 while self
._keepGoing
:
88 # This could block--how to handle that?
89 text
= file.readline()
90 if text
== '' or text
== None:
91 self
._keepGoing
= False
92 elif not self
._accumulate
and self
._keepGoing
:
93 self
._callback
_function
(text
)
95 # Should use a buffer? StringIO?
97 # Seems as though the read blocks if we got an error, so, to be
98 # sure that at least some of the exception gets printed, always
99 # send the first hundred lines back as they come in.
100 if self
._lineCount
< 100 and self
._keepGoing
:
101 self
._callback
_function
(output
)
104 elif time
.time() - start
> 0.25 and self
._keepGoing
:
106 self
._callback
_function
(output
)
107 except wx
._core
.PyDeadObjectError
:
108 # GUI was killed while we were blocked.
109 self
._keepGoing
= False
115 tp
, val
, tb
= sys
.exc_info()
116 print "Exception in OutputReaderThread.run():", tp
, val
117 self
._keepGoing
= False
118 if self
._callbackOnExit
:
120 self
._callbackOnExit
()
121 except wx
._core
.PyDeadObjectError
:
123 if _VERBOSE
: print "Exiting OutputReaderThread"
126 self
._keepGoing
= False
128 import wx
.lib
.newevent
129 (UpdateTextEvent
, EVT_UPDATE_STDTEXT
) = wx
.lib
.newevent
.NewEvent()
130 (UpdateErrorEvent
, EVT_UPDATE_ERRTEXT
) = wx
.lib
.newevent
.NewEvent()
134 def GetPythonExecutablePath():
135 config
= wx
.ConfigBase_Get()
136 path
= config
.Read("ActiveGridPythonLocation")
139 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"))
141 GetPythonExecutablePath
= staticmethod(GetPythonExecutablePath
)
143 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):
144 self
._fileName
= fileName
145 self
._stdOutCallback
= self
.OutCall
146 self
._stdErrCallback
= self
.ErrCall
147 self
._callbackOnExit
= callbackOnExit
148 self
._wxComponent
= wxComponent
149 path
= Executor
.GetPythonExecutablePath()
150 self
._cmd
= '"' + path
+ '" -u \"' + fileName
+ '\"'
151 #Better way to do this? Quotes needed for windows file paths.
153 self
._cmd
+= ' \"' + arg1
+ '\"'
155 self
._cmd
+= ' \"' + arg2
+ '\"'
157 self
._cmd
+= ' \"' + arg3
+ '\"'
159 self
._cmd
+= ' \"' + arg4
+ '\"'
161 self
._cmd
+= ' \"' + arg5
+ '\"'
163 self
._cmd
+= ' \"' + arg6
+ '\"'
165 self
._cmd
+= ' \"' + arg7
+ '\"'
167 self
._cmd
+= ' \"' + arg8
+ '\"'
169 self
._cmd
+= ' \"' + arg9
+ '\"'
171 self
._stdOutReader
= None
172 self
._stdErrReader
= None
175 def OutCall(self
, text
):
176 evt
= UpdateTextEvent(value
= text
)
177 wx
.PostEvent(self
._wxComponent
, evt
)
179 def ErrCall(self
, text
):
180 evt
= UpdateErrorEvent(value
= text
)
181 wx
.PostEvent(self
._wxComponent
, evt
)
183 def Execute(self
, arguments
, startIn
=None, environment
=None):
185 startIn
= str(os
.getcwd())
186 startIn
= os
.path
.abspath(startIn
)
187 command
= self
._cmd
+ ' ' + arguments
188 self
._process
= process
.ProcessOpen(command
, mode
='b', cwd
=startIn
, env
=environment
)
189 # Kick off threads to read stdout and stderr and write them
190 # to our text control.
191 self
._stdOutReader
= OutputReaderThread(self
._process
.stdout
, self
._stdOutCallback
, callbackOnExit
=self
._callbackOnExit
)
192 self
._stdOutReader
.start()
193 self
._stdErrReader
= OutputReaderThread(self
._process
.stderr
, self
._stdErrCallback
, accumulate
=False)
194 self
._stdErrReader
.start()
196 def DoStopExecution(self
):
197 # See comment on DebugCommandUI.StopExecution
198 if(self
._process
!= None):
199 self
._stdOutReader
.AskToStop()
200 self
._stdErrReader
.AskToStop()
202 self
._process
.kill(gracePeriod
=2.0)
207 class RunCommandUI(wx
.Panel
):
210 def ShutdownAllRunners():
211 # See comment on DebugCommandUI.StopExecution
212 for runner
in RunCommandUI
.runners
:
214 runner
.StopExecution(None)
215 except wx
._core
.PyDeadObjectError
:
217 RunCommandUI
.runners
= []
218 ShutdownAllRunners
= staticmethod(ShutdownAllRunners
)
220 def __init__(self
, parent
, id, fileName
):
221 wx
.Panel
.__init
__(self
, parent
, id)
222 self
._noteBook
= parent
224 threading
._VERBOSE
= _VERBOSE
226 self
.KILL_PROCESS_ID
= wx
.NewId()
227 self
.CLOSE_TAB_ID
= wx
.NewId()
230 # GUI Initialization follows
231 sizer
= wx
.BoxSizer(wx
.HORIZONTAL
)
232 self
._tb
= tb
= wx
.ToolBar(self
, -1, wx
.DefaultPosition
, (30,1000), wx
.TB_VERTICAL| wx
.TB_FLAT
, "Runner" )
233 tb
.SetToolBitmapSize((16,16))
234 sizer
.Add(tb
, 0, wx
.EXPAND|wx
.ALIGN_LEFT|wx
.ALL
, 1)
236 close_bmp
= getCloseBitmap()
237 tb
.AddSimpleTool( self
.CLOSE_TAB_ID
, close_bmp
, _('Close Window'))
238 wx
.EVT_TOOL(self
, self
.CLOSE_TAB_ID
, self
.OnToolClicked
)
240 stop_bmp
= getStopBitmap()
241 tb
.AddSimpleTool(self
.KILL_PROCESS_ID
, stop_bmp
, _("Stop the Run."))
242 wx
.EVT_TOOL(self
, self
.KILL_PROCESS_ID
, self
.OnToolClicked
)
245 self
._textCtrl
= STCTextEditor
.TextCtrl(self
, wx
.NewId()) #id)
246 sizer
.Add(self
._textCtrl
, 1, wx
.ALIGN_LEFT|wx
.ALL|wx
.EXPAND
, 1)
247 self
._textCtrl
.SetViewLineNumbers(False)
248 self
._textCtrl
.SetReadOnly(True)
249 if wx
.Platform
== '__WXMSW__':
253 self
._textCtrl
.SetFont(wx
.Font(9, wx
.DEFAULT
, wx
.NORMAL
, wx
.NORMAL
, faceName
= font
))
254 self
._textCtrl
.SetFontColor(wx
.BLACK
)
255 self
._textCtrl
.StyleClearAll()
257 #Disabling for now...may interfere with file open. wx.stc.EVT_STC_DOUBLECLICK(self._textCtrl, self._textCtrl.GetId(), self.OnDoubleClick)
262 self
._stopped
= False
263 # Executor initialization
264 self
._executor
= Executor(fileName
, self
, callbackOnExit
=self
.ExecutorFinished
)
265 self
.Bind(EVT_UPDATE_STDTEXT
, self
.AppendText
)
266 self
.Bind(EVT_UPDATE_ERRTEXT
, self
.AppendErrorText
)
268 RunCommandUI
.runners
.append(self
)
271 # See comment on DebugCommandUI.StopExecution
272 self
._executor
.DoStopExecution()
274 def Execute(self
, initialArgs
, startIn
, environment
):
275 self
._executor
.Execute(initialArgs
, startIn
, environment
)
277 def ExecutorFinished(self
):
278 self
._tb
.EnableTool(self
.KILL_PROCESS_ID
, False)
279 nb
= self
.GetParent()
280 for i
in range(0,nb
.GetPageCount()):
281 if self
== nb
.GetPage(i
):
282 text
= nb
.GetPageText(i
)
283 newText
= text
.replace("Running", "Finished")
284 nb
.SetPageText(i
, newText
)
287 def StopExecution(self
):
288 if not self
._stopped
:
290 self
.Unbind(EVT_UPDATE_STDTEXT
)
291 self
.Unbind(EVT_UPDATE_ERRTEXT
)
292 self
._executor
.DoStopExecution()
294 def AppendText(self
, event
):
295 self
._textCtrl
.SetReadOnly(False)
296 self
._textCtrl
.AddText(event
.value
)
297 self
._textCtrl
.ScrollToLine(self
._textCtrl
.GetLineCount())
298 self
._textCtrl
.SetReadOnly(True)
300 def AppendErrorText(self
, event
):
301 self
._textCtrl
.SetReadOnly(False)
302 self
._textCtrl
.SetFontColor(wx
.RED
)
303 self
._textCtrl
.StyleClearAll()
304 self
._textCtrl
.AddText(event
.value
)
305 self
._textCtrl
.ScrollToLine(self
._textCtrl
.GetLineCount())
306 self
._textCtrl
.SetFontColor(wx
.BLACK
)
307 self
._textCtrl
.StyleClearAll()
308 self
._textCtrl
.SetReadOnly(True)
310 #------------------------------------------------------------------------------
312 #-----------------------------------------------------------------------------
314 def OnToolClicked(self
, event
):
317 if id == self
.KILL_PROCESS_ID
:
320 elif id == self
.CLOSE_TAB_ID
:
322 index
= self
._noteBook
.GetSelection()
323 self
._noteBook
.GetPage(index
).Show(False)
324 self
._noteBook
.RemovePage(index
)
326 def OnDoubleClick(self
, event
):
327 # Looking for a stack trace line.
328 lineText
, pos
= self
._textCtrl
.GetCurLine()
329 fileBegin
= lineText
.find("File \"")
330 fileEnd
= lineText
.find("\", line ")
331 lineEnd
= lineText
.find(", in ")
332 if lineText
== "\n" or fileBegin
== -1 or fileEnd
== -1 or lineEnd
== -1:
333 # Check the line before the one that was clicked on
334 lineNumber
= self
._textCtrl
.GetCurrentLine()
337 lineText
= self
._textCtrl
.GetLine(lineNumber
- 1)
338 fileBegin
= lineText
.find("File \"")
339 fileEnd
= lineText
.find("\", line ")
340 lineEnd
= lineText
.find(", in ")
341 if lineText
== "\n" or fileBegin
== -1 or fileEnd
== -1 or lineEnd
== -1:
344 filename
= lineText
[fileBegin
+ 6:fileEnd
]
345 lineNum
= int(lineText
[fileEnd
+ 8:lineEnd
])
348 openDocs
= wx
.GetApp().GetDocumentManager().GetDocuments()
349 for openDoc
in openDocs
:
350 if openDoc
.GetFilename() == filename
:
351 foundView
= openDoc
.GetFirstView()
355 doc
= wx
.GetApp().GetDocumentManager().CreateDocument(filename
, wx
.lib
.docview
.DOC_SILENT
)
356 foundView
= doc
.GetFirstView()
359 foundView
.GetFrame().SetFocus()
361 foundView
.GotoLine(lineNum
)
362 startPos
= foundView
.PositionFromLine(lineNum
)
364 # FACTOR THIS INTO DocManager
365 openDocs
= wx
.GetApp().GetDocumentManager().GetDocuments()
366 for openDoc
in openDocs
:
367 if(isinstance(openDoc
.GetFirstView(), CodeEditor
.CodeView
)):
368 openDoc
.GetFirstView().GetCtrl().ClearCurrentLineMarkers()
370 foundView
.GetCtrl().MarkerAdd(lineNum
-1, CodeEditor
.CodeCtrl
.CURRENT_LINE_MARKER_NUM
)
374 DEFAULT_HOST
= 'localhost'
377 class DebugCommandUI(wx
.Panel
):
378 debuggerPortList
= None
381 def NotifyDebuggersOfBreakpointChange():
382 for debugger
in DebugCommandUI
.debuggers
:
383 debugger
.BreakPointChange()
385 NotifyDebuggersOfBreakpointChange
= staticmethod(NotifyDebuggersOfBreakpointChange
)
387 def DebuggerRunning():
388 for debugger
in DebugCommandUI
.debuggers
:
389 if debugger
._executor
:
392 DebuggerRunning
= staticmethod(DebuggerRunning
)
394 def ShutdownAllDebuggers():
395 # See comment on DebugCommandUI.StopExecution
396 for debugger
in DebugCommandUI
.debuggers
:
398 debugger
.StopExecution(None)
399 except wx
._core
.PyDeadObjectError
:
401 DebugCommandUI
.debuggers
= []
402 ShutdownAllDebuggers
= staticmethod(ShutdownAllDebuggers
)
404 def GetAvailablePort():
405 for index
in range( 0, len(DebugCommandUI
.debuggerPortList
)):
406 port
= DebugCommandUI
.debuggerPortList
[index
]
407 if DebugCommandUI
.PortAvailable(port
):
408 DebugCommandUI
.debuggerPortList
.pop(index
)
410 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"))
411 assert False, "Out of ports for debugger."
413 GetAvailablePort
= staticmethod(GetAvailablePort
)
415 def ReturnPortToPool(port
):
416 config
= wx
.ConfigBase_Get()
417 startingPort
= config
.ReadInt("DebuggerStartingPort", DEFAULT_PORT
)
418 if port
in range(startingPort
, startingPort
+ PORT_COUNT
):
419 DebugCommandUI
.debuggerPortList
.append(port
)
421 ReturnPortToPool
= staticmethod(ReturnPortToPool
)
423 def PortAvailable(port
):
424 config
= wx
.ConfigBase_Get()
425 hostname
= config
.Read("DebuggerHostName", DEFAULT_HOST
)
427 server
= AGXMLRPCServer((hostname
, port
))
428 server
.server_close()
429 if _VERBOSE
: print "Port ", str(port
), " available."
432 tp
,val
,tb
= sys
.exc_info()
433 if _VERBOSE
: traceback
.print_exception(tp
, val
, tb
)
434 if _VERBOSE
: print "Port ", str(port
), " unavailable."
437 PortAvailable
= staticmethod(PortAvailable
)
440 config
= wx
.ConfigBase_Get()
441 startingPort
= config
.ReadInt("DebuggerStartingPort", DEFAULT_PORT
)
442 DebugCommandUI
.debuggerPortList
= range(startingPort
, startingPort
+ PORT_COUNT
)
443 NewPortRange
= staticmethod(NewPortRange
)
445 def __init__(self
, parent
, id, command
, service
):
446 # Check for ports before creating the panel.
447 if not DebugCommandUI
.debuggerPortList
:
448 DebugCommandUI
.NewPortRange()
449 self
._debuggerPort
= str(DebugCommandUI
.GetAvailablePort())
450 self
._guiPort
= str(DebugCommandUI
.GetAvailablePort())
451 self
._debuggerBreakPort
= str(DebugCommandUI
.GetAvailablePort())
453 wx
.Panel
.__init
__(self
, parent
, id)
455 self
._parentNoteBook
= parent
456 self
._command
= command
457 self
._service
= service
458 self
._executor
= None
459 self
.STEP_ID
= wx
.NewId()
460 self
.CONTINUE_ID
= wx
.NewId()
461 self
.STEP_OUT_ID
= wx
.NewId()
462 self
.NEXT_ID
= wx
.NewId()
463 self
.KILL_PROCESS_ID
= wx
.NewId()
464 self
.CLOSE_WINDOW_ID
= wx
.NewId()
465 self
.BREAK_INTO_DEBUGGER_ID
= wx
.NewId()
466 self
.CLEAR_ID
= wx
.NewId()
467 self
.ADD_WATCH_ID
= wx
.NewId()
468 sizer
= wx
.BoxSizer(wx
.VERTICAL
)
469 self
._tb
= tb
= wx
.ToolBar(self
, -1, wx
.DefaultPosition
, (1000,30), wx
.TB_HORIZONTAL| wx
.NO_BORDER| wx
.TB_FLAT| wx
.TB_TEXT
, "Debugger" )
470 sizer
.Add(tb
, 0, wx
.EXPAND |wx
.ALIGN_LEFT|wx
.ALL
, 1)
471 tb
.SetToolBitmapSize((16,16))
473 close_bmp
= getCloseBitmap()
474 tb
.AddSimpleTool( self
.CLOSE_WINDOW_ID
, close_bmp
, _('Close Window'))
475 wx
.EVT_TOOL(self
, self
.CLOSE_WINDOW_ID
, self
.StopAndRemoveUI
)
477 stop_bmp
= getStopBitmap()
478 tb
.AddSimpleTool( self
.KILL_PROCESS_ID
, stop_bmp
, _("Stop Debugging"))
479 wx
.EVT_TOOL(self
, self
.KILL_PROCESS_ID
, self
.StopExecution
)
483 break_bmp
= getBreakBitmap()
484 tb
.AddSimpleTool( self
.BREAK_INTO_DEBUGGER_ID
, break_bmp
, _("Break into Debugger"))
485 wx
.EVT_TOOL(self
, self
.BREAK_INTO_DEBUGGER_ID
, self
.BreakExecution
)
489 continue_bmp
= getContinueBitmap()
490 tb
.AddSimpleTool( self
.CONTINUE_ID
, continue_bmp
, _("Continue Execution"))
491 wx
.EVT_TOOL(self
, self
.CONTINUE_ID
, self
.OnContinue
)
495 next_bmp
= getNextBitmap()
496 tb
.AddSimpleTool( self
.NEXT_ID
, next_bmp
, _("Step to next line"))
497 wx
.EVT_TOOL(self
, self
.NEXT_ID
, self
.OnNext
)
499 step_bmp
= getStepInBitmap()
500 tb
.AddSimpleTool( self
.STEP_ID
, step_bmp
, _("Step in"))
501 wx
.EVT_TOOL(self
, self
.STEP_ID
, self
.OnSingleStep
)
503 stepOut_bmp
= getStepReturnBitmap()
504 tb
.AddSimpleTool(self
.STEP_OUT_ID
, stepOut_bmp
, _("Stop at function return"))
505 wx
.EVT_TOOL(self
, self
.STEP_OUT_ID
, self
.OnStepOut
)
509 watch_bmp
= getAddWatchBitmap()
510 tb
.AddSimpleTool(self
.ADD_WATCH_ID
, watch_bmp
, _("Add a watch"))
511 wx
.EVT_TOOL(self
, self
.ADD_WATCH_ID
, self
.OnAddWatch
)
514 clear_bmp
= getClearOutputBitmap()
515 tb
.AddSimpleTool(self
.CLEAR_ID
, clear_bmp
, _("Clear output pane"))
516 wx
.EVT_TOOL(self
, self
.CLEAR_ID
, self
.OnClearOutput
)
518 self
.framesTab
= None
519 self
.DisableWhileDebuggerRunning()
520 self
.framesTab
= self
.MakeFramesUI(self
, wx
.NewId(), None)
521 sizer
.Add(self
.framesTab
, 1, wx
.ALIGN_LEFT|wx
.ALL|wx
.EXPAND
, 1)
522 self
._statusBar
= wx
.StatusBar( self
, -1)
523 self
._statusBar
.SetFieldsCount(1)
524 sizer
.Add(self
._statusBar
, 0, wx
.EXPAND |wx
.ALIGN_LEFT|wx
.ALL
, 1)
526 self
.SetStatusText("Starting debug...")
531 config
= wx
.ConfigBase_Get()
532 self
._debuggerHost
= self
._guiHost
= config
.Read("DebuggerHostName", DEFAULT_HOST
)
533 url
= 'http://' + self
._debuggerHost
+ ':' + self
._debuggerPort
+ '/'
534 self
._breakURL
= 'http://' + self
._debuggerHost
+ ':' + self
._debuggerBreakPort
+ '/'
535 self
._callback
= DebuggerCallback(self
._guiHost
, self
._guiPort
, url
, self
._breakURL
, self
)
536 if DebuggerHarness
.__file
__.find('library.zip') > 0:
538 fname
= DebuggerHarness
.__file
__
539 parts
= fname
.split('library.zip')
540 path
= os
.path
.join(parts
[0],'activegrid', 'tool', 'DebuggerHarness.py')
542 tp
, val
, tb
= sys
.exc_info()
543 traceback
.print_exception(tp
, val
, tb
)
546 print "Starting debugger on these ports: %s, %s, %s" % (str(self
._debuggerPort
) , str(self
._guiPort
) , str(self
._debuggerBreakPort
))
547 path
= DebuggerService
.ExpandPath(DebuggerHarness
.__file
__)
548 self
._executor
= Executor(path
, self
, self
._debuggerHost
, \
549 self
._debuggerPort
, self
._debuggerBreakPort
, self
._guiHost
, self
._guiPort
, self
._command
, callbackOnExit
=self
.ExecutorFinished
)
551 self
.Bind(EVT_UPDATE_STDTEXT
, self
.AppendText
)
552 self
.Bind(EVT_UPDATE_ERRTEXT
, self
.AppendErrorText
)
553 DebugCommandUI
.debuggers
.append(self
)
554 self
._stopped
= False
556 def OnSingleStep(self
, event
):
557 self
._callback
.SingleStep()
559 def OnContinue(self
, event
):
560 self
._callback
.Continue()
562 def OnStepOut(self
, event
):
563 self
._callback
.Return()
565 def OnNext(self
, event
):
566 self
._callback
.Next()
568 def BreakPointChange(self
):
569 if not self
._stopped
:
570 self
._callback
.pushBreakpoints()
571 self
.framesTab
.PopulateBPList()
574 # See comment on DebugCommandUI.StopExecution
575 self
.StopExecution(None)
577 def DisableWhileDebuggerRunning(self
):
578 self
._tb
.EnableTool(self
.STEP_ID
, False)
579 self
._tb
.EnableTool(self
.CONTINUE_ID
, False)
580 self
._tb
.EnableTool(self
.STEP_OUT_ID
, False)
581 self
._tb
.EnableTool(self
.NEXT_ID
, False)
582 self
._tb
.EnableTool(self
.BREAK_INTO_DEBUGGER_ID
, True)
584 self
._tb
.EnableTool(self
.ADD_WATCH_ID
, False)
585 openDocs
= wx
.GetApp().GetDocumentManager().GetDocuments()
586 for openDoc
in openDocs
:
587 if(isinstance(openDoc
.GetFirstView(), CodeEditor
.CodeView
)):
588 openDoc
.GetFirstView().GetCtrl().ClearCurrentLineMarkers()
590 self
.framesTab
.ClearWhileRunning()
592 def EnableWhileDebuggerStopped(self
):
593 self
._tb
.EnableTool(self
.STEP_ID
, True)
594 self
._tb
.EnableTool(self
.CONTINUE_ID
, True)
595 self
._tb
.EnableTool(self
.STEP_OUT_ID
, True)
596 self
._tb
.EnableTool(self
.NEXT_ID
, True)
598 self
._tb
.EnableTool(self
.ADD_WATCH_ID
, True)
599 self
._tb
.EnableTool(self
.BREAK_INTO_DEBUGGER_ID
, False)
601 def ExecutorFinished(self
):
602 if _VERBOSE
: print "In ExectorFinished"
604 self
.DisableAfterStop()
605 except wx
._core
.PyDeadObjectError
:
608 nb
= self
.GetParent()
609 for i
in range(0, nb
.GetPageCount()):
610 if self
== nb
.GetPage(i
):
611 text
= nb
.GetPageText(i
)
612 newText
= text
.replace("Debugging", "Finished")
613 nb
.SetPageText(i
, newText
)
614 if _VERBOSE
: print "In ExectorFinished, changed tab title."
617 if _VERBOSE
: print "In ExectorFinished, got exception"
619 def DisableAfterStop(self
):
620 self
.DisableWhileDebuggerRunning()
621 self
._tb
.EnableTool(self
.BREAK_INTO_DEBUGGER_ID
, False)
622 self
._tb
.EnableTool(self
.KILL_PROCESS_ID
, False)
624 def SynchCurrentLine(self
, filename
, lineNum
):
625 # FACTOR THIS INTO DocManager
626 self
.DeleteCurrentLineMarkers()
628 # Filename will be <string> if we're in a bit of code that was executed from
629 # a string (rather than a file). I haven't been able to get the original string
631 if filename
== '<string>':
634 openDocs
= wx
.GetApp().GetDocumentManager().GetDocuments()
635 for openDoc
in openDocs
:
636 # This ugliness to prevent comparison failing because the drive letter
637 # gets lowercased occasionally. Don't know why that happens or why it
638 # only happens occasionally.
639 if DebuggerService
.ComparePaths(openDoc
.GetFilename(),filename
):
640 foundView
= openDoc
.GetFirstView()
645 print "filename=", filename
646 doc
= wx
.GetApp().GetDocumentManager().CreateDocument(DebuggerService
.ExpandPath(filename
), wx
.lib
.docview
.DOC_SILENT
)
647 foundView
= doc
.GetFirstView()
650 foundView
.GetFrame().SetFocus()
652 foundView
.GotoLine(lineNum
)
653 startPos
= foundView
.PositionFromLine(lineNum
)
655 foundView
.GetCtrl().MarkerAdd(lineNum
-1, CodeEditor
.CodeCtrl
.CURRENT_LINE_MARKER_NUM
)
657 def DeleteCurrentLineMarkers(self
):
658 openDocs
= wx
.GetApp().GetDocumentManager().GetDocuments()
659 for openDoc
in openDocs
:
660 if(isinstance(openDoc
.GetFirstView(), CodeEditor
.CodeView
)):
661 openDoc
.GetFirstView().GetCtrl().ClearCurrentLineMarkers()
663 def LoadFramesListXML(self
, framesXML
):
664 self
.framesTab
.LoadFramesListXML(framesXML
)
666 def SetStatusText(self
, text
):
667 self
._statusBar
.SetStatusText(text
,0)
669 def Execute(self
, initialArgs
, startIn
, environment
):
670 self
._callback
.start()
671 self
._executor
.Execute(initialArgs
, startIn
, environment
)
672 self
._callback
.waitForRPC()
674 def BreakExecution(self
, event
):
675 self
._callback
.BreakExecution()
678 def StopExecution(self
, event
):
679 # This is a general comment on shutdown for the running and debugged processes. Basically, the
680 # current state of this is the result of trial and error coding. The common problems were memory
681 # access violations and threads that would not exit. Making the OutputReaderThreads daemons seems
682 # to have side-stepped the hung thread issue. Being very careful not to touch things after calling
683 # process.py:ProcessOpen.kill() also seems to have fixed the memory access violations, but if there
684 # were more ugliness discovered I would not be surprised. If anyone has any help/advice, please send
685 # it on to mfryer@activegrid.com.
686 if not self
._stopped
:
689 self
.DisableAfterStop()
690 except wx
._core
.PyDeadObjectError
:
693 self
._callback
.ShutdownServer()
695 tp
,val
,tb
= sys
.exc_info()
696 traceback
.print_exception(tp
, val
, tb
)
699 self
.DeleteCurrentLineMarkers()
703 DebugCommandUI
.ReturnPortToPool(self
._debuggerPort
)
704 DebugCommandUI
.ReturnPortToPool(self
._guiPort
)
705 DebugCommandUI
.ReturnPortToPool(self
._debuggerBreakPort
)
710 self
._executor
.DoStopExecution()
711 self
._executor
= None
713 tp
,val
,tb
= sys
.exc_info()
714 traceback
.print_exception(tp
, val
, tb
)
715 def StopAndRemoveUI(self
, event
):
716 self
.StopExecution(None)
717 if self
in DebugCommandUI
.debuggers
:
718 DebugCommandUI
.debuggers
.remove(self
)
719 index
= self
._parentNoteBook
.GetSelection()
720 self
._parentNoteBook
.GetPage(index
).Show(False)
721 self
._parentNoteBook
.RemovePage(index
)
723 def OnAddWatch(self
, event
):
725 self
.framesTab
.OnWatch(event
)
727 def MakeFramesUI(self
, parent
, id, debugger
):
728 panel
= FramesUI(parent
, id, self
)
731 def AppendText(self
, event
):
732 self
.framesTab
.AppendText(event
.value
)
734 def AppendErrorText(self
, event
):
735 self
.framesTab
.AppendErrorText(event
.value
)
737 def OnClearOutput(self
, event
):
738 self
.framesTab
.ClearOutput(None)
740 def SwitchToOutputTab(self
):
741 self
.framesTab
.SwitchToOutputTab()
743 class BreakpointsUI(wx
.Panel
):
744 def __init__(self
, parent
, id, ui
):
745 wx
.Panel
.__init
__(self
, parent
, id)
747 self
.currentItem
= None
748 self
.clearBPID
= wx
.NewId()
749 self
.Bind(wx
.EVT_MENU
, self
.ClearBreakPoint
, id=self
.clearBPID
)
750 self
.syncLineID
= wx
.NewId()
751 self
.Bind(wx
.EVT_MENU
, self
.SyncBPLine
, id=self
.syncLineID
)
752 sizer
= wx
.BoxSizer(wx
.VERTICAL
)
754 self
._bpListCtrl
= wx
.ListCtrl(p1
, -1, pos
=wx
.DefaultPosition
, size
=(1000,1000), style
=wx
.LC_REPORT
)
755 sizer
.Add(self
._bpListCtrl
, 1, wx
.ALIGN_LEFT|wx
.ALL|wx
.EXPAND
, 1)
756 self
._bpListCtrl
.InsertColumn(0, "File")
757 self
._bpListCtrl
.InsertColumn(1, "Line")
758 self
._bpListCtrl
.InsertColumn(2, "Path")
759 self
._bpListCtrl
.SetColumnWidth(0, 150)
760 self
._bpListCtrl
.SetColumnWidth(1, 50)
761 self
._bpListCtrl
.SetColumnWidth(2, 450)
762 self
._bpListCtrl
.Bind(wx
.EVT_LIST_ITEM_RIGHT_CLICK
, self
.OnListRightClick
)
763 self
.Bind(wx
.EVT_LIST_ITEM_SELECTED
, self
.ListItemSelected
, self
._bpListCtrl
)
764 self
.Bind(wx
.EVT_LIST_ITEM_DESELECTED
, self
.ListItemDeselected
, self
._bpListCtrl
)
766 def OnLeftDoubleClick(event
):
767 self
.SyncBPLine(event
)
769 wx
.EVT_LEFT_DCLICK(self
._bpListCtrl
, OnLeftDoubleClick
)
771 self
.PopulateBPList()
777 def PopulateBPList(self
):
778 list = self
._bpListCtrl
779 list.DeleteAllItems()
781 bps
= wx
.GetApp().GetService(DebuggerService
).GetMasterBreakpointDict()
783 for fileName
in bps
.keys():
784 shortFile
= os
.path
.basename(fileName
)
785 lines
= bps
[fileName
]
788 list.InsertStringItem(index
, shortFile
)
789 list.SetStringItem(index
, 1, str(line
))
790 list.SetStringItem(index
, 2, fileName
)
792 def OnListRightClick(self
, event
):
794 item
= wx
.MenuItem(menu
, self
.clearBPID
, "Clear Breakpoint")
795 menu
.AppendItem(item
)
796 item
= wx
.MenuItem(menu
, self
.syncLineID
, "Goto Source Line")
797 menu
.AppendItem(item
)
798 self
.PopupMenu(menu
, event
.GetPosition())
801 def SyncBPLine(self
, event
):
802 if self
.currentItem
!= -1:
803 list = self
._bpListCtrl
804 fileName
= list.GetItem(self
.currentItem
, 2).GetText()
805 lineNumber
= list.GetItem(self
.currentItem
, 1).GetText()
806 self
._ui
.SynchCurrentLine( fileName
, int(lineNumber
) )
808 def ClearBreakPoint(self
, event
):
809 if self
.currentItem
>= 0:
810 list = self
._bpListCtrl
811 fileName
= list.GetItem(self
.currentItem
, 2).GetText()
812 lineNumber
= list.GetItem(self
.currentItem
, 1).GetText()
813 wx
.GetApp().GetService(DebuggerService
).OnToggleBreakpoint(None, line
=int(lineNumber
) -1, fileName
=fileName
)
815 def ListItemSelected(self
, event
):
816 self
.currentItem
= event
.m_itemIndex
818 def ListItemDeselected(self
, event
):
819 self
.currentItem
= -1
827 def __init__(self
, name
, command
, show_code
=CODE_ALL_FRAMES
):
829 self
._command
= command
830 self
._show
_code
= show_code
832 class WatchDialog(wx
.Dialog
):
833 WATCH_ALL_FRAMES
= "Watch in all frames"
834 WATCH_THIS_FRAME
= "Watch in this frame only"
835 WATCH_ONCE
= "Watch once and delete"
836 def __init__(self
, parent
, title
, chain
):
837 wx
.Dialog
.__init
__(self
, parent
, -1, title
, style
=wx
.DEFAULT_DIALOG_STYLE
)
839 self
.label_2
= wx
.StaticText(self
, -1, "Watch Name:")
840 self
._watchNameTextCtrl
= wx
.TextCtrl(self
, -1, "")
841 self
.label_3
= wx
.StaticText(self
, -1, "eval(", style
=wx
.ALIGN_RIGHT
)
842 self
._watchValueTextCtrl
= wx
.TextCtrl(self
, -1, "")
843 self
.label_4
= wx
.StaticText(self
, -1, ",frame.f_globals, frame.f_locals)")
844 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
)
846 self
._okButton
= wx
.Button(self
, wx
.ID_OK
, "OK", size
=(75,-1))
847 self
._okButton
.SetDefault()
848 self
._okButton
.SetHelpText(_("The OK button completes the dialog"))
849 def OnOkClick(event
):
850 if self
._watchNameTextCtrl
.GetValue() == "":
851 wx
.MessageBox(_("You must enter a name for the watch."), _("Add Watch"))
853 if self
._watchValueTextCtrl
.GetValue() == "":
854 wx
.MessageBox(_("You must enter some code to run for the watch."), _("Add Watch"))
856 self
.EndModal(wx
.ID_OK
)
857 self
.Bind(wx
.EVT_BUTTON
, OnOkClick
, self
._okButton
)
859 self
._cancelButton
= wx
.Button(self
, wx
.ID_CANCEL
, _("Cancel"), size
=(75,-1))
860 self
._cancelButton
.SetHelpText(_("The Cancel button cancels the dialog."))
862 self
.__set
_properties
()
865 def GetSettings(self
):
866 return self
._watchNameTextCtrl
.GetValue(), self
._watchValueTextCtrl
.GetValue(), self
.GetSendFrame(), self
.GetRunOnce()
868 def GetSendFrame(self
):
869 return (WatchDialog
.WATCH_ALL_FRAMES
!= self
.radio_box_1
.GetStringSelection())
871 def GetRunOnce(self
):
872 return (WatchDialog
.WATCH_ONCE
== self
.radio_box_1
.GetStringSelection())
874 def __set_properties(self
):
875 self
.SetTitle("Add a Watch")
876 #self.SetSize((400, 250))
877 self
.radio_box_1
.SetSelection(0)
879 def __do_layout(self
):
880 sizer_1
= wx
.BoxSizer(wx
.VERTICAL
)
881 grid_sizer_4
= wx
.FlexGridSizer(1, 3, 5, 5)
882 grid_sizer_2
= wx
.FlexGridSizer(1, 2, 5, 5)
883 grid_sizer_2
.Add(self
.label_2
, 0, wx
.ALIGN_CENTER_VERTICAL|wx
.FIXED_MINSIZE
, 0)
884 grid_sizer_2
.Add(self
._watchNameTextCtrl
, 0, wx
.EXPAND
, 0)
885 grid_sizer_2
.AddGrowableCol(1)
886 sizer_1
.Add(grid_sizer_2
, 1, wx
.EXPAND
, 0)
887 grid_sizer_4
.Add(self
.label_3
, 0, wx
.ALIGN_CENTER_VERTICAL|wx
.FIXED_MINSIZE
, 0)
888 grid_sizer_4
.Add(self
._watchValueTextCtrl
, 0, wx
.EXPAND
, 0)
889 grid_sizer_4
.AddGrowableCol(1)
890 grid_sizer_4
.Add(self
.label_4
, 0, wx
.ALIGN_CENTER_VERTICAL|wx
.FIXED_MINSIZE
, 0)
891 sizer_1
.Add(grid_sizer_4
, 0, wx
.EXPAND
, 0)
892 sizer_1
.Add(self
.radio_box_1
, 0, wx
.EXPAND
, 0)
894 box
= wx
.BoxSizer(wx
.HORIZONTAL
)
895 box
.Add(self
._okButton
, 0, wx
.ALIGN_RIGHT|wx
.ALL
, 5)
896 box
.Add(self
._cancelButton
, 0, wx
.ALIGN_RIGHT|wx
.ALL
, 5)
897 sizer_1
.Add(box
, 1, wx
.EXPAND
, 0)
898 self
.SetAutoLayout(True)
899 self
.SetSizer(sizer_1
)
902 class FramesUI(wx
.SplitterWindow
):
903 def __init__(self
, parent
, id, ui
):
904 wx
.SplitterWindow
.__init
__(self
, parent
, id, style
= wx
.SP_3D
)
906 self
._p
1 = p1
= wx
.ScrolledWindow(self
, -1)
908 sizer
= wx
.BoxSizer(wx
.HORIZONTAL
)
909 framesLabel
= wx
.StaticText(self
, -1, "Stack Frame:")
910 sizer
.Add(framesLabel
, 0, flag
=wx
.ALIGN_CENTER_VERTICAL|wx
.ALIGN_LEFT|wx
.LEFT
, border
=2)
912 self
._framesChoiceCtrl
= wx
.Choice(p1
, -1, choices
=[" "])
913 sizer
.Add(self
._framesChoiceCtrl
, 1, wx
.ALIGN_LEFT|wx
.ALL|wx
.EXPAND
, 1)
914 self
._framesChoiceCtrl
.Bind(wx
.EVT_LIST_ITEM_RIGHT_CLICK
, self
.OnListRightClick
)
915 self
.Bind(wx
.EVT_CHOICE
, self
.ListItemSelected
, self
._framesChoiceCtrl
)
917 sizer2
= wx
.BoxSizer(wx
.VERTICAL
)
920 self
._treeCtrl
= wx
.gizmos
.TreeListCtrl(p1
, -1, style
=wx
.TR_DEFAULT_STYLE| wx
.TR_FULL_ROW_HIGHLIGHT
)
921 self
._treeCtrl
.Bind(wx
.EVT_TREE_ITEM_RIGHT_CLICK
, self
.OnRightClick
)
922 sizer2
.Add(sizer
, 0, wx
.ALIGN_LEFT|wx
.ALL|wx
.EXPAND
, 1)
923 sizer2
.Add(self
._treeCtrl
,1, wx
.ALIGN_LEFT|wx
.ALL|wx
.EXPAND
, 1)
924 tree
= self
._treeCtrl
925 tree
.AddColumn("Thing")
926 tree
.AddColumn("Value")
927 tree
.SetMainColumn(0) # the one with the tree in it...
928 tree
.SetColumnWidth(0, 175)
929 tree
.SetColumnWidth(1, 355)
930 self
._root
= tree
.AddRoot("Frame")
931 tree
.SetItemText(self
._root
, "", 1)
932 tree
.Bind(wx
.EVT_TREE_ITEM_EXPANDING
, self
.IntrospectCallback
)
934 self
._p
2 = p2
= wx
.Window(self
, -1)
935 sizer3
= wx
.BoxSizer(wx
.HORIZONTAL
)
937 p2
.Bind(wx
.EVT_SIZE
, self
.OnSize
)
938 self
._notebook
= wx
.Notebook(p2
, -1, size
=(20,20))
939 self
._notebook
.Hide()
940 sizer3
.Add(self
._notebook
, 1, wx
.ALIGN_LEFT|wx
.ALL|wx
.EXPAND
, 1)
941 self
.consoleTab
= self
.MakeConsoleTab(self
._notebook
, wx
.NewId())
942 self
.inspectConsoleTab
= self
.MakeInspectConsoleTab(self
._notebook
, wx
.NewId())
943 self
.breakPointsTab
= self
.MakeBreakPointsTab(self
._notebook
, wx
.NewId())
944 self
._notebook
.AddPage(self
.consoleTab
, "Output")
945 self
._notebook
.AddPage(self
.inspectConsoleTab
, "Interact")
946 self
._notebook
.AddPage(self
.breakPointsTab
, "Break Points")
948 self
.SetMinimumPaneSize(20)
949 self
.SplitVertically(p1
, p2
, 550)
950 self
.currentItem
= None
951 self
._notebook
.Show(True)
953 def PopulateBPList(self
):
954 self
.breakPointsTab
.PopulateBPList()
956 def OnSize(self
, event
):
957 self
._notebook
.SetSize(self
._p
2.GetSize())
959 def MakeConsoleTab(self
, parent
, id):
960 panel
= wx
.Panel(parent
, id)
961 sizer
= wx
.BoxSizer(wx
.HORIZONTAL
)
962 self
._textCtrl
= STCTextEditor
.TextCtrl(panel
, wx
.NewId())
963 sizer
.Add(self
._textCtrl
, 1, wx
.ALIGN_LEFT|wx
.ALL|wx
.EXPAND
, 2)
964 self
._textCtrl
.SetViewLineNumbers(False)
965 self
._textCtrl
.SetReadOnly(True)
966 if wx
.Platform
== '__WXMSW__':
970 self
._textCtrl
.SetFont(wx
.Font(9, wx
.DEFAULT
, wx
.NORMAL
, wx
.NORMAL
, faceName
= font
))
971 self
._textCtrl
.SetFontColor(wx
.BLACK
)
972 self
._textCtrl
.StyleClearAll()
973 panel
.SetSizer(sizer
)
978 def MakeInspectConsoleTab(self
, parent
, id):
979 self
.command_list
= []
980 self
.command_index
= 0
981 def ExecuteCommand(command
):
982 if not len(self
.command_list
) or not command
== self
.command_list
[len(self
.command_list
) -1]:
983 self
.command_list
.append(command
)
984 self
.command_index
= len(self
.command_list
) - 1
985 retval
= self
._ui
._callback
._debuggerServer
.execute_in_frame(self
._framesChoiceCtrl
.GetStringSelection(), command
)
986 self
._interCtrl
.AddText("\n" + str(retval
))
987 self
._interCtrl
.ScrollToLine(self
._interCtrl
.GetLineCount())
988 # Refresh the tree view in case this command resulted in changes there. TODO: Need to reopen tree items.
989 self
.PopulateTreeFromFrameMessage(self
._framesChoiceCtrl
.GetStringSelection())
991 def ReplaceLastLine(command
):
992 line
= self
._interCtrl
.GetLineCount() - 1
993 self
._interCtrl
.GotoLine(line
)
994 start
= self
._interCtrl
.GetCurrentPos()
995 self
._interCtrl
.SetTargetStart(start
)
996 end
= self
._interCtrl
.GetLineEndPosition(line
)
997 self
._interCtrl
.SetTargetEnd(end
)
998 self
._interCtrl
.ReplaceTarget(">>> " + command
)
999 self
._interCtrl
.GotoLine(line
)
1000 self
._interCtrl
.SetSelectionStart(self
._interCtrl
.GetLineEndPosition(line
))
1002 def OnKeyPressed(event
):
1003 key
= event
.KeyCode()
1004 if key
== wx
.WXK_DELETE
or key
== wx
.WXK_BACK
:
1005 if self
._interCtrl
.GetLine(self
._interCtrl
.GetCurrentLine()) == ">>> ":
1007 elif key
== wx
.WXK_RETURN
:
1008 command
= self
._interCtrl
.GetLine(self
._interCtrl
.GetCurrentLine())[4:]
1009 ExecuteCommand(command
)
1010 self
._interCtrl
.AddText("\n>>> ")
1012 elif key
== wx
.WXK_UP
:
1013 if not len(self
.command_list
):
1015 ReplaceLastLine(self
.command_list
[self
.command_index
])
1016 if self
.command_index
== 0:
1017 self
.command_index
= len(self
.command_list
) - 1
1019 self
.command_index
= self
.command_index
- 1
1021 elif key
== wx
.WXK_DOWN
:
1022 if not len(self
.command_list
):
1024 if self
.command_index
< len(self
.command_list
) - 1:
1025 self
.command_index
= self
.command_index
+ 1
1027 self
.command_index
= 0
1028 ReplaceLastLine(self
.command_list
[self
.command_index
])
1033 panel
= wx
.Panel(parent
, id)
1034 sizer
= wx
.BoxSizer(wx
.HORIZONTAL
)
1035 self
._interCtrl
= STCTextEditor
.TextCtrl(panel
, wx
.NewId())
1036 sizer
.Add(self
._interCtrl
, 1, wx
.ALIGN_LEFT|wx
.ALL|wx
.EXPAND
, 2)
1037 self
._interCtrl
.SetViewLineNumbers(False)
1038 if wx
.Platform
== '__WXMSW__':
1039 font
= "Courier New"
1042 self
._interCtrl
.SetFont(wx
.Font(9, wx
.DEFAULT
, wx
.NORMAL
, wx
.NORMAL
, faceName
= font
))
1043 self
._interCtrl
.SetFontColor(wx
.BLACK
)
1044 self
._interCtrl
.StyleClearAll()
1045 wx
.EVT_KEY_DOWN(self
._interCtrl
, OnKeyPressed
)
1046 self
._interCtrl
.AddText(">>> ")
1047 panel
.SetSizer(sizer
)
1049 tp
, val
, tb
= sys
.exc_info()
1050 traceback
.print_exception(tp
, val
, tb
)
1054 def MakeBreakPointsTab(self
, parent
, id):
1055 panel
= BreakpointsUI(parent
, id, self
._ui
)
1058 def OnRightClick(self
, event
):
1060 self
._introspectItem
= event
.GetItem()
1061 self
._parentChain
= self
.GetItemChain(event
.GetItem())
1062 watchOnly
= len(self
._parentChain
) < 1
1063 if not _WATCHES_ON
and watchOnly
:
1067 if not hasattr(self
, "watchID"):
1068 self
.watchID
= wx
.NewId()
1069 self
.Bind(wx
.EVT_MENU
, self
.OnWatch
, id=self
.watchID
)
1070 item
= wx
.MenuItem(menu
, self
.watchID
, "Create a Watch")
1071 menu
.AppendItem(item
)
1072 menu
.AppendSeparator()
1074 if not hasattr(self
, "viewID"):
1075 self
.viewID
= wx
.NewId()
1076 self
.Bind(wx
.EVT_MENU
, self
.OnView
, id=self
.viewID
)
1077 item
= wx
.MenuItem(menu
, self
.viewID
, "View in Dialog")
1078 menu
.AppendItem(item
)
1079 offset
= wx
.Point(x
=0, y
=20)
1080 menuSpot
= event
.GetPoint() + offset
1081 self
._treeCtrl
.PopupMenu(menu
, menuSpot
)
1083 self
._parentChain
= None
1084 self
._introspectItem
= None
1086 def GetItemChain(self
, item
):
1089 if _VERBOSE
: print 'Exploding: %s' % self
._treeCtrl
.GetItemText(item
, 0)
1090 while item
!= self
._root
:
1091 text
= self
._treeCtrl
.GetItemText(item
, 0)
1092 if _VERBOSE
: print "Appending ", text
1093 parentChain
.append(text
)
1094 item
= self
._treeCtrl
.GetItemParent(item
)
1095 parentChain
.reverse()
1098 def OnView(self
, event
):
1099 title
= self
._treeCtrl
.GetItemText(self
._introspectItem
,0)
1100 value
= self
._treeCtrl
.GetItemText(self
._introspectItem
,1)
1101 dlg
= wx
.lib
.dialogs
.ScrolledMessageDialog(self
, value
, title
, style
=wx
.DD_DEFAULT_STYLE | wx
.RESIZE_BORDER
)
1104 def OnWatch(self
, event
):
1106 if hasattr(self
, '_parentChain'):
1107 wd
= WatchDialog(wx
.GetApp().GetTopWindow(), "Add a Watch", self
._parentChain
)
1109 wd
= WatchDialog(wx
.GetApp().GetTopWindow(), "Add a Watch", None)
1110 if wd
.ShowModal() == wx
.ID_OK
:
1111 name
, text
, send_frame
, run_once
= wd
.GetSettings()
1113 frameNode
= self
._stack
[int(self
.currentItem
)]
1114 message
= frameNode
.getAttribute("message")
1117 binType
= self
._ui
._callback
._debuggerServer
.add_watch(name
, text
, message
, run_once
)
1118 xmldoc
= bz2
.decompress(binType
.data
)
1119 domDoc
= parseString(xmldoc
)
1120 nodeList
= domDoc
.getElementsByTagName('watch')
1121 if len(nodeList
) == 1:
1122 watchValue
= nodeList
.item(0).getAttribute("message")
1124 tp
, val
, tb
= sys
.exc_info()
1125 traceback
.print_exception(tp
, val
, tb
)
1127 def OnIntrospect(self
, event
):
1128 wx
.GetApp().GetTopWindow().SetCursor(wx
.StockCursor(wx
.CURSOR_WAIT
))
1131 list = self
._framesChoiceCtrl
1132 frameNode
= self
._stack
[int(self
.currentItem
)]
1133 message
= frameNode
.getAttribute("message")
1134 binType
= self
._ui
._callback
._debuggerServer
.attempt_introspection(message
, self
._parentChain
)
1135 xmldoc
= bz2
.decompress(binType
.data
)
1136 domDoc
= parseString(xmldoc
)
1137 #wx.MessageBox(xmldoc, "result of introspection")
1138 nodeList
= domDoc
.getElementsByTagName('replacement')
1139 replacementNode
= nodeList
.item(0)
1140 if len(replacementNode
.childNodes
):
1141 thingToWalk
= replacementNode
.childNodes
.item(0)
1142 tree
= self
._treeCtrl
1143 parent
= tree
.GetItemParent(self
._introspectItem
)
1144 treeNode
= self
.AppendSubTreeFromNode(thingToWalk
, thingToWalk
.getAttribute('name'), parent
, insertBefore
=self
._introspectItem
)
1145 self
._treeCtrl
.Expand(treeNode
)
1146 tree
.Delete(self
._introspectItem
)
1148 tp
,val
,tb
= sys
.exc_info()
1149 traceback
.print_exception(tp
, val
, tb
)
1151 wx
.GetApp().GetTopWindow().SetCursor(wx
.StockCursor(wx
.CURSOR_DEFAULT
))
1153 def ClearWhileRunning(self
):
1154 list = self
._framesChoiceCtrl
1157 tree
= self
._treeCtrl
1159 tree
.DeleteChildren(root
)
1160 self
._interCtrl
.Enable(False)
1164 def OnListRightClick(self
, event
):
1165 if not hasattr(self
, "syncFrameID"):
1166 self
.syncFrameID
= wx
.NewId()
1167 self
.Bind(wx
.EVT_MENU
, self
.OnSyncFrame
, id=self
.syncFrameID
)
1169 item
= wx
.MenuItem(menu
, self
.syncFrameID
, "Goto Source Line")
1170 menu
.AppendItem(item
)
1171 self
.PopupMenu(menu
, event
.GetPosition())
1174 def OnSyncFrame(self
, event
):
1175 list = self
._framesChoiceCtrl
1176 frameNode
= self
._stack
[int(self
.currentItem
)]
1177 file = frameNode
.getAttribute("file")
1178 line
= frameNode
.getAttribute("line")
1179 self
._ui
.SynchCurrentLine( file, int(line
) )
1181 def LoadFramesListXML(self
, framesXML
):
1182 wx
.GetApp().GetTopWindow().SetCursor(wx
.StockCursor(wx
.CURSOR_WAIT
))
1183 self
._interCtrl
.Enable(True)
1186 domDoc
= parseString(framesXML
)
1187 list = self
._framesChoiceCtrl
1190 nodeList
= domDoc
.getElementsByTagName('frame')
1192 for index
in range(0, nodeList
.length
):
1193 frameNode
= nodeList
.item(index
)
1194 message
= frameNode
.getAttribute("message")
1195 list.Append(message
)
1196 self
._stack
.append(frameNode
)
1198 index
= len(self
._stack
) - 1
1199 list.SetSelection(index
)
1201 node
= self
._stack
[index
]
1202 self
.currentItem
= index
1203 self
.PopulateTreeFromFrameNode(node
)
1204 self
.OnSyncFrame(None)
1206 self
._p
1.FitInside()
1207 frameNode
= nodeList
.item(index
)
1208 file = frameNode
.getAttribute("file")
1209 line
= frameNode
.getAttribute("line")
1210 self
._ui
.SynchCurrentLine( file, int(line
) )
1212 tp
,val
,tb
=sys
.exc_info()
1213 traceback
.print_exception(tp
, val
, tb
)
1215 wx
.GetApp().GetTopWindow().SetCursor(wx
.StockCursor(wx
.CURSOR_DEFAULT
))
1218 def ListItemSelected(self
, event
):
1219 self
.PopulateTreeFromFrameMessage(event
.GetString())
1220 self
.OnSyncFrame(None)
1222 def PopulateTreeFromFrameMessage(self
, message
):
1224 for node
in self
._stack
:
1225 if node
.getAttribute("message") == message
:
1226 binType
= self
._ui
._callback
._debuggerServer
.request_frame_document(message
)
1227 xmldoc
= bz2
.decompress(binType
.data
)
1228 domDoc
= parseString(xmldoc
)
1229 nodeList
= domDoc
.getElementsByTagName('frame')
1230 self
.currentItem
= index
1232 self
.PopulateTreeFromFrameNode(nodeList
[0])
1236 def PopulateTreeFromFrameNode(self
, frameNode
):
1237 list = self
._framesChoiceCtrl
1239 tree
= self
._treeCtrl
1242 tree
.DeleteChildren(root
)
1243 children
= frameNode
.childNodes
1245 for index
in range(0, children
.length
):
1246 subNode
= children
.item(index
)
1247 treeNode
= self
.AppendSubTreeFromNode(subNode
, subNode
.getAttribute('name'), root
)
1249 firstChild
= treeNode
1252 tree
.Expand(firstChild
)
1253 self
._p
2.FitInside()
1255 def IntrospectCallback(self
, event
):
1256 tree
= self
._treeCtrl
1257 item
= event
.GetItem()
1259 print "In introspectCallback item is %s, pydata is %s" % (event
.GetItem(), tree
.GetPyData(item
))
1260 if tree
.GetPyData(item
) != "Introspect":
1263 self
._introspectItem
= item
1264 self
._parentChain
= self
.GetItemChain(item
)
1265 self
.OnIntrospect(event
)
1268 def AppendSubTreeFromNode(self
, node
, name
, parent
, insertBefore
=None):
1269 tree
= self
._treeCtrl
1270 if insertBefore
!= None:
1271 treeNode
= tree
.InsertItem(parent
, insertBefore
, name
)
1273 treeNode
= tree
.AppendItem(parent
, name
)
1274 children
= node
.childNodes
1275 intro
= node
.getAttribute('intro')
1278 tree
.SetItemHasChildren(treeNode
, True)
1279 tree
.SetPyData(treeNode
, "Introspect")
1280 if node
.getAttribute("value"):
1281 tree
.SetItemText(treeNode
, self
.StripOuterSingleQuotes(node
.getAttribute("value")), 1)
1282 for index
in range(0, children
.length
):
1283 subNode
= children
.item(index
)
1284 if self
.HasChildren(subNode
):
1285 self
.AppendSubTreeFromNode(subNode
, subNode
.getAttribute("name"), treeNode
)
1287 name
= subNode
.getAttribute("name")
1288 value
= self
.StripOuterSingleQuotes(subNode
.getAttribute("value"))
1289 n
= tree
.AppendItem(treeNode
, name
)
1290 tree
.SetItemText(n
, value
, 1)
1291 intro
= subNode
.getAttribute('intro')
1293 tree
.SetItemHasChildren(n
, True)
1294 tree
.SetPyData(n
, "Introspect")
1298 def StripOuterSingleQuotes(self
, string
):
1299 if string
.startswith("'") and string
.endswith("'"):
1300 retval
= string
[1:-1]
1301 elif string
.startswith("\"") and string
.endswith("\""):
1302 retval
= string
[1:-1]
1305 if retval
.startswith("u'") and retval
.endswith("'"):
1309 def HasChildren(self
, node
):
1311 return node
.childNodes
.length
> 0
1313 tp
,val
,tb
=sys
.exc_info()
1316 def AppendText(self
, text
):
1317 self
._textCtrl
.SetReadOnly(False)
1318 self
._textCtrl
.AddText(text
)
1319 self
._textCtrl
.ScrollToLine(self
._textCtrl
.GetLineCount())
1320 self
._textCtrl
.SetReadOnly(True)
1322 def AppendErrorText(self
, text
):
1323 self
._textCtrl
.SetReadOnly(False)
1324 self
._textCtrl
.SetFontColor(wx
.RED
)
1325 self
._textCtrl
.StyleClearAll()
1326 self
._textCtrl
.AddText(text
)
1327 self
._textCtrl
.ScrollToLine(self
._textCtrl
.GetLineCount())
1328 self
._textCtrl
.SetFontColor(wx
.BLACK
)
1329 self
._textCtrl
.StyleClearAll()
1330 self
._textCtrl
.SetReadOnly(True)
1332 def ClearOutput(self
, event
):
1333 self
._textCtrl
.SetReadOnly(False)
1334 self
._textCtrl
.ClearAll()
1335 self
._textCtrl
.SetReadOnly(True)
1337 def SwitchToOutputTab(self
):
1338 self
._notebook
.SetSelection(0)
1340 class DebuggerView(Service
.ServiceView
):
1342 #----------------------------------------------------------------------------
1343 # Overridden methods
1344 #----------------------------------------------------------------------------
1346 def __init__(self
, service
):
1347 Service
.ServiceView
.__init
__(self
, service
)
1349 def _CreateControl(self
, parent
, id):
1352 #------------------------------------------------------------------------------
1354 #-----------------------------------------------------------------------------
1356 def OnToolClicked(self
, event
):
1357 self
.GetFrame().ProcessEvent(event
)
1359 def ProcessUpdateUIEvent(self
, event
):
1362 def ProcessEvent(self
, event
):
1365 #------------------------------------------------------------------------------
1367 #-----------------------------------------------------------------------------
1370 def __init__(self
, message
, framesXML
, info
=None, quit
=False):
1371 self
._framesXML
= framesXML
1372 self
._message
= message
1376 def getFramesXML(self
):
1377 return self
._framesXML
1379 def getMessage(self
):
1380 return self
._message
1388 class AGXMLRPCServer(SimpleXMLRPCServer
.SimpleXMLRPCServer
):
1389 def __init__(self
, address
, logRequests
=0):
1390 SimpleXMLRPCServer
.SimpleXMLRPCServer
.__init
__(self
, address
, logRequests
=logRequests
)
1392 class RequestHandlerThread(threading
.Thread
):
1393 def __init__(self
, queue
, address
):
1394 threading
.Thread
.__init
__(self
)
1395 self
._keepGoing
= True
1397 self
._address
= address
1398 self
._server
= AGXMLRPCServer(self
._address
,logRequests
=0)
1399 self
._server
.register_function(self
.interaction
)
1400 self
._server
.register_function(self
.quit
)
1401 self
._server
.register_function(self
.dummyOperation
)
1402 if _VERBOSE
: print "RequestHandlerThread on fileno %s" % str(self
._server
.fileno())
1405 while self
._keepGoing
:
1407 self
._server
.handle_request()
1409 tp
, val
, tb
= sys
.exc_info()
1410 traceback
.print_exception(tp
, val
, tb
)
1411 self
._keepGoing
= False
1412 if _VERBOSE
: print "Exiting Request Handler Thread."
1414 def interaction(self
, message
, frameXML
, info
):
1415 if _VERBOSE
: print "In RequestHandlerThread.interaction -- adding to queue"
1416 interaction
= Interaction(message
, frameXML
, info
)
1417 self
._queue
.put(interaction
)
1421 interaction
= Interaction(None, None, info
=None, quit
=True)
1422 self
._queue
.put(interaction
)
1425 def dummyOperation(self
):
1428 def AskToStop(self
):
1429 self
._keepGoing
= False
1430 if type(self
._server
) is not types
.NoneType
:
1432 # This is a really ugly way to make sure this thread isn't blocked in
1434 url
= 'http://' + self
._address
[0] + ':' + str(self
._address
[1]) + '/'
1435 tempServer
= xmlrpclib
.ServerProxy(url
, allow_none
=1)
1436 tempServer
.dummyOperation()
1438 tp
, val
, tb
= sys
.exc_info()
1439 traceback
.print_exception(tp
, val
, tb
)
1440 self
._server
.server_close()
1443 class RequestBreakThread(threading
.Thread
):
1444 def __init__(self
, server
, interrupt
=False, pushBreakpoints
=False, breakDict
=None, kill
=False):
1445 threading
.Thread
.__init
__(self
)
1446 self
._server
= server
1448 self
._interrupt
= interrupt
1449 self
._pushBreakpoints
= pushBreakpoints
1450 self
._breakDict
= breakDict
1455 if _VERBOSE
: print "RequestBreakThread, before call"
1457 self
._server
.break_requested()
1458 if self
._pushBreakpoints
:
1459 self
._server
.update_breakpoints(xmlrpclib
.Binary(pickle
.dumps(self
._breakDict
)))
1465 if _VERBOSE
: print "RequestBreakThread, after call"
1467 tp
,val
,tb
= sys
.exc_info()
1468 traceback
.print_exception(tp
, val
, tb
)
1470 class DebuggerOperationThread(threading
.Thread
):
1471 def __init__(self
, function
):
1472 threading
.Thread
.__init
__(self
)
1473 self
._function
= function
1476 if _VERBOSE
: print "In DOT, before call"
1480 tp
,val
,tb
= sys
.exc_info()
1481 traceback
.print_exception(tp
, val
, tb
)
1482 if _VERBOSE
: print "In DOT, after call"
1484 class DebuggerCallback
:
1486 def __init__(self
, host
, port
, debugger_url
, break_url
, debuggerUI
):
1487 if _VERBOSE
: print "+++++++ Creating server on port, ", str(port
)
1489 self
._queue
= Queue
.Queue(50)
1491 self
._port
= int(port
)
1492 threading
._VERBOSE
= _VERBOSE
1493 self
._serverHandlerThread
= RequestHandlerThread(self
._queue
, (self
._host
, self
._port
))
1495 self
._debugger
_url
= debugger_url
1496 self
._debuggerServer
= None
1497 self
._waiting
= False
1498 self
._service
= wx
.GetApp().GetService(DebuggerService
)
1499 self
._debuggerUI
= debuggerUI
1500 self
._break
_url
= break_url
1501 self
._breakServer
= None
1502 self
._firstInteraction
= True
1503 self
._pendingBreak
= False
1506 self
._serverHandlerThread
.start()
1508 def ShutdownServer(self
):
1509 #rbt = RequestBreakThread(self._breakServer, kill=True)
1511 self
.setWaiting(False)
1512 if self
._serverHandlerThread
:
1513 self
._serverHandlerThread
.AskToStop()
1514 self
._serverHandlerThread
= None
1516 def BreakExecution(self
):
1517 rbt
= RequestBreakThread(self
._breakServer
, interrupt
=True)
1520 def SingleStep(self
):
1521 self
._debuggerUI
.DisableWhileDebuggerRunning()
1522 self
._debuggerServer
.set_step() # Figure out where to set allowNone
1526 self
._debuggerUI
.DisableWhileDebuggerRunning()
1527 self
._debuggerServer
.set_next()
1531 self
._debuggerUI
.DisableWhileDebuggerRunning()
1532 self
._debuggerServer
.set_continue()
1536 self
._debuggerUI
.DisableWhileDebuggerRunning()
1537 self
._debuggerServer
.set_return()
1540 def setWaiting(self
, value
):
1541 self
._waiting
= value
1543 def getWaiting(self
):
1544 return self
._waiting
1546 def readQueue(self
):
1547 if self
._queue
.qsize():
1549 item
= self
._queue
.get_nowait()
1551 self
.interaction(None, None, None, True)
1553 data
= bz2
.decompress(item
.getFramesXML().data
)
1554 self
.interaction(item
.getMessage().data
, data
, item
.getInfo(), False)
1558 def pushBreakpoints(self
):
1559 rbt
= RequestBreakThread(self
._breakServer
, pushBreakpoints
=True, breakDict
=self
._service
.GetMasterBreakpointDict())
1563 def waitForRPC(self
):
1564 self
.setWaiting(True)
1565 while self
.getWaiting():
1571 tp
, val
, tb
= sys
.exc_info()
1572 traceback
.print_exception(tp
, val
, tb
)
1573 wx
.GetApp().Yield(True)
1574 if _VERBOSE
: print "Exiting waitForRPC."
1576 def interaction(self
, message
, frameXML
, info
, quit
):
1578 #This method should be hit as the debugger starts.
1579 if self
._firstInteraction
:
1580 self
._firstInteraction
= False
1581 self
._debuggerServer
= xmlrpclib
.ServerProxy(self
._debugger
_url
, allow_none
=1)
1582 self
._breakServer
= xmlrpclib
.ServerProxy(self
._break
_url
, allow_none
=1)
1583 self
.pushBreakpoints()
1584 self
.setWaiting(False)
1585 if _VERBOSE
: print "+"*40
1587 self
._debuggerUI
.StopExecution(None)
1590 if _VERBOSE
: print "Hit interaction with exception"
1591 #self._debuggerUI.StopExecution(None)
1592 #self._debuggerUI.SetStatusText("Got exception: " + str(info))
1593 self
._debuggerUI
.SwitchToOutputTab()
1595 if _VERBOSE
: print "Hit interaction no exception"
1596 self
._debuggerUI
.SetStatusText(message
)
1597 self
._debuggerUI
.LoadFramesListXML(frameXML
)
1598 self
._debuggerUI
.EnableWhileDebuggerStopped()
1599 if _VERBOSE
: print "+"*40
1601 class DebuggerService(Service
.Service
):
1603 #----------------------------------------------------------------------------
1605 #----------------------------------------------------------------------------
1606 TOGGLE_BREAKPOINT_ID
= wx
.NewId()
1607 CLEAR_ALL_BREAKPOINTS
= wx
.NewId()
1609 DEBUG_ID
= wx
.NewId()
1610 DEBUG_WEBSERVER_ID
= wx
.NewId()
1613 def ComparePaths(first
, second
):
1614 one
= DebuggerService
.ExpandPath(first
)
1615 two
= DebuggerService
.ExpandPath(second
)
1617 return one
.lower() == two
.lower()
1620 ComparePaths
= staticmethod(ComparePaths
)
1622 # Make sure we're using an expanded path on windows.
1623 def ExpandPath(path
):
1626 return win32api
.GetLongPathName(path
)
1629 print "Cannot get long path for %s" % path
1633 ExpandPath
= staticmethod(ExpandPath
)
1635 #----------------------------------------------------------------------------
1636 # Overridden methods
1637 #----------------------------------------------------------------------------
1639 def __init__(self
, serviceName
, embeddedWindowLocation
= wx
.lib
.pydocview
.EMBEDDED_WINDOW_LEFT
):
1640 Service
.Service
.__init
__(self
, serviceName
, embeddedWindowLocation
)
1641 self
.BREAKPOINT_DICT_STRING
= "MasterBreakpointDict"
1642 config
= wx
.ConfigBase_Get()
1643 pickledbps
= config
.Read(self
.BREAKPOINT_DICT_STRING
)
1646 self
._masterBPDict
= pickle
.loads(pickledbps
.encode('ascii'))
1648 tp
, val
, tb
= sys
.exc_info()
1649 traceback
.print_exception(tp
,val
,tb
)
1650 self
._masterBPDict
= {}
1652 self
._masterBPDict
= {}
1654 def OnCloseFrame(self
, event
):
1655 # IS THIS THE RIGHT PLACE?
1657 config
= wx
.ConfigBase_Get()
1658 config
.Write(self
.BREAKPOINT_DICT_STRING
, pickle
.dumps(self
._masterBPDict
))
1660 tp
,val
,tb
= sys
.exc_info()
1661 traceback
.print_exception(tp
, val
, tb
)
1664 def _CreateView(self
):
1665 return DebuggerView(self
)
1668 #----------------------------------------------------------------------------
1669 # Service specific methods
1670 #----------------------------------------------------------------------------
1672 def InstallControls(self
, frame
, menuBar
= None, toolBar
= None, statusBar
= None, document
= None):
1673 #Service.Service.InstallControls(self, frame, menuBar, toolBar, statusBar, document)
1675 config
= wx
.ConfigBase_Get()
1677 debuggerMenu
= wx
.Menu()
1678 if not menuBar
.FindItemById(DebuggerService
.CLEAR_ALL_BREAKPOINTS
):
1680 debuggerMenu
.Append(DebuggerService
.RUN_ID
, _("&Run...\tCtrl+R"), _("Runs a file"))
1681 wx
.EVT_MENU(frame
, DebuggerService
.RUN_ID
, frame
.ProcessEvent
)
1682 wx
.EVT_UPDATE_UI(frame
, DebuggerService
.RUN_ID
, frame
.ProcessUpdateUIEvent
)
1684 debuggerMenu
.Append(DebuggerService
.DEBUG_ID
, _("&Debug...\tCtrl+D"), _("Debugs a file"))
1685 wx
.EVT_MENU(frame
, DebuggerService
.DEBUG_ID
, frame
.ProcessEvent
)
1686 wx
.EVT_UPDATE_UI(frame
, DebuggerService
.DEBUG_ID
, frame
.ProcessUpdateUIEvent
)
1688 if not ACTIVEGRID_BASE_IDE
:
1689 debuggerMenu
.AppendSeparator()
1690 debuggerMenu
.Append(DebuggerService
.DEBUG_WEBSERVER_ID
, _("Debug Internal Web Server"), _("Debugs the internal webservier"))
1691 wx
.EVT_MENU(frame
, DebuggerService
.DEBUG_WEBSERVER_ID
, frame
.ProcessEvent
)
1692 wx
.EVT_UPDATE_UI(frame
, DebuggerService
.DEBUG_WEBSERVER_ID
, frame
.ProcessUpdateUIEvent
)
1694 debuggerMenu
.AppendSeparator()
1696 debuggerMenu
.Append(DebuggerService
.TOGGLE_BREAKPOINT_ID
, _("&Toggle Breakpoint...\tCtrl+B"), _("Toggle a breakpoint"))
1697 wx
.EVT_MENU(frame
, DebuggerService
.TOGGLE_BREAKPOINT_ID
, self
.ProcessEvent
)
1698 wx
.EVT_UPDATE_UI(frame
, DebuggerService
.TOGGLE_BREAKPOINT_ID
, self
.ProcessUpdateUIEvent
)
1700 debuggerMenu
.Append(DebuggerService
.CLEAR_ALL_BREAKPOINTS
, _("&Clear All Breakpoints"), _("Clear All Breakpoints"))
1701 wx
.EVT_MENU(frame
, DebuggerService
.CLEAR_ALL_BREAKPOINTS
, self
.ProcessEvent
)
1702 wx
.EVT_UPDATE_UI(frame
, DebuggerService
.CLEAR_ALL_BREAKPOINTS
, self
.ProcessUpdateUIEvent
)
1705 viewMenuIndex
= menuBar
.FindMenu(_("&Project"))
1706 menuBar
.Insert(viewMenuIndex
+ 1, debuggerMenu
, _("&Run"))
1712 #----------------------------------------------------------------------------
1713 # Event Processing Methods
1714 #----------------------------------------------------------------------------
1716 def ProcessEventBeforeWindows(self
, event
):
1720 def ProcessEvent(self
, event
):
1721 if Service
.Service
.ProcessEvent(self
, event
):
1724 an_id
= event
.GetId()
1725 if an_id
== DebuggerService
.TOGGLE_BREAKPOINT_ID
:
1726 self
.OnToggleBreakpoint(event
)
1728 elif an_id
== DebuggerService
.CLEAR_ALL_BREAKPOINTS
:
1729 self
.ClearAllBreakpoints()
1731 elif an_id
== DebuggerService
.RUN_ID
:
1732 self
.OnRunProject(event
)
1734 elif an_id
== DebuggerService
.DEBUG_ID
:
1735 self
.OnDebugProject(event
)
1737 elif an_id
== DebuggerService
.DEBUG_WEBSERVER_ID
:
1738 self
.OnDebugWebServer(event
)
1742 def ProcessUpdateUIEvent(self
, event
):
1743 if Service
.Service
.ProcessUpdateUIEvent(self
, event
):
1746 an_id
= event
.GetId()
1747 if an_id
== DebuggerService
.TOGGLE_BREAKPOINT_ID
:
1748 currentView
= self
.GetDocumentManager().GetCurrentView()
1749 event
.Enable(isinstance(currentView
, PythonEditor
.PythonView
))
1751 elif an_id
== DebuggerService
.CLEAR_ALL_BREAKPOINTS
:
1752 event
.Enable(self
.HasBreakpointsSet())
1754 elif (an_id
== DebuggerService
.RUN_ID
1755 or an_id
== DebuggerService
.DEBUG_ID
):
1756 event
.Enable(self
.HasAnyFiles())
1761 #----------------------------------------------------------------------------
1763 #----------------------------------------------------------------------------
1765 def OnDebugProject(self
, event
):
1766 if _WINDOWS
and not _PYWIN32_INSTALLED
:
1767 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."))
1769 if not Executor
.GetPythonExecutablePath():
1771 if DebugCommandUI
.DebuggerRunning():
1772 wx
.MessageBox(_("A debugger is already running. Please shut down the other debugger first."), _("Debugger Running"))
1774 self
.ShowWindow(True)
1775 projectService
= wx
.GetApp().GetService(ProjectEditor
.ProjectService
)
1776 project
= projectService
.GetView().GetDocument()
1778 dlg
= CommandPropertiesDialog(self
.GetView().GetFrame(), 'Debug Python File', projectService
, None, pythonOnly
=True, okButtonName
="Debug", debugging
=True)
1781 if dlg
.ShowModal() == wx
.ID_OK
:
1782 fileToDebug
, initialArgs
, startIn
, isPython
, environment
= dlg
.GetSettings()
1787 self
.PromptToSaveFiles()
1789 shortFile
= os
.path
.basename(fileToDebug
)
1790 fileToDebug
= DebuggerService
.ExpandPath(fileToDebug
)
1792 page
= DebugCommandUI(Service
.ServiceView
.bottomTab
, -1, str(fileToDebug
), self
)
1793 count
= Service
.ServiceView
.bottomTab
.GetPageCount()
1794 Service
.ServiceView
.bottomTab
.AddPage(page
, _("Debugging: ") + shortFile
)
1795 Service
.ServiceView
.bottomTab
.SetSelection(count
)
1796 page
.Execute(initialArgs
, startIn
, environment
)
1800 def OnDebugWebServer(self
, event
):
1801 if _WINDOWS
and not _PYWIN32_INSTALLED
:
1802 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."))
1804 if not Executor
.GetPythonExecutablePath():
1806 if DebugCommandUI
.DebuggerRunning():
1807 wx
.MessageBox(_("A debugger is already running. Please shut down the other debugger first."), _("Debugger Running"))
1809 import WebServerService
1810 wsService
= wx
.GetApp().GetService(WebServerService
.WebServerService
)
1811 fileName
, args
= wsService
.StopAndPrepareToDebug()
1813 page
= DebugCommandUI(Service
.ServiceView
.bottomTab
, -1, str(fileName
), self
)
1814 count
= Service
.ServiceView
.bottomTab
.GetPageCount()
1815 Service
.ServiceView
.bottomTab
.AddPage(page
, _("Debugging: Internal WebServer"))
1816 Service
.ServiceView
.bottomTab
.SetSelection(count
)
1817 page
.Execute(args
, startIn
=os
.getcwd(), environment
=os
.environ
)
1822 def HasAnyFiles(self
):
1823 docs
= wx
.GetApp().GetDocumentManager().GetDocuments()
1824 return len(docs
) > 0
1826 def PromptToSaveFiles(self
, running
=True):
1827 filesModified
= False
1828 docs
= wx
.GetApp().GetDocumentManager().GetDocuments()
1830 if doc
.IsModified():
1831 filesModified
= True
1834 frame
= self
.GetView().GetFrame()
1836 yesNoMsg
= wx
.MessageDialog(frame
,
1837 _("Files have been modified.\nWould you like to save all files before running?"),
1839 wx
.YES_NO|wx
.ICON_QUESTION
1842 yesNoMsg
= wx
.MessageDialog(frame
,
1843 _("Files have been modified.\nWould you like to save all files before debugging?"),
1845 wx
.YES_NO|wx
.ICON_QUESTION
1847 if yesNoMsg
.ShowModal() == wx
.ID_YES
:
1848 docs
= wx
.GetApp().GetDocumentManager().GetDocuments()
1853 DebugCommandUI
.ShutdownAllDebuggers()
1854 RunCommandUI
.ShutdownAllRunners()
1856 def OnRunProject(self
, event
):
1857 if _WINDOWS
and not _PYWIN32_INSTALLED
:
1858 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."))
1860 if not Executor
.GetPythonExecutablePath():
1862 projectService
= wx
.GetApp().GetService(ProjectEditor
.ProjectService
)
1863 project
= projectService
.GetView().GetDocument()
1865 dlg
= CommandPropertiesDialog(self
.GetView().GetFrame(), 'Run', projectService
, None)
1868 if dlg
.ShowModal() == wx
.ID_OK
:
1869 fileToRun
, initialArgs
, startIn
, isPython
, environment
= dlg
.GetSettings()
1876 self
.PromptToSaveFiles()
1877 # This will need to change when we can run more than .py and .bpel files.
1879 projectService
.RunProcessModel(fileToRun
)
1882 self
.ShowWindow(True)
1883 shortFile
= os
.path
.basename(fileToRun
)
1884 page
= RunCommandUI(Service
.ServiceView
.bottomTab
, -1, str(fileToRun
))
1885 count
= Service
.ServiceView
.bottomTab
.GetPageCount()
1886 Service
.ServiceView
.bottomTab
.AddPage(page
, "Running: " + shortFile
)
1887 Service
.ServiceView
.bottomTab
.SetSelection(count
)
1888 page
.Execute(initialArgs
, startIn
, environment
)
1890 def OnToggleBreakpoint(self
, event
, line
=-1, fileName
=None):
1892 view
= wx
.GetApp().GetDocumentManager().GetCurrentView()
1893 # Test to make sure we aren't the project view.
1894 if not hasattr(view
, 'MarkerExists'):
1896 fileName
= wx
.GetApp().GetDocumentManager().GetCurrentDocument().GetFilename()
1898 line
= view
.GetCtrl().GetCurrentLine()
1899 if self
.BreakpointSet(fileName
, line
+ 1):
1900 self
.ClearBreak(fileName
, line
+ 1)
1902 self
.SetBreak(fileName
, line
+ 1)
1903 # Now refresh all the markers icons in all the open views.
1904 self
.ClearAllBreakpointMarkers()
1905 self
.SetAllBreakpointMarkers()
1907 def SilentToggleBreakpoint(self
, fileName
, line
):
1909 for lineNumber
in self
.GetBreakpointList(fileName
):
1910 if int(lineNumber
) == int(line
):
1914 self
.SetBreak(fileName
, line
)
1916 self
.ClearBreak(fileName
, line
)
1918 def SetBreak(self
, fileName
, line
):
1919 expandedName
= DebuggerService
.ExpandPath(fileName
)
1920 if not self
._masterBPDict
.has_key(expandedName
):
1921 self
._masterBPDict
[expandedName
] = [line
]
1923 self
._masterBPDict
[expandedName
] += [line
]
1924 # If we're already debugging, pass this bp off to the DebuggerCallback
1925 self
.NotifyDebuggersOfBreakpointChange()
1927 def NotifyDebuggersOfBreakpointChange(self
):
1928 DebugCommandUI
.NotifyDebuggersOfBreakpointChange()
1930 def GetBreakpointList(self
, fileName
):
1931 expandedName
= DebuggerService
.ExpandPath(fileName
)
1932 if not self
._masterBPDict
.has_key(expandedName
):
1935 return self
._masterBPDict
[expandedName
]
1937 def BreakpointSet(self
, fileName
, line
):
1938 expandedName
= DebuggerService
.ExpandPath(fileName
)
1939 if not self
._masterBPDict
.has_key(expandedName
):
1943 for number
in self
._masterBPDict
[expandedName
]:
1944 if(int(number
) == int(line
)):
1948 def ClearBreak(self
, fileName
, line
):
1949 expandedName
= DebuggerService
.ExpandPath(fileName
)
1950 if not self
._masterBPDict
.has_key(expandedName
):
1951 print "In ClearBreak: no key"
1955 for number
in self
._masterBPDict
[expandedName
]:
1956 if(int(number
) != int(line
)):
1957 newList
.append(number
)
1958 self
._masterBPDict
[expandedName
] = newList
1959 self
.NotifyDebuggersOfBreakpointChange()
1961 def HasBreakpointsSet(self
):
1962 for key
, value
in self
._masterBPDict
.items():
1967 def ClearAllBreakpoints(self
):
1968 self
._masterBPDict
= {}
1969 self
.NotifyDebuggersOfBreakpointChange()
1970 self
.ClearAllBreakpointMarkers()
1972 def ClearAllBreakpointMarkers(self
):
1973 openDocs
= wx
.GetApp().GetDocumentManager().GetDocuments()
1974 for openDoc
in openDocs
:
1975 if(isinstance(openDoc
.GetFirstView(), CodeEditor
.CodeView
)):
1976 openDoc
.GetFirstView().MarkerDeleteAll(CodeEditor
.CodeCtrl
.BREAKPOINT_MARKER_NUM
)
1978 def GetMasterBreakpointDict(self
):
1979 return self
._masterBPDict
1981 def SetAllBreakpointMarkers(self
):
1982 openDocs
= wx
.GetApp().GetDocumentManager().GetDocuments()
1983 for openDoc
in openDocs
:
1984 if(isinstance(openDoc
.GetFirstView(), CodeEditor
.CodeView
)):
1985 self
.SetCurrentBreakpointMarkers(openDoc
.GetFirstView())
1987 def SetCurrentBreakpointMarkers(self
, view
):
1988 if isinstance(view
, CodeEditor
.CodeView
) and hasattr(view
, 'GetDocument'):
1989 view
.MarkerDeleteAll(CodeEditor
.CodeCtrl
.BREAKPOINT_MARKER_NUM
)
1990 for linenum
in self
.GetBreakpointList(view
.GetDocument().GetFilename()):
1991 view
.MarkerAdd(lineNum
=int(linenum
) - 1, marker_index
=CodeEditor
.CodeCtrl
.BREAKPOINT_MARKER_NUM
)
1993 class DebuggerOptionsPanel(wx
.Panel
):
1996 def __init__(self
, parent
, id):
1997 wx
.Panel
.__init
__(self
, parent
, id)
1999 config
= wx
.ConfigBase_Get()
2000 localHostStaticText
= wx
.StaticText(self
, -1, _("Local Host Name:"))
2001 self
._LocalHostTextCtrl
= wx
.TextCtrl(self
, -1, config
.Read("DebuggerHostName", DEFAULT_HOST
), size
= (150, -1))
2002 portNumberStaticText
= wx
.StaticText(self
, -1, _("Port Range:"))
2003 dashStaticText
= wx
.StaticText(self
, -1, _("through to"))
2004 startingPort
=config
.ReadInt("DebuggerStartingPort", DEFAULT_PORT
)
2005 self
._PortNumberTextCtrl
= wx
.lib
.intctrl
.IntCtrl(self
, -1, startingPort
, size
= (50, -1))
2006 self
._PortNumberTextCtrl
.SetMin(1)#What are real values?
2007 self
._PortNumberTextCtrl
.SetMax(65514) #What are real values?
2008 self
.Bind(wx
.lib
.intctrl
.EVT_INT
, self
.MinPortChange
, self
._PortNumberTextCtrl
)
2010 self
._EndPortNumberTextCtrl
= wx
.lib
.intctrl
.IntCtrl(self
, -1, startingPort
+ PORT_COUNT
, size
= (50, -1))
2011 self
._EndPortNumberTextCtrl
.SetMin(22)#What are real values?
2012 self
._EndPortNumberTextCtrl
.SetMax(65535)#What are real values?
2013 self
._EndPortNumberTextCtrl
.Enable( False )
2014 debuggerPanelBorderSizer
= wx
.BoxSizer(wx
.VERTICAL
)
2015 debuggerPanelSizer
= wx
.GridBagSizer(hgap
= 5, vgap
= 5)
2016 debuggerPanelSizer
.Add( localHostStaticText
, (0,0), flag
=wx
.ALIGN_CENTER_VERTICAL|wx
.ALIGN_LEFT
)
2017 debuggerPanelSizer
.Add( self
._LocalHostTextCtrl
, (0,1), (1,3), flag
=wx
.EXPAND|wx
.ALIGN_CENTER
)
2018 debuggerPanelSizer
.Add( portNumberStaticText
, (1,0), flag
=wx
.ALIGN_LEFT|wx
.ALIGN_CENTER_VERTICAL
)
2019 debuggerPanelSizer
.Add( self
._PortNumberTextCtrl
, (1,1), flag
=wx
.ALIGN_CENTER
)
2020 debuggerPanelSizer
.Add( dashStaticText
, (1,2), flag
=wx
.ALIGN_CENTER
)
2021 debuggerPanelSizer
.Add( self
._EndPortNumberTextCtrl
, (1,3), flag
=wx
.ALIGN_CENTER
)
2022 FLUSH_PORTS_ID
= wx
.NewId()
2023 self
._flushPortsButton
= wx
.Button(self
, FLUSH_PORTS_ID
, "Reset Port List")
2024 wx
.EVT_BUTTON(parent
, FLUSH_PORTS_ID
, self
.FlushPorts
)
2025 debuggerPanelSizer
.Add(self
._flushPortsButton
, (2,2), (1,2), flag
=wx
.ALIGN_RIGHT
)
2027 debuggerPanelBorderSizer
.Add(debuggerPanelSizer
, 0, wx
.ALL
, SPACE
)
2028 self
.SetSizer(debuggerPanelBorderSizer
)
2030 parent
.AddPage(self
, _("Debugger"))
2032 def FlushPorts(self
, event
):
2033 if self
._PortNumberTextCtrl
.IsInBounds():
2034 config
= wx
.ConfigBase_Get()
2035 config
.WriteInt("DebuggerStartingPort", self
._PortNumberTextCtrl
.GetValue())
2036 DebugCommandUI
.NewPortRange()
2038 wx
.MessageBox(_("The starting port is not valid. Please change the value and try again.", "Invalid Starting Port Number"))
2040 def MinPortChange(self
, event
):
2041 self
._EndPortNumberTextCtrl
.Enable( True )
2042 self
._EndPortNumberTextCtrl
.SetValue( self
._PortNumberTextCtrl
.GetValue() + PORT_COUNT
)
2043 self
._EndPortNumberTextCtrl
.Enable( False )
2045 def OnOK(self
, optionsDialog
):
2046 config
= wx
.ConfigBase_Get()
2047 config
.Write("DebuggerHostName", self
._LocalHostTextCtrl
.GetValue())
2048 if self
._PortNumberTextCtrl
.IsInBounds():
2049 config
.WriteInt("DebuggerStartingPort", self
._PortNumberTextCtrl
.GetValue())
2051 class CommandPropertiesDialog(wx
.Dialog
):
2053 def __init__(self
, parent
, title
, projectService
, currentProjectDocument
, pythonOnly
=False, okButtonName
="Run", debugging
=False):
2054 self
._projService
= projectService
2057 for template
in self
._projService
.GetDocumentManager().GetTemplates():
2058 if not ACTIVEGRID_BASE_IDE
and template
.GetDocumentType() == ProcessModelEditor
.ProcessModelDocument
:
2059 self
._pmext
= template
.GetDefaultExtension()
2060 if template
.GetDocumentType() == PythonEditor
.PythonDocument
:
2061 self
._pyext
= template
.GetDefaultExtension()
2062 self
._pythonOnly
= pythonOnly
2063 self
._currentProj
= currentProjectDocument
2064 self
._projectNameList
, self
._projectDocumentList
, selectedIndex
= self
.GetProjectList()
2065 if not self
._projectNameList
:
2066 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"))
2069 wx
.Dialog
.__init
__(self
, parent
, -1, title
)
2071 wx
.Dialog
.__init
__(self
, parent
, -1, title
, size
=(390,270))
2073 projStaticText
= wx
.StaticText(self
, -1, _("Project:"))
2074 fileStaticText
= wx
.StaticText(self
, -1, _("File:"))
2075 argsStaticText
= wx
.StaticText(self
, -1, _("Arguments:"))
2076 startInStaticText
= wx
.StaticText(self
, -1, _("Start in:"))
2077 pythonPathStaticText
= wx
.StaticText(self
, -1, _("PYTHONPATH:"))
2078 postpendStaticText
= _("Postpend win32api path")
2079 cpPanelBorderSizer
= wx
.BoxSizer(wx
.VERTICAL
)
2080 self
._projList
= wx
.Choice(self
, -1, (200,-1), choices
=self
._projectNameList
)
2081 self
.Bind(wx
.EVT_CHOICE
, self
.EvtListBox
, self
._projList
)
2083 flexGridSizer
= wx
.FlexGridSizer(cols
= 3, vgap
= 10, hgap
= 10)
2085 flexGridSizer
.Add(projStaticText
, 0, flag
=wx
.ALIGN_CENTER_VERTICAL|wx
.ALIGN_LEFT
)
2086 flexGridSizer
.Add(self
._projList
, 1, flag
=wx
.EXPAND
)
2087 flexGridSizer
.Add(wx
.StaticText(parent
, -1, ""), 0)
2089 flexGridSizer
.Add(fileStaticText
, 0, flag
=wx
.ALIGN_CENTER_VERTICAL|wx
.ALIGN_LEFT
)
2090 self
._fileList
= wx
.Choice(self
, -1, (200,-1))
2091 self
.Bind(wx
.EVT_CHOICE
, self
.OnFileSelected
, self
._fileList
)
2092 flexGridSizer
.Add(self
._fileList
, 1, flag
=wx
.EXPAND
)
2093 flexGridSizer
.Add(wx
.StaticText(parent
, -1, ""), 0)
2095 config
= wx
.ConfigBase_Get()
2096 self
._lastArguments
= config
.Read("LastRunArguments")
2097 self
._argsEntry
= wx
.TextCtrl(self
, -1, str(self
._lastArguments
))
2098 self
._argsEntry
.SetToolTipString(str(self
._lastArguments
))
2100 flexGridSizer
.Add(argsStaticText
, 0, flag
=wx
.ALIGN_CENTER_VERTICAL|wx
.ALIGN_LEFT
)
2101 flexGridSizer
.Add(self
._argsEntry
, 1, flag
=wx
.EXPAND
)
2102 flexGridSizer
.Add(wx
.StaticText(parent
, -1, ""), 0)
2104 flexGridSizer
.Add(startInStaticText
, 0, flag
=wx
.ALIGN_CENTER_VERTICAL|wx
.ALIGN_LEFT
)
2105 self
._lastStartIn
= config
.Read("LastRunStartIn")
2106 if not self
._lastStartIn
:
2107 self
._lastStartIn
= str(os
.getcwd())
2108 self
._startEntry
= wx
.TextCtrl(self
, -1, self
._lastStartIn
)
2109 self
._startEntry
.SetToolTipString(self
._lastStartIn
)
2111 flexGridSizer
.Add(self
._startEntry
, 1, wx
.EXPAND
)
2112 self
._findDir
= wx
.Button(self
, -1, _("Browse..."))
2113 self
.Bind(wx
.EVT_BUTTON
, self
.OnFindDirClick
, self
._findDir
)
2114 flexGridSizer
.Add(self
._findDir
, 0, wx
.RIGHT
, 10)
2116 flexGridSizer
.Add(pythonPathStaticText
, 0, flag
=wx
.ALIGN_CENTER_VERTICAL|wx
.ALIGN_LEFT
)
2117 if os
.environ
.has_key('PYTHONPATH'):
2118 startval
= os
.environ
['PYTHONPATH']
2121 self
._lastPythonPath
= config
.Read("LastPythonPath", startval
)
2122 self
._pythonPathEntry
= wx
.TextCtrl(self
, -1, self
._lastPythonPath
)
2123 self
._pythonPathEntry
.SetToolTipString(self
._lastPythonPath
)
2124 flexGridSizer
.Add(self
._pythonPathEntry
, 1, wx
.EXPAND
)
2125 flexGridSizer
.Add(wx
.StaticText(parent
, -1, ""), 0)
2126 flexGridSizer
.Add(wx
.StaticText(parent
, -1, ""), 0)
2128 self
._postpendCheckBox
= wx
.CheckBox(self
, -1, postpendStaticText
)
2129 checked
= bool(config
.ReadInt("PythonPathPostpend", 1))
2130 self
._postpendCheckBox
.SetValue(checked
)
2131 flexGridSizer
.Add(self
._postpendCheckBox
, 1, wx
.EXPAND
)
2132 flexGridSizer
.Add(wx
.StaticText(parent
, -1, ""), 0)
2133 cpPanelBorderSizer
.Add(flexGridSizer
, 0, wx
.ALL
, 10)
2135 box
= wx
.BoxSizer(wx
.HORIZONTAL
)
2136 self
._okButton
= wx
.Button(self
, wx
.ID_OK
, okButtonName
)
2137 self
._okButton
.SetDefault()
2138 self
._okButton
.SetHelpText(_("The ") + okButtonName
+ _(" button completes the dialog"))
2139 box
.Add(self
._okButton
, 0, wx
.ALIGN_RIGHT|wx
.ALL
, 5)
2140 self
.Bind(wx
.EVT_BUTTON
, self
.OnOKClick
, self
._okButton
)
2141 btn
= wx
.Button(self
, wx
.ID_CANCEL
, _("Cancel"))
2142 btn
.SetHelpText(_("The Cancel button cancels the dialog."))
2143 box
.Add(btn
, 0, wx
.ALIGN_RIGHT|wx
.ALL
, 5)
2144 cpPanelBorderSizer
.Add(box
, 0, wx
.ALIGN_RIGHT|wx
.BOTTOM
, 5)
2146 self
.SetSizer(cpPanelBorderSizer
)
2148 self
.GetSizer().Fit(self
)
2152 # Set up selections based on last values used.
2153 self
._fileNameList
= None
2154 self
._selectedFileIndex
= 0
2155 lastProject
= config
.Read("LastRunProject")
2156 lastFile
= config
.Read("LastRunFile")
2158 if lastProject
in self
._projectNameList
:
2159 selectedIndex
= self
._projectNameList
.index(lastProject
)
2160 elif selectedIndex
< 0:
2162 self
._projList
.Select(selectedIndex
)
2163 self
._selectedProjectIndex
= selectedIndex
2164 self
._selectedProjectDocument
= self
._projectDocumentList
[selectedIndex
]
2165 self
.PopulateFileList(self
._selectedProjectDocument
, lastFile
)
2167 def OnOKClick(self
, event
):
2168 startIn
= self
._startEntry
.GetValue()
2169 fileToRun
= self
._fileList
.GetStringSelection()
2171 wx
.MessageBox(_("You must select a file to proceed. Note that not all projects have files that can be run or debugged."))
2173 isPython
= fileToRun
.endswith(self
._pyext
)
2174 if isPython
and not os
.path
.exists(startIn
):
2175 wx
.MessageBox(_("Starting directory does not exist. Please change this value."))
2177 config
= wx
.ConfigBase_Get()
2178 config
.Write("LastRunProject", self
._projectNameList
[self
._selectedProjectIndex
])
2179 config
.Write("LastRunFile", fileToRun
)
2180 # Don't update the arguments or starting directory unless we're runing python.
2182 config
.Write("LastRunArguments", self
._argsEntry
.GetValue())
2183 config
.Write("LastRunStartIn", self
._startEntry
.GetValue())
2184 config
.Write("LastPythonPath",self
._pythonPathEntry
.GetValue())
2185 if hasattr(self
, "_postpendCheckBox"):
2186 config
.WriteInt("PythonPathPostpend", int(self
._postpendCheckBox
.GetValue()))
2188 self
.EndModal(wx
.ID_OK
)
2190 def GetSettings(self
):
2191 filename
= self
._fileNameList
[self
._selectedFileIndex
]
2192 args
= self
._argsEntry
.GetValue()
2193 startIn
= self
._startEntry
.GetValue()
2194 isPython
= filename
.endswith(self
._pyext
)
2196 if hasattr(self
, "_postpendCheckBox"):
2197 postpend
= self
._postpendCheckBox
.GetValue()
2201 env
['PYTHONPATH'] = self
._pythonPathEntry
.GetValue() + os
.pathsep
+ os
.path
.join(os
.getcwd(), "3rdparty", "pywin32")
2203 env
['PYTHONPATH'] = self
._pythonPathEntry
.GetValue()
2205 return filename
, args
, startIn
, isPython
, env
2207 def OnFileSelected(self
, event
):
2208 self
._selectedFileIndex
= self
._fileList
.GetSelection()
2209 self
.EnableForFileType(event
.GetString())
2211 def EnableForFileType(self
, fileName
):
2212 show
= fileName
.endswith(self
._pyext
)
2213 self
._startEntry
.Enable(show
)
2214 self
._findDir
.Enable(show
)
2215 self
._argsEntry
.Enable(show
)
2218 self
._lastStartIn
= self
._startEntry
.GetValue()
2219 self
._startEntry
.SetValue("")
2220 self
._lastArguments
= self
._argsEntry
.GetValue()
2221 self
._argsEntry
.SetValue("")
2223 self
._startEntry
.SetValue(self
._lastStartIn
)
2224 self
._argsEntry
.SetValue(self
._lastArguments
)
2228 def OnFindDirClick(self
, event
):
2229 dlg
= wx
.DirDialog(self
, "Choose a starting directory:", self
._startEntry
.GetValue(),
2230 style
=wx
.DD_DEFAULT_STYLE|wx
.DD_NEW_DIR_BUTTON
)
2232 if dlg
.ShowModal() == wx
.ID_OK
:
2233 self
._startEntry
.SetValue(dlg
.GetPath())
2237 def EvtListBox(self
, event
):
2238 if event
.GetString():
2239 index
= self
._projectNameList
.index(event
.GetString())
2240 self
._selectedProjectDocument
= self
._projectDocumentList
[index
]
2241 self
._selectedProjectIndex
= index
2242 self
.PopulateFileList(self
._selectedProjectDocument
)
2244 def FilterFileList(self
, list):
2245 if self
._pythonOnly
:
2246 files
= filter(lambda f
: f
.endswith(self
._pyext
), list)
2248 files
= filter(lambda f
: (self
._pmext
and f
.endswith(self
._pmext
)) or f
.endswith(self
._pyext
), list)
2251 def PopulateFileList(self
, project
, shortNameToSelect
=None):
2252 self
._fileNameList
= self
.FilterFileList(project
.GetFiles()[:])
2253 self
._fileList
.Clear()
2254 if not self
._fileNameList
:
2256 self
._fileNameList
.sort(lambda a
, b
: cmp(os
.path
.basename(a
).lower(), os
.path
.basename(b
).lower()))
2257 strings
= map(lambda file: os
.path
.basename(file), self
._fileNameList
)
2258 for index
in range(0, len(strings
)):
2259 if shortNameToSelect
== strings
[index
]:
2260 self
._selectedFileIndex
= index
2262 self
._fileList
.Hide()
2263 self
._fileList
.AppendItems(strings
)
2264 self
._fileList
.Show()
2265 if self
._selectedFileIndex
not in range(0, len(strings
)) : self
._selectedFileIndex
= 0
2266 self
._fileList
.SetSelection(self
._selectedFileIndex
)
2267 self
.EnableForFileType(strings
[self
._selectedFileIndex
])
2269 def GetProjectList(self
):
2275 for document
in self
._projService
.GetDocumentManager().GetDocuments():
2276 if document
.GetDocumentTemplate().GetDocumentType() == ProjectEditor
.ProjectDocument
and len(document
.GetFiles()):
2277 docList
.append(document
)
2278 nameList
.append(os
.path
.basename(document
.GetFilename()))
2279 if document
== self
._currentProj
:
2283 #Check for open files not in any of these projects and add them to a default project
2284 def AlreadyInProject(fileName
):
2285 for projectDocument
in docList
:
2286 if projectDocument
.IsFileInProject(fileName
):
2290 unprojectedFiles
= []
2291 for document
in self
._projService
.GetDocumentManager().GetDocuments():
2292 if not ACTIVEGRID_BASE_IDE
and type(document
) == ProcessModelEditor
.ProcessModelDocument
:
2293 if not AlreadyInProject(document
.GetFilename()):
2294 unprojectedFiles
.append(document
.GetFilename())
2295 if type(document
) == PythonEditor
.PythonDocument
:
2296 if not AlreadyInProject(document
.GetFilename()):
2297 unprojectedFiles
.append(document
.GetFilename())
2299 if unprojectedFiles
:
2300 unprojProj
= ProjectEditor
.ProjectDocument()
2301 unprojProj
.SetFilename(_("Not in any Project"))
2302 unprojProj
.AddFiles(unprojectedFiles
)
2303 docList
.append(unprojProj
)
2304 nameList
.append(_("Not in any Project"))
2306 return nameList
, docList
, index
2309 #----------------------------------------------------------------------
2310 from wx
import ImageFromStream
, BitmapFromImage
2313 #----------------------------------------------------------------------
2316 '\x89PNG\r\n\x1a\n\x00\x00\x00\rIHDR\x00\x00\x00\x10\x00\x00\x00\x10\x08\x02\
2317 \x00\x00\x00\x90\x91h6\x00\x00\x00\x03sBIT\x08\x08\x08\xdb\xe1O\xe0\x00\x00\
2318 \x00\x85IDAT(\x91\xbd\x92A\x16\x03!\x08CI\xdf\xdc\x0b\x8e\xe6\xd1\xe0d\xe9\
2319 \x82\xd6\xc7(\x9di7\xfd\xab<\x14\x13Q\xb8\xbb\xfc\xc2\xe3\xd3\x82\x99\xb9\
2320 \xe9\xaeq\xe1`f)HF\xc4\x8dC2\x06\xbf\x8a4\xcf\x1e\x03K\xe5h\x1bH\x02\x98\xc7\
2321 \x03\x98\xa9z\x07\x00%\xd6\xa9\xd27\x90\xac\xbbk\xe5\x15I\xcdD$\xdc\xa7\xceT\
2322 5a\xce\xf3\xe4\xa0\xaa\x8bO\x12\x11\xabC\xcb\x9c}\xd57\xef\xb0\xf3\xb7\x86p\
2323 \x97\xf7\xb5\xaa\xde\xb9\xfa|-O\xbdjN\x9b\xf8\x06A\xcb\x00\x00\x00\x00IEND\
2326 def getBreakBitmap():
2327 return BitmapFromImage(getBreakImage())
2329 def getBreakImage():
2330 stream
= cStringIO
.StringIO(getBreakData())
2331 return ImageFromStream(stream
)
2334 return wx
.IconFromBitmap(getBreakBitmap())
2336 #----------------------------------------------------------------------
2338 def getClearOutputData():
2340 '\x89PNG\r\n\x1a\n\x00\x00\x00\rIHDR\x00\x00\x00\x10\x00\x00\x00\x10\x08\x06\
2341 \x00\x00\x00\x1f\xf3\xffa\x00\x00\x00\x04sBIT\x08\x08\x08\x08|\x08d\x88\x00\
2342 \x00\x00\xb7IDAT8\x8d\xa5\x93\xdd\x11\xc3 \x0c\x83%`\xa3\xee\xd4\xaeA\xc6\
2343 \xe8N\xedF%\xea\x03\t\x81\xf0\x97\xbb\xf8%G\xce\xfe\x90eC\x1a\x8b;\xe1\xf2\
2344 \x83\xd6\xa0Q2\x8de\xf5oW\xa05H\xea\xd7\x93\x84$\x18\xeb\n\x88;\'.\xd5\x1d\
2345 \x80\x07\xe1\xa1\x1d\xa2\x1cbF\x92\x0f\x80\xe0\xd1 \xb7\x14\x8c \x00*\x15\
2346 \x97\x14\x8c\x8246\x1a\xf8\x98\'/\xdf\xd8Jn\xe65\xc0\xa7\x90_L"\x01\xde\x9d\
2347 \xda\xa7\x92\xfb\xc5w\xdf\t\x07\xc4\x05ym{\xd0\x1a\xe3\xb9xS\x81\x04\x18\x05\
2348 \xc9\x04\xc9a\x00Dc9\x9d\x82\xa4\xbc\xe8P\xb2\xb5P\xac\xf2\x0c\xd4\xf5\x00\
2349 \x88>\xac\xe17\x84\xe4\xb9G\x8b7\x9f\xf3\x1fsUl^\x7f\xe7y\x0f\x00\x00\x00\
2352 def getClearOutputBitmap():
2353 return BitmapFromImage(getClearOutputImage())
2355 def getClearOutputImage():
2356 stream
= cStringIO
.StringIO(getClearOutputData())
2357 return ImageFromStream(stream
)
2359 def getClearOutputIcon():
2360 return wx
.IconFromBitmap(getClearOutputBitmap())
2362 #----------------------------------------------------------------------
2365 '\x89PNG\r\n\x1a\n\x00\x00\x00\rIHDR\x00\x00\x00\x10\x00\x00\x00\x10\x08\x02\
2366 \x00\x00\x00\x90\x91h6\x00\x00\x00\x03sBIT\x08\x08\x08\xdb\xe1O\xe0\x00\x00\
2367 \x00\xedIDAT(\x91\xa5\x90!\xae\x840\x10\x86g_\xd6"*kz\x82j\xb0h\x1c\t\' x\
2368 \x92Z\xc2\x05\x10\x95\x18\x0e\x00\x02M\x82 \xe1\nMF#jz\x80\xea&+\x9a\x10\x96\
2369 \xdd}\xfb\xc8\x1b\xd7?\xdf\x97\xfe3\xb7u]\xe1\xca\xfc\\\xa2\xff- \xe24M\xc7\
2370 \xc49wJ\xee\xc7G]\xd7\x8c1\xc6\x18\xe7\xdc\'B\x08k\xed1y\xfaa\x1cG\xad\xb5\
2371 \x94\x12\x11\x9dsy\x9e+\xa5\x84\x10;\r\x00\xb7\xd3\x95\x8c1UU\x05A\x00\x00\
2372 \xd6\xda,\xcb\x92$\xf9\xb8\x03\x00PJ\x85\x10Zk\xa5\xd4+\xfdF\x00\x80\xae\xeb\
2373 \x08!\x84\x90y\x9e\x11\xf1\x8bP\x96\xa5\xef\xdd\xb6\xad\xb5VJ\xf9\x9b\xe0\
2374 \xe9\xa6i8\xe7\xbe\xdb\xb6mi\x9a\x0e\xc3\xf0F\x88\xe3\x18\x00\xfa\xbe\x0f\
2375 \xc3\xd0\'\x9c\xf3eY\xa2(*\x8ab\xc7\x9e\xaed\x8c\xa1\x94\xben\xf5\xb1\xd2W\
2376 \xfa,\xfce.\x0b\x0f\xb8\x96e\x90gS\xe0v\x00\x00\x00\x00IEND\xaeB`\x82'
2378 def getCloseBitmap():
2379 return BitmapFromImage(getCloseImage())
2381 def getCloseImage():
2382 stream
= cStringIO
.StringIO(getCloseData())
2383 return ImageFromStream(stream
)
2386 return wx
.IconFromBitmap(getCloseBitmap())
2388 #----------------------------------------------------------------------
2389 def getContinueData():
2391 '\x89PNG\r\n\x1a\n\x00\x00\x00\rIHDR\x00\x00\x00\x10\x00\x00\x00\x10\x08\x06\
2392 \x00\x00\x00\x1f\xf3\xffa\x00\x00\x00\x04sBIT\x08\x08\x08\x08|\x08d\x88\x00\
2393 \x00\x00\xcdIDAT8\x8d\xa5\x93\xd1\r\xc20\x0cD\xef\xec,\xc0b\x88\x8d`$\x06Cb\
2394 \x81\xc6\xc7GI\xeb\x94RZq?U"\xdby\xe7SIs\xfc#\xfbU\xa0\xa8\xba\xc6\xa0og\xee\
2395 !P\xd4y\x80\x04\xf3\xc2U\x82{\x9ct\x8f\x93\xb0\xa2\xdbm\xf5\xba\'h\xcdg=`\
2396 \xeeTT\xd1\xc6o& \t\x9a\x13\x00J\x9ev\xb1\'\xa3~\x14+\xbfN\x12\x92\x00@\xe6\
2397 \x85\xdd\x00\x000w\xe6\xe2\xde\xc7|\xdf\x08\xba\x1d(\xaa2n+\xca\xcd\x8d,\xea\
2398 \x98\xc4\x07\x01\x00D\x1dd^\xa8\xa8j\x9ew\xed`\xa9\x16\x99\xde\xa6G\x8b\xd3Y\
2399 \xe6\x85]\n\r\x7f\x99\xf5\x96Jnlz#\xab\xdb\xc1\x17\x19\xb0XV\xc2\xdf\xa3)\
2400 \x85<\xe4\x88\x85.F\x9a\xf3H3\xb0\xf3g\xda\xd2\x0b\xc5_|\x17\xe8\xf5R\xd6\
2401 \x00\x00\x00\x00IEND\xaeB`\x82'
2403 def getContinueBitmap():
2404 return BitmapFromImage(getContinueImage())
2406 def getContinueImage():
2407 stream
= cStringIO
.StringIO(getContinueData())
2408 return ImageFromStream(stream
)
2410 def getContinueIcon():
2411 return wx
.IconFromBitmap(getContinueBitmap())
2413 #----------------------------------------------------------------------
2416 '\x89PNG\r\n\x1a\n\x00\x00\x00\rIHDR\x00\x00\x00\x10\x00\x00\x00\x10\x08\x06\
2417 \x00\x00\x00\x1f\xf3\xffa\x00\x00\x00\x04sBIT\x08\x08\x08\x08|\x08d\x88\x00\
2418 \x00\x00\x8eIDAT8\x8d\xa5SA\x12\xc4 \x08K\xb0\xff\xde\xe9\xbf\xb7\xa6\x87\
2419 \x1d:\xba\xa2tZn(\x84`"i\x05obk\x13\xd5CmN+\xcc\x00l\xd6\x0c\x00\xf5\xf8\x0e\
2420 gK\x06\x00 \xa5=k\x00\x00\xb0\xb2]\xd4?5f\xb1\xdb\xaf\xc6\xa2\xcb\xa8\xf0?\
2421 \x1c\x98\xae\x82\xbf\x81\xa4\x8eA\x16\xe1\n\xd1\xa4\x19\xb3\xe9\n\xce\xe8\
2422 \xf1\n\x9eg^\x18\x18\x90\xec<\x11\xf9#\x04XMZ\x19\xaac@+\x94\xd4\x99)SeP\xa1\
2423 )\xd6\x1dI\xe7*\xdc\xf4\x03\xdf~\xe7\x13T^Q?:X\x19d\x00\x00\x00\x00IEND\xaeB\
2426 def getNextBitmap():
2427 return BitmapFromImage(getNextImage())
2430 stream
= cStringIO
.StringIO(getNextData())
2431 return ImageFromStream(stream
)
2434 return wx
.IconFromBitmap(getNextBitmap())
2436 #----------------------------------------------------------------------
2437 def getStepInData():
2439 '\x89PNG\r\n\x1a\n\x00\x00\x00\rIHDR\x00\x00\x00\x10\x00\x00\x00\x10\x08\x06\
2440 \x00\x00\x00\x1f\xf3\xffa\x00\x00\x00\x04sBIT\x08\x08\x08\x08|\x08d\x88\x00\
2441 \x00\x00\x87IDAT8\x8d\xadSA\x12\x84 \x0ck\x8a\xffv\xfc\xb74{X\xeb0P@\x07s\
2442 \x84\xa4$\x01\x00M\xb2\x02]R\x8b\xc86\xda\xdc\xedd\xb4~\xe8\x86\xc6\x01-\x93\
2443 \x96\xd9#\xf6\x06\xc3;p1I\xd1\x14\x0b#|\x17aF\xec\r\xeeF\xa0eB\xd34\xca\xd0A\
2444 ]j\x84\xa6\x03\x00""\xb7\xb0tRZ\xf7x\xb7\x83\x91]\xcb\x7fa\xd9\x89\x0fC\xfd\
2445 \x94\x9d|9\x99^k\x13\xa1 \xb3\x16\x0f#\xd4\x88N~\x14\xe1-\x96\x7f\xe3\x0f\
2446 \x11\x91UC\x0cX\'\x1e\x00\x00\x00\x00IEND\xaeB`\x82'
2448 def getStepInBitmap():
2449 return BitmapFromImage(getStepInImage())
2451 def getStepInImage():
2452 stream
= cStringIO
.StringIO(getStepInData())
2453 return ImageFromStream(stream
)
2455 def getStepInIcon():
2456 return wx
.IconFromBitmap(getStepInBitmap())
2458 #----------------------------------------------------------------------
2461 '\x89PNG\r\n\x1a\n\x00\x00\x00\rIHDR\x00\x00\x00\x10\x00\x00\x00\x10\x08\x06\
2462 \x00\x00\x00\x1f\xf3\xffa\x00\x00\x00\x04sBIT\x08\x08\x08\x08|\x08d\x88\x00\
2463 \x00\x00QIDAT8\x8d\xdd\x93A\n\xc00\x08\x04g\xb5\xff\x7fq\x13sn\xda&\x01\x0b\
2464 \xa5]\xf0"\xec(.J\xe6dd)\xf7\x13\x80\xadoD-12\xc8\\\xd3\r\xe2\xa6\x00j\xd9\
2465 \x0f\x03\xde\xbf\xc1\x0f\x00\xa7\x18\x01t\xd5\\\x05\xc8\\}T#\xe9\xfb\xbf\x90\
2466 \x064\xd8\\\x12\x1fQM\xf5\xd9\x00\x00\x00\x00IEND\xaeB`\x82'
2468 def getStopBitmap():
2469 return BitmapFromImage(getStopImage())
2472 stream
= cStringIO
.StringIO(getStopData())
2473 return ImageFromStream(stream
)
2476 return wx
.IconFromBitmap(getStopBitmap())
2478 #----------------------------------------------------------------------
2479 def getStepReturnData():
2481 "\x89PNG\r\n\x1a\n\x00\x00\x00\rIHDR\x00\x00\x00\x10\x00\x00\x00\x10\x08\x06\
2482 \x00\x00\x00\x1f\xf3\xffa\x00\x00\x00\x04sBIT\x08\x08\x08\x08|\x08d\x88\x00\
2483 \x00\x00\x8dIDAT8\x8d\xa5S\xd1\x0e\xc4 \x08\xa3\xb0\xff\xbe\xdc\x7fO\xba'6\
2484 \xf1\xf44\xb3O$Phk\x04\xd4d\x07\xba\xc5\x16\x91#\nza\xdb\x84\x1a\xa2\xfe\xf8\
2485 \x99\xfa_=p+\xe8\x91ED\xbc<\xa4 \xb4\x0b\x01\xb5{\x01\xf9\xbbG-\x13\x87\x16f\
2486 \x84\xbf\x16V\xb0l\x01@\no\x86\xae\x82Q\xa8=\xa4\x0c\x80\xe70\xbd\x10jh\xbd\
2487 \x07R\x06#\xc9^N\xb6\xde\x03)\x83\x18\xaeU\x90\x9c>a\xb2P\r\xb3&/Y\xa8\xd1^^\
2488 \xb6\xf0\x16\xdb\xbf\xf1\x02\x81\xa5TK\x1d\x07\xde\x92\x00\x00\x00\x00IEND\
2491 def getStepReturnBitmap():
2492 return BitmapFromImage(getStepReturnImage())
2494 def getStepReturnImage():
2495 stream
= cStringIO
.StringIO(getStepReturnData())
2496 return ImageFromStream(stream
)
2498 def getStepReturnIcon():
2499 return wx
.IconFromBitmap(getStepReturnBitmap())
2501 #----------------------------------------------------------------------
2502 def getAddWatchData():
2504 '\x89PNG\r\n\x1a\n\x00\x00\x00\rIHDR\x00\x00\x00\x10\x00\x00\x00\x10\x08\x06\
2505 \x00\x00\x00\x1f\xf3\xffa\x00\x00\x00\x04sBIT\x08\x08\x08\x08|\x08d\x88\x00\
2506 \x00\x00\x85IDAT8\x8dc`\x18h\xc0\x88.\xd0\xc0\xf0\xff?*\x9f\x11C\rN\x80\xae\
2507 \x19\x97\x18\xd1\x9a\x896\x84\x18[p\xa9aA\xe6\xfc7f\xc0P\xc4x\x163\x9cp\x1a0\
2508 \xeb,!w\x100 \x1dK\xac\x10\r\x08\x05".yFL\x85\x8c\x18b\xa8|Ty\xa2\x13\x92\'\
2509 \xc3\xe4\xff\x9f\x18\x1e3\xb82t\xa2\x88\x13\xedg.\x06aa&\x06VV\x7f\x86\xb9\
2510 \xcfU\x19\xbc\xb0\xba\x86h\xe0\xc8\xd0\xfc\xbf\x80\xe1>q)\x94\xe6\x00\x00\
2511 \x85\x923_\xd22\xa4\xcd\x00\x00\x00\x00IEND\xaeB`\x82'
2513 def getAddWatchBitmap():
2514 return BitmapFromImage(getAddWatchImage())
2516 def getAddWatchImage():
2517 stream
= cStringIO
.StringIO(getAddWatchData())
2518 return ImageFromStream(stream
)
2520 def getAddWatchIcon():
2521 return wx
.IconFromBitmap(getAddWatchBitmap())