1 #----------------------------------------------------------------------------
2 # Name: DebuggerService.py
3 # Purpose: Debugger Service for Python and PHP
9 # Copyright: (c) 2004-2005 ActiveGrid, Inc.
10 # License: wxWindows License
11 #----------------------------------------------------------------------------
19 import wx
.lib
.pydocview
26 import activegrid
.model
.projectmodel
as projectmodel
27 from IDE
import ACTIVEGRID_BASE_IDE
28 if not ACTIVEGRID_BASE_IDE
:
29 import ProcessModelEditor
30 import wx
.lib
.scrolledpanel
as scrolled
33 import SimpleXMLRPCServer
41 from xml
.dom
.minidom
import parse
, parseString
44 import DebuggerHarness
48 import activegrid
.util
.sysutils
as sysutilslib
52 if wx
.Platform
== '__WXMSW__':
55 _PYWIN32_INSTALLED
= True
57 _PYWIN32_INSTALLED
= False
62 if not _WINDOWS
or _PYWIN32_INSTALLED
:
70 import wx
.lib
.newevent
71 (UpdateTextEvent
, EVT_UPDATE_STDTEXT
) = wx
.lib
.newevent
.NewEvent()
72 (UpdateErrorEvent
, EVT_UPDATE_ERRTEXT
) = wx
.lib
.newevent
.NewEvent()
73 (DebugInternalWebServer
, EVT_DEBUG_INTERNAL
) = wx
.lib
.newevent
.NewEvent()
75 # Class to read from stdout or stderr and write the result to a text control.
76 # Args: file=file-like object
77 # callback_function= function that takes a single argument, the line of text
79 class OutputReaderThread(threading
.Thread
):
80 def __init__(self
, file, callback_function
, callbackOnExit
=None, accumulate
=True):
81 threading
.Thread
.__init
__(self
)
83 self
._callback
_function
= callback_function
84 self
._keepGoing
= True
86 self
._accumulate
= accumulate
87 self
._callbackOnExit
= callbackOnExit
91 # See comment on PythonDebuggerUI.StopExecution
92 self
._keepGoing
= False
98 while self
._keepGoing
:
100 # This could block--how to handle that?
101 text
= file.readline()
102 if text
== '' or text
== None:
103 self
._keepGoing
= False
104 elif not self
._accumulate
and self
._keepGoing
:
105 self
._callback
_function
(text
)
107 # Should use a buffer? StringIO?
109 # Seems as though the read blocks if we got an error, so, to be
110 # sure that at least some of the exception gets printed, always
111 # send the first hundred lines back as they come in.
112 if self
._lineCount
< 100 and self
._keepGoing
:
113 self
._callback
_function
(output
)
116 elif time
.time() - start
> 0.25 and self
._keepGoing
:
118 self
._callback
_function
(output
)
119 except wx
._core
.PyDeadObjectError
:
120 # GUI was killed while we were blocked.
121 self
._keepGoing
= False
127 tp
, val
, tb
= sys
.exc_info()
128 print "Exception in OutputReaderThread.run():", tp
, val
129 self
._keepGoing
= False
130 if self
._callbackOnExit
:
132 self
._callbackOnExit
()
133 except wx
._core
.PyDeadObjectError
:
135 if _VERBOSE
: print "Exiting OutputReaderThread"
138 self
._keepGoing
= False
142 PHP_CGI_BIN_PATH_WIN
= "../../3rdparty/php"
143 PHP_CGI_BIN_PATH_UNIX
= "../../../3rdparty/php/bin"
144 PHP_CGI_BIN_PATH_OSX
= "../3rdparty/php/bin"
145 PHP_CGI_EXEC_WIN
= "php-cgi.exe"
146 PHP_CGI_EXEC_UNIX
= "php"
147 PHP_CGI_EXEC_OSX
= "php-cgi"
149 def GetPythonExecutablePath():
150 path
= UICommon
.GetPythonExecPath()
153 wx
.MessageBox(_("To proceed we 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"))
155 GetPythonExecutablePath
= staticmethod(GetPythonExecutablePath
)
157 def GetPHPExecutablePath():
158 if sysutilslib
.isWindows():
159 phpCgiBinPath
= Executor
.PHP_CGI_BIN_PATH_WIN
160 phpCgiExec
= Executor
.PHP_CGI_EXEC_WIN
161 elif sys
.platform
== "darwin":
162 phpCgiBinPath
= Executor
.PHP_CGI_BIN_PATH_OSX
163 phpCgiExec
= Executor
.PHP_CGI_EXEC_OSX
165 phpCgiBinPath
= Executor
.PHP_CGI_BIN_PATH_UNIX
166 phpCgiExec
= Executor
.PHP_CGI_EXEC_UNIX
168 if sysutilslib
.isRelease():
169 phpCgiExecFullPath
= os
.path
.normpath(os
.path
.join(sysutilslib
.mainModuleDir
, phpCgiBinPath
, phpCgiExec
))
171 phpCgiExecFullPath
= phpCgiExec
174 print "php cgi executable full path is: %s" % phpCgiExecFullPath
176 return phpCgiExecFullPath
177 GetPHPExecutablePath
= staticmethod(GetPHPExecutablePath
)
179 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):
180 self
._fileName
= fileName
181 self
._stdOutCallback
= self
.OutCall
182 self
._stdErrCallback
= self
.ErrCall
183 self
._callbackOnExit
= callbackOnExit
184 self
._wxComponent
= wxComponent
185 if fileName
.endswith('.py') or fileName
.endswith('.pyc'):
186 self
._path
= Executor
.GetPythonExecutablePath()
187 self
._cmd
= '"' + self
._path
+ '" -u \"' + fileName
+ '\"'
189 self
._path
= Executor
.GetPHPExecutablePath()
190 self
._cmd
= '"' + self
._path
+ '"'
191 #Better way to do this? Quotes needed for windows file paths.
192 def spaceAndQuote(text
):
193 if text
.startswith("\"") and text
.endswith("\""):
196 return ' \"' + text
+ '\"'
198 self
._cmd
+= spaceAndQuote(arg1
)
200 self
._cmd
+= spaceAndQuote(arg2
)
202 self
._cmd
+= spaceAndQuote(arg3
)
204 self
._cmd
+= spaceAndQuote(arg4
)
206 self
._cmd
+= spaceAndQuote(arg5
)
208 self
._cmd
+= spaceAndQuote(arg6
)
210 self
._cmd
+= spaceAndQuote(arg7
)
212 self
._cmd
+= spaceAndQuote(arg8
)
214 self
._cmd
+= spaceAndQuote(arg9
)
216 self
._stdOutReader
= None
217 self
._stdErrReader
= None
220 def OutCall(self
, text
):
221 evt
= UpdateTextEvent(value
= text
)
222 wx
.PostEvent(self
._wxComponent
, evt
)
224 def ErrCall(self
, text
):
225 evt
= UpdateErrorEvent(value
= text
)
226 wx
.PostEvent(self
._wxComponent
, evt
)
228 def Execute(self
, arguments
, startIn
=None, environment
=None):
230 startIn
= str(os
.getcwd())
231 startIn
= os
.path
.abspath(startIn
)
233 if arguments
and arguments
!= " ":
234 command
= self
._cmd
+ ' ' + arguments
238 if _VERBOSE
: print "start debugger executable: " + command
+ "\n"
239 self
._process
= process
.ProcessOpen(command
, mode
='b', cwd
=startIn
, env
=environment
)
240 # Kick off threads to read stdout and stderr and write them
241 # to our text control.
242 self
._stdOutReader
= OutputReaderThread(self
._process
.stdout
, self
._stdOutCallback
, callbackOnExit
=self
._callbackOnExit
)
243 self
._stdOutReader
.start()
244 self
._stdErrReader
= OutputReaderThread(self
._process
.stderr
, self
._stdErrCallback
, accumulate
=False)
245 self
._stdErrReader
.start()
247 def DoStopExecution(self
):
248 # See comment on PythonDebuggerUI.StopExecution
249 if(self
._process
!= None):
250 self
._stdOutReader
.AskToStop()
251 self
._stdErrReader
.AskToStop()
253 self
._process
.kill(gracePeriod
=2.0)
258 def GetExecPath(self
):
261 class RunCommandUI(wx
.Panel
):
264 def ShutdownAllRunners():
265 # See comment on PythonDebuggerUI.StopExecution
266 for runner
in RunCommandUI
.runners
:
268 runner
.StopExecution(None)
269 except wx
._core
.PyDeadObjectError
:
271 RunCommandUI
.runners
= []
272 ShutdownAllRunners
= staticmethod(ShutdownAllRunners
)
274 def __init__(self
, parent
, id, fileName
):
275 wx
.Panel
.__init
__(self
, parent
, id)
276 self
._noteBook
= parent
278 threading
._VERBOSE
= _VERBOSE
280 self
.KILL_PROCESS_ID
= wx
.NewId()
281 self
.CLOSE_TAB_ID
= wx
.NewId()
284 # GUI Initialization follows
285 sizer
= wx
.BoxSizer(wx
.HORIZONTAL
)
286 self
._tb
= tb
= wx
.ToolBar(self
, -1, wx
.DefaultPosition
, (30,1000), wx
.TB_VERTICAL| wx
.TB_FLAT
, "Runner" )
287 tb
.SetToolBitmapSize((16,16))
288 sizer
.Add(tb
, 0, wx
.EXPAND|wx
.ALIGN_LEFT|wx
.ALL
, 1)
290 close_bmp
= getCloseBitmap()
291 tb
.AddSimpleTool( self
.CLOSE_TAB_ID
, close_bmp
, _('Close Window'))
292 wx
.EVT_TOOL(self
, self
.CLOSE_TAB_ID
, self
.OnToolClicked
)
294 stop_bmp
= getStopBitmap()
295 tb
.AddSimpleTool(self
.KILL_PROCESS_ID
, stop_bmp
, _("Stop the Run."))
296 wx
.EVT_TOOL(self
, self
.KILL_PROCESS_ID
, self
.OnToolClicked
)
299 self
._textCtrl
= STCTextEditor
.TextCtrl(self
, wx
.NewId()) #id)
300 sizer
.Add(self
._textCtrl
, 1, wx
.ALIGN_LEFT|wx
.ALL|wx
.EXPAND
, 1)
301 self
._textCtrl
.SetViewLineNumbers(False)
302 self
._textCtrl
.SetReadOnly(True)
303 if wx
.Platform
== '__WXMSW__':
307 self
._textCtrl
.SetFont(wx
.Font(9, wx
.DEFAULT
, wx
.NORMAL
, wx
.NORMAL
, faceName
= font
))
308 self
._textCtrl
.SetFontColor(wx
.BLACK
)
309 self
._textCtrl
.StyleClearAll()
311 wx
.stc
.EVT_STC_DOUBLECLICK(self
._textCtrl
, self
._textCtrl
.GetId(), self
.OnDoubleClick
)
316 self
._stopped
= False
317 # Executor initialization
318 self
._executor
= Executor(fileName
, self
, callbackOnExit
=self
.ExecutorFinished
)
319 self
.Bind(EVT_UPDATE_STDTEXT
, self
.AppendText
)
320 self
.Bind(EVT_UPDATE_ERRTEXT
, self
.AppendErrorText
)
322 RunCommandUI
.runners
.append(self
)
325 # See comment on PythonDebuggerUI.StopExecution
326 self
._executor
.DoStopExecution()
328 def Execute(self
, initialArgs
, startIn
, environment
, onWebServer
= False):
329 self
._executor
.Execute(initialArgs
, startIn
, environment
)
331 def ExecutorFinished(self
):
332 self
._tb
.EnableTool(self
.KILL_PROCESS_ID
, False)
333 nb
= self
.GetParent()
334 for i
in range(0,nb
.GetPageCount()):
335 if self
== nb
.GetPage(i
):
336 text
= nb
.GetPageText(i
)
337 newText
= text
.replace("Running", "Finished")
338 nb
.SetPageText(i
, newText
)
341 def StopExecution(self
):
342 if not self
._stopped
:
344 self
.Unbind(EVT_UPDATE_STDTEXT
)
345 self
.Unbind(EVT_UPDATE_ERRTEXT
)
346 self
._executor
.DoStopExecution()
348 def AppendText(self
, event
):
349 self
._textCtrl
.SetReadOnly(False)
350 self
._textCtrl
.AddText(event
.value
)
351 self
._textCtrl
.ScrollToLine(self
._textCtrl
.GetLineCount())
352 self
._textCtrl
.SetReadOnly(True)
354 def AppendErrorText(self
, event
):
355 self
._textCtrl
.SetReadOnly(False)
356 self
._textCtrl
.SetFontColor(wx
.RED
)
357 self
._textCtrl
.StyleClearAll()
358 self
._textCtrl
.AddText(event
.value
)
359 self
._textCtrl
.ScrollToLine(self
._textCtrl
.GetLineCount())
360 self
._textCtrl
.SetFontColor(wx
.BLACK
)
361 self
._textCtrl
.StyleClearAll()
362 self
._textCtrl
.SetReadOnly(True)
364 def StopAndRemoveUI(self
, event
):
367 index
= self
._noteBook
.GetSelection()
368 self
._noteBook
.GetPage(index
).Show(False)
369 self
._noteBook
.RemovePage(index
)
371 #------------------------------------------------------------------------------
373 #-----------------------------------------------------------------------------
375 def OnToolClicked(self
, event
):
378 if id == self
.KILL_PROCESS_ID
:
381 elif id == self
.CLOSE_TAB_ID
:
382 self
.StopAndRemoveUI(event
)
384 def OnDoubleClick(self
, event
):
385 # Looking for a stack trace line.
386 lineText
, pos
= self
._textCtrl
.GetCurLine()
387 fileBegin
= lineText
.find("File \"")
388 fileEnd
= lineText
.find("\", line ")
389 lineEnd
= lineText
.find(", in ")
390 if lineText
== "\n" or fileBegin
== -1 or fileEnd
== -1 or lineEnd
== -1:
391 # Check the line before the one that was clicked on
392 lineNumber
= self
._textCtrl
.GetCurrentLine()
395 lineText
= self
._textCtrl
.GetLine(lineNumber
- 1)
396 fileBegin
= lineText
.find("File \"")
397 fileEnd
= lineText
.find("\", line ")
398 lineEnd
= lineText
.find(", in ")
399 if lineText
== "\n" or fileBegin
== -1 or fileEnd
== -1 or lineEnd
== -1:
402 filename
= lineText
[fileBegin
+ 6:fileEnd
]
403 lineNum
= int(lineText
[fileEnd
+ 8:lineEnd
])
406 openDocs
= wx
.GetApp().GetDocumentManager().GetDocuments()
407 for openDoc
in openDocs
:
408 if openDoc
.GetFilename() == filename
:
409 foundView
= openDoc
.GetFirstView()
413 doc
= wx
.GetApp().GetDocumentManager().CreateDocument(filename
, wx
.lib
.docview
.DOC_SILENT
)
414 foundView
= doc
.GetFirstView()
417 foundView
.GetFrame().SetFocus()
419 foundView
.GotoLine(lineNum
)
420 startPos
= foundView
.PositionFromLine(lineNum
)
421 lineText
= foundView
.GetCtrl().GetLine(lineNum
- 1)
422 foundView
.SetSelection(startPos
, startPos
+ len(lineText
.rstrip("\n")))
423 import OutlineService
424 wx
.GetApp().GetService(OutlineService
.OutlineService
).LoadOutline(foundView
, position
=startPos
)
428 DEFAULT_HOST
= 'localhost'
431 class BaseDebuggerUI(wx
.Panel
):
434 def NotifyDebuggersOfBreakpointChange():
435 for debugger
in BaseDebuggerUI
.debuggers
:
436 debugger
.BreakPointChange()
438 NotifyDebuggersOfBreakpointChange
= staticmethod(NotifyDebuggersOfBreakpointChange
)
440 def DebuggerRunning():
441 for debugger
in BaseDebuggerUI
.debuggers
:
442 if debugger
._executor
:
445 DebuggerRunning
= staticmethod(DebuggerRunning
)
447 def DebuggerInWait():
448 for debugger
in BaseDebuggerUI
.debuggers
:
449 if debugger
._executor
:
450 if debugger
._callback
._waiting
:
453 DebuggerInWait
= staticmethod(DebuggerInWait
)
455 def DebuggerPastAutoContinue():
456 for debugger
in BaseDebuggerUI
.debuggers
:
457 if debugger
._executor
:
458 if debugger
._callback
._waiting
and not debugger
._callback
._autoContinue
:
461 DebuggerPastAutoContinue
= staticmethod(DebuggerPastAutoContinue
)
463 def ShutdownAllDebuggers():
464 for debugger
in BaseDebuggerUI
.debuggers
:
466 debugger
.StopExecution(None)
467 except wx
._core
.PyDeadObjectError
:
469 BaseDebuggerUI
.debuggers
= []
470 ShutdownAllDebuggers
= staticmethod(ShutdownAllDebuggers
)
472 def __init__(self
, parent
, id):
473 wx
.Panel
.__init
__(self
, parent
, id)
474 self
._parentNoteBook
= parent
477 self
._executor
= None
478 self
._callback
= None
479 self
._stopped
= False
481 BaseDebuggerUI
.debuggers
.append(self
)
483 self
.Bind(EVT_UPDATE_STDTEXT
, self
.AppendText
)
484 self
.Bind(EVT_UPDATE_ERRTEXT
, self
.AppendErrorText
)
485 self
._executor
= None
487 self
.STEP_ID
= wx
.NewId()
488 self
.CONTINUE_ID
= wx
.NewId()
489 self
.STEP_OUT_ID
= wx
.NewId()
490 self
.NEXT_ID
= wx
.NewId()
491 self
.KILL_PROCESS_ID
= wx
.NewId()
492 self
.CLOSE_WINDOW_ID
= wx
.NewId()
493 self
.BREAK_INTO_DEBUGGER_ID
= wx
.NewId()
494 self
.CLEAR_ID
= wx
.NewId()
495 self
.ADD_WATCH_ID
= wx
.NewId()
496 sizer
= wx
.BoxSizer(wx
.VERTICAL
)
497 self
._tb
= tb
= wx
.ToolBar(self
, -1, wx
.DefaultPosition
, (1000,30), wx
.TB_HORIZONTAL| wx
.NO_BORDER| wx
.TB_FLAT| wx
.TB_TEXT
, "Debugger" )
498 sizer
.Add(tb
, 0, wx
.EXPAND |wx
.ALIGN_LEFT|wx
.ALL
, 1)
499 tb
.SetToolBitmapSize((16,16))
501 close_bmp
= getCloseBitmap()
502 tb
.AddSimpleTool( self
.CLOSE_WINDOW_ID
, close_bmp
, _('Close Window'))
503 wx
.EVT_TOOL(self
, self
.CLOSE_WINDOW_ID
, self
.StopAndRemoveUI
)
505 stop_bmp
= getStopBitmap()
506 tb
.AddSimpleTool( self
.KILL_PROCESS_ID
, stop_bmp
, _("Stop Debugging"))
507 wx
.EVT_TOOL(self
, self
.KILL_PROCESS_ID
, self
.StopExecution
)
511 break_bmp
= getBreakBitmap()
512 tb
.AddSimpleTool( self
.BREAK_INTO_DEBUGGER_ID
, break_bmp
, _("Break into Debugger"))
513 wx
.EVT_TOOL(self
, self
.BREAK_INTO_DEBUGGER_ID
, self
.BreakExecution
)
517 continue_bmp
= getContinueBitmap()
518 tb
.AddSimpleTool( self
.CONTINUE_ID
, continue_bmp
, _("Continue Execution"))
519 wx
.EVT_TOOL(self
, self
.CONTINUE_ID
, self
.OnContinue
)
520 self
.Bind(EVT_DEBUG_INTERNAL
, self
.OnContinue
)
523 next_bmp
= getNextBitmap()
524 tb
.AddSimpleTool( self
.NEXT_ID
, next_bmp
, _("Step to next line"))
525 wx
.EVT_TOOL(self
, self
.NEXT_ID
, self
.OnNext
)
527 step_bmp
= getStepInBitmap()
528 tb
.AddSimpleTool( self
.STEP_ID
, step_bmp
, _("Step in"))
529 wx
.EVT_TOOL(self
, self
.STEP_ID
, self
.OnSingleStep
)
531 stepOut_bmp
= getStepReturnBitmap()
532 tb
.AddSimpleTool(self
.STEP_OUT_ID
, stepOut_bmp
, _("Stop at function return"))
533 wx
.EVT_TOOL(self
, self
.STEP_OUT_ID
, self
.OnStepOut
)
537 watch_bmp
= getAddWatchBitmap()
538 tb
.AddSimpleTool(self
.ADD_WATCH_ID
, watch_bmp
, _("Add a watch"))
539 wx
.EVT_TOOL(self
, self
.ADD_WATCH_ID
, self
.OnAddWatch
)
542 clear_bmp
= getClearOutputBitmap()
543 tb
.AddSimpleTool(self
.CLEAR_ID
, clear_bmp
, _("Clear output pane"))
544 wx
.EVT_TOOL(self
, self
.CLEAR_ID
, self
.OnClearOutput
)
546 self
._toolEnabled
= True
547 self
.framesTab
= None
548 self
.DisableWhileDebuggerRunning()
549 self
.framesTab
= self
.MakeFramesUI(self
, wx
.NewId(), None)
550 sizer
.Add(self
.framesTab
, 1, wx
.ALIGN_LEFT|wx
.ALL|wx
.EXPAND
, 1)
551 self
._statusBar
= wx
.StatusBar( self
, -1)
552 self
._statusBar
.SetFieldsCount(1)
553 sizer
.Add(self
._statusBar
, 0, wx
.EXPAND |wx
.ALIGN_LEFT|wx
.ALL
, 1)
554 self
.SetStatusText("Starting debug...")
559 def OnSingleStep(self
, event
):
560 self
._callback
.SingleStep()
562 def OnContinue(self
, event
):
563 self
._callback
.Continue()
565 def OnStepOut(self
, event
):
566 self
._callback
.Return()
568 def OnNext(self
, event
):
569 self
._callback
.Next()
571 def BreakPointChange(self
):
572 if not self
._stopped
:
573 self
._callback
.PushBreakpoints()
574 self
.framesTab
.PopulateBPList()
577 # See comment on PythonDebuggerUI.StopExecution
578 self
.StopExecution(None)
580 def DisableWhileDebuggerRunning(self
):
581 if self
._toolEnabled
:
582 self
._tb
.EnableTool(self
.STEP_ID
, False)
583 self
._tb
.EnableTool(self
.CONTINUE_ID
, False)
584 self
._tb
.EnableTool(self
.STEP_OUT_ID
, False)
585 self
._tb
.EnableTool(self
.NEXT_ID
, False)
586 self
._tb
.EnableTool(self
.BREAK_INTO_DEBUGGER_ID
, True)
589 self
._tb
.EnableTool(self
.ADD_WATCH_ID
, False)
591 self
.DeleteCurrentLineMarkers()
594 self
.framesTab
.ClearWhileRunning()
596 self
._toolEnabled
= False
598 def EnableWhileDebuggerStopped(self
):
599 self
._tb
.EnableTool(self
.STEP_ID
, True)
600 self
._tb
.EnableTool(self
.CONTINUE_ID
, True)
601 self
._tb
.EnableTool(self
.STEP_OUT_ID
, True)
602 self
._tb
.EnableTool(self
.NEXT_ID
, True)
603 self
._tb
.EnableTool(self
.BREAK_INTO_DEBUGGER_ID
, False)
604 self
._tb
.EnableTool(self
.KILL_PROCESS_ID
, True)
607 self
._tb
.EnableTool(self
.ADD_WATCH_ID
, True)
609 self
._toolEnabled
= True
611 def DisableAfterStop(self
):
612 if self
._toolEnabled
:
613 self
.DisableWhileDebuggerRunning()
614 self
._tb
.EnableTool(self
.BREAK_INTO_DEBUGGER_ID
, False)
615 self
._tb
.EnableTool(self
.KILL_PROCESS_ID
, False)
617 def ExecutorFinished(self
):
618 if _VERBOSE
: print "In ExectorFinished"
620 self
.DisableAfterStop()
621 except wx
._core
.PyDeadObjectError
:
624 nb
= self
.GetParent()
625 for i
in range(0, nb
.GetPageCount()):
626 if self
== nb
.GetPage(i
):
627 text
= nb
.GetPageText(i
)
628 newText
= text
.replace("Debugging", "Finished")
629 nb
.SetPageText(i
, newText
)
630 if _VERBOSE
: print "In ExectorFinished, changed tab title."
633 if _VERBOSE
: print "In ExectorFinished, got exception"
635 def SetStatusText(self
, text
):
636 self
._statusBar
.SetStatusText(text
,0)
638 def BreakExecution(self
, event
):
639 self
._callback
.BreakExecution()
641 def StopExecution(self
, event
):
642 self
._callback
.ShutdownServer()
644 def Execute(self
, initialArgs
, startIn
, environment
, onWebServer
= False):
645 assert False, "Execute not overridden"
647 def SynchCurrentLine(self
, filename
, lineNum
, noArrow
=False):
648 self
.DeleteCurrentLineMarkers()
650 # Filename will be <string> if we're in a bit of code that was executed from
651 # a string (rather than a file). I haven't been able to get the original string
653 if filename
== '<string>':
656 openDocs
= wx
.GetApp().GetDocumentManager().GetDocuments()
657 for openDoc
in openDocs
:
658 # This ugliness to prevent comparison failing because the drive letter
659 # gets lowercased occasionally. Don't know why that happens or why it
660 # only happens occasionally.
661 if DebuggerService
.ComparePaths(openDoc
.GetFilename(),filename
):
662 foundView
= openDoc
.GetFirstView()
667 print "filename=", filename
668 doc
= wx
.GetApp().GetDocumentManager().CreateDocument(DebuggerService
.ExpandPath(filename
), wx
.lib
.docview
.DOC_SILENT
)
669 foundView
= doc
.GetFirstView()
672 foundView
.GetFrame().SetFocus()
674 foundView
.GotoLine(lineNum
)
675 startPos
= foundView
.PositionFromLine(lineNum
)
678 foundView
.GetCtrl().MarkerAdd(lineNum
-1, CodeEditor
.CodeCtrl
.CURRENT_LINE_MARKER_NUM
)
680 def DeleteCurrentLineMarkers(self
):
681 openDocs
= wx
.GetApp().GetDocumentManager().GetDocuments()
682 for openDoc
in openDocs
:
683 if(isinstance(openDoc
, CodeEditor
.CodeDocument
)):
684 openDoc
.GetFirstView().GetCtrl().ClearCurrentLineMarkers()
686 def StopAndRemoveUI(self
, event
):
687 self
.StopExecution(None)
688 if self
in BaseDebuggerUI
.debuggers
:
689 BaseDebuggerUI
.debuggers
.remove(self
)
690 index
= self
._parentNoteBook
.GetSelection()
691 self
._parentNoteBook
.GetPage(index
).Show(False)
692 self
._parentNoteBook
.RemovePage(index
)
694 def OnAddWatch(self
, event
):
696 self
.framesTab
.OnWatch(event
)
698 def MakeFramesUI(self
, parent
, id, debugger
):
699 assert False, "MakeFramesUI not overridden"
701 def AppendText(self
, event
):
702 self
.framesTab
.AppendText(event
.value
)
704 def AppendErrorText(self
, event
):
705 self
.framesTab
.AppendErrorText(event
.value
)
707 def OnClearOutput(self
, event
):
708 self
.framesTab
.ClearOutput(None)
710 def SwitchToOutputTab(self
):
711 self
.framesTab
.SwitchToOutputTab()
714 class PHPDebuggerUI(BaseDebuggerUI
):
715 DEFAULT_LISTENER_HOST
= "127.0.0.1"
716 DEFAULT_LISTENER_PORT
= 10001
717 DEFAULT_DBG_MOD_TIMEOUT
= 300
718 DEFAULT_DBG_MAX_EXEC_TIME
= 240
721 def __init__(self
, parent
, id, command
, service
):
722 BaseDebuggerUI
.__init
__(self
, parent
, id)
723 #Note host and port need to come out of options or a pool.
724 self
._dbgHost
= PHPDebuggerUI
.DEFAULT_LISTENER_HOST
725 self
._dbgPort
= PHPDebuggerUI
.DEFAULT_LISTENER_PORT
726 self
._dbgTimeout
= PHPDebuggerUI
.DEFAULT_DBG_MOD_TIMEOUT
727 self
._dbgMaxExecTime
= PHPDebuggerUI
.DEFAULT_DBG_MAX_EXEC_TIME
728 self
._dbgSessId
= None
729 self
._dbgSessParam
= None
730 self
._dbgPhpIniFile
= None
731 self
._callback
= PHPDebugger
.PHPDebuggerCallback(self
, service
, self
._dbgHost
, self
._dbgPort
)
732 self
._executor
= Executor(command
, self
)
733 self
._service
= service
734 self
._stopped
= False
735 self
._allStopped
= False
737 self
._createPhpDbgSess
()
739 def showErrorDialog(self
, message
, title
):
740 wx
.MessageBox(_(message
), _(title
))
743 def _createPhpDbgSess(self
):
744 currTimeStr
= str(time
.time())
745 (secStr
, usecStr
) = currTimeStr
.split('.')
746 secLongInt
= long(secStr
)
747 usecLongInt
= long(usecStr
)
748 self
._dbgSessId
= "%06ld%06ld%04d" % (secLongInt
, usecLongInt
, PHPDebuggerUI
.dbgSessSeqId
)
749 PHPDebuggerUI
.dbgSessSeqId
= PHPDebuggerUI
.dbgSessSeqId
+ 1
750 self
._dbgSessParam
= "DBGSESSID=%s@clienthost:%d" % (self
._dbgSessId
, self
._dbgPort
)
753 print "phpDbgParam=%s" % self
._dbgSessParam
755 self
._service
.SetPhpDbgParam(self
._dbgSessParam
)
757 def _preparePhpIniFile(self
):
760 phpCgiExec
= Executor
.GetPHPExecutablePath()
761 phpExec
= phpCgiExec
.replace("php-cgi", "php")
762 iniPath
= self
._getPhpIniFromRunningPhp
(phpExec
)
765 iniDbgPath
= os
.path
.normpath(iniPath
+ ".ag_debug_enabled")
766 dbgFile
= open(iniDbgPath
, "w")
767 oriFile
= open(iniPath
, "r")
770 oneOriLine
= oriFile
.readline()
774 if not oneOriLine
.startswith("debugger.") and not oneOriLine
.startswith("max_execution_time="):
775 dbgFile
.write(oneOriLine
)
780 dbgExtFile
= "php_dbg.dll"
782 dbgExtFile
= "dbg.so"
785 # TODO: we should make all of these options configurable.
787 configStr
= "\n; ===============================================================\n; The followings are added by ActiveGrid IDE PHP Debugger Runtime\n; ===============================================================\n\n; As we are running with the dbg module, it takes a much longer time for each script to run.\nmax_execution_time=%d\n\n[debugger]\nextension=%s\ndebugger.enabled=On\ndebugger.JIT_enabled=On\ndebugger.JIT_host=%s\ndebugger.JIT_port=%d\ndebugger.fail_silently=Off\ndebugger.timeout_seconds=%d\ndebugger.ignore_nops=Off\ndebugger.enable_session_cookie=On\ndebugger.session_nocache=On\ndebugger.profiler_enabled=Off\n" % (self
._dbgMaxExecTime
, dbgExtFile
, self
._dbgHost
, self
._dbgPort
, self
._dbgTimeout
)
788 dbgFile
.write(configStr
)
792 #TODO: print stack trace.
793 print "Caught exceptions while minipulating php.ini files"
796 self
._dbgPhpIniFile
= iniDbgPath
798 self
._dbgPhpIniFile
= None
800 def _getPhpIniFromRunningPhp(self
, phpExec
):
804 if cmdEnv
.has_key('PYTHONPATH'):
805 del cmdEnv
['PYTHONPATH']
807 cmdLine
= [phpExec
, "-r", "phpinfo();"]
808 phpProc
= subprocess
.Popen(args
=cmdLine
, bufsize
=0, executable
=None, stdin
=subprocess
.PIPE
, stdout
=subprocess
.PIPE
, stderr
=subprocess
.PIPE
, preexec_fn
=None, close_fds
=False, shell
=False, cwd
=None, env
=os
.environ
, universal_newlines
=False, startupinfo
=None, creationflags
=0)
809 phpOutput
= phpProc
.stdout
811 phpIniPattern
= "Configuration File (php.ini) Path => "
813 oneLine
= phpOutput
.readline()
817 if oneLine
.startswith(phpIniPattern
):
818 if oneLine
.endswith("\n"):
819 endIndex
= oneLine
.index("\n")
820 phpIniPath
= oneLine
[len(phpIniPattern
):endIndex
]
822 phpIniPath
= oneLine
[len(phpIniPattern
):]
824 if phpIniPath
and len(phpIniPath
) > 0:
825 phpIniPath
= os
.path
.normpath(phpIniPath
)
831 print "php.ini path is: %s" % repr(phpIniPath
)
835 def Execute(self
, initialArgs
, startIn
, environment
, onWebServer
= False):
836 self
._preparePhpIniFile
()
837 self
._callback
.Start()
840 if self
._dbgPhpIniFile
:
841 args
= '-c "' + self
._dbgPhpIniFile
+ '" ' + initialArgs
845 self
._executor
.Execute(args
, startIn
, environment
)
847 def StopExecution(self
, event
):
848 # This is a general comment on shutdown for the running and debugged processes. Basically, the
849 # current state of this is the result of trial and error coding. The common problems were memory
850 # access violations and threads that would not exit. Making the OutputReaderThreads daemons seems
851 # to have side-stepped the hung thread issue. Being very careful not to touch things after calling
852 # process.py:ProcessOpen.kill() also seems to have fixed the memory access violations, but if there
853 # were more ugliness discovered I would not be surprised. If anyone has any help/advice, please send
854 # it on to mfryer@activegrid.com.
855 if not self
._allStopped
:
858 self
.DisableAfterStop()
859 except wx
._core
.PyDeadObjectError
:
864 # If this is called by clicking the "Stop" button, we only stop
865 # the current running php script, and keep the listener
869 self
._callback
.ShutdownServer(stopLsnr
= False)
871 self
._callback
.ShutdownServer(stopLsnr
= True)
872 self
._allStopped
= True
874 tp
,val
,tb
= sys
.exc_info()
875 traceback
.print_exception(tp
, val
, tb
)
878 self
.DeleteCurrentLineMarkers()
884 self
._executor
.DoStopExecution()
885 self
._executor
= None
887 tp
,val
,tb
= sys
.exc_info()
888 traceback
.print_exception(tp
, val
, tb
)
890 def MakeFramesUI(self
, parent
, id, debugger
):
891 return PHPFramesUI(parent
, id, self
)
893 def LoadPHPFramesList(self
, stackList
):
894 self
.framesTab
.LoadFramesList(stackList
)
897 # TODO: this is a hack to overwrite BaseDebuggerUI's function. The purpose
898 # is to always push breakpoints no matter if a php is running or not. If
899 # no php is running, an exception will be thrown and handled like nothing
902 def BreakPointChange(self
):
903 self
._callback
.PushBreakpoints()
904 self
.framesTab
.PopulateBPList()
907 class PythonDebuggerUI(BaseDebuggerUI
):
908 debuggerPortList
= None
910 def GetAvailablePort():
911 for index
in range( 0, len(PythonDebuggerUI
.debuggerPortList
)):
912 port
= PythonDebuggerUI
.debuggerPortList
[index
]
913 if PythonDebuggerUI
.PortAvailable(port
):
914 PythonDebuggerUI
.debuggerPortList
.pop(index
)
916 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"))
917 assert False, "Out of ports for debugger."
919 GetAvailablePort
= staticmethod(GetAvailablePort
)
921 def ReturnPortToPool(port
):
922 config
= wx
.ConfigBase_Get()
923 startingPort
= config
.ReadInt("DebuggerStartingPort", DEFAULT_PORT
)
924 val
= int(startingPort
) + int(PORT_COUNT
)
925 if int(port
) >= startingPort
and (int(port
) <= val
):
926 PythonDebuggerUI
.debuggerPortList
.append(int(port
))
928 ReturnPortToPool
= staticmethod(ReturnPortToPool
)
930 def PortAvailable(port
):
931 config
= wx
.ConfigBase_Get()
932 hostname
= config
.Read("DebuggerHostName", DEFAULT_HOST
)
934 server
= AGXMLRPCServer((hostname
, port
))
935 server
.server_close()
936 if _VERBOSE
: print "Port ", str(port
), " available."
939 tp
,val
,tb
= sys
.exc_info()
940 if _VERBOSE
: traceback
.print_exception(tp
, val
, tb
)
941 if _VERBOSE
: print "Port ", str(port
), " unavailable."
944 PortAvailable
= staticmethod(PortAvailable
)
947 config
= wx
.ConfigBase_Get()
948 startingPort
= config
.ReadInt("DebuggerStartingPort", DEFAULT_PORT
)
949 PythonDebuggerUI
.debuggerPortList
= range(startingPort
, startingPort
+ PORT_COUNT
)
950 NewPortRange
= staticmethod(NewPortRange
)
952 def __init__(self
, parent
, id, command
, service
, autoContinue
=True):
953 # Check for ports before creating the panel.
954 if not PythonDebuggerUI
.debuggerPortList
:
955 PythonDebuggerUI
.NewPortRange()
956 self
._debuggerPort
= str(PythonDebuggerUI
.GetAvailablePort())
957 self
._guiPort
= str(PythonDebuggerUI
.GetAvailablePort())
958 self
._debuggerBreakPort
= str(PythonDebuggerUI
.GetAvailablePort())
959 BaseDebuggerUI
.__init
__(self
, parent
, id)
960 self
._command
= command
961 self
._service
= service
962 config
= wx
.ConfigBase_Get()
963 self
._debuggerHost
= self
._guiHost
= config
.Read("DebuggerHostName", DEFAULT_HOST
)
965 url
= 'http://' + self
._debuggerHost
+ ':' + self
._debuggerPort
+ '/'
966 self
._breakURL
= 'http://' + self
._debuggerHost
+ ':' + self
._debuggerBreakPort
+ '/'
967 self
._callback
= PythonDebuggerCallback(self
._guiHost
, self
._guiPort
, url
, self
._breakURL
, self
, autoContinue
)
968 if DebuggerHarness
.__file
__.find('library.zip') > 0:
970 fname
= DebuggerHarness
.__file
__
971 parts
= fname
.split('library.zip')
972 path
= os
.path
.join(parts
[0],'activegrid', 'tool', 'DebuggerHarness.py')
974 tp
, val
, tb
= sys
.exc_info()
975 traceback
.print_exception(tp
, val
, tb
)
978 print "Starting debugger on these ports: %s, %s, %s" % (str(self
._debuggerPort
) , str(self
._guiPort
) , str(self
._debuggerBreakPort
))
979 path
= DebuggerService
.ExpandPath(DebuggerHarness
.__file
__)
980 self
._executor
= Executor(path
, self
, self
._debuggerHost
, \
981 self
._debuggerPort
, self
._debuggerBreakPort
, self
._guiHost
, self
._guiPort
, self
._command
, callbackOnExit
=self
.ExecutorFinished
)
983 self
._stopped
= False
985 def LoadPythonFramesList(self
, framesXML
):
986 self
.framesTab
.LoadFramesList(framesXML
)
988 def Execute(self
, initialArgs
, startIn
, environment
, onWebServer
= False):
989 self
._callback
.Start()
990 self
._executor
.Execute(initialArgs
, startIn
, environment
)
991 self
._callback
.WaitForRPC()
994 def StopExecution(self
, event
):
995 # This is a general comment on shutdown for the running and debugged processes. Basically, the
996 # current state of this is the result of trial and error coding. The common problems were memory
997 # access violations and threads that would not exit. Making the OutputReaderThreads daemons seems
998 # to have side-stepped the hung thread issue. Being very careful not to touch things after calling
999 # process.py:ProcessOpen.kill() also seems to have fixed the memory access violations, but if there
1000 # were more ugliness discovered I would not be surprised. If anyone has any help/advice, please send
1001 # it on to mfryer@activegrid.com.
1002 if not self
._stopped
:
1003 self
._stopped
= True
1005 self
.DisableAfterStop()
1006 except wx
._core
.PyDeadObjectError
:
1009 self
._callback
.ShutdownServer()
1011 tp
,val
,tb
= sys
.exc_info()
1012 traceback
.print_exception(tp
, val
, tb
)
1015 self
.DeleteCurrentLineMarkers()
1019 PythonDebuggerUI
.ReturnPortToPool(self
._debuggerPort
)
1020 PythonDebuggerUI
.ReturnPortToPool(self
._guiPort
)
1021 PythonDebuggerUI
.ReturnPortToPool(self
._debuggerBreakPort
)
1026 self
._executor
.DoStopExecution()
1027 self
._executor
= None
1029 tp
,val
,tb
= sys
.exc_info()
1030 traceback
.print_exception(tp
, val
, tb
)
1033 def MakeFramesUI(self
, parent
, id, debugger
):
1034 panel
= PythonFramesUI(parent
, id, self
)
1038 class BreakpointsUI(wx
.Panel
):
1039 def __init__(self
, parent
, id, ui
):
1040 wx
.Panel
.__init
__(self
, parent
, id)
1042 self
.currentItem
= None
1043 self
.clearBPID
= wx
.NewId()
1044 self
.Bind(wx
.EVT_MENU
, self
.ClearBreakPoint
, id=self
.clearBPID
)
1045 self
.syncLineID
= wx
.NewId()
1046 self
.Bind(wx
.EVT_MENU
, self
.SyncBPLine
, id=self
.syncLineID
)
1047 sizer
= wx
.BoxSizer(wx
.VERTICAL
)
1049 self
._bpListCtrl
= wx
.ListCtrl(p1
, -1, pos
=wx
.DefaultPosition
, size
=(1000,1000), style
=wx
.LC_REPORT
)
1050 sizer
.Add(self
._bpListCtrl
, 1, wx
.ALIGN_LEFT|wx
.ALL|wx
.EXPAND
, 1)
1051 self
._bpListCtrl
.InsertColumn(0, "File")
1052 self
._bpListCtrl
.InsertColumn(1, "Line")
1053 self
._bpListCtrl
.InsertColumn(2, "Path")
1054 self
._bpListCtrl
.SetColumnWidth(0, 150)
1055 self
._bpListCtrl
.SetColumnWidth(1, 50)
1056 self
._bpListCtrl
.SetColumnWidth(2, 450)
1057 self
._bpListCtrl
.Bind(wx
.EVT_LIST_ITEM_RIGHT_CLICK
, self
.OnListRightClick
)
1058 self
.Bind(wx
.EVT_LIST_ITEM_SELECTED
, self
.ListItemSelected
, self
._bpListCtrl
)
1059 self
.Bind(wx
.EVT_LIST_ITEM_DESELECTED
, self
.ListItemDeselected
, self
._bpListCtrl
)
1061 def OnLeftDoubleClick(event
):
1062 self
.SyncBPLine(event
)
1064 wx
.EVT_LEFT_DCLICK(self
._bpListCtrl
, OnLeftDoubleClick
)
1066 self
.PopulateBPList()
1072 def PopulateBPList(self
):
1073 list = self
._bpListCtrl
1074 list.DeleteAllItems()
1076 bps
= wx
.GetApp().GetService(DebuggerService
).GetMasterBreakpointDict()
1078 for fileName
in bps
.keys():
1079 shortFile
= os
.path
.basename(fileName
)
1080 lines
= bps
[fileName
]
1083 list.InsertStringItem(index
, shortFile
)
1084 list.SetStringItem(index
, 1, str(line
))
1085 list.SetStringItem(index
, 2, fileName
)
1087 def OnListRightClick(self
, event
):
1089 item
= wx
.MenuItem(menu
, self
.clearBPID
, "Clear Breakpoint")
1090 menu
.AppendItem(item
)
1091 item
= wx
.MenuItem(menu
, self
.syncLineID
, "Goto Source Line")
1092 menu
.AppendItem(item
)
1093 self
.PopupMenu(menu
, event
.GetPosition())
1096 def SyncBPLine(self
, event
):
1097 if self
.currentItem
!= -1:
1098 list = self
._bpListCtrl
1099 fileName
= list.GetItem(self
.currentItem
, 2).GetText()
1100 lineNumber
= list.GetItem(self
.currentItem
, 1).GetText()
1101 self
._ui
.SynchCurrentLine( fileName
, int(lineNumber
) , noArrow
=True)
1103 def ClearBreakPoint(self
, event
):
1104 if self
.currentItem
>= 0:
1105 list = self
._bpListCtrl
1106 fileName
= list.GetItem(self
.currentItem
, 2).GetText()
1107 lineNumber
= list.GetItem(self
.currentItem
, 1).GetText()
1108 wx
.GetApp().GetService(DebuggerService
).OnToggleBreakpoint(None, line
=int(lineNumber
) -1, fileName
=fileName
)
1110 def ListItemSelected(self
, event
):
1111 self
.currentItem
= event
.m_itemIndex
1113 def ListItemDeselected(self
, event
):
1114 self
.currentItem
= -1
1122 def __init__(self
, name
, command
, show_code
=CODE_ALL_FRAMES
):
1124 self
._command
= command
1125 self
._show
_code
= show_code
1127 class WatchDialog(wx
.Dialog
):
1128 WATCH_ALL_FRAMES
= "Watch in all frames"
1129 WATCH_THIS_FRAME
= "Watch in this frame only"
1130 WATCH_ONCE
= "Watch once and delete"
1131 def __init__(self
, parent
, title
, chain
):
1132 wx
.Dialog
.__init
__(self
, parent
, -1, title
, style
=wx
.DEFAULT_DIALOG_STYLE
)
1134 self
.label_2
= wx
.StaticText(self
, -1, "Watch Name:")
1135 self
._watchNameTextCtrl
= wx
.TextCtrl(self
, -1, "")
1136 self
.label_3
= wx
.StaticText(self
, -1, "eval(", style
=wx
.ALIGN_RIGHT
)
1137 self
._watchValueTextCtrl
= wx
.TextCtrl(self
, -1, "")
1138 self
.label_4
= wx
.StaticText(self
, -1, ",frame.f_globals, frame.f_locals)")
1139 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
)
1141 self
._okButton
= wx
.Button(self
, wx
.ID_OK
, "OK")
1142 self
._okButton
.SetDefault()
1143 self
._okButton
.SetHelpText(_("The OK button completes the dialog"))
1144 def OnOkClick(event
):
1145 if self
._watchNameTextCtrl
.GetValue() == "":
1146 wx
.MessageBox(_("You must enter a name for the watch."), _("Add Watch"))
1148 if self
._watchValueTextCtrl
.GetValue() == "":
1149 wx
.MessageBox(_("You must enter some code to run for the watch."), _("Add Watch"))
1151 self
.EndModal(wx
.ID_OK
)
1152 self
.Bind(wx
.EVT_BUTTON
, OnOkClick
, self
._okButton
)
1154 self
._cancelButton
= wx
.Button(self
, wx
.ID_CANCEL
, _("Cancel"))
1155 self
._cancelButton
.SetHelpText(_("The Cancel button cancels the dialog."))
1157 self
.__set
_properties
()
1160 def GetSettings(self
):
1161 return self
._watchNameTextCtrl
.GetValue(), self
._watchValueTextCtrl
.GetValue(), self
.GetSendFrame(), self
.GetRunOnce()
1163 def GetSendFrame(self
):
1164 return (WatchDialog
.WATCH_ALL_FRAMES
!= self
.radio_box_1
.GetStringSelection())
1166 def GetRunOnce(self
):
1167 return (WatchDialog
.WATCH_ONCE
== self
.radio_box_1
.GetStringSelection())
1169 def __set_properties(self
):
1170 self
.SetTitle("Add a Watch")
1171 #self.SetSize((400, 250))
1172 self
.radio_box_1
.SetSelection(0)
1174 def __do_layout(self
):
1175 sizer_1
= wx
.BoxSizer(wx
.VERTICAL
)
1176 grid_sizer_4
= wx
.FlexGridSizer(1, 3, 5, 5)
1177 grid_sizer_2
= wx
.FlexGridSizer(1, 2, 5, 5)
1178 grid_sizer_2
.Add(self
.label_2
, 0, wx
.ALIGN_CENTER_VERTICAL|wx
.FIXED_MINSIZE
, 0)
1179 grid_sizer_2
.Add(self
._watchNameTextCtrl
, 0, wx
.EXPAND
, 0)
1180 grid_sizer_2
.AddGrowableCol(1)
1181 sizer_1
.Add(grid_sizer_2
, 1, wx
.EXPAND
, 0)
1182 grid_sizer_4
.Add(self
.label_3
, 0, wx
.ALIGN_CENTER_VERTICAL|wx
.FIXED_MINSIZE
, 0)
1183 grid_sizer_4
.Add(self
._watchValueTextCtrl
, 0, wx
.EXPAND
, 0)
1184 grid_sizer_4
.AddGrowableCol(1)
1185 grid_sizer_4
.Add(self
.label_4
, 0, wx
.ALIGN_CENTER_VERTICAL|wx
.FIXED_MINSIZE
, 0)
1186 sizer_1
.Add(grid_sizer_4
, 0, wx
.EXPAND
, 0)
1187 sizer_1
.Add(self
.radio_box_1
, 0, wx
.EXPAND
, 0)
1189 box
= wx
.BoxSizer(wx
.HORIZONTAL
)
1190 box
.Add(self
._okButton
, 0, wx
.ALIGN_RIGHT|wx
.ALL
, 5)
1191 box
.Add(self
._cancelButton
, 0, wx
.ALIGN_RIGHT|wx
.ALL
, 5)
1192 sizer_1
.Add(box
, 1, wx
.EXPAND
, 0)
1193 self
.SetSizer(sizer_1
)
1196 class BaseFramesUI(wx
.SplitterWindow
):
1197 def __init__(self
, parent
, id, ui
):
1198 wx
.SplitterWindow
.__init
__(self
, parent
, id, style
= wx
.SP_3D
)
1200 self
._p
1 = p1
= wx
.ScrolledWindow(self
, -1)
1202 sizer
= wx
.BoxSizer(wx
.HORIZONTAL
)
1203 framesLabel
= wx
.StaticText(self
, -1, "Stack Frame:")
1204 sizer
.Add(framesLabel
, 0, flag
=wx
.ALIGN_CENTER_VERTICAL|wx
.ALIGN_LEFT|wx
.LEFT
, border
=2)
1206 self
._framesChoiceCtrl
= wx
.Choice(p1
, -1, choices
=[" "])
1207 sizer
.Add(self
._framesChoiceCtrl
, 1, wx
.ALIGN_LEFT|wx
.ALL|wx
.EXPAND
, 1)
1208 self
._framesChoiceCtrl
.Bind(wx
.EVT_LIST_ITEM_RIGHT_CLICK
, self
.OnListRightClick
)
1209 self
.Bind(wx
.EVT_CHOICE
, self
.ListItemSelected
, self
._framesChoiceCtrl
)
1211 sizer2
= wx
.BoxSizer(wx
.VERTICAL
)
1213 self
._treeCtrl
= wx
.gizmos
.TreeListCtrl(p1
, -1, style
=wx
.TR_DEFAULT_STYLE| wx
.TR_FULL_ROW_HIGHLIGHT
)
1214 self
._treeCtrl
.Bind(wx
.EVT_TREE_ITEM_RIGHT_CLICK
, self
.OnRightClick
)
1215 sizer2
.Add(sizer
, 0, wx
.ALIGN_LEFT|wx
.ALL|wx
.EXPAND
, 1)
1216 sizer2
.Add(self
._treeCtrl
,1, wx
.ALIGN_LEFT|wx
.ALL|wx
.EXPAND
, 1)
1217 tree
= self
._treeCtrl
1218 tree
.AddColumn("Thing")
1219 tree
.AddColumn("Value")
1220 tree
.SetMainColumn(0) # the one with the tree in it...
1221 tree
.SetColumnWidth(0, 175)
1222 tree
.SetColumnWidth(1, 355)
1223 self
._root
= tree
.AddRoot("Frame")
1224 tree
.SetPyData(self
._root
, "root")
1225 tree
.SetItemText(self
._root
, "", 1)
1226 tree
.Bind(wx
.EVT_TREE_ITEM_EXPANDING
, self
.IntrospectCallback
)
1227 self
._p
2 = p2
= wx
.Window(self
, -1)
1228 sizer3
= wx
.BoxSizer(wx
.HORIZONTAL
)
1230 p2
.Bind(wx
.EVT_SIZE
, self
.OnSize
)
1231 self
._notebook
= wx
.Notebook(p2
, -1, size
=(20,20))
1232 self
._notebook
.Hide()
1233 sizer3
.Add(self
._notebook
, 1, wx
.ALIGN_LEFT|wx
.ALL|wx
.EXPAND
, 1)
1234 self
.consoleTab
= self
.MakeConsoleTab(self
._notebook
, wx
.NewId())
1235 self
.inspectConsoleTab
= self
.MakeInspectConsoleTab(self
._notebook
, wx
.NewId())
1236 self
.breakPointsTab
= self
.MakeBreakPointsTab(self
._notebook
, wx
.NewId())
1237 self
._notebook
.AddPage(self
.consoleTab
, "Output")
1238 self
._notebook
.AddPage(self
.inspectConsoleTab
, "Interact")
1239 self
._notebook
.AddPage(self
.breakPointsTab
, "Break Points")
1240 self
.SetMinimumPaneSize(20)
1241 self
.SplitVertically(p1
, p2
, 550)
1242 self
.currentItem
= None
1243 self
._notebook
.Show(True)
1245 def PopulateBPList(self
):
1246 self
.breakPointsTab
.PopulateBPList()
1248 def OnSize(self
, event
):
1249 self
._notebook
.SetSize(self
._p
2.GetSize())
1251 def OnDoubleClick(self
, event
):
1252 # Looking for a stack trace line.
1253 lineText
, pos
= self
._textCtrl
.GetCurLine()
1254 fileBegin
= lineText
.find("File \"")
1255 fileEnd
= lineText
.find("\", line ")
1256 lineEnd
= lineText
.find(", in ")
1257 if lineText
== "\n" or fileBegin
== -1 or fileEnd
== -1 or lineEnd
== -1:
1258 # Check the line before the one that was clicked on
1259 lineNumber
= self
._textCtrl
.GetCurrentLine()
1260 if(lineNumber
== 0):
1262 lineText
= self
._textCtrl
.GetLine(lineNumber
- 1)
1263 fileBegin
= lineText
.find("File \"")
1264 fileEnd
= lineText
.find("\", line ")
1265 lineEnd
= lineText
.find(", in ")
1266 if lineText
== "\n" or fileBegin
== -1 or fileEnd
== -1 or lineEnd
== -1:
1269 filename
= lineText
[fileBegin
+ 6:fileEnd
]
1270 lineNum
= int(lineText
[fileEnd
+ 8:lineEnd
])
1273 openDocs
= wx
.GetApp().GetDocumentManager().GetDocuments()
1274 for openDoc
in openDocs
:
1275 if openDoc
.GetFilename() == filename
:
1276 foundView
= openDoc
.GetFirstView()
1280 doc
= wx
.GetApp().GetDocumentManager().CreateDocument(filename
, wx
.lib
.docview
.DOC_SILENT
)
1281 foundView
= doc
.GetFirstView()
1284 foundView
.GetFrame().SetFocus()
1285 foundView
.Activate()
1286 foundView
.GotoLine(lineNum
)
1287 startPos
= foundView
.PositionFromLine(lineNum
)
1288 lineText
= foundView
.GetCtrl().GetLine(lineNum
- 1)
1289 foundView
.SetSelection(startPos
, startPos
+ len(lineText
.rstrip("\n")))
1290 import OutlineService
1291 wx
.GetApp().GetService(OutlineService
.OutlineService
).LoadOutline(foundView
, position
=startPos
)
1293 def MakeConsoleTab(self
, parent
, id):
1294 panel
= wx
.Panel(parent
, id)
1295 sizer
= wx
.BoxSizer(wx
.HORIZONTAL
)
1296 self
._textCtrl
= STCTextEditor
.TextCtrl(panel
, wx
.NewId())
1297 sizer
.Add(self
._textCtrl
, 1, wx
.ALIGN_LEFT|wx
.ALL|wx
.EXPAND
, 2)
1298 self
._textCtrl
.SetViewLineNumbers(False)
1299 self
._textCtrl
.SetReadOnly(True)
1300 if wx
.Platform
== '__WXMSW__':
1301 font
= "Courier New"
1304 self
._textCtrl
.SetFont(wx
.Font(9, wx
.DEFAULT
, wx
.NORMAL
, wx
.NORMAL
, faceName
= font
))
1305 self
._textCtrl
.SetFontColor(wx
.BLACK
)
1306 self
._textCtrl
.StyleClearAll()
1307 wx
.stc
.EVT_STC_DOUBLECLICK(self
._textCtrl
, self
._textCtrl
.GetId(), self
.OnDoubleClick
)
1309 panel
.SetSizer(sizer
)
1313 def ExecuteCommand(self
, command
):
1314 assert False, "ExecuteCommand not overridden"
1316 def MakeInspectConsoleTab(self
, parent
, id):
1317 def handleCommand():
1318 cmdStr
= self
._cmdInput
.GetValue()
1320 self
._cmdList
.append(cmdStr
)
1321 self
._cmdIndex
= len(self
._cmdList
)
1322 self
._cmdInput
.Clear()
1323 self
._cmdOutput
.SetDefaultStyle(style
=self
._cmdOutputTextStyle
)
1324 self
._cmdOutput
.AppendText(">>> " + cmdStr
+ "\n")
1325 self
._cmdOutput
.SetDefaultStyle(style
=self
._defaultOutputTextStyle
)
1326 self
.ExecuteCommand(cmdStr
)
1329 def OnCmdButtonPressed(event
):
1333 def OnKeyPressed(event
):
1334 key
= event
.KeyCode()
1335 if key
== wx
.WXK_RETURN
:
1337 elif key
== wx
.WXK_UP
:
1338 if len(self
._cmdList
) < 1 or self
._cmdIndex
< 1:
1341 self
._cmdInput
.Clear()
1342 self
._cmdInput
.AppendText(self
._cmdList
[self
._cmdIndex
- 1])
1343 self
._cmdIndex
= self
._cmdIndex
- 1
1344 elif key
== wx
.WXK_DOWN
:
1345 if len(self
._cmdList
) < 1 or self
._cmdIndex
>= len(self
._cmdList
):
1348 self
._cmdInput
.Clear()
1349 self
._cmdInput
.AppendText(self
._cmdList
[self
._cmdIndex
- 1])
1350 self
._cmdIndex
= self
._cmdIndex
+ 1
1355 def OnClrButtonPressed(event
):
1356 self
._cmdOutput
.Clear()
1358 panel
= wx
.Panel(parent
, id)
1360 cmdLabel
= wx
.StaticText(panel
, -1, "Cmd: ")
1361 self
._cmdInput
= wx
.TextCtrl(panel
)
1362 cmdButton
= wx
.Button(panel
, label
="Execute")
1363 clrButton
= wx
.Button(panel
, label
="Clear")
1364 self
._cmdOutput
= wx
.TextCtrl(panel
, style
=wx
.TE_MULTILINE | wx
.HSCROLL | wx
.TE_READONLY | wx
.TE_RICH2
)
1366 hbox
= wx
.BoxSizer()
1367 hbox
.Add(cmdLabel
, proportion
=0, flag
=wx
.LEFT|wx
.ALIGN_CENTER_VERTICAL
)
1368 hbox
.Add(self
._cmdInput
, proportion
=1, flag
=wx
.EXPAND
)
1369 hbox
.Add(cmdButton
, proportion
=0, flag
=wx
.RIGHT
)
1370 hbox
.Add(clrButton
, proportion
=0, flag
=wx
.RIGHT
)
1372 vbox
= wx
.BoxSizer(wx
.VERTICAL
)
1373 vbox
.Add(hbox
, proportion
=0, flag
=wx
.EXPAND | wx
.ALL
, border
=2)
1374 vbox
.Add(self
._cmdOutput
, proportion
=1, flag
=wx
.EXPAND | wx
.LEFT
, border
=2)
1376 panel
.SetSizer(vbox
)
1377 cmdButton
.Bind(wx
.EVT_BUTTON
, OnCmdButtonPressed
)
1378 clrButton
.Bind(wx
.EVT_BUTTON
, OnClrButtonPressed
)
1379 wx
.EVT_KEY_DOWN(self
._cmdInput
, OnKeyPressed
)
1381 fixedFont
= wx
.Font(self
._cmdInput
.GetFont().GetPointSize(), family
=wx
.TELETYPE
, style
=wx
.NORMAL
, weight
=wx
.NORMAL
)
1382 self
._defaultOutputTextStyle
= wx
.TextAttr("BLACK", wx
.NullColour
, fixedFont
)
1383 self
._cmdOutputTextStyle
= wx
.TextAttr("RED", wx
.NullColour
, fixedFont
)
1384 self
._cmdOutput
.SetDefaultStyle(style
=self
._defaultOutputTextStyle
)
1391 def MakeBreakPointsTab(self
, parent
, id):
1392 panel
= BreakpointsUI(parent
, id, self
._ui
)
1395 def OnRightClick(self
, event
):
1396 assert False, "OnRightClick not overridden"
1398 def ClearWhileRunning(self
):
1399 list = self
._framesChoiceCtrl
1402 tree
= self
._treeCtrl
1404 tree
.DeleteChildren(root
)
1405 self
._cmdInput
.Enable(False)
1406 self
._cmdOutput
.Enable(False)
1408 def OnListRightClick(self
, event
):
1409 if not hasattr(self
, "syncFrameID"):
1410 self
.syncFrameID
= wx
.NewId()
1411 self
.Bind(wx
.EVT_MENU
, self
.OnSyncFrame
, id=self
.syncFrameID
)
1413 item
= wx
.MenuItem(menu
, self
.syncFrameID
, "Goto Source Line")
1414 menu
.AppendItem(item
)
1415 self
.PopupMenu(menu
, event
.GetPosition())
1418 def OnSyncFrame(self
, event
):
1419 assert False, "OnSyncFrame not overridden"
1421 def LoadFramesList(self
, framesXML
):
1422 assert False, "LoadFramesList not overridden"
1424 def ListItemSelected(self
, event
):
1425 assert False, "ListItemSelected not overridden"
1427 def PopulateTreeFromFrameMessage(self
, message
):
1428 assert False, "PopulateTreeFromFrameMessage not overridden"
1430 def IntrospectCallback(self
, event
):
1431 assert False, "IntrospectCallback not overridden"
1433 def AppendText(self
, text
):
1434 self
._textCtrl
.SetReadOnly(False)
1435 self
._textCtrl
.AddText(text
)
1436 self
._textCtrl
.ScrollToLine(self
._textCtrl
.GetLineCount())
1437 self
._textCtrl
.SetReadOnly(True)
1439 def AppendErrorText(self
, text
):
1440 self
._textCtrl
.SetReadOnly(False)
1441 self
._textCtrl
.SetFontColor(wx
.RED
)
1442 self
._textCtrl
.StyleClearAll()
1443 self
._textCtrl
.AddText(text
)
1444 self
._textCtrl
.ScrollToLine(self
._textCtrl
.GetLineCount())
1445 self
._textCtrl
.SetFontColor(wx
.BLACK
)
1446 self
._textCtrl
.StyleClearAll()
1447 self
._textCtrl
.SetReadOnly(True)
1449 def ClearOutput(self
, event
):
1450 self
._textCtrl
.SetReadOnly(False)
1451 self
._textCtrl
.ClearAll()
1452 self
._textCtrl
.SetReadOnly(True)
1454 def SwitchToOutputTab(self
):
1455 self
._notebook
.SetSelection(0)
1457 class PHPFramesUI(BaseFramesUI
):
1458 def __init__(self
, parent
, id, ui
):
1459 BaseFramesUI
.__init
__(self
, parent
, id, ui
)
1461 def LoadFramesList(self
, stackList
):
1462 wx
.GetApp().GetTopWindow().SetCursor(wx
.StockCursor(wx
.CURSOR_WAIT
))
1464 self
._cmdInput
.Enable(True)
1465 self
._cmdOutput
.Enable(True)
1467 self
._stack
= stackList
1468 list = self
._framesChoiceCtrl
1471 if len(stackList
) > 0:
1472 self
._displayVariableTreeRootNode
()
1474 for stackFrame
in stackList
:
1475 message
= stackFrame
.getDisplayStr(stackList
)
1476 list.Append(message
)
1478 self
.currentItem
= index
1479 list.SetSelection(index
)
1481 self
.OnSyncFrame(None)
1482 self
._p
1.FitInside()
1484 wx
.GetApp().GetTopWindow().SetCursor(wx
.StockCursor(wx
.CURSOR_DEFAULT
))
1486 def PopulateTreeFromStackFrame(self
, frameNode
):
1487 vars = frameNode
.getVariables()
1488 tree
= self
._treeCtrl
1489 rootTreeNode
= self
._root
1492 # Build a new sub variable tree from the root node.
1494 tree
.DeleteChildren(rootTreeNode
)
1496 aTreeNode
= self
.AppendSubTreeFromAVariable(tree
, var
, rootTreeNode
)
1499 # No need to expand the node here, as the IntrospectCallback() has
1500 # already called it.
1502 self
._p
2.FitInside()
1504 def AppendSubTreeFromAVariable(self
, tree
, var
, parentTreeNode
, previousOne
= None):
1505 varName
= var
.getName()
1506 varValueStr
= var
.getValueString()
1509 # If previously we already have this item in the tree, replace it.
1510 # Otherwise, insert a new one.
1513 newNode
= tree
.InsertItem(parentTreeNode
, previousOne
, varName
)
1515 newNode
= tree
.AppendItem(parentTreeNode
, varName
)
1518 # Associate this variable object with this newNode.
1520 tree
.SetPyData(newNode
, var
)
1523 # Set this variable's value string (for displaying).
1525 if varValueStr
and len(varValueStr
) > 0:
1526 tree
.SetItemText(newNode
, varValueStr
, 1)
1529 # If this variable has child variables, recursively build the sub
1532 if var
.hasChildren():
1533 childrenVarList
= var
.getChildrenVariables()
1534 for childVar
in childrenVarList
:
1535 self
.AppendSubTreeFromAVariable(tree
, childVar
, newNode
)
1538 # If its child variables are sortable, sort it.
1540 if var
.childrenIsSortable():
1541 tree
.SortChildren(newNode
)
1545 def IntrospectCallback(self
, event
):
1546 tree
= self
._treeCtrl
1547 item
= event
.GetItem()
1550 # Only when the introspection happens to root, we get the whole
1551 # variable tree. For all the individual nodes, we have populated
1552 # the subtree already, so don't need to do anything.
1554 if tree
.GetPyData(item
) == "root" and self
._stack
and self
._stack
[self
.currentItem
]:
1555 stackFrame
= self
._stack
[self
.currentItem
]
1556 self
.PopulateTreeFromStackFrame(stackFrame
)
1560 def OnSyncFrame(self
, event
):
1561 stackFrame
= self
._stack
[self
.currentItem
]
1562 fileName
= stackFrame
.getFileName()
1563 lineNo
= stackFrame
.getLineNo()
1565 print "OnSyncFrame(): about to sync: fileName: %s, lineNo: %d" % (fileName
, lineNo
)
1566 self
._ui
.SynchCurrentLine(fileName
, lineNo
)
1568 print "OnSyncFrame(): sync done"
1570 def ListItemSelected(self
, event
):
1571 selectedStackFrameStr
= event
.GetString()
1573 if not self
._stack
or len(self
._stack
) < 1:
1577 for stackFrame
in self
._stack
:
1578 if stackFrame
.getDisplayStr() == selectedStackFrameStr
:
1579 self
.currentItem
= stackFrame
.getFrameIndex()
1584 self
._displayVariableTreeRootNode
()
1585 self
.OnSyncFrame(None)
1589 def _displayVariableTreeRootNode(self
):
1591 # Add a dummy item to rootTreeNode so that it will be shown as
1592 # expandable. Only do real tree population on the fly when the
1593 # rootTreeNode is expanded in OnIntrospection().
1595 tree
= self
._treeCtrl
1596 rootTreeNode
= self
._root
1597 dummyNode
= tree
.AppendItem(rootTreeNode
, "dummy")
1598 tree
.Collapse(rootTreeNode
)
1603 class PythonFramesUI(BaseFramesUI
):
1604 def __init__(self
, parent
, id, ui
):
1605 BaseFramesUI
.__init
__(self
, parent
, id, ui
)
1607 def ExecuteCommand(self
, command
):
1608 retval
= self
._ui
._callback
._debuggerServer
.execute_in_frame(self
._framesChoiceCtrl
.GetStringSelection(), command
)
1609 self
._cmdOutput
.AppendText(str(retval
) + "\n")
1610 # Refresh the tree view in case this command resulted in changes there. TODO: Need to reopen tree items.
1611 self
.PopulateTreeFromFrameMessage(self
._framesChoiceCtrl
.GetStringSelection())
1613 def OnRightClick(self
, event
):
1615 self
._introspectItem
= event
.GetItem()
1616 self
._parentChain
= self
.GetItemChain(event
.GetItem())
1617 watchOnly
= len(self
._parentChain
) < 1
1618 if not _WATCHES_ON
and watchOnly
:
1622 if not hasattr(self
, "watchID"):
1623 self
.watchID
= wx
.NewId()
1624 self
.Bind(wx
.EVT_MENU
, self
.OnWatch
, id=self
.watchID
)
1625 item
= wx
.MenuItem(menu
, self
.watchID
, "Create a Watch")
1626 menu
.AppendItem(item
)
1627 menu
.AppendSeparator()
1629 if not hasattr(self
, "viewID"):
1630 self
.viewID
= wx
.NewId()
1631 self
.Bind(wx
.EVT_MENU
, self
.OnView
, id=self
.viewID
)
1632 item
= wx
.MenuItem(menu
, self
.viewID
, "View in Dialog")
1633 menu
.AppendItem(item
)
1634 if not hasattr(self
, "toInteractID"):
1635 self
.toInteractID
= wx
.NewId()
1636 self
.Bind(wx
.EVT_MENU
, self
.OnSendToInteract
, id=self
.toInteractID
)
1637 item
= wx
.MenuItem(menu
, self
.toInteractID
, "Send to Interact")
1638 menu
.AppendItem(item
)
1640 offset
= wx
.Point(x
=0, y
=20)
1641 menuSpot
= event
.GetPoint() + offset
1642 self
._treeCtrl
.PopupMenu(menu
, menuSpot
)
1644 self
._parentChain
= None
1645 self
._introspectItem
= None
1647 def GetItemChain(self
, item
):
1650 if _VERBOSE
: print 'Exploding: %s' % self
._treeCtrl
.GetItemText(item
, 0)
1651 while item
!= self
._root
:
1652 text
= self
._treeCtrl
.GetItemText(item
, 0)
1653 if _VERBOSE
: print "Appending ", text
1654 parentChain
.append(text
)
1655 item
= self
._treeCtrl
.GetItemParent(item
)
1656 parentChain
.reverse()
1659 def OnView(self
, event
):
1660 title
= self
._treeCtrl
.GetItemText(self
._introspectItem
,0)
1661 value
= self
._treeCtrl
.GetItemText(self
._introspectItem
,1)
1662 dlg
= wx
.lib
.dialogs
.ScrolledMessageDialog(self
, value
, title
, style
=wx
.DD_DEFAULT_STYLE | wx
.RESIZE_BORDER
)
1665 def OnSendToInteract(self
, event
):
1668 for item
in self
._parentChain
:
1670 if item
.find(prevItem
+ '[') != -1:
1671 value
+= item
[item
.find('['):]
1675 if item
== 'globals':
1677 if item
!= 'locals':
1681 self
.ExecuteCommand(value
)
1683 def OnWatch(self
, event
):
1685 if hasattr(self
, '_parentChain'):
1686 wd
= WatchDialog(wx
.GetApp().GetTopWindow(), "Add a Watch", self
._parentChain
)
1688 wd
= WatchDialog(wx
.GetApp().GetTopWindow(), "Add a Watch", None)
1690 if wd
.ShowModal() == wx
.ID_OK
:
1691 name
, text
, send_frame
, run_once
= wd
.GetSettings()
1693 frameNode
= self
._stack
[int(self
.currentItem
)]
1694 message
= frameNode
.getAttribute("message")
1697 binType
= self
._ui
._callback
._debuggerServer
.add_watch(name
, text
, message
, run_once
)
1698 xmldoc
= bz2
.decompress(binType
.data
)
1699 domDoc
= parseString(xmldoc
)
1700 nodeList
= domDoc
.getElementsByTagName('watch')
1701 if len(nodeList
) == 1:
1702 watchValue
= nodeList
.item(0).getAttribute("message")
1705 tp
, val
, tb
= sys
.exc_info()
1706 traceback
.print_exception(tp
, val
, tb
)
1708 def OnIntrospect(self
, event
):
1709 wx
.GetApp().GetTopWindow().SetCursor(wx
.StockCursor(wx
.CURSOR_WAIT
))
1714 list = self
._framesChoiceCtrl
1715 frameNode
= self
._stack
[int(self
.currentItem
)]
1716 message
= frameNode
.getAttribute("message")
1717 binType
= self
._ui
._callback
._debuggerServer
.attempt_introspection(message
, self
._parentChain
)
1718 xmldoc
= bz2
.decompress(binType
.data
)
1719 domDoc
= parseString(xmldoc
)
1720 nodeList
= domDoc
.getElementsByTagName('replacement')
1721 replacementNode
= nodeList
.item(0)
1722 if len(replacementNode
.childNodes
):
1723 thingToWalk
= replacementNode
.childNodes
.item(0)
1724 tree
= self
._treeCtrl
1725 parent
= tree
.GetItemParent(self
._introspectItem
)
1726 treeNode
= self
.AppendSubTreeFromNode(thingToWalk
, thingToWalk
.getAttribute('name'), parent
, insertBefore
=self
._introspectItem
)
1727 if thingToWalk
.getAttribute('name').find('[') == -1:
1728 self
._treeCtrl
.SortChildren(treeNode
)
1729 self
._treeCtrl
.Expand(treeNode
)
1730 tree
.Delete(self
._introspectItem
)
1732 tp
,val
,tb
= sys
.exc_info()
1733 traceback
.print_exception(tp
, val
, tb
)
1736 wx
.GetApp().GetTopWindow().SetCursor(wx
.StockCursor(wx
.CURSOR_DEFAULT
))
1738 def OnSyncFrame(self
, event
):
1739 list = self
._framesChoiceCtrl
1740 frameNode
= self
._stack
[int(self
.currentItem
)]
1741 file = frameNode
.getAttribute("file")
1742 line
= frameNode
.getAttribute("line")
1743 self
._ui
.SynchCurrentLine( file, int(line
) )
1745 def LoadFramesList(self
, framesXML
):
1746 wx
.GetApp().GetTopWindow().SetCursor(wx
.StockCursor(wx
.CURSOR_WAIT
))
1748 self
._cmdInput
.Enable(True)
1749 self
._cmdOutput
.Enable(True)
1752 domDoc
= parseString(framesXML
)
1753 list = self
._framesChoiceCtrl
1756 nodeList
= domDoc
.getElementsByTagName('frame')
1758 for index
in range(0, nodeList
.length
):
1759 frameNode
= nodeList
.item(index
)
1760 message
= frameNode
.getAttribute("message")
1761 list.Append(message
)
1762 self
._stack
.append(frameNode
)
1764 index
= len(self
._stack
) - 1
1765 list.SetSelection(index
)
1767 node
= self
._stack
[index
]
1768 self
.currentItem
= index
1769 self
.PopulateTreeFromFrameNode(node
)
1770 self
.OnSyncFrame(None)
1772 self
._p
1.FitInside()
1773 frameNode
= nodeList
.item(index
)
1774 file = frameNode
.getAttribute("file")
1775 line
= frameNode
.getAttribute("line")
1776 self
._ui
.SynchCurrentLine( file, int(line
) )
1778 tp
,val
,tb
=sys
.exc_info()
1779 traceback
.print_exception(tp
, val
, tb
)
1782 wx
.GetApp().GetTopWindow().SetCursor(wx
.StockCursor(wx
.CURSOR_DEFAULT
))
1785 def ListItemSelected(self
, event
):
1786 self
.PopulateTreeFromFrameMessage(event
.GetString())
1787 self
.OnSyncFrame(None)
1789 def PopulateTreeFromFrameMessage(self
, message
):
1791 for node
in self
._stack
:
1792 if node
.getAttribute("message") == message
:
1793 binType
= self
._ui
._callback
._debuggerServer
.request_frame_document(message
)
1794 xmldoc
= bz2
.decompress(binType
.data
)
1795 domDoc
= parseString(xmldoc
)
1796 nodeList
= domDoc
.getElementsByTagName('frame')
1797 self
.currentItem
= index
1799 self
.PopulateTreeFromFrameNode(nodeList
[0])
1803 def PopulateTreeFromFrameNode(self
, frameNode
):
1804 list = self
._framesChoiceCtrl
1806 tree
= self
._treeCtrl
1809 tree
.DeleteChildren(root
)
1810 children
= frameNode
.childNodes
1812 for index
in range(0, children
.length
):
1813 subNode
= children
.item(index
)
1814 treeNode
= self
.AppendSubTreeFromNode(subNode
, subNode
.getAttribute('name'), root
)
1816 firstChild
= treeNode
1819 tree
.Expand(firstChild
)
1820 self
._p
2.FitInside()
1822 def IntrospectCallback(self
, event
):
1823 tree
= self
._treeCtrl
1824 item
= event
.GetItem()
1826 print "In introspectCallback item is %s, pydata is %s" % (event
.GetItem(), tree
.GetPyData(item
))
1827 if tree
.GetPyData(item
) != "Introspect":
1830 self
._introspectItem
= item
1831 self
._parentChain
= self
.GetItemChain(item
)
1832 self
.OnIntrospect(event
)
1835 def AppendSubTreeFromNode(self
, node
, name
, parent
, insertBefore
=None):
1836 tree
= self
._treeCtrl
1837 if insertBefore
!= None:
1838 treeNode
= tree
.InsertItem(parent
, insertBefore
, name
)
1840 treeNode
= tree
.AppendItem(parent
, name
)
1841 children
= node
.childNodes
1842 intro
= node
.getAttribute('intro')
1845 tree
.SetItemHasChildren(treeNode
, True)
1846 tree
.SetPyData(treeNode
, "Introspect")
1847 if node
.getAttribute("value"):
1848 tree
.SetItemText(treeNode
, self
.StripOuterSingleQuotes(node
.getAttribute("value")), 1)
1849 for index
in range(0, children
.length
):
1850 subNode
= children
.item(index
)
1851 if self
.HasChildren(subNode
):
1852 self
.AppendSubTreeFromNode(subNode
, subNode
.getAttribute("name"), treeNode
)
1854 name
= subNode
.getAttribute("name")
1855 value
= self
.StripOuterSingleQuotes(subNode
.getAttribute("value"))
1856 n
= tree
.AppendItem(treeNode
, name
)
1857 tree
.SetItemText(n
, value
, 1)
1858 intro
= subNode
.getAttribute('intro')
1860 tree
.SetItemHasChildren(n
, True)
1861 tree
.SetPyData(n
, "Introspect")
1862 if name
.find('[') == -1:
1863 self
._treeCtrl
.SortChildren(treeNode
)
1866 def StripOuterSingleQuotes(self
, string
):
1867 if string
.startswith("'") and string
.endswith("'"):
1868 retval
= string
[1:-1]
1869 elif string
.startswith("\"") and string
.endswith("\""):
1870 retval
= string
[1:-1]
1873 if retval
.startswith("u'") and retval
.endswith("'"):
1877 def HasChildren(self
, node
):
1879 return node
.childNodes
.length
> 0
1881 tp
,val
,tb
=sys
.exc_info()
1885 class DebuggerView(Service
.ServiceView
):
1887 #----------------------------------------------------------------------------
1888 # Overridden methods
1889 #----------------------------------------------------------------------------
1891 def __init__(self
, service
):
1892 Service
.ServiceView
.__init
__(self
, service
)
1894 def _CreateControl(self
, parent
, id):
1897 #------------------------------------------------------------------------------
1899 #-----------------------------------------------------------------------------
1901 def OnToolClicked(self
, event
):
1902 self
.GetFrame().ProcessEvent(event
)
1904 #------------------------------------------------------------------------------
1906 #-----------------------------------------------------------------------------
1909 def __init__(self
, message
, framesXML
, info
=None, quit
=False):
1910 self
._framesXML
= framesXML
1911 self
._message
= message
1915 def getFramesXML(self
):
1916 return self
._framesXML
1918 def getMessage(self
):
1919 return self
._message
1927 class AGXMLRPCServer(SimpleXMLRPCServer
.SimpleXMLRPCServer
):
1928 def __init__(self
, address
, logRequests
=0):
1929 SimpleXMLRPCServer
.SimpleXMLRPCServer
.__init
__(self
, address
, logRequests
=logRequests
)
1931 class RequestHandlerThread(threading
.Thread
):
1932 def __init__(self
, queue
, address
):
1933 threading
.Thread
.__init
__(self
)
1934 self
._keepGoing
= True
1936 self
._address
= address
1937 self
._server
= AGXMLRPCServer(self
._address
,logRequests
=0)
1938 self
._server
.register_function(self
.interaction
)
1939 self
._server
.register_function(self
.quit
)
1940 self
._server
.register_function(self
.dummyOperation
)
1941 if _VERBOSE
: print "RequestHandlerThread on fileno %s" % str(self
._server
.fileno())
1944 while self
._keepGoing
:
1946 self
._server
.handle_request()
1948 tp
, val
, tb
= sys
.exc_info()
1949 traceback
.print_exception(tp
, val
, tb
)
1950 self
._keepGoing
= False
1951 if _VERBOSE
: print "Exiting Request Handler Thread."
1953 def interaction(self
, message
, frameXML
, info
):
1954 if _VERBOSE
: print "In RequestHandlerThread.interaction -- adding to queue"
1955 interaction
= Interaction(message
, frameXML
, info
)
1956 self
._queue
.put(interaction
)
1960 interaction
= Interaction(None, None, info
=None, quit
=True)
1961 self
._queue
.put(interaction
)
1964 def dummyOperation(self
):
1967 def AskToStop(self
):
1968 self
._keepGoing
= False
1969 if type(self
._server
) is not types
.NoneType
:
1971 # This is a really ugly way to make sure this thread isn't blocked in
1973 url
= 'http://' + self
._address
[0] + ':' + str(self
._address
[1]) + '/'
1974 tempServer
= xmlrpclib
.ServerProxy(url
, allow_none
=1)
1975 tempServer
.dummyOperation()
1977 tp
, val
, tb
= sys
.exc_info()
1978 traceback
.print_exception(tp
, val
, tb
)
1979 self
._server
.server_close()
1982 class RequestBreakThread(threading
.Thread
):
1983 def __init__(self
, server
, interrupt
=False, pushBreakpoints
=False, breakDict
=None, kill
=False):
1984 threading
.Thread
.__init
__(self
)
1985 self
._server
= server
1987 self
._interrupt
= interrupt
1988 self
._pushBreakpoints
= pushBreakpoints
1989 self
._breakDict
= breakDict
1994 if _VERBOSE
: print "RequestBreakThread, before call"
1996 self
._server
.break_requested()
1997 if self
._pushBreakpoints
:
1998 self
._server
.update_breakpoints(xmlrpclib
.Binary(pickle
.dumps(self
._breakDict
)))
2004 if _VERBOSE
: print "RequestBreakThread, after call"
2006 tp
,val
,tb
= sys
.exc_info()
2007 traceback
.print_exception(tp
, val
, tb
)
2009 class DebuggerOperationThread(threading
.Thread
):
2010 def __init__(self
, function
):
2011 threading
.Thread
.__init
__(self
)
2012 self
._function
= function
2015 if _VERBOSE
: print "In DOT, before call"
2019 tp
,val
,tb
= sys
.exc_info()
2020 traceback
.print_exception(tp
, val
, tb
)
2022 print "In DOT, after call"
2024 class BaseDebuggerCallback(object):
2027 assert False, "Start not overridden"
2029 def ShutdownServer(self
):
2030 assert False, "ShutdownServer not overridden"
2032 def BreakExecution(self
):
2033 assert False, "BreakExecution not overridden"
2035 def SingleStep(self
):
2036 assert False, "SingleStep not overridden"
2039 assert False, "Next not overridden"
2042 assert False, "Start not overridden"
2045 assert False, "Return not overridden"
2047 def PushBreakpoints(self
):
2048 assert False, "PushBreakpoints not overridden"
2050 class PythonDebuggerCallback(BaseDebuggerCallback
):
2052 def __init__(self
, host
, port
, debugger_url
, break_url
, debuggerUI
, autoContinue
=False):
2053 if _VERBOSE
: print "+++++++ Creating server on port, ", str(port
)
2055 self
._queue
= Queue
.Queue(50)
2057 self
._port
= int(port
)
2058 threading
._VERBOSE
= _VERBOSE
2059 self
._serverHandlerThread
= RequestHandlerThread(self
._queue
, (self
._host
, self
._port
))
2061 self
._debugger
_url
= debugger_url
2062 self
._debuggerServer
= None
2063 self
._waiting
= False
2064 self
._service
= wx
.GetApp().GetService(DebuggerService
)
2065 self
._debuggerUI
= debuggerUI
2066 self
._break
_url
= break_url
2067 self
._breakServer
= None
2068 self
._firstInteraction
= True
2069 self
._pendingBreak
= False
2070 self
._autoContinue
= autoContinue
2073 self
._serverHandlerThread
.start()
2075 def ShutdownServer(self
):
2076 #rbt = RequestBreakThread(self._breakServer, kill=True)
2078 self
._waiting
= False
2079 if self
._serverHandlerThread
:
2080 self
._serverHandlerThread
.AskToStop()
2081 self
._serverHandlerThread
= None
2083 def BreakExecution(self
):
2084 rbt
= RequestBreakThread(self
._breakServer
, interrupt
=True)
2087 def SingleStep(self
):
2088 self
._debuggerUI
.DisableWhileDebuggerRunning()
2089 self
._debuggerServer
.set_step() # Figure out where to set allowNone
2093 self
._debuggerUI
.DisableWhileDebuggerRunning()
2094 self
._debuggerServer
.set_next()
2098 self
._debuggerUI
.DisableWhileDebuggerRunning()
2099 self
._debuggerServer
.set_continue()
2103 self
._debuggerUI
.DisableWhileDebuggerRunning()
2104 self
._debuggerServer
.set_return()
2107 def ReadQueue(self
):
2108 if self
._queue
.qsize():
2110 item
= self
._queue
.get_nowait()
2112 self
.interaction(None, None, None, True)
2114 data
= bz2
.decompress(item
.getFramesXML().data
)
2115 self
.interaction(item
.getMessage().data
, data
, item
.getInfo(), False)
2119 def PushBreakpoints(self
):
2120 rbt
= RequestBreakThread(self
._breakServer
, pushBreakpoints
=True, breakDict
=self
._service
.GetMasterBreakpointDict())
2124 def WaitForRPC(self
):
2125 self
._waiting
= True
2126 while self
._waiting
:
2132 tp
, val
, tb
= sys
.exc_info()
2133 traceback
.print_exception(tp
, val
, tb
)
2134 wx
.GetApp().Yield(True)
2135 if _VERBOSE
: print "Exiting WaitForRPC."
2137 def interaction(self
, message
, frameXML
, info
, quit
):
2139 #This method should be hit as the debugger starts.
2140 if self
._firstInteraction
:
2141 self
._firstInteraction
= False
2142 self
._debuggerServer
= xmlrpclib
.ServerProxy(self
._debugger
_url
, allow_none
=1)
2143 self
._breakServer
= xmlrpclib
.ServerProxy(self
._break
_url
, allow_none
=1)
2144 self
.PushBreakpoints()
2145 self
._waiting
= False
2146 if _VERBOSE
: print "+"*40
2148 self
._debuggerUI
.StopExecution(None)
2151 if _VERBOSE
: print "Hit interaction with exception"
2152 #self._debuggerUI.StopExecution(None)
2153 #self._debuggerUI.SetStatusText("Got exception: " + str(info))
2154 self
._debuggerUI
.SwitchToOutputTab()
2156 if _VERBOSE
: print "Hit interaction no exception"
2157 #if not self._autoContinue:
2158 self
._debuggerUI
.SetStatusText(message
)
2159 if not self
._autoContinue
:
2160 self
._debuggerUI
.LoadPythonFramesList(frameXML
)
2161 self
._debuggerUI
.EnableWhileDebuggerStopped()
2163 if self
._autoContinue
:
2164 self
._timer
= wx
.PyTimer(self
.DoContinue
)
2165 self
._autoContinue
= False
2166 self
._timer
.Start(250)
2167 if _VERBOSE
: print "+"*40
2169 def DoContinue(self
):
2171 dbgService
= wx
.GetApp().GetService(DebuggerService
)
2172 evt
= DebugInternalWebServer()
2173 evt
.SetId(self
._debuggerUI
.CONTINUE_ID
)
2174 wx
.PostEvent(self
._debuggerUI
, evt
)
2175 if _VERBOSE
: print "Event Continue posted"
2177 evt
= DebugInternalWebServer()
2178 evt
.SetId(DebuggerService
.DEBUG_WEBSERVER_NOW_RUN_PROJECT_ID
)
2179 wx
.PostEvent(dbgService
._frame
, evt
)
2180 if _VERBOSE
: print "Event RunProject posted"
2182 def SendRunEvent(self
):
2183 class SendEventThread(threading
.Thread
):
2185 threading
.Thread
.__init
__(self
)
2188 dbgService
= wx
.GetApp().GetService(DebuggerService
)
2189 evt
= DebugInternalWebServer()
2190 evt
.SetId(DebuggerService
.DEBUG_WEBSERVER_NOW_RUN_PROJECT_ID
)
2191 wx
.PostEvent(dbgService
._frame
, evt
)
2192 print "Event posted"
2193 set = SendEventThread()
2196 class DebuggerService(Service
.Service
):
2198 #----------------------------------------------------------------------------
2200 #----------------------------------------------------------------------------
2201 TOGGLE_BREAKPOINT_ID
= wx
.NewId()
2202 CLEAR_ALL_BREAKPOINTS
= wx
.NewId()
2204 DEBUG_ID
= wx
.NewId()
2205 RUN_LAST_ID
= wx
.NewId()
2206 DEBUG_LAST_ID
= wx
.NewId()
2207 DEBUG_WEBSERVER_ID
= wx
.NewId()
2208 RUN_WEBSERVER_ID
= wx
.NewId()
2209 DEBUG_WEBSERVER_CONTINUE_ID
= wx
.NewId()
2210 DEBUG_WEBSERVER_NOW_RUN_PROJECT_ID
= wx
.NewId()
2211 def ComparePaths(first
, second
):
2212 one
= DebuggerService
.ExpandPath(first
)
2213 two
= DebuggerService
.ExpandPath(second
)
2215 return one
.lower() == two
.lower()
2218 ComparePaths
= staticmethod(ComparePaths
)
2220 # Make sure we're using an expanded path on windows.
2221 def ExpandPath(path
):
2224 return win32api
.GetLongPathName(path
)
2227 print "Cannot get long path for %s" % path
2231 ExpandPath
= staticmethod(ExpandPath
)
2233 #----------------------------------------------------------------------------
2234 # Overridden methods
2235 #----------------------------------------------------------------------------
2237 def __init__(self
, serviceName
, embeddedWindowLocation
= wx
.lib
.pydocview
.EMBEDDED_WINDOW_LEFT
):
2238 Service
.Service
.__init
__(self
, serviceName
, embeddedWindowLocation
)
2239 self
.BREAKPOINT_DICT_STRING
= "MasterBreakpointDict"
2240 config
= wx
.ConfigBase_Get()
2241 pickledbps
= config
.Read(self
.BREAKPOINT_DICT_STRING
)
2244 self
._masterBPDict
= pickle
.loads(pickledbps
.encode('ascii'))
2246 tp
, val
, tb
= sys
.exc_info()
2247 traceback
.print_exception(tp
,val
,tb
)
2248 self
._masterBPDict
= {}
2250 self
._masterBPDict
= {}
2252 self
.projectPath
= None
2253 self
.fileToDebug
= None
2254 self
.phpDbgParam
= None
2255 self
.dbgLanguage
= projectmodel
.LANGUAGE_DEFAULT
2257 def OnCloseFrame(self
, event
):
2258 # IS THIS THE RIGHT PLACE?
2260 config
= wx
.ConfigBase_Get()
2261 config
.Write(self
.BREAKPOINT_DICT_STRING
, pickle
.dumps(self
._masterBPDict
))
2263 tp
,val
,tb
= sys
.exc_info()
2264 traceback
.print_exception(tp
, val
, tb
)
2267 def _CreateView(self
):
2268 return DebuggerView(self
)
2271 #----------------------------------------------------------------------------
2272 # Service specific methods
2273 #----------------------------------------------------------------------------
2275 def InstallControls(self
, frame
, menuBar
= None, toolBar
= None, statusBar
= None, document
= None):
2276 #Service.Service.InstallControls(self, frame, menuBar, toolBar, statusBar, document)
2278 config
= wx
.ConfigBase_Get()
2280 debuggerMenu
= wx
.Menu()
2281 if not menuBar
.FindItemById(DebuggerService
.CLEAR_ALL_BREAKPOINTS
):
2283 debuggerMenu
.Append(DebuggerService
.RUN_ID
, _("&Run...\tCtrl+R"), _("Runs a file"))
2284 wx
.EVT_MENU(frame
, DebuggerService
.RUN_ID
, frame
.ProcessEvent
)
2285 wx
.EVT_UPDATE_UI(frame
, DebuggerService
.RUN_ID
, frame
.ProcessUpdateUIEvent
)
2287 debuggerMenu
.Append(DebuggerService
.DEBUG_ID
, _("&Debug...\tCtrl+D"), _("Debugs a file"))
2288 wx
.EVT_MENU(frame
, DebuggerService
.DEBUG_ID
, frame
.ProcessEvent
)
2289 wx
.EVT_UPDATE_UI(frame
, DebuggerService
.DEBUG_ID
, frame
.ProcessUpdateUIEvent
)
2291 debuggerMenu
.Append(DebuggerService
.RUN_LAST_ID
, _("&Run Using Last Settings\tF5"), _("Runs a file using previous settings"))
2292 wx
.EVT_MENU(frame
, DebuggerService
.RUN_LAST_ID
, frame
.ProcessEvent
)
2293 wx
.EVT_UPDATE_UI(frame
, DebuggerService
.RUN_LAST_ID
, frame
.ProcessUpdateUIEvent
)
2295 debuggerMenu
.Append(DebuggerService
.DEBUG_LAST_ID
, _("&Debug Using Last Settings\tF8"), _("Debugs a file using previous settings"))
2296 wx
.EVT_MENU(frame
, DebuggerService
.DEBUG_LAST_ID
, frame
.ProcessEvent
)
2297 wx
.EVT_UPDATE_UI(frame
, DebuggerService
.DEBUG_LAST_ID
, frame
.ProcessUpdateUIEvent
)
2299 if not ACTIVEGRID_BASE_IDE
:
2300 debuggerMenu
.AppendSeparator()
2301 debuggerMenu
.Append(DebuggerService
.DEBUG_WEBSERVER_ID
, _("Debug Internal Web Server"), _("Debugs the internal webservier"))
2302 wx
.EVT_MENU(frame
, DebuggerService
.DEBUG_WEBSERVER_ID
, frame
.ProcessEvent
)
2303 wx
.EVT_UPDATE_UI(frame
, DebuggerService
.DEBUG_WEBSERVER_ID
, frame
.ProcessUpdateUIEvent
)
2304 debuggerMenu
.Append(DebuggerService
.RUN_WEBSERVER_ID
, _("Restart Internal Web Server"), _("Restarts the internal webservier"))
2305 wx
.EVT_MENU(frame
, DebuggerService
.RUN_WEBSERVER_ID
, frame
.ProcessEvent
)
2306 wx
.EVT_UPDATE_UI(frame
, DebuggerService
.RUN_WEBSERVER_ID
, frame
.ProcessUpdateUIEvent
)
2308 frame
.Bind(EVT_DEBUG_INTERNAL
, frame
.ProcessEvent
)
2309 debuggerMenu
.AppendSeparator()
2311 debuggerMenu
.Append(DebuggerService
.TOGGLE_BREAKPOINT_ID
, _("&Toggle Breakpoint\tCtrl+B"), _("Toggle a breakpoint"))
2312 wx
.EVT_MENU(frame
, DebuggerService
.TOGGLE_BREAKPOINT_ID
, self
.ProcessEvent
)
2313 wx
.EVT_UPDATE_UI(frame
, DebuggerService
.TOGGLE_BREAKPOINT_ID
, self
.ProcessUpdateUIEvent
)
2315 debuggerMenu
.Append(DebuggerService
.CLEAR_ALL_BREAKPOINTS
, _("&Clear All Breakpoints"), _("Clear All Breakpoints"))
2316 wx
.EVT_MENU(frame
, DebuggerService
.CLEAR_ALL_BREAKPOINTS
, self
.ProcessEvent
)
2317 wx
.EVT_UPDATE_UI(frame
, DebuggerService
.CLEAR_ALL_BREAKPOINTS
, self
.ProcessUpdateUIEvent
)
2320 viewMenuIndex
= menuBar
.FindMenu(_("&Project"))
2321 menuBar
.Insert(viewMenuIndex
+ 1, debuggerMenu
, _("&Run"))
2323 toolBar
.AddSeparator()
2324 toolBar
.AddTool(DebuggerService
.RUN_LAST_ID
, getRunningManBitmap(), shortHelpString
= _("Run Using Last Settings"), longHelpString
= _("Run Using Last Settings"))
2325 toolBar
.AddTool(DebuggerService
.DEBUG_LAST_ID
, getDebuggingManBitmap(), shortHelpString
= _("Debug Using Last Settings"), longHelpString
= _("Debug Using Last Settings"))
2332 #----------------------------------------------------------------------------
2333 # Event Processing Methods
2334 #----------------------------------------------------------------------------
2336 def ProcessEventBeforeWindows(self
, event
):
2340 def ProcessEvent(self
, event
):
2341 if Service
.Service
.ProcessEvent(self
, event
):
2344 an_id
= event
.GetId()
2345 if an_id
== DebuggerService
.TOGGLE_BREAKPOINT_ID
:
2346 self
.OnToggleBreakpoint(event
)
2348 elif an_id
== DebuggerService
.CLEAR_ALL_BREAKPOINTS
:
2349 self
.ClearAllBreakpoints()
2351 elif an_id
== DebuggerService
.RUN_ID
:
2352 self
.OnRunProject(event
)
2354 elif an_id
== DebuggerService
.DEBUG_ID
:
2355 self
.OnDebugProject(event
)
2357 elif an_id
== DebuggerService
.RUN_LAST_ID
:
2358 self
.OnRunProject(event
, showDialog
=False)
2360 elif an_id
== DebuggerService
.DEBUG_LAST_ID
:
2361 self
.OnDebugProject(event
, showDialog
=False)
2363 elif an_id
== DebuggerService
.DEBUG_WEBSERVER_ID
:
2364 self
.OnDebugWebServer(event
)
2366 elif an_id
== DebuggerService
.DEBUG_WEBSERVER_CONTINUE_ID
:
2367 self
.OnDebugWebServerContinue(event
)
2369 elif an_id
== DebuggerService
.DEBUG_WEBSERVER_NOW_RUN_PROJECT_ID
:
2370 self
.WaitDebuggerThenRunProject()
2372 elif an_id
== DebuggerService
.RUN_WEBSERVER_ID
:
2373 self
.OnRunWebServer(event
)
2377 def ProcessUpdateUIEvent(self
, event
):
2378 if Service
.Service
.ProcessUpdateUIEvent(self
, event
):
2381 an_id
= event
.GetId()
2382 if an_id
== DebuggerService
.TOGGLE_BREAKPOINT_ID
:
2383 currentView
= self
.GetDocumentManager().GetCurrentView()
2384 event
.Enable(isinstance(currentView
, PythonEditor
.PythonView
))
2386 elif an_id
== DebuggerService
.CLEAR_ALL_BREAKPOINTS
:
2387 event
.Enable(self
.HasBreakpointsSet())
2389 elif (an_id
== DebuggerService
.RUN_ID
2390 or an_id
== DebuggerService
.RUN_LAST_ID
2391 or an_id
== DebuggerService
.DEBUG_ID
2392 or an_id
== DebuggerService
.DEBUG_LAST_ID
):
2393 event
.Enable(self
.HasAnyFiles())
2398 #----------------------------------------------------------------------------
2400 #----------------------------------------------------------------------------
2402 def OnDebugProject(self
, event
, showDialog
=True):
2403 if _WINDOWS
and not _PYWIN32_INSTALLED
:
2404 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."))
2406 if not Executor
.GetPythonExecutablePath():
2408 if BaseDebuggerUI
.DebuggerRunning():
2409 wx
.MessageBox(_("A debugger is already running. Please shut down the other debugger first."), _("Debugger Running"))
2411 config
= wx
.ConfigBase_Get()
2412 host
= config
.Read("DebuggerHostName", DEFAULT_HOST
)
2414 wx
.MessageBox(_("No debugger host set. Please go to Tools->Options->Debugger and set one."), _("No Debugger Host"))
2417 self
.ShowWindow(True)
2418 projectService
= wx
.GetApp().GetService(ProjectEditor
.ProjectService
)
2420 dlg
= CommandPropertiesDialog(self
.GetView().GetFrame(), 'Debug File', projectService
, None, okButtonName
="Debug", debugging
=True)
2423 dlg
.CenterOnParent()
2425 showDialog
= dlg
.MustShowDialog()
2426 if showDialog
and dlg
.ShowModal() == wx
.ID_OK
:
2427 projectPath
, fileToDebug
, initialArgs
, startIn
, isPython
, environment
= dlg
.GetSettings()
2428 elif not showDialog
:
2429 projectPath
, fileToDebug
, initialArgs
, startIn
, isPython
, environment
= dlg
.GetSettings()
2434 self
.PromptToSaveFiles()
2435 shortFile
= os
.path
.basename(fileToDebug
)
2436 fileToDebug
= DebuggerService
.ExpandPath(fileToDebug
)
2437 if fileToDebug
.endswith('.bpel'):
2438 self
.projectPath
= projectPath
2439 self
.fileToDebug
= fileToDebug
2442 # TODO: merge getting project stuff and save the results for
2443 # WaitDebuggerThenRunProject() which currently does it again.
2445 projects
= projectService
.FindProjectByFile(projectPath
)
2448 project
= projects
[0]
2449 lang
= project
.GetAppInfo().language
2451 self
.dbgLanguage
= lang
2453 dbgService
= wx
.GetApp().GetService(DebuggerService
)
2455 evt
= DebugInternalWebServer()
2456 evt
.SetId(DebuggerService
.DEBUG_WEBSERVER_CONTINUE_ID
)
2457 wx
.PostEvent(dbgService
._frame
, evt
)
2459 if lang
== projectmodel
.LANGUAGE_PHP
:
2460 evt
= DebugInternalWebServer()
2461 evt
.SetId(DebuggerService
.DEBUG_WEBSERVER_NOW_RUN_PROJECT_ID
)
2462 wx
.PostEvent(dbgService
._frame
, evt
)
2466 elif fileToDebug
.endswith('.php'):
2467 page
= PHPDebuggerUI(Service
.ServiceView
.bottomTab
, -1, str(fileToDebug
), self
)
2468 count
= Service
.ServiceView
.bottomTab
.GetPageCount()
2469 Service
.ServiceView
.bottomTab
.AddPage(page
, _("Debugging: ") + shortFile
)
2470 Service
.ServiceView
.bottomTab
.SetSelection(count
)
2472 fullPhpScriptPath
= os
.path
.normpath(fileToDebug
)
2473 environment
["REDIRECT_STATUS"] = "200"
2474 environment
["REDIRECT_URL"] = fullPhpScriptPath
2475 environment
["SERVER_SOFTWARE"] = "AG PHP Debugger 1.7"
2476 environment
["SERVER_NAME"] = "localhost"
2477 environment
["SERVER_ADDR"] = "127.0.0.1"
2478 environment
["SERVER_PORT"] = "80"
2479 environment
["REMOTE_ADDR"] = "127.0.0.1"
2480 environment
["SCRIPT_FILENAME"] = "php"
2481 environment
["GATEWAY_INTERFACE"] = "CGI/1.1"
2482 environment
["SERVER_PROTOCOL"] = "HTTP/1.1"
2483 environment
["REQUEST_METHOD"] = "GET"
2484 environment
["REQUEST_URI"] = fullPhpScriptPath
2485 environment
["PATH_INFO"] = fullPhpScriptPath
2486 environment
["PATH_TRANSLATED"] = fullPhpScriptPath
2487 environment
["HTTP_COOKIE"] = "DBGSESSID=11439636363807700001@clienthost:10001"
2489 page
.Execute(initialArgs
, startIn
, environment
)
2492 page
= PythonDebuggerUI(Service
.ServiceView
.bottomTab
, -1, str(fileToDebug
), self
)
2493 count
= Service
.ServiceView
.bottomTab
.GetPageCount()
2494 Service
.ServiceView
.bottomTab
.AddPage(page
, _("Debugging: ") + shortFile
)
2495 Service
.ServiceView
.bottomTab
.SetSelection(count
)
2496 page
.Execute(initialArgs
, startIn
, environment
)
2500 def WaitDebuggerThenRunProject(self
):
2502 #while not BaseDebuggerUI.DebuggerPastAutoContinue():
2504 # wx.GetApp().Yield(True)
2505 # print "After Yield"
2507 projectService
= wx
.GetApp().GetService(ProjectEditor
.ProjectService
)
2508 projects
= projectService
.FindProjectByFile(self
.projectPath
)
2511 project
= projects
[0]
2513 deployFilePath
= project
.GenerateDeployment()
2514 except ProjectEditor
.DataServiceExistenceException
, e
:
2515 dataSourceName
= str(e
)
2516 projectService
.PromptForMissingDataSource(dataSourceName
)
2518 projectService
.RunProcessModel(self
.fileToDebug
, project
.GetAppInfo().language
, deployFilePath
)
2520 def OnDebugWebServerContinue(self
, event
):
2521 self
.OnDebugWebServer(event
, autoContinue
=True)
2523 def OnDebugWebServer(self
, event
, autoContinue
=False):
2524 #print "xxxxx debugging OnDebugWebServer"
2525 if _WINDOWS
and not _PYWIN32_INSTALLED
:
2526 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."))
2528 if not Executor
.GetPythonExecutablePath():
2530 if BaseDebuggerUI
.DebuggerRunning():
2531 wx
.MessageBox(_("A debugger is already running. Please shut down the other debugger first."), _("Debugger Running"))
2533 import WebServerService
2534 wsService
= wx
.GetApp().GetService(WebServerService
.WebServerService
)
2535 fileName
, args
= wsService
.StopAndPrepareToDebug()
2536 #print "xxxxx OnDebugWebServer: fileName=%s, args=%s" % (repr(fileName), repr(args))
2537 config
= wx
.ConfigBase_Get()
2538 host
= config
.Read("DebuggerHostName", DEFAULT_HOST
)
2540 wx
.MessageBox(_("No debugger host set. Please go to Tools->Options->Debugger and set one."), _("No Debugger Host"))
2543 if self
.dbgLanguage
== projectmodel
.LANGUAGE_PHP
:
2544 page
= PHPDebuggerUI(Service
.ServiceView
.bottomTab
, -1, fileName
, self
)
2546 page
= PythonDebuggerUI(Service
.ServiceView
.bottomTab
, -1, fileName
, self
, autoContinue
)
2548 count
= Service
.ServiceView
.bottomTab
.GetPageCount()
2549 Service
.ServiceView
.bottomTab
.AddPage(page
, _("Debugging: Internal WebServer"))
2550 Service
.ServiceView
.bottomTab
.SetSelection(count
)
2551 page
.Execute(args
, startIn
=sysutilslib
.mainModuleDir
, environment
=os
.environ
, onWebServer
= True)
2555 def OnRunWebServer(self
, event
):
2556 if not Executor
.GetPythonExecutablePath():
2558 import WebServerService
2559 wsService
= wx
.GetApp().GetService(WebServerService
.WebServerService
)
2560 wsService
.ShutDownAndRestart()
2562 def HasAnyFiles(self
):
2563 docs
= wx
.GetApp().GetDocumentManager().GetDocuments()
2564 return len(docs
) > 0
2566 def PromptToSaveFiles(self
, running
=True):
2567 filesModified
= False
2568 docs
= wx
.GetApp().GetDocumentManager().GetDocuments()
2570 if doc
.IsModified():
2571 filesModified
= True
2574 frame
= self
.GetView().GetFrame()
2576 yesNoMsg
= wx
.MessageDialog(frame
,
2577 _("Files have been modified.\nWould you like to save all files before running?"),
2579 wx
.YES_NO|wx
.ICON_QUESTION
2582 yesNoMsg
= wx
.MessageDialog(frame
,
2583 _("Files have been modified.\nWould you like to save all files before debugging?"),
2585 wx
.YES_NO|wx
.ICON_QUESTION
2587 yesNoMsg
.CenterOnParent()
2588 if yesNoMsg
.ShowModal() == wx
.ID_YES
:
2589 docs
= wx
.GetApp().GetDocumentManager().GetDocuments()
2595 BaseDebuggerUI
.ShutdownAllDebuggers()
2596 RunCommandUI
.ShutdownAllRunners()
2598 def OnRunProject(self
, event
, showDialog
=True):
2599 if _WINDOWS
and not _PYWIN32_INSTALLED
:
2600 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."))
2602 if not Executor
.GetPythonExecutablePath():
2604 projectService
= wx
.GetApp().GetService(ProjectEditor
.ProjectService
)
2606 dlg
= CommandPropertiesDialog(self
.GetView().GetFrame(), 'Run', projectService
, None)
2609 dlg
.CenterOnParent()
2611 showDialog
= dlg
.MustShowDialog()
2612 if showDialog
and dlg
.ShowModal() == wx
.ID_OK
:
2613 projectPath
, fileToRun
, initialArgs
, startIn
, isPython
, environment
= dlg
.GetSettings()
2614 elif not showDialog
:
2615 projectPath
, fileToRun
, initialArgs
, startIn
, isPython
, environment
= dlg
.GetSettings()
2620 self
.PromptToSaveFiles()
2621 if fileToRun
.endswith('bpel'):
2622 projects
= projectService
.FindProjectByFile(projectPath
)
2625 project
= projects
[0]
2627 deployFilePath
= project
.GenerateDeployment()
2628 except ProjectEditor
.DataServiceExistenceException
, e
:
2629 dataSourceName
= str(e
)
2630 projectService
.PromptForMissingDataSource(dataSourceName
)
2632 projectService
.RunProcessModel(fileToRun
, project
.GetAppInfo().language
, deployFilePath
)
2635 self
.ShowWindow(True)
2636 shortFile
= os
.path
.basename(fileToRun
)
2637 page
= RunCommandUI(Service
.ServiceView
.bottomTab
, -1, str(fileToRun
))
2638 count
= Service
.ServiceView
.bottomTab
.GetPageCount()
2639 Service
.ServiceView
.bottomTab
.AddPage(page
, "Running: " + shortFile
)
2640 Service
.ServiceView
.bottomTab
.SetSelection(count
)
2641 page
.Execute(initialArgs
, startIn
, environment
, onWebServer
= True)
2643 def OnToggleBreakpoint(self
, event
, line
=-1, fileName
=None):
2645 view
= wx
.GetApp().GetDocumentManager().GetCurrentView()
2646 # Test to make sure we aren't the project view.
2647 if not hasattr(view
, 'MarkerExists'):
2649 fileName
= wx
.GetApp().GetDocumentManager().GetCurrentDocument().GetFilename()
2651 line
= view
.GetCtrl().GetCurrentLine()
2654 if self
.BreakpointSet(fileName
, line
+ 1):
2655 self
.ClearBreak(fileName
, line
+ 1)
2657 view
.GetCtrl().Refresh()
2659 self
.SetBreak(fileName
, line
+ 1)
2661 view
.GetCtrl().Refresh()
2662 # Now refresh all the markers icons in all the open views.
2663 self
.ClearAllBreakpointMarkers()
2664 self
.SetAllBreakpointMarkers()
2666 def SilentToggleBreakpoint(self
, fileName
, line
):
2668 for lineNumber
in self
.GetBreakpointList(fileName
):
2669 if int(lineNumber
) == int(line
):
2673 self
.SetBreak(fileName
, line
)
2675 self
.ClearBreak(fileName
, line
)
2677 def SetBreak(self
, fileName
, line
):
2678 expandedName
= DebuggerService
.ExpandPath(fileName
)
2679 if not self
._masterBPDict
.has_key(expandedName
):
2680 self
._masterBPDict
[expandedName
] = [line
]
2682 self
._masterBPDict
[expandedName
] += [line
]
2683 # If we're already debugging, pass this bp off to the PythonDebuggerCallback
2684 self
.NotifyDebuggersOfBreakpointChange()
2686 def NotifyDebuggersOfBreakpointChange(self
):
2687 BaseDebuggerUI
.NotifyDebuggersOfBreakpointChange()
2689 def GetBreakpointList(self
, fileName
):
2690 expandedName
= DebuggerService
.ExpandPath(fileName
)
2691 if not self
._masterBPDict
.has_key(expandedName
):
2694 return self
._masterBPDict
[expandedName
]
2696 def SetBreakpointList(self
, fileName
, bplist
):
2697 expandedName
= DebuggerService
.ExpandPath(fileName
)
2698 self
._masterBPDict
[expandedName
] = bplist
2700 def BreakpointSet(self
, fileName
, line
):
2701 expandedName
= DebuggerService
.ExpandPath(fileName
)
2702 if not self
._masterBPDict
.has_key(expandedName
):
2706 for number
in self
._masterBPDict
[expandedName
]:
2707 if(int(number
) == int(line
)):
2711 def ClearBreak(self
, fileName
, line
):
2712 expandedName
= DebuggerService
.ExpandPath(fileName
)
2713 if not self
._masterBPDict
.has_key(expandedName
):
2714 print "In ClearBreak: no key"
2718 for number
in self
._masterBPDict
[expandedName
]:
2719 if(int(number
) != int(line
)):
2720 newList
.append(number
)
2721 self
._masterBPDict
[expandedName
] = newList
2722 self
.NotifyDebuggersOfBreakpointChange()
2724 def HasBreakpointsSet(self
):
2725 for key
, value
in self
._masterBPDict
.items():
2730 def ClearAllBreakpoints(self
):
2731 self
._masterBPDict
= {}
2732 self
.NotifyDebuggersOfBreakpointChange()
2733 self
.ClearAllBreakpointMarkers()
2735 def ClearAllBreakpointMarkers(self
):
2736 openDocs
= wx
.GetApp().GetDocumentManager().GetDocuments()
2737 for openDoc
in openDocs
:
2738 if isinstance(openDoc
, CodeEditor
.CodeDocument
):
2739 openDoc
.GetFirstView().MarkerDeleteAll(CodeEditor
.CodeCtrl
.BREAKPOINT_MARKER_NUM
)
2741 def UpdateBreakpointsFromMarkers(self
, view
, fileName
):
2742 newbpLines
= view
.GetMarkerLines(CodeEditor
.CodeCtrl
.BREAKPOINT_MARKER_NUM
)
2743 self
.SetBreakpointList(fileName
, newbpLines
)
2745 def GetMasterBreakpointDict(self
):
2746 return self
._masterBPDict
2748 def SetAllBreakpointMarkers(self
):
2749 openDocs
= wx
.GetApp().GetDocumentManager().GetDocuments()
2750 for openDoc
in openDocs
:
2751 if(isinstance(openDoc
, CodeEditor
.CodeDocument
)):
2752 self
.SetCurrentBreakpointMarkers(openDoc
.GetFirstView())
2754 def SetCurrentBreakpointMarkers(self
, view
):
2755 if isinstance(view
, CodeEditor
.CodeView
) and hasattr(view
, 'GetDocument'):
2756 view
.MarkerDeleteAll(CodeEditor
.CodeCtrl
.BREAKPOINT_MARKER_NUM
)
2757 for linenum
in self
.GetBreakpointList(view
.GetDocument().GetFilename()):
2758 view
.MarkerAdd(lineNum
=int(linenum
) - 1, marker_index
=CodeEditor
.CodeCtrl
.BREAKPOINT_MARKER_NUM
)
2760 def GetPhpDbgParam(self
):
2761 return self
.phpDbgParam
2763 def SetPhpDbgParam(self
, value
= None):
2764 self
.phpDbgParam
= value
2766 class DebuggerOptionsPanel(wx
.Panel
):
2769 def __init__(self
, parent
, id):
2770 wx
.Panel
.__init
__(self
, parent
, id)
2772 config
= wx
.ConfigBase_Get()
2773 localHostStaticText
= wx
.StaticText(self
, -1, _("Local Host Name:"))
2774 self
._LocalHostTextCtrl
= wx
.TextCtrl(self
, -1, config
.Read("DebuggerHostName", DEFAULT_HOST
), size
= (150, -1))
2775 portNumberStaticText
= wx
.StaticText(self
, -1, _("Port Range:"))
2776 dashStaticText
= wx
.StaticText(self
, -1, _("through to"))
2777 startingPort
=config
.ReadInt("DebuggerStartingPort", DEFAULT_PORT
)
2778 self
._PortNumberTextCtrl
= wx
.lib
.intctrl
.IntCtrl(self
, -1, startingPort
, size
= (50, -1))
2779 self
._PortNumberTextCtrl
.SetMin(1)#What are real values?
2780 self
._PortNumberTextCtrl
.SetMax(65514) #What are real values?
2781 self
.Bind(wx
.lib
.intctrl
.EVT_INT
, self
.MinPortChange
, self
._PortNumberTextCtrl
)
2783 self
._EndPortNumberTextCtrl
= wx
.lib
.intctrl
.IntCtrl(self
, -1, startingPort
+ PORT_COUNT
, size
= (50, -1))
2784 self
._EndPortNumberTextCtrl
.SetMin(22)#What are real values?
2785 self
._EndPortNumberTextCtrl
.SetMax(65535)#What are real values?
2786 self
._EndPortNumberTextCtrl
.Enable( False )
2787 debuggerPanelBorderSizer
= wx
.BoxSizer(wx
.VERTICAL
)
2788 debuggerPanelSizer
= wx
.GridBagSizer(hgap
= 5, vgap
= 5)
2789 debuggerPanelSizer
.Add( localHostStaticText
, (0,0), flag
=wx
.ALIGN_CENTER_VERTICAL|wx
.ALIGN_LEFT
)
2790 debuggerPanelSizer
.Add( self
._LocalHostTextCtrl
, (0,1), (1,3), flag
=wx
.EXPAND|wx
.ALIGN_CENTER
)
2791 debuggerPanelSizer
.Add( portNumberStaticText
, (1,0), flag
=wx
.ALIGN_LEFT|wx
.ALIGN_CENTER_VERTICAL
)
2792 debuggerPanelSizer
.Add( self
._PortNumberTextCtrl
, (1,1), flag
=wx
.ALIGN_CENTER
)
2793 debuggerPanelSizer
.Add( dashStaticText
, (1,2), flag
=wx
.ALIGN_CENTER
)
2794 debuggerPanelSizer
.Add( self
._EndPortNumberTextCtrl
, (1,3), flag
=wx
.ALIGN_CENTER
)
2795 FLUSH_PORTS_ID
= wx
.NewId()
2796 self
._flushPortsButton
= wx
.Button(self
, FLUSH_PORTS_ID
, "Reset Port List")
2797 wx
.EVT_BUTTON(parent
, FLUSH_PORTS_ID
, self
.FlushPorts
)
2798 debuggerPanelSizer
.Add(self
._flushPortsButton
, (2,2), (1,2), flag
=wx
.ALIGN_RIGHT
)
2800 debuggerPanelBorderSizer
.Add(debuggerPanelSizer
, 0, wx
.ALL
, SPACE
)
2801 self
.SetSizer(debuggerPanelBorderSizer
)
2803 parent
.AddPage(self
, _("Debugger"))
2805 def FlushPorts(self
, event
):
2806 if self
._PortNumberTextCtrl
.IsInBounds():
2807 config
= wx
.ConfigBase_Get()
2808 config
.WriteInt("DebuggerStartingPort", self
._PortNumberTextCtrl
.GetValue())
2809 PythonDebuggerUI
.NewPortRange()
2811 wx
.MessageBox(_("The starting port is not valid. Please change the value and try again.", "Invalid Starting Port Number"))
2813 def MinPortChange(self
, event
):
2814 self
._EndPortNumberTextCtrl
.Enable( True )
2815 self
._EndPortNumberTextCtrl
.SetValue( self
._PortNumberTextCtrl
.GetValue() + PORT_COUNT
)
2816 self
._EndPortNumberTextCtrl
.Enable( False )
2818 def OnOK(self
, optionsDialog
):
2819 config
= wx
.ConfigBase_Get()
2820 config
.Write("DebuggerHostName", self
._LocalHostTextCtrl
.GetValue())
2821 if self
._PortNumberTextCtrl
.IsInBounds():
2822 config
.WriteInt("DebuggerStartingPort", self
._PortNumberTextCtrl
.GetValue())
2826 return getContinueIcon()
2829 class CommandPropertiesDialog(wx
.Dialog
):
2830 def __init__(self
, parent
, title
, projectService
, currentProjectDocument
, okButtonName
="Run", debugging
=False):
2831 self
._projService
= projectService
2834 self
._phpext
= '.php'
2835 for template
in self
._projService
.GetDocumentManager().GetTemplates():
2836 if not ACTIVEGRID_BASE_IDE
and template
.GetDocumentType() == ProcessModelEditor
.ProcessModelDocument
:
2837 self
._pmext
= template
.GetDefaultExtension()
2839 self
._currentProj
= projectService
.GetCurrentProject()
2840 self
._projectNameList
, self
._projectDocumentList
, selectedIndex
= self
.GetProjectList()
2841 if not self
._projectNameList
:
2842 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"))
2843 raise Exception("Nothing to Run or Debug.")
2845 wx
.Dialog
.__init
__(self
, parent
, -1, title
)
2847 projStaticText
= wx
.StaticText(self
, -1, _("Project:"))
2848 fileStaticText
= wx
.StaticText(self
, -1, _("File:"))
2849 argsStaticText
= wx
.StaticText(self
, -1, _("Arguments:"))
2850 startInStaticText
= wx
.StaticText(self
, -1, _("Start in:"))
2851 pythonPathStaticText
= wx
.StaticText(self
, -1, _("PYTHONPATH:"))
2852 postpendStaticText
= _("Postpend win32api path")
2853 cpPanelBorderSizer
= wx
.BoxSizer(wx
.VERTICAL
)
2854 self
._projList
= wx
.Choice(self
, -1, choices
=self
._projectNameList
)
2855 self
.Bind(wx
.EVT_CHOICE
, self
.EvtListBox
, self
._projList
)
2858 if wx
.Platform
== "__WXMAC__":
2860 flexGridSizer
= wx
.GridBagSizer(GAP
, GAP
)
2862 flexGridSizer
.Add(projStaticText
, (0,0), flag
=wx
.ALIGN_CENTER_VERTICAL|wx
.ALIGN_LEFT
)
2863 flexGridSizer
.Add(self
._projList
, (0,1), (1,2), flag
=wx
.EXPAND
)
2865 flexGridSizer
.Add(fileStaticText
, (1,0), flag
=wx
.ALIGN_CENTER_VERTICAL|wx
.ALIGN_LEFT
)
2866 self
._fileList
= wx
.Choice(self
, -1)
2867 self
.Bind(wx
.EVT_CHOICE
, self
.OnFileSelected
, self
._fileList
)
2868 flexGridSizer
.Add(self
._fileList
, (1,1), (1,2), flag
=wx
.EXPAND
)
2870 config
= wx
.ConfigBase_Get()
2871 self
._lastArguments
= config
.Read(self
.GetKey("LastRunArguments"))
2872 self
._argsEntry
= wx
.TextCtrl(self
, -1, str(self
._lastArguments
))
2873 self
._argsEntry
.SetToolTipString(str(self
._lastArguments
))
2875 flexGridSizer
.Add(argsStaticText
, (2,0), flag
=wx
.ALIGN_CENTER_VERTICAL|wx
.ALIGN_LEFT
)
2876 flexGridSizer
.Add(self
._argsEntry
, (2,1), (1,2), flag
=wx
.EXPAND
)
2878 flexGridSizer
.Add(startInStaticText
, (3,0), flag
=wx
.ALIGN_CENTER_VERTICAL|wx
.ALIGN_LEFT
)
2879 self
._lastStartIn
= config
.Read(self
.GetKey("LastRunStartIn"))
2880 if not self
._lastStartIn
:
2881 self
._lastStartIn
= str(os
.getcwd())
2882 self
._startEntry
= wx
.TextCtrl(self
, -1, self
._lastStartIn
)
2883 self
._startEntry
.SetToolTipString(self
._lastStartIn
)
2885 flexGridSizer
.Add(self
._startEntry
, (3,1), flag
=wx
.EXPAND
)
2886 self
._findDir
= wx
.Button(self
, -1, _("Browse..."))
2887 self
.Bind(wx
.EVT_BUTTON
, self
.OnFindDirClick
, self
._findDir
)
2888 flexGridSizer
.Add(self
._findDir
, (3,2))
2890 flexGridSizer
.Add(pythonPathStaticText
, (4,0), flag
=wx
.ALIGN_CENTER_VERTICAL|wx
.ALIGN_LEFT
)
2891 if os
.environ
.has_key('PYTHONPATH'):
2892 startval
= os
.environ
['PYTHONPATH']
2895 self
._lastPythonPath
= config
.Read(self
.GetKey("LastPythonPath"), startval
)
2896 self
._pythonPathEntry
= wx
.TextCtrl(self
, -1, self
._lastPythonPath
)
2897 self
._pythonPathEntry
.SetToolTipString(self
._lastPythonPath
)
2898 flexGridSizer
.Add(self
._pythonPathEntry
, (4,1), (1,2), flag
=wx
.EXPAND
)
2900 if debugging
and _WINDOWS
:
2901 self
._postpendCheckBox
= wx
.CheckBox(self
, -1, postpendStaticText
)
2902 checked
= bool(config
.ReadInt(self
.GetKey("PythonPathPostpend"), 1))
2903 self
._postpendCheckBox
.SetValue(checked
)
2904 flexGridSizer
.Add(self
._postpendCheckBox
, (5,1), flag
=wx
.EXPAND
)
2905 cpPanelBorderSizer
.Add(flexGridSizer
, 0, flag
=wx
.ALL
, border
=10)
2907 box
= wx
.StdDialogButtonSizer()
2908 self
._okButton
= wx
.Button(self
, wx
.ID_OK
, okButtonName
)
2909 self
._okButton
.SetDefault()
2910 self
._okButton
.SetHelpText(_("The ") + okButtonName
+ _(" button completes the dialog"))
2911 box
.AddButton(self
._okButton
)
2912 self
.Bind(wx
.EVT_BUTTON
, self
.OnOKClick
, self
._okButton
)
2913 btn
= wx
.Button(self
, wx
.ID_CANCEL
, _("Cancel"))
2914 btn
.SetHelpText(_("The Cancel button cancels the dialog."))
2917 cpPanelBorderSizer
.Add(box
, 0, flag
=wx
.ALIGN_RIGHT|wx
.ALL
, border
=5)
2919 self
.SetSizer(cpPanelBorderSizer
)
2921 # Set up selections based on last values used.
2922 self
._fileNameList
= None
2923 self
._selectedFileIndex
= -1
2924 lastProject
= config
.Read(self
.GetKey("LastRunProject"))
2925 lastFile
= config
.Read(self
.GetKey("LastRunFile"))
2926 self
._mustShow
= not lastFile
2928 if lastProject
in self
._projectNameList
:
2929 selectedIndex
= self
._projectNameList
.index(lastProject
)
2930 elif selectedIndex
< 0:
2932 self
._projList
.Select(selectedIndex
)
2933 self
._selectedProjectIndex
= selectedIndex
2934 self
._selectedProjectDocument
= self
._projectDocumentList
[selectedIndex
]
2935 self
.PopulateFileList(self
._selectedProjectDocument
, lastFile
)
2937 cpPanelBorderSizer
.Fit(self
)
2939 def MustShowDialog(self
):
2940 return self
._mustShow
2942 def GetKey(self
, lastPart
):
2943 if self
._currentProj
:
2944 return "%s/%s/%s" % (ProjectEditor
.PROJECT_KEY
, self
._currentProj
.GetFilename().replace(os
.sep
, '|'), lastPart
)
2947 def OnOKClick(self
, event
):
2948 startIn
= self
._startEntry
.GetValue()
2949 fileToRun
= self
._fileList
.GetStringSelection()
2951 wx
.MessageBox(_("You must select a file to proceed. Note that not all projects have files that can be run or debugged."))
2953 isPython
= fileToRun
.endswith(self
._pyext
)
2954 if isPython
and not os
.path
.exists(startIn
):
2955 wx
.MessageBox(_("Starting directory does not exist. Please change this value."))
2957 config
= wx
.ConfigBase_Get()
2958 config
.Write(self
.GetKey("LastRunProject"), self
._projectNameList
[self
._selectedProjectIndex
])
2959 config
.Write(self
.GetKey("LastRunFile"), fileToRun
)
2960 # Don't update the arguments or starting directory unless we're runing python.
2962 config
.Write(self
.GetKey("LastRunArguments"), self
._argsEntry
.GetValue())
2963 config
.Write(self
.GetKey("LastRunStartIn"), self
._startEntry
.GetValue())
2964 config
.Write(self
.GetKey("LastPythonPath"),self
._pythonPathEntry
.GetValue())
2965 if hasattr(self
, "_postpendCheckBox"):
2966 config
.WriteInt(self
.GetKey("PythonPathPostpend"), int(self
._postpendCheckBox
.GetValue()))
2968 self
.EndModal(wx
.ID_OK
)
2970 def GetSettings(self
):
2971 projectPath
= self
._selectedProjectDocument
.GetFilename()
2972 filename
= self
._fileNameList
[self
._selectedFileIndex
]
2973 args
= self
._argsEntry
.GetValue()
2974 startIn
= self
._startEntry
.GetValue()
2975 isPython
= filename
.endswith(self
._pyext
)
2977 if hasattr(self
, "_postpendCheckBox"):
2978 postpend
= self
._postpendCheckBox
.GetValue()
2982 env
['PYTHONPATH'] = self
._pythonPathEntry
.GetValue() + os
.pathsep
+ os
.path
.join(os
.getcwd(), "3rdparty", "pywin32")
2984 env
['PYTHONPATH'] = self
._pythonPathEntry
.GetValue()
2986 return projectPath
, filename
, args
, startIn
, isPython
, env
2988 def OnFileSelected(self
, event
):
2989 self
._selectedFileIndex
= self
._fileList
.GetSelection()
2990 self
.EnableForFileType(event
.GetString())
2992 def EnableForFileType(self
, fileName
):
2993 show
= fileName
.endswith(self
._pyext
) or fileName
.endswith(self
._phpext
)
2994 self
._startEntry
.Enable(show
)
2995 self
._findDir
.Enable(show
)
2996 self
._argsEntry
.Enable(show
)
2999 self
._lastStartIn
= self
._startEntry
.GetValue()
3000 self
._startEntry
.SetValue("")
3001 self
._lastArguments
= self
._argsEntry
.GetValue()
3002 self
._argsEntry
.SetValue("")
3004 if fileName
.endswith(self
._phpext
):
3005 self
._startEntry
.SetValue(os
.path
.dirname(fileName
))
3007 self
._startEntry
.SetValue(self
._lastStartIn
)
3008 self
._argsEntry
.SetValue(self
._lastArguments
)
3012 def OnFindDirClick(self
, event
):
3013 dlg
= wx
.DirDialog(self
, "Choose a starting directory:", self
._startEntry
.GetValue(),
3014 style
=wx
.DD_DEFAULT_STYLE|wx
.DD_NEW_DIR_BUTTON
)
3016 dlg
.CenterOnParent()
3017 if dlg
.ShowModal() == wx
.ID_OK
:
3018 self
._startEntry
.SetValue(dlg
.GetPath())
3023 def EvtListBox(self
, event
):
3024 if event
.GetString():
3025 index
= self
._projectNameList
.index(event
.GetString())
3026 self
._selectedProjectDocument
= self
._projectDocumentList
[index
]
3027 self
._selectedProjectIndex
= index
3028 self
.PopulateFileList(self
._selectedProjectDocument
)
3030 def FilterFileList(self
, list):
3031 files
= filter(lambda f
: (self
._phpext
and f
.endswith(self
._phpext
)) or (self
._pmext
and f
.endswith(self
._pmext
)) or f
.endswith(self
._pyext
), list)
3034 def PopulateFileList(self
, project
, shortNameToSelect
=None):
3035 self
._fileNameList
= self
.FilterFileList(project
.GetFiles()[:])
3036 self
._fileList
.Clear()
3037 if not self
._fileNameList
:
3039 self
._fileNameList
.sort(lambda a
, b
: cmp(os
.path
.basename(a
).lower(), os
.path
.basename(b
).lower()))
3040 strings
= map(lambda file: os
.path
.basename(file), self
._fileNameList
)
3041 for index
in range(0, len(strings
)):
3042 if shortNameToSelect
== strings
[index
]:
3043 self
._selectedFileIndex
= index
3045 self
._fileList
.Hide()
3046 self
._fileList
.AppendItems(strings
)
3047 self
._fileList
.Show()
3048 if self
._selectedFileIndex
not in range(0, len(strings
)):
3049 # Pick first bpel file if there is one.
3050 for index
in range(0, len(strings
)):
3051 if strings
[index
].endswith('.bpel'):
3052 self
._selectedFileIndex
= index
3054 # Still no selected file, use first file.
3055 if self
._selectedFileIndex
not in range(0, len(strings
)):
3056 self
._selectedFileIndex
= 0
3057 self
._fileList
.SetSelection(self
._selectedFileIndex
)
3058 self
.EnableForFileType(strings
[self
._selectedFileIndex
])
3060 def GetProjectList(self
):
3066 for document
in self
._projService
.GetDocumentManager().GetDocuments():
3067 if document
.GetDocumentTemplate().GetDocumentType() == ProjectEditor
.ProjectDocument
and len(document
.GetFiles()):
3068 docList
.append(document
)
3069 nameList
.append(os
.path
.basename(document
.GetFilename()))
3070 if document
== self
._currentProj
:
3074 #Check for open files not in any of these projects and add them to a default project
3075 def AlreadyInProject(fileName
):
3076 for projectDocument
in docList
:
3077 if projectDocument
.IsFileInProject(fileName
):
3081 unprojectedFiles
= []
3082 for document
in self
._projService
.GetDocumentManager().GetDocuments():
3083 if not ACTIVEGRID_BASE_IDE
and type(document
) == ProcessModelEditor
.ProcessModelDocument
:
3084 if not AlreadyInProject(document
.GetFilename()):
3085 unprojectedFiles
.append(document
.GetFilename())
3086 if type(document
) == PythonEditor
.PythonDocument
or type(document
) == PHPEditor
.PHPDocument
:
3087 if not AlreadyInProject(document
.GetFilename()):
3088 unprojectedFiles
.append(document
.GetFilename())
3090 if unprojectedFiles
:
3091 unprojProj
= ProjectEditor
.ProjectDocument()
3092 unprojProj
.SetFilename(_("Not in any Project"))
3093 unprojProj
.AddFiles(unprojectedFiles
)
3094 docList
.append(unprojProj
)
3095 nameList
.append(_("Not in any Project"))
3097 return nameList
, docList
, index
3100 #----------------------------------------------------------------------
3101 from wx
import ImageFromStream
, BitmapFromImage
3104 #----------------------------------------------------------------------
3107 '\x89PNG\r\n\x1a\n\x00\x00\x00\rIHDR\x00\x00\x00\x10\x00\x00\x00\x10\x08\x02\
3108 \x00\x00\x00\x90\x91h6\x00\x00\x00\x03sBIT\x08\x08\x08\xdb\xe1O\xe0\x00\x00\
3109 \x00\x85IDAT(\x91\xbd\x92A\x16\x03!\x08CI\xdf\xdc\x0b\x8e\xe6\xd1\xe0d\xe9\
3110 \x82\xd6\xc7(\x9di7\xfd\xab<\x14\x13Q\xb8\xbb\xfc\xc2\xe3\xd3\x82\x99\xb9\
3111 \xe9\xaeq\xe1`f)HF\xc4\x8dC2\x06\xbf\x8a4\xcf\x1e\x03K\xe5h\x1bH\x02\x98\xc7\
3112 \x03\x98\xa9z\x07\x00%\xd6\xa9\xd27\x90\xac\xbbk\xe5\x15I\xcdD$\xdc\xa7\xceT\
3113 5a\xce\xf3\xe4\xa0\xaa\x8bO\x12\x11\xabC\xcb\x9c}\xd57\xef\xb0\xf3\xb7\x86p\
3114 \x97\xf7\xb5\xaa\xde\xb9\xfa|-O\xbdjN\x9b\xf8\x06A\xcb\x00\x00\x00\x00IEND\
3117 def getBreakBitmap():
3118 return BitmapFromImage(getBreakImage())
3120 def getBreakImage():
3121 stream
= cStringIO
.StringIO(getBreakData())
3122 return ImageFromStream(stream
)
3125 return wx
.IconFromBitmap(getBreakBitmap())
3127 #----------------------------------------------------------------------
3129 def getClearOutputData():
3131 '\x89PNG\r\n\x1a\n\x00\x00\x00\rIHDR\x00\x00\x00\x10\x00\x00\x00\x10\x08\x06\
3132 \x00\x00\x00\x1f\xf3\xffa\x00\x00\x00\x04sBIT\x08\x08\x08\x08|\x08d\x88\x00\
3133 \x00\x00\xb7IDAT8\x8d\xa5\x93\xdd\x11\xc3 \x0c\x83%`\xa3\xee\xd4\xaeA\xc6\
3134 \xe8N\xedF%\xea\x03\t\x81\xf0\x97\xbb\xf8%G\xce\xfe\x90eC\x1a\x8b;\xe1\xf2\
3135 \x83\xd6\xa0Q2\x8de\xf5oW\xa05H\xea\xd7\x93\x84$\x18\xeb\n\x88;\'.\xd5\x1d\
3136 \x80\x07\xe1\xa1\x1d\xa2\x1cbF\x92\x0f\x80\xe0\xd1 \xb7\x14\x8c \x00*\x15\
3137 \x97\x14\x8c\x8246\x1a\xf8\x98\'/\xdf\xd8Jn\xe65\xc0\xa7\x90_L"\x01\xde\x9d\
3138 \xda\xa7\x92\xfb\xc5w\xdf\t\x07\xc4\x05ym{\xd0\x1a\xe3\xb9xS\x81\x04\x18\x05\
3139 \xc9\x04\xc9a\x00Dc9\x9d\x82\xa4\xbc\xe8P\xb2\xb5P\xac\xf2\x0c\xd4\xf5\x00\
3140 \x88>\xac\xe17\x84\xe4\xb9G\x8b7\x9f\xf3\x1fsUl^\x7f\xe7y\x0f\x00\x00\x00\
3143 def getClearOutputBitmap():
3144 return BitmapFromImage(getClearOutputImage())
3146 def getClearOutputImage():
3147 stream
= cStringIO
.StringIO(getClearOutputData())
3148 return ImageFromStream(stream
)
3150 def getClearOutputIcon():
3151 return wx
.IconFromBitmap(getClearOutputBitmap())
3153 #----------------------------------------------------------------------
3156 '\x89PNG\r\n\x1a\n\x00\x00\x00\rIHDR\x00\x00\x00\x10\x00\x00\x00\x10\x08\x02\
3157 \x00\x00\x00\x90\x91h6\x00\x00\x00\x03sBIT\x08\x08\x08\xdb\xe1O\xe0\x00\x00\
3158 \x00\xedIDAT(\x91\xa5\x90!\xae\x840\x10\x86g_\xd6"*kz\x82j\xb0h\x1c\t\' x\
3159 \x92Z\xc2\x05\x10\x95\x18\x0e\x00\x02M\x82 \xe1\nMF#jz\x80\xea&+\x9a\x10\x96\
3160 \xdd}\xfb\xc8\x1b\xd7?\xdf\x97\xfe3\xb7u]\xe1\xca\xfc\\\xa2\xff- \xe24M\xc7\
3161 \xc49wJ\xee\xc7G]\xd7\x8c1\xc6\x18\xe7\xdc\'B\x08k\xed1y\xfaa\x1cG\xad\xb5\
3162 \x94\x12\x11\x9dsy\x9e+\xa5\x84\x10;\r\x00\xb7\xd3\x95\x8c1UU\x05A\x00\x00\
3163 \xd6\xda,\xcb\x92$\xf9\xb8\x03\x00PJ\x85\x10Zk\xa5\xd4+\xfdF\x00\x80\xae\xeb\
3164 \x08!\x84\x90y\x9e\x11\xf1\x8bP\x96\xa5\xef\xdd\xb6\xad\xb5VJ\xf9\x9b\xe0\
3165 \xe9\xa6i8\xe7\xbe\xdb\xb6mi\x9a\x0e\xc3\xf0F\x88\xe3\x18\x00\xfa\xbe\x0f\
3166 \xc3\xd0\'\x9c\xf3eY\xa2(*\x8ab\xc7\x9e\xaed\x8c\xa1\x94\xben\xf5\xb1\xd2W\
3167 \xfa,\xfce.\x0b\x0f\xb8\x96e\x90gS\xe0v\x00\x00\x00\x00IEND\xaeB`\x82'
3169 def getCloseBitmap():
3170 return BitmapFromImage(getCloseImage())
3172 def getCloseImage():
3173 stream
= cStringIO
.StringIO(getCloseData())
3174 return ImageFromStream(stream
)
3177 return wx
.IconFromBitmap(getCloseBitmap())
3179 #----------------------------------------------------------------------
3180 def getContinueData():
3182 '\x89PNG\r\n\x1a\n\x00\x00\x00\rIHDR\x00\x00\x00\x10\x00\x00\x00\x10\x08\x06\
3183 \x00\x00\x00\x1f\xf3\xffa\x00\x00\x00\x04sBIT\x08\x08\x08\x08|\x08d\x88\x00\
3184 \x00\x00\xcdIDAT8\x8d\xa5\x93\xd1\r\xc20\x0cD\xef\xec,\xc0b\x88\x8d`$\x06Cb\
3185 \x81\xc6\xc7GI\xeb\x94RZq?U"\xdby\xe7SIs\xfc#\xfbU\xa0\xa8\xba\xc6\xa0og\xee\
3186 !P\xd4y\x80\x04\xf3\xc2U\x82{\x9ct\x8f\x93\xb0\xa2\xdbm\xf5\xba\'h\xcdg=`\
3187 \xeeTT\xd1\xc6o& \t\x9a\x13\x00J\x9ev\xb1\'\xa3~\x14+\xbfN\x12\x92\x00@\xe6\
3188 \x85\xdd\x00\x000w\xe6\xe2\xde\xc7|\xdf\x08\xba\x1d(\xaa2n+\xca\xcd\x8d,\xea\
3189 \x98\xc4\x07\x01\x00D\x1dd^\xa8\xa8j\x9ew\xed`\xa9\x16\x99\xde\xa6G\x8b\xd3Y\
3190 \xe6\x85]\n\r\x7f\x99\xf5\x96Jnlz#\xab\xdb\xc1\x17\x19\xb0XV\xc2\xdf\xa3)\
3191 \x85<\xe4\x88\x85.F\x9a\xf3H3\xb0\xf3g\xda\xd2\x0b\xc5_|\x17\xe8\xf5R\xd6\
3192 \x00\x00\x00\x00IEND\xaeB`\x82'
3194 def getContinueBitmap():
3195 return BitmapFromImage(getContinueImage())
3197 def getContinueImage():
3198 stream
= cStringIO
.StringIO(getContinueData())
3199 return ImageFromStream(stream
)
3201 def getContinueIcon():
3202 return wx
.IconFromBitmap(getContinueBitmap())
3204 #----------------------------------------------------------------------
3207 '\x89PNG\r\n\x1a\n\x00\x00\x00\rIHDR\x00\x00\x00\x10\x00\x00\x00\x10\x08\x06\
3208 \x00\x00\x00\x1f\xf3\xffa\x00\x00\x00\x04sBIT\x08\x08\x08\x08|\x08d\x88\x00\
3209 \x00\x00\x8eIDAT8\x8d\xa5SA\x12\xc4 \x08K\xb0\xff\xde\xe9\xbf\xb7\xa6\x87\
3210 \x1d:\xba\xa2tZn(\x84`"i\x05obk\x13\xd5CmN+\xcc\x00l\xd6\x0c\x00\xf5\xf8\x0e\
3211 gK\x06\x00 \xa5=k\x00\x00\xb0\xb2]\xd4?5f\xb1\xdb\xaf\xc6\xa2\xcb\xa8\xf0?\
3212 \x1c\x98\xae\x82\xbf\x81\xa4\x8eA\x16\xe1\n\xd1\xa4\x19\xb3\xe9\n\xce\xe8\
3213 \xf1\n\x9eg^\x18\x18\x90\xec<\x11\xf9#\x04XMZ\x19\xaac@+\x94\xd4\x99)SeP\xa1\
3214 )\xd6\x1dI\xe7*\xdc\xf4\x03\xdf~\xe7\x13T^Q?:X\x19d\x00\x00\x00\x00IEND\xaeB\
3217 def getNextBitmap():
3218 return BitmapFromImage(getNextImage())
3221 stream
= cStringIO
.StringIO(getNextData())
3222 return ImageFromStream(stream
)
3225 return wx
.IconFromBitmap(getNextBitmap())
3227 #----------------------------------------------------------------------
3228 def getStepInData():
3230 '\x89PNG\r\n\x1a\n\x00\x00\x00\rIHDR\x00\x00\x00\x10\x00\x00\x00\x10\x08\x06\
3231 \x00\x00\x00\x1f\xf3\xffa\x00\x00\x00\x04sBIT\x08\x08\x08\x08|\x08d\x88\x00\
3232 \x00\x00\x87IDAT8\x8d\xadSA\x12\x84 \x0ck\x8a\xffv\xfc\xb74{X\xeb0P@\x07s\
3233 \x84\xa4$\x01\x00M\xb2\x02]R\x8b\xc86\xda\xdc\xedd\xb4~\xe8\x86\xc6\x01-\x93\
3234 \x96\xd9#\xf6\x06\xc3;p1I\xd1\x14\x0b#|\x17aF\xec\r\xeeF\xa0eB\xd34\xca\xd0A\
3235 ]j\x84\xa6\x03\x00""\xb7\xb0tRZ\xf7x\xb7\x83\x91]\xcb\x7fa\xd9\x89\x0fC\xfd\
3236 \x94\x9d|9\x99^k\x13\xa1 \xb3\x16\x0f#\xd4\x88N~\x14\xe1-\x96\x7f\xe3\x0f\
3237 \x11\x91UC\x0cX\'\x1e\x00\x00\x00\x00IEND\xaeB`\x82'
3239 def getStepInBitmap():
3240 return BitmapFromImage(getStepInImage())
3242 def getStepInImage():
3243 stream
= cStringIO
.StringIO(getStepInData())
3244 return ImageFromStream(stream
)
3246 def getStepInIcon():
3247 return wx
.IconFromBitmap(getStepInBitmap())
3249 #----------------------------------------------------------------------
3252 '\x89PNG\r\n\x1a\n\x00\x00\x00\rIHDR\x00\x00\x00\x10\x00\x00\x00\x10\x08\x06\
3253 \x00\x00\x00\x1f\xf3\xffa\x00\x00\x00\x04sBIT\x08\x08\x08\x08|\x08d\x88\x00\
3254 \x00\x00QIDAT8\x8d\xdd\x93A\n\xc00\x08\x04g\xb5\xff\x7fq\x13sn\xda&\x01\x0b\
3255 \xa5]\xf0"\xec(.J\xe6dd)\xf7\x13\x80\xadoD-12\xc8\\\xd3\r\xe2\xa6\x00j\xd9\
3256 \x0f\x03\xde\xbf\xc1\x0f\x00\xa7\x18\x01t\xd5\\\x05\xc8\\}T#\xe9\xfb\xbf\x90\
3257 \x064\xd8\\\x12\x1fQM\xf5\xd9\x00\x00\x00\x00IEND\xaeB`\x82'
3259 def getStopBitmap():
3260 return BitmapFromImage(getStopImage())
3263 stream
= cStringIO
.StringIO(getStopData())
3264 return ImageFromStream(stream
)
3267 return wx
.IconFromBitmap(getStopBitmap())
3269 #----------------------------------------------------------------------
3270 def getStepReturnData():
3272 "\x89PNG\r\n\x1a\n\x00\x00\x00\rIHDR\x00\x00\x00\x10\x00\x00\x00\x10\x08\x06\
3273 \x00\x00\x00\x1f\xf3\xffa\x00\x00\x00\x04sBIT\x08\x08\x08\x08|\x08d\x88\x00\
3274 \x00\x00\x8dIDAT8\x8d\xa5S\xd1\x0e\xc4 \x08\xa3\xb0\xff\xbe\xdc\x7fO\xba'6\
3275 \xf1\xf44\xb3O$Phk\x04\xd4d\x07\xba\xc5\x16\x91#\nza\xdb\x84\x1a\xa2\xfe\xf8\
3276 \x99\xfa_=p+\xe8\x91ED\xbc<\xa4 \xb4\x0b\x01\xb5{\x01\xf9\xbbG-\x13\x87\x16f\
3277 \x84\xbf\x16V\xb0l\x01@\no\x86\xae\x82Q\xa8=\xa4\x0c\x80\xe70\xbd\x10jh\xbd\
3278 \x07R\x06#\xc9^N\xb6\xde\x03)\x83\x18\xaeU\x90\x9c>a\xb2P\r\xb3&/Y\xa8\xd1^^\
3279 \xb6\xf0\x16\xdb\xbf\xf1\x02\x81\xa5TK\x1d\x07\xde\x92\x00\x00\x00\x00IEND\
3282 def getStepReturnBitmap():
3283 return BitmapFromImage(getStepReturnImage())
3285 def getStepReturnImage():
3286 stream
= cStringIO
.StringIO(getStepReturnData())
3287 return ImageFromStream(stream
)
3289 def getStepReturnIcon():
3290 return wx
.IconFromBitmap(getStepReturnBitmap())
3292 #----------------------------------------------------------------------
3293 def getAddWatchData():
3295 '\x89PNG\r\n\x1a\n\x00\x00\x00\rIHDR\x00\x00\x00\x10\x00\x00\x00\x10\x08\x06\
3296 \x00\x00\x00\x1f\xf3\xffa\x00\x00\x00\x04sBIT\x08\x08\x08\x08|\x08d\x88\x00\
3297 \x00\x00\x85IDAT8\x8dc`\x18h\xc0\x88.\xd0\xc0\xf0\xff?*\x9f\x11C\rN\x80\xae\
3298 \x19\x97\x18\xd1\x9a\x896\x84\x18[p\xa9aA\xe6\xfc7f\xc0P\xc4x\x163\x9cp\x1a0\
3299 \xeb,!w\x100 \x1dK\xac\x10\r\x08\x05".yFL\x85\x8c\x18b\xa8|Ty\xa2\x13\x92\'\
3300 \xc3\xe4\xff\x9f\x18\x1e3\xb82t\xa2\x88\x13\xedg.\x06aa&\x06VV\x7f\x86\xb9\
3301 \xcfU\x19\xbc\xb0\xba\x86h\xe0\xc8\xd0\xfc\xbf\x80\xe1>q)\x94\xe6\x00\x00\
3302 \x85\x923_\xd22\xa4\xcd\x00\x00\x00\x00IEND\xaeB`\x82'
3304 def getAddWatchBitmap():
3305 return BitmapFromImage(getAddWatchImage())
3307 def getAddWatchImage():
3308 stream
= cStringIO
.StringIO(getAddWatchData())
3309 return ImageFromStream(stream
)
3311 def getAddWatchIcon():
3312 return wx
.IconFromBitmap(getAddWatchBitmap())
3314 #----------------------------------------------------------------------
3315 def getRunningManData():
3317 '\x89PNG\r\n\x1a\n\x00\x00\x00\rIHDR\x00\x00\x00\x10\x00\x00\x00\x10\x08\x06\
3318 \x00\x00\x00\x1f\xf3\xffa\x00\x00\x00\x04sBIT\x08\x08\x08\x08|\x08d\x88\x00\
3319 \x00\x01\x86IDAT8\x8d\xa5\x93\xb1K\x02Q\x1c\xc7\xbf\xcf\x9a\x1bZl\x88\xb4\
3320 \x04\x83\x10\xa2\x96\xc0A\xa8\x96\x96\xf4h\xe9\xf0\x1f\xd0\xcd(Bpi\x13nH\xb2\
3321 %\x9d\x1a"\xb9)\xb4\x16i\x10\n\x13MA\x84\xa3&\xa1\xa1A\xa1E\xbdw\x97\xa2\xbd\
3322 \x06\xf1(\xef,\xac\xef\xf6x\xdf\xf7}\x9f\xdf\x97\xf7\x081M\xe0?\x9a\xfc\xcd \
3323 \\\xdc2\x99\xb6A[\x14\x91C\x9e\x8c\x1d\x00\x00\xd5\xa7*\x9a\x8a\xfa7\x82u\
3324 \xfb\x14dj\x03mQ\xc3}\xf2\xb5\x83\xc7B\x9e\x89\xf7/\xda\xba\xd1\x94\x01\x00j\
3325 CF\xe2t\xef\x1b>\x1f\x8c3Q\xf0\x11\xd3p\xa2yf\x1a\xbc\xcb\n\xdee\x85\xdd>\
3326 \x07\xb5!C\xe9\xb4\xb1\xe9=b\x03\x8fc\xc3\xcf\xbcN\xb3\x9e`@\x11\xb9\xaa`\
3327 \x7fg\x19\'\x97y\xd8\x96\xfa\xf8\x95\xf23d\xa5O4\xbfh\x87(\xf8\x88a\xc0 $|~\
3328 \x87n\xf7\x03\xaa\xf2\x8e\xc0\xee\n\x00 \x91\xab\xc3\xeb4\xc3\xed\xe1\xb4qF\
3329 \x96\xb8`\xb3h\xb7\xa6Jo\xa0\x9d\x1eD\xc1G\xc4!\x9f\xae\x03\x00\xa8\xd5jh4e\
3330 \r\xb9\xf0P\x82T,\x83\xf3\x0bl\xd8k\x18\xe0\xf6p\x84vz\xa0M\x8aB\xf2\x98\x84\
3331 \x03[\xb0.XP\xcafu^m\x04>\x18\xd7\x9aM\xe4\xea\xba\xc0x\xec\x8c\xa9\xca*^\
3332 \xa5\x1b}\xc0u*\xc9B\xd14\x12\xe8\x97%\x15\xcbF`\xdaH\xba\x80P4\r)\x13#R\xc6\
3333 \xf0\xdc\x8f2\x01\x80\x94\x89\xe9>\xc9(\xcd:\xb6\xd9\x1aw\xa0\x95i\xf8\x0e\
3334 \xc6\xd1\'\'\x86\xa2\xd5\x8d \xbe@\x00\x00\x00\x00IEND\xaeB`\x82'
3336 def getRunningManBitmap():
3337 return BitmapFromImage(getRunningManImage())
3339 def getRunningManImage():
3340 stream
= cStringIO
.StringIO(getRunningManData())
3341 return ImageFromStream(stream
)
3343 def getRunningManIcon():
3345 icon
.CopyFromBitmap(getRunningManBitmap())
3348 #----------------------------------------------------------------------
3349 def getDebuggingManData():
3351 '\x89PNG\r\n\x1a\n\x00\x00\x00\rIHDR\x00\x00\x00\x10\x00\x00\x00\x10\x08\x06\
3352 \x00\x00\x00\x1f\xf3\xffa\x00\x00\x00\x04sBIT\x08\x08\x08\x08|\x08d\x88\x00\
3353 \x00\x01\xafIDAT8\x8d\x8d\x93\xbfK[Q\x14\xc7?7\n:\t\xb5SA\xc1?@\xc1A\x9c,%\
3354 \xd0\xa9\x83\xb5\x98!(b\t\xbc\xa7q("m\x1c\n5V]D\xd4-\xf8\x83\xa7\xa2\t\xa1\
3355 \xa6\xed$8\x08\x92\xa1\x8b\x14A\xd0YB"\xa4\xf4\x87\x90\x97K\xa8\xcb\xed\xf0\
3356 \xc8m\xae\xfa\xd4\x03\x07.\xe7\x9e\xf3\xfd\x9e\x9f\x88@\x1d\xb5\xba\x94\xca\
3357 \xaa\xeb\xb6\xbb4\xc0\x03d&\xb1\xa7\xfc\xfe\x0c\x80L\xdaQ\xd2\xad\x90I;F\x80\
3358 ++\xbe\xe0bve\xdf\xd7y\xfemH\xc4\x162\xaa\xbb\xa5D(\x1c\x11\xb7\x02\x88@\x9d\
3359 f?*4\xd1\xf6\xa2\x0f\x80\x93\xf4\x8e\xe1\xb8\xf2\xf1\xb5\x18\x9cH(\x80\xe4bT\
3360 \x83\xd5W\x1f\xa1pD\x8c|\xd8T\x00\xdf\xd6\xd7\xe8\x1f\xb3tp\xf1\n^\xfe\xf8\
3361 \xa5^u7\x00P\x1eYP\xd2\x95\x1c\xa4\xa6\x84\x18\x8do\xab*C&\xed\xa8\xafG\x7f\
3362 \xe9\x1f\xb3x\xdc\x08\xad\x8f \x7f\tg%\xf8Y\x82\xe3\x8de\x86\x82\xcdF9\xba\
3363 \x84\xc1\x89\x84*K\t\xc0\xf0\xbbq:\x9f\xfcO\x7f?\xe7\x01\x9c\xff\x86Br\x8e\
3364 \x83\xd4\x94\x06\xd0SH.F\xc5P\xb0\x19\xe9z \xf9KOmkN\x07\x03\x14/r\xb4?\x8b\
3365 \xe8\xc6\xeb\x1e\x00l\x1f\xfe\xd15\x17\xaf<\xdb\xd37\xef\xd9\x9d\xb4\xe9\x8a\
3366 \xadj\xbfx\xb4\x878(#\x03\x00\xe9JF{[\xf92\xeb\xb1V\x99\xbbb\xab|\x9f\xb7\
3367 \x8d\xa9\x9cf\x1dq\x9au\xc4\x8dM\x0c\x85#\xa2x\x91cw\xd2\xd6i\x83\trk\x13\
3368 \x9f\x0fL\xab\xda\xe6\xd4\xd6Y+\xf1h\x8f\xb9T~G\xd2\x11\xb4\xd4\xe7O[\xf7\
3369 \x1e\xd6\x9d\xc7\xe4\xb7\xbe\x86\xf8\xb1?\xf4\x9c\xff\x01\xbe\xe9\xaf\x96\
3370 \xf0\x7fPA\x00\x00\x00\x00IEND\xaeB`\x82'
3372 def getDebuggingManBitmap():
3373 return BitmapFromImage(getDebuggingManImage())
3375 def getDebuggingManImage():
3376 stream
= cStringIO
.StringIO(getDebuggingManData())
3377 return ImageFromStream(stream
)
3379 def getDebuggingManIcon():
3381 icon
.CopyFromBitmap(getDebuggingManBitmap())
3384 #----------------------------------------------------------------------