Files
wxWidgets/wxPython/samples/ide/activegrid/tool/DebuggerService.py
Robin Dunn aca310e5cc DocView and ActiveGrid IDE updates from Morgan Hua:
New Features: In Tab-View mode, Ctrl-number will take the user to
    the numbered tab view.  Modified files now show an '*' astrisk in
    the view title.  Debugger framework can now support PHP debugging.
    Not important for python development, but at least that means the
    debugger framework is more generalized.


git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@38852 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775
2006-04-20 06:26:03 +00:00

3386 lines
136 KiB
Python

#----------------------------------------------------------------------------
# Name: DebuggerService.py
# Purpose: Debugger Service for Python and PHP
#
# Author: Matt Fryer
#
# Created: 12/9/04
# CVS-ID: $Id$
# Copyright: (c) 2004-2005 ActiveGrid, Inc.
# License: wxWindows License
#----------------------------------------------------------------------------
import wx
import wx.lib.intctrl
import wx.lib.docview
import wx.lib.dialogs
import wx.gizmos
import wx._core
import wx.lib.pydocview
import Service
import STCTextEditor
import CodeEditor
import PythonEditor
import PHPEditor
import PHPDebugger
import activegrid.model.projectmodel as projectmodel
from IDE import ACTIVEGRID_BASE_IDE
if not ACTIVEGRID_BASE_IDE:
import ProcessModelEditor
import wx.lib.scrolledpanel as scrolled
import sys
import time
import SimpleXMLRPCServer
import xmlrpclib
import os
import threading
import Queue
import SocketServer
import ProjectEditor
import types
from xml.dom.minidom import parse, parseString
import bz2
import pickle
import DebuggerHarness
import traceback
import StringIO
import UICommon
import activegrid.util.sysutils as sysutilslib
import subprocess
import shutil
if wx.Platform == '__WXMSW__':
try:
import win32api
_PYWIN32_INSTALLED = True
except ImportError:
_PYWIN32_INSTALLED = False
_WINDOWS = True
else:
_WINDOWS = False
if not _WINDOWS or _PYWIN32_INSTALLED:
import process
_ = wx.GetTranslation
_VERBOSE = False
_WATCHES_ON = False
import wx.lib.newevent
(UpdateTextEvent, EVT_UPDATE_STDTEXT) = wx.lib.newevent.NewEvent()
(UpdateErrorEvent, EVT_UPDATE_ERRTEXT) = wx.lib.newevent.NewEvent()
(DebugInternalWebServer, EVT_DEBUG_INTERNAL) = wx.lib.newevent.NewEvent()
# Class to read from stdout or stderr and write the result to a text control.
# Args: file=file-like object
# callback_function= function that takes a single argument, the line of text
# read.
class OutputReaderThread(threading.Thread):
def __init__(self, file, callback_function, callbackOnExit=None, accumulate=True):
threading.Thread.__init__(self)
self._file = file
self._callback_function = callback_function
self._keepGoing = True
self._lineCount = 0
self._accumulate = accumulate
self._callbackOnExit = callbackOnExit
self.setDaemon(True)
def __del__(self):
# See comment on PythonDebuggerUI.StopExecution
self._keepGoing = False
def run(self):
file = self._file
start = time.time()
output = ""
while self._keepGoing:
try:
# This could block--how to handle that?
text = file.readline()
if text == '' or text == None:
self._keepGoing = False
elif not self._accumulate and self._keepGoing:
self._callback_function(text)
else:
# Should use a buffer? StringIO?
output += text
# Seems as though the read blocks if we got an error, so, to be
# sure that at least some of the exception gets printed, always
# send the first hundred lines back as they come in.
if self._lineCount < 100 and self._keepGoing:
self._callback_function(output)
self._lineCount += 1
output = ""
elif time.time() - start > 0.25 and self._keepGoing:
try:
self._callback_function(output)
except wx._core.PyDeadObjectError:
# GUI was killed while we were blocked.
self._keepGoing = False
start = time.time()
output = ""
#except TypeError:
# pass
except:
tp, val, tb = sys.exc_info()
print "Exception in OutputReaderThread.run():", tp, val
self._keepGoing = False
if self._callbackOnExit:
try:
self._callbackOnExit()
except wx._core.PyDeadObjectError:
pass
if _VERBOSE: print "Exiting OutputReaderThread"
def AskToStop(self):
self._keepGoing = False
class Executor:
PHP_CGI_BIN_PATH_WIN = "../../3rdparty/php"
PHP_CGI_BIN_PATH_UNIX = "../../../3rdparty/php/bin"
PHP_CGI_BIN_PATH_OSX = "../3rdparty/php/bin"
PHP_CGI_EXEC_WIN = "php-cgi.exe"
PHP_CGI_EXEC_UNIX = "php"
PHP_CGI_EXEC_OSX = "php-cgi"
def GetPythonExecutablePath():
path = UICommon.GetPythonExecPath()
if path:
return path
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"))
return None
GetPythonExecutablePath = staticmethod(GetPythonExecutablePath)
def GetPHPExecutablePath():
if sysutilslib.isWindows():
phpCgiBinPath = Executor.PHP_CGI_BIN_PATH_WIN
phpCgiExec = Executor.PHP_CGI_EXEC_WIN
elif sys.platform == "darwin":
phpCgiBinPath = Executor.PHP_CGI_BIN_PATH_OSX
phpCgiExec = Executor.PHP_CGI_EXEC_OSX
else:
phpCgiBinPath = Executor.PHP_CGI_BIN_PATH_UNIX
phpCgiExec = Executor.PHP_CGI_EXEC_UNIX
if sysutilslib.isRelease():
phpCgiExecFullPath = os.path.normpath(os.path.join(sysutilslib.mainModuleDir, phpCgiBinPath, phpCgiExec))
else:
phpCgiExecFullPath = phpCgiExec
if _VERBOSE:
print "php cgi executable full path is: %s" % phpCgiExecFullPath
return phpCgiExecFullPath
GetPHPExecutablePath = staticmethod(GetPHPExecutablePath)
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):
self._fileName = fileName
self._stdOutCallback = self.OutCall
self._stdErrCallback = self.ErrCall
self._callbackOnExit = callbackOnExit
self._wxComponent = wxComponent
if fileName.endswith('.py') or fileName.endswith('.pyc'):
self._path = Executor.GetPythonExecutablePath()
self._cmd = '"' + self._path + '" -u \"' + fileName + '\"'
else:
self._path = Executor.GetPHPExecutablePath()
self._cmd = '"' + self._path + '"'
#Better way to do this? Quotes needed for windows file paths.
def spaceAndQuote(text):
if text.startswith("\"") and text.endswith("\""):
return ' ' + text
else:
return ' \"' + text + '\"'
if(arg1 != None):
self._cmd += spaceAndQuote(arg1)
if(arg2 != None):
self._cmd += spaceAndQuote(arg2)
if(arg3 != None):
self._cmd += spaceAndQuote(arg3)
if(arg4 != None):
self._cmd += spaceAndQuote(arg4)
if(arg5 != None):
self._cmd += spaceAndQuote(arg5)
if(arg6 != None):
self._cmd += spaceAndQuote(arg6)
if(arg7 != None):
self._cmd += spaceAndQuote(arg7)
if(arg8 != None):
self._cmd += spaceAndQuote(arg8)
if(arg9 != None):
self._cmd += spaceAndQuote(arg9)
self._stdOutReader = None
self._stdErrReader = None
self._process = None
def OutCall(self, text):
evt = UpdateTextEvent(value = text)
wx.PostEvent(self._wxComponent, evt)
def ErrCall(self, text):
evt = UpdateErrorEvent(value = text)
wx.PostEvent(self._wxComponent, evt)
def Execute(self, arguments, startIn=None, environment=None):
if not startIn:
startIn = str(os.getcwd())
startIn = os.path.abspath(startIn)
if arguments and arguments != " ":
command = self._cmd + ' ' + arguments
else:
command = self._cmd
if _VERBOSE: print "start debugger executable: " + command + "\n"
self._process = process.ProcessOpen(command, mode='b', cwd=startIn, env=environment)
# Kick off threads to read stdout and stderr and write them
# to our text control.
self._stdOutReader = OutputReaderThread(self._process.stdout, self._stdOutCallback, callbackOnExit=self._callbackOnExit)
self._stdOutReader.start()
self._stdErrReader = OutputReaderThread(self._process.stderr, self._stdErrCallback, accumulate=False)
self._stdErrReader.start()
def DoStopExecution(self):
# See comment on PythonDebuggerUI.StopExecution
if(self._process != None):
self._stdOutReader.AskToStop()
self._stdErrReader.AskToStop()
try:
self._process.kill(gracePeriod=2.0)
except:
pass
self._process = None
def GetExecPath(self):
return self._path
class RunCommandUI(wx.Panel):
runners = []
def ShutdownAllRunners():
# See comment on PythonDebuggerUI.StopExecution
for runner in RunCommandUI.runners:
try:
runner.StopExecution(None)
except wx._core.PyDeadObjectError:
pass
RunCommandUI.runners = []
ShutdownAllRunners = staticmethod(ShutdownAllRunners)
def __init__(self, parent, id, fileName):
wx.Panel.__init__(self, parent, id)
self._noteBook = parent
threading._VERBOSE = _VERBOSE
self.KILL_PROCESS_ID = wx.NewId()
self.CLOSE_TAB_ID = wx.NewId()
# GUI Initialization follows
sizer = wx.BoxSizer(wx.HORIZONTAL)
self._tb = tb = wx.ToolBar(self, -1, wx.DefaultPosition, (30,1000), wx.TB_VERTICAL| wx.TB_FLAT, "Runner" )
tb.SetToolBitmapSize((16,16))
sizer.Add(tb, 0, wx.EXPAND|wx.ALIGN_LEFT|wx.ALL, 1)
close_bmp = getCloseBitmap()
tb.AddSimpleTool( self.CLOSE_TAB_ID, close_bmp, _('Close Window'))
wx.EVT_TOOL(self, self.CLOSE_TAB_ID, self.OnToolClicked)
stop_bmp = getStopBitmap()
tb.AddSimpleTool(self.KILL_PROCESS_ID, stop_bmp, _("Stop the Run."))
wx.EVT_TOOL(self, self.KILL_PROCESS_ID, self.OnToolClicked)
tb.Realize()
self._textCtrl = STCTextEditor.TextCtrl(self, wx.NewId()) #id)
sizer.Add(self._textCtrl, 1, wx.ALIGN_LEFT|wx.ALL|wx.EXPAND, 1)
self._textCtrl.SetViewLineNumbers(False)
self._textCtrl.SetReadOnly(True)
if wx.Platform == '__WXMSW__':
font = "Courier New"
else:
font = "Courier"
self._textCtrl.SetFont(wx.Font(9, wx.DEFAULT, wx.NORMAL, wx.NORMAL, faceName = font))
self._textCtrl.SetFontColor(wx.BLACK)
self._textCtrl.StyleClearAll()
wx.stc.EVT_STC_DOUBLECLICK(self._textCtrl, self._textCtrl.GetId(), self.OnDoubleClick)
self.SetSizer(sizer)
sizer.Fit(self)
self._stopped = False
# Executor initialization
self._executor = Executor(fileName, self, callbackOnExit=self.ExecutorFinished)
self.Bind(EVT_UPDATE_STDTEXT, self.AppendText)
self.Bind(EVT_UPDATE_ERRTEXT, self.AppendErrorText)
RunCommandUI.runners.append(self)
def __del__(self):
# See comment on PythonDebuggerUI.StopExecution
self._executor.DoStopExecution()
def Execute(self, initialArgs, startIn, environment, onWebServer = False):
self._executor.Execute(initialArgs, startIn, environment)
def ExecutorFinished(self):
self._tb.EnableTool(self.KILL_PROCESS_ID, False)
nb = self.GetParent()
for i in range(0,nb.GetPageCount()):
if self == nb.GetPage(i):
text = nb.GetPageText(i)
newText = text.replace("Running", "Finished")
nb.SetPageText(i, newText)
break
def StopExecution(self):
if not self._stopped:
self._stopped = True
self.Unbind(EVT_UPDATE_STDTEXT)
self.Unbind(EVT_UPDATE_ERRTEXT)
self._executor.DoStopExecution()
def AppendText(self, event):
self._textCtrl.SetReadOnly(False)
self._textCtrl.AddText(event.value)
self._textCtrl.ScrollToLine(self._textCtrl.GetLineCount())
self._textCtrl.SetReadOnly(True)
def AppendErrorText(self, event):
self._textCtrl.SetReadOnly(False)
self._textCtrl.SetFontColor(wx.RED)
self._textCtrl.StyleClearAll()
self._textCtrl.AddText(event.value)
self._textCtrl.ScrollToLine(self._textCtrl.GetLineCount())
self._textCtrl.SetFontColor(wx.BLACK)
self._textCtrl.StyleClearAll()
self._textCtrl.SetReadOnly(True)
def StopAndRemoveUI(self, event):
self.StopExecution()
self.StopExecution()
index = self._noteBook.GetSelection()
self._noteBook.GetPage(index).Show(False)
self._noteBook.RemovePage(index)
#------------------------------------------------------------------------------
# Event handling
#-----------------------------------------------------------------------------
def OnToolClicked(self, event):
id = event.GetId()
if id == self.KILL_PROCESS_ID:
self.StopExecution()
elif id == self.CLOSE_TAB_ID:
self.StopAndRemoveUI(event)
def OnDoubleClick(self, event):
# Looking for a stack trace line.
lineText, pos = self._textCtrl.GetCurLine()
fileBegin = lineText.find("File \"")
fileEnd = lineText.find("\", line ")
lineEnd = lineText.find(", in ")
if lineText == "\n" or fileBegin == -1 or fileEnd == -1 or lineEnd == -1:
# Check the line before the one that was clicked on
lineNumber = self._textCtrl.GetCurrentLine()
if(lineNumber == 0):
return
lineText = self._textCtrl.GetLine(lineNumber - 1)
fileBegin = lineText.find("File \"")
fileEnd = lineText.find("\", line ")
lineEnd = lineText.find(", in ")
if lineText == "\n" or fileBegin == -1 or fileEnd == -1 or lineEnd == -1:
return
filename = lineText[fileBegin + 6:fileEnd]
lineNum = int(lineText[fileEnd + 8:lineEnd])
foundView = None
openDocs = wx.GetApp().GetDocumentManager().GetDocuments()
for openDoc in openDocs:
if openDoc.GetFilename() == filename:
foundView = openDoc.GetFirstView()
break
if not foundView:
doc = wx.GetApp().GetDocumentManager().CreateDocument(filename, wx.lib.docview.DOC_SILENT)
foundView = doc.GetFirstView()
if foundView:
foundView.GetFrame().SetFocus()
foundView.Activate()
foundView.GotoLine(lineNum)
startPos = foundView.PositionFromLine(lineNum)
lineText = foundView.GetCtrl().GetLine(lineNum - 1)
foundView.SetSelection(startPos, startPos + len(lineText.rstrip("\n")))
import OutlineService
wx.GetApp().GetService(OutlineService.OutlineService).LoadOutline(foundView, position=startPos)
DEFAULT_PORT = 32032
DEFAULT_HOST = 'localhost'
PORT_COUNT = 21
class BaseDebuggerUI(wx.Panel):
debuggers = []
def NotifyDebuggersOfBreakpointChange():
for debugger in BaseDebuggerUI.debuggers:
debugger.BreakPointChange()
NotifyDebuggersOfBreakpointChange = staticmethod(NotifyDebuggersOfBreakpointChange)
def DebuggerRunning():
for debugger in BaseDebuggerUI.debuggers:
if debugger._executor:
return True
return False
DebuggerRunning = staticmethod(DebuggerRunning)
def DebuggerInWait():
for debugger in BaseDebuggerUI.debuggers:
if debugger._executor:
if debugger._callback._waiting:
return True
return False
DebuggerInWait = staticmethod(DebuggerInWait)
def DebuggerPastAutoContinue():
for debugger in BaseDebuggerUI.debuggers:
if debugger._executor:
if debugger._callback._waiting and not debugger._callback._autoContinue:
return True
return False
DebuggerPastAutoContinue = staticmethod(DebuggerPastAutoContinue)
def ShutdownAllDebuggers():
for debugger in BaseDebuggerUI.debuggers:
try:
debugger.StopExecution(None)
except wx._core.PyDeadObjectError:
pass
BaseDebuggerUI.debuggers = []
ShutdownAllDebuggers = staticmethod(ShutdownAllDebuggers)
def __init__(self, parent, id):
wx.Panel.__init__(self, parent, id)
self._parentNoteBook = parent
self._service = None
self._executor = None
self._callback = None
self._stopped = False
BaseDebuggerUI.debuggers.append(self)
self._stopped = True
self.Bind(EVT_UPDATE_STDTEXT, self.AppendText)
self.Bind(EVT_UPDATE_ERRTEXT, self.AppendErrorText)
self._executor = None
self.STEP_ID = wx.NewId()
self.CONTINUE_ID = wx.NewId()
self.STEP_OUT_ID = wx.NewId()
self.NEXT_ID = wx.NewId()
self.KILL_PROCESS_ID = wx.NewId()
self.CLOSE_WINDOW_ID = wx.NewId()
self.BREAK_INTO_DEBUGGER_ID = wx.NewId()
self.CLEAR_ID = wx.NewId()
self.ADD_WATCH_ID = wx.NewId()
sizer = wx.BoxSizer(wx.VERTICAL)
self._tb = tb = wx.ToolBar(self, -1, wx.DefaultPosition, (1000,30), wx.TB_HORIZONTAL| wx.NO_BORDER| wx.TB_FLAT| wx.TB_TEXT, "Debugger" )
sizer.Add(tb, 0, wx.EXPAND |wx.ALIGN_LEFT|wx.ALL, 1)
tb.SetToolBitmapSize((16,16))
close_bmp = getCloseBitmap()
tb.AddSimpleTool( self.CLOSE_WINDOW_ID, close_bmp, _('Close Window'))
wx.EVT_TOOL(self, self.CLOSE_WINDOW_ID, self.StopAndRemoveUI)
stop_bmp = getStopBitmap()
tb.AddSimpleTool( self.KILL_PROCESS_ID, stop_bmp, _("Stop Debugging"))
wx.EVT_TOOL(self, self.KILL_PROCESS_ID, self.StopExecution)
tb.AddSeparator()
break_bmp = getBreakBitmap()
tb.AddSimpleTool( self.BREAK_INTO_DEBUGGER_ID, break_bmp, _("Break into Debugger"))
wx.EVT_TOOL(self, self.BREAK_INTO_DEBUGGER_ID, self.BreakExecution)
tb.AddSeparator()
continue_bmp = getContinueBitmap()
tb.AddSimpleTool( self.CONTINUE_ID, continue_bmp, _("Continue Execution"))
wx.EVT_TOOL(self, self.CONTINUE_ID, self.OnContinue)
self.Bind(EVT_DEBUG_INTERNAL, self.OnContinue)
tb.AddSeparator()
next_bmp = getNextBitmap()
tb.AddSimpleTool( self.NEXT_ID, next_bmp, _("Step to next line"))
wx.EVT_TOOL(self, self.NEXT_ID, self.OnNext)
step_bmp = getStepInBitmap()
tb.AddSimpleTool( self.STEP_ID, step_bmp, _("Step in"))
wx.EVT_TOOL(self, self.STEP_ID, self.OnSingleStep)
stepOut_bmp = getStepReturnBitmap()
tb.AddSimpleTool(self.STEP_OUT_ID, stepOut_bmp, _("Stop at function return"))
wx.EVT_TOOL(self, self.STEP_OUT_ID, self.OnStepOut)
tb.AddSeparator()
if _WATCHES_ON:
watch_bmp = getAddWatchBitmap()
tb.AddSimpleTool(self.ADD_WATCH_ID, watch_bmp, _("Add a watch"))
wx.EVT_TOOL(self, self.ADD_WATCH_ID, self.OnAddWatch)
tb.AddSeparator()
clear_bmp = getClearOutputBitmap()
tb.AddSimpleTool(self.CLEAR_ID, clear_bmp, _("Clear output pane"))
wx.EVT_TOOL(self, self.CLEAR_ID, self.OnClearOutput)
self._toolEnabled = True
self.framesTab = None
self.DisableWhileDebuggerRunning()
self.framesTab = self.MakeFramesUI(self, wx.NewId(), None)
sizer.Add(self.framesTab, 1, wx.ALIGN_LEFT|wx.ALL|wx.EXPAND, 1)
self._statusBar = wx.StatusBar( self, -1)
self._statusBar.SetFieldsCount(1)
sizer.Add(self._statusBar, 0, wx.EXPAND |wx.ALIGN_LEFT|wx.ALL, 1)
self.SetStatusText("Starting debug...")
self.SetSizer(sizer)
tb.Realize()
sizer.Fit(self)
def OnSingleStep(self, event):
self._callback.SingleStep()
def OnContinue(self, event):
self._callback.Continue()
def OnStepOut(self, event):
self._callback.Return()
def OnNext(self, event):
self._callback.Next()
def BreakPointChange(self):
if not self._stopped:
self._callback.PushBreakpoints()
self.framesTab.PopulateBPList()
def __del__(self):
# See comment on PythonDebuggerUI.StopExecution
self.StopExecution(None)
def DisableWhileDebuggerRunning(self):
if self._toolEnabled:
self._tb.EnableTool(self.STEP_ID, False)
self._tb.EnableTool(self.CONTINUE_ID, False)
self._tb.EnableTool(self.STEP_OUT_ID, False)
self._tb.EnableTool(self.NEXT_ID, False)
self._tb.EnableTool(self.BREAK_INTO_DEBUGGER_ID, True)
if _WATCHES_ON:
self._tb.EnableTool(self.ADD_WATCH_ID, False)
self.DeleteCurrentLineMarkers()
if self.framesTab:
self.framesTab.ClearWhileRunning()
self._toolEnabled = False
def EnableWhileDebuggerStopped(self):
self._tb.EnableTool(self.STEP_ID, True)
self._tb.EnableTool(self.CONTINUE_ID, True)
self._tb.EnableTool(self.STEP_OUT_ID, True)
self._tb.EnableTool(self.NEXT_ID, True)
self._tb.EnableTool(self.BREAK_INTO_DEBUGGER_ID, False)
self._tb.EnableTool(self.KILL_PROCESS_ID, True)
if _WATCHES_ON:
self._tb.EnableTool(self.ADD_WATCH_ID, True)
self._toolEnabled = True
def DisableAfterStop(self):
if self._toolEnabled:
self.DisableWhileDebuggerRunning()
self._tb.EnableTool(self.BREAK_INTO_DEBUGGER_ID, False)
self._tb.EnableTool(self.KILL_PROCESS_ID, False)
def ExecutorFinished(self):
if _VERBOSE: print "In ExectorFinished"
try:
self.DisableAfterStop()
except wx._core.PyDeadObjectError:
pass
try:
nb = self.GetParent()
for i in range(0, nb.GetPageCount()):
if self == nb.GetPage(i):
text = nb.GetPageText(i)
newText = text.replace("Debugging", "Finished")
nb.SetPageText(i, newText)
if _VERBOSE: print "In ExectorFinished, changed tab title."
break
except:
if _VERBOSE: print "In ExectorFinished, got exception"
def SetStatusText(self, text):
self._statusBar.SetStatusText(text,0)
def BreakExecution(self, event):
self._callback.BreakExecution()
def StopExecution(self, event):
self._callback.ShutdownServer()
def Execute(self, initialArgs, startIn, environment, onWebServer = False):
assert False, "Execute not overridden"
def SynchCurrentLine(self, filename, lineNum, noArrow=False):
self.DeleteCurrentLineMarkers()
# Filename will be <string> if we're in a bit of code that was executed from
# a string (rather than a file). I haven't been able to get the original string
# for display.
if filename == '<string>':
return
foundView = None
openDocs = wx.GetApp().GetDocumentManager().GetDocuments()
for openDoc in openDocs:
# This ugliness to prevent comparison failing because the drive letter
# gets lowercased occasionally. Don't know why that happens or why it
# only happens occasionally.
if DebuggerService.ComparePaths(openDoc.GetFilename(),filename):
foundView = openDoc.GetFirstView()
break
if not foundView:
if _VERBOSE:
print "filename=", filename
doc = wx.GetApp().GetDocumentManager().CreateDocument(DebuggerService.ExpandPath(filename), wx.lib.docview.DOC_SILENT)
foundView = doc.GetFirstView()
if foundView:
foundView.GetFrame().SetFocus()
foundView.Activate()
foundView.GotoLine(lineNum)
startPos = foundView.PositionFromLine(lineNum)
if not noArrow:
foundView.GetCtrl().MarkerAdd(lineNum -1, CodeEditor.CodeCtrl.CURRENT_LINE_MARKER_NUM)
def DeleteCurrentLineMarkers(self):
openDocs = wx.GetApp().GetDocumentManager().GetDocuments()
for openDoc in openDocs:
if(isinstance(openDoc, CodeEditor.CodeDocument)):
openDoc.GetFirstView().GetCtrl().ClearCurrentLineMarkers()
def StopAndRemoveUI(self, event):
self.StopExecution(None)
if self in BaseDebuggerUI.debuggers:
BaseDebuggerUI.debuggers.remove(self)
index = self._parentNoteBook.GetSelection()
self._parentNoteBook.GetPage(index).Show(False)
self._parentNoteBook.RemovePage(index)
def OnAddWatch(self, event):
if self.framesTab:
self.framesTab.OnWatch(event)
def MakeFramesUI(self, parent, id, debugger):
assert False, "MakeFramesUI not overridden"
def AppendText(self, event):
self.framesTab.AppendText(event.value)
def AppendErrorText(self, event):
self.framesTab.AppendErrorText(event.value)
def OnClearOutput(self, event):
self.framesTab.ClearOutput(None)
def SwitchToOutputTab(self):
self.framesTab.SwitchToOutputTab()
class PHPDebuggerUI(BaseDebuggerUI):
DEFAULT_LISTENER_HOST = "127.0.0.1"
DEFAULT_LISTENER_PORT = 10001
DEFAULT_DBG_MOD_TIMEOUT = 300
DEFAULT_DBG_MAX_EXEC_TIME = 240
dbgSessSeqId = 1
def __init__(self, parent, id, command, service):
BaseDebuggerUI.__init__(self, parent, id)
#Note host and port need to come out of options or a pool.
self._dbgHost = PHPDebuggerUI.DEFAULT_LISTENER_HOST
self._dbgPort = PHPDebuggerUI.DEFAULT_LISTENER_PORT
self._dbgTimeout = PHPDebuggerUI.DEFAULT_DBG_MOD_TIMEOUT
self._dbgMaxExecTime = PHPDebuggerUI.DEFAULT_DBG_MAX_EXEC_TIME
self._dbgSessId = None
self._dbgSessParam = None
self._dbgPhpIniFile = None
self._callback = PHPDebugger.PHPDebuggerCallback(self, service, self._dbgHost, self._dbgPort)
self._executor = Executor(command, self)
self._service = service
self._stopped = False
self._allStopped = False
self._createPhpDbgSess()
def showErrorDialog(self, message, title):
wx.MessageBox(_(message), _(title))
return
def _createPhpDbgSess(self):
currTimeStr = str(time.time())
(secStr, usecStr) = currTimeStr.split('.')
secLongInt = long(secStr)
usecLongInt = long(usecStr)
self._dbgSessId = "%06ld%06ld%04d" % (secLongInt, usecLongInt, PHPDebuggerUI.dbgSessSeqId)
PHPDebuggerUI.dbgSessSeqId = PHPDebuggerUI.dbgSessSeqId + 1
self._dbgSessParam = "DBGSESSID=%s@clienthost:%d" % (self._dbgSessId, self._dbgPort)
if _VERBOSE:
print "phpDbgParam=%s" % self._dbgSessParam
self._service.SetPhpDbgParam(self._dbgSessParam)
def _preparePhpIniFile(self):
success = False
phpCgiExec = Executor.GetPHPExecutablePath()
phpExec = phpCgiExec.replace("php-cgi", "php")
iniPath = self._getPhpIniFromRunningPhp(phpExec)
try:
iniDbgPath = os.path.normpath(iniPath + ".ag_debug_enabled")
dbgFile = open(iniDbgPath, "w")
oriFile = open(iniPath, "r")
while True:
oneOriLine = oriFile.readline()
if oneOriLine == '':
break
if not oneOriLine.startswith("debugger.") and not oneOriLine.startswith("max_execution_time="):
dbgFile.write(oneOriLine)
oriFile.close()
if _WINDOWS:
dbgExtFile = "php_dbg.dll"
else:
dbgExtFile = "dbg.so"
#
# TODO: we should make all of these options configurable.
#
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)
dbgFile.write(configStr)
dbgFile.close()
success = True
except:
#TODO: print stack trace.
print "Caught exceptions while minipulating php.ini files"
if success:
self._dbgPhpIniFile = iniDbgPath
else:
self._dbgPhpIniFile = None
def _getPhpIniFromRunningPhp(self, phpExec):
phpIniPath = None
cmdEnv = os.environ
if cmdEnv.has_key('PYTHONPATH'):
del cmdEnv['PYTHONPATH']
cmdLine = [phpExec, "-r", "phpinfo();"]
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)
phpOutput = phpProc.stdout
phpIniPattern = "Configuration File (php.ini) Path => "
while True:
oneLine = phpOutput.readline()
if oneLine == '':
break
if oneLine.startswith(phpIniPattern):
if oneLine.endswith("\n"):
endIndex = oneLine.index("\n")
phpIniPath = oneLine[len(phpIniPattern):endIndex]
else:
phpIniPath = oneLine[len(phpIniPattern):]
if phpIniPath and len(phpIniPath) > 0:
phpIniPath = os.path.normpath(phpIniPath)
break
phpOutput.close()
if _VERBOSE:
print "php.ini path is: %s" % repr(phpIniPath)
return phpIniPath
def Execute(self, initialArgs, startIn, environment, onWebServer = False):
self._preparePhpIniFile()
self._callback.Start()
if not onWebServer:
if self._dbgPhpIniFile:
args = '-c "' + self._dbgPhpIniFile + '" ' + initialArgs
else:
args = initialArgs
self._executor.Execute(args, startIn, environment)
def StopExecution(self, event):
# This is a general comment on shutdown for the running and debugged processes. Basically, the
# current state of this is the result of trial and error coding. The common problems were memory
# access violations and threads that would not exit. Making the OutputReaderThreads daemons seems
# to have side-stepped the hung thread issue. Being very careful not to touch things after calling
# process.py:ProcessOpen.kill() also seems to have fixed the memory access violations, but if there
# were more ugliness discovered I would not be surprised. If anyone has any help/advice, please send
# it on to mfryer@activegrid.com.
if not self._allStopped:
self._stopped = True
try:
self.DisableAfterStop()
except wx._core.PyDeadObjectError:
pass
try:
#
# If this is called by clicking the "Stop" button, we only stop
# the current running php script, and keep the listener
# running.
#
if event:
self._callback.ShutdownServer(stopLsnr = False)
else:
self._callback.ShutdownServer(stopLsnr = True)
self._allStopped = True
except:
tp,val,tb = sys.exc_info()
traceback.print_exception(tp, val, tb)
try:
self.DeleteCurrentLineMarkers()
except:
pass
try:
if self._executor:
self._executor.DoStopExecution()
self._executor = None
except:
tp,val,tb = sys.exc_info()
traceback.print_exception(tp, val, tb)
def MakeFramesUI(self, parent, id, debugger):
return PHPFramesUI(parent, id, self)
def LoadPHPFramesList(self, stackList):
self.framesTab.LoadFramesList(stackList)
#
# TODO: this is a hack to overwrite BaseDebuggerUI's function. The purpose
# is to always push breakpoints no matter if a php is running or not. If
# no php is running, an exception will be thrown and handled like nothing
# happened.
#
def BreakPointChange(self):
self._callback.PushBreakpoints()
self.framesTab.PopulateBPList()
class PythonDebuggerUI(BaseDebuggerUI):
debuggerPortList = None
def GetAvailablePort():
for index in range( 0, len(PythonDebuggerUI.debuggerPortList)):
port = PythonDebuggerUI.debuggerPortList[index]
if PythonDebuggerUI.PortAvailable(port):
PythonDebuggerUI.debuggerPortList.pop(index)
return port
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"))
assert False, "Out of ports for debugger."
GetAvailablePort = staticmethod(GetAvailablePort)
def ReturnPortToPool(port):
config = wx.ConfigBase_Get()
startingPort = config.ReadInt("DebuggerStartingPort", DEFAULT_PORT)
val = int(startingPort) + int(PORT_COUNT)
if int(port) >= startingPort and (int(port) <= val):
PythonDebuggerUI.debuggerPortList.append(int(port))
ReturnPortToPool = staticmethod(ReturnPortToPool)
def PortAvailable(port):
config = wx.ConfigBase_Get()
hostname = config.Read("DebuggerHostName", DEFAULT_HOST)
try:
server = AGXMLRPCServer((hostname, port))
server.server_close()
if _VERBOSE: print "Port ", str(port), " available."
return True
except:
tp,val,tb = sys.exc_info()
if _VERBOSE: traceback.print_exception(tp, val, tb)
if _VERBOSE: print "Port ", str(port), " unavailable."
return False
PortAvailable = staticmethod(PortAvailable)
def NewPortRange():
config = wx.ConfigBase_Get()
startingPort = config.ReadInt("DebuggerStartingPort", DEFAULT_PORT)
PythonDebuggerUI.debuggerPortList = range(startingPort, startingPort + PORT_COUNT)
NewPortRange = staticmethod(NewPortRange)
def __init__(self, parent, id, command, service, autoContinue=True):
# Check for ports before creating the panel.
if not PythonDebuggerUI.debuggerPortList:
PythonDebuggerUI.NewPortRange()
self._debuggerPort = str(PythonDebuggerUI.GetAvailablePort())
self._guiPort = str(PythonDebuggerUI.GetAvailablePort())
self._debuggerBreakPort = str(PythonDebuggerUI.GetAvailablePort())
BaseDebuggerUI.__init__(self, parent, id)
self._command = command
self._service = service
config = wx.ConfigBase_Get()
self._debuggerHost = self._guiHost = config.Read("DebuggerHostName", DEFAULT_HOST)
url = 'http://' + self._debuggerHost + ':' + self._debuggerPort + '/'
self._breakURL = 'http://' + self._debuggerHost + ':' + self._debuggerBreakPort + '/'
self._callback = PythonDebuggerCallback(self._guiHost, self._guiPort, url, self._breakURL, self, autoContinue)
if DebuggerHarness.__file__.find('library.zip') > 0:
try:
fname = DebuggerHarness.__file__
parts = fname.split('library.zip')
path = os.path.join(parts[0],'activegrid', 'tool', 'DebuggerHarness.py')
except:
tp, val, tb = sys.exc_info()
traceback.print_exception(tp, val, tb)
else:
print "Starting debugger on these ports: %s, %s, %s" % (str(self._debuggerPort) , str(self._guiPort) , str(self._debuggerBreakPort))
path = DebuggerService.ExpandPath(DebuggerHarness.__file__)
self._executor = Executor(path, self, self._debuggerHost, \
self._debuggerPort, self._debuggerBreakPort, self._guiHost, self._guiPort, self._command, callbackOnExit=self.ExecutorFinished)
self._stopped = False
def LoadPythonFramesList(self, framesXML):
self.framesTab.LoadFramesList(framesXML)
def Execute(self, initialArgs, startIn, environment, onWebServer = False):
self._callback.Start()
self._executor.Execute(initialArgs, startIn, environment)
self._callback.WaitForRPC()
def StopExecution(self, event):
# This is a general comment on shutdown for the running and debugged processes. Basically, the
# current state of this is the result of trial and error coding. The common problems were memory
# access violations and threads that would not exit. Making the OutputReaderThreads daemons seems
# to have side-stepped the hung thread issue. Being very careful not to touch things after calling
# process.py:ProcessOpen.kill() also seems to have fixed the memory access violations, but if there
# were more ugliness discovered I would not be surprised. If anyone has any help/advice, please send
# it on to mfryer@activegrid.com.
if not self._stopped:
self._stopped = True
try:
self.DisableAfterStop()
except wx._core.PyDeadObjectError:
pass
try:
self._callback.ShutdownServer()
except:
tp,val,tb = sys.exc_info()
traceback.print_exception(tp, val, tb)
try:
self.DeleteCurrentLineMarkers()
except:
pass
try:
PythonDebuggerUI.ReturnPortToPool(self._debuggerPort)
PythonDebuggerUI.ReturnPortToPool(self._guiPort)
PythonDebuggerUI.ReturnPortToPool(self._debuggerBreakPort)
except:
pass
try:
if self._executor:
self._executor.DoStopExecution()
self._executor = None
except:
tp,val,tb = sys.exc_info()
traceback.print_exception(tp, val, tb)
def MakeFramesUI(self, parent, id, debugger):
panel = PythonFramesUI(parent, id, self)
return panel
class BreakpointsUI(wx.Panel):
def __init__(self, parent, id, ui):
wx.Panel.__init__(self, parent, id)
self._ui = ui
self.currentItem = None
self.clearBPID = wx.NewId()
self.Bind(wx.EVT_MENU, self.ClearBreakPoint, id=self.clearBPID)
self.syncLineID = wx.NewId()
self.Bind(wx.EVT_MENU, self.SyncBPLine, id=self.syncLineID)
sizer = wx.BoxSizer(wx.VERTICAL)
p1 = self
self._bpListCtrl = wx.ListCtrl(p1, -1, pos=wx.DefaultPosition, size=(1000,1000), style=wx.LC_REPORT)
sizer.Add(self._bpListCtrl, 1, wx.ALIGN_LEFT|wx.ALL|wx.EXPAND, 1)
self._bpListCtrl.InsertColumn(0, "File")
self._bpListCtrl.InsertColumn(1, "Line")
self._bpListCtrl.InsertColumn(2, "Path")
self._bpListCtrl.SetColumnWidth(0, 150)
self._bpListCtrl.SetColumnWidth(1, 50)
self._bpListCtrl.SetColumnWidth(2, 450)
self._bpListCtrl.Bind(wx.EVT_LIST_ITEM_RIGHT_CLICK, self.OnListRightClick)
self.Bind(wx.EVT_LIST_ITEM_SELECTED, self.ListItemSelected, self._bpListCtrl)
self.Bind(wx.EVT_LIST_ITEM_DESELECTED, self.ListItemDeselected, self._bpListCtrl)
def OnLeftDoubleClick(event):
self.SyncBPLine(event)
wx.EVT_LEFT_DCLICK(self._bpListCtrl, OnLeftDoubleClick)
self.PopulateBPList()
p1.SetSizer(sizer)
sizer.Fit(p1)
p1.Layout()
def PopulateBPList(self):
list = self._bpListCtrl
list.DeleteAllItems()
bps = wx.GetApp().GetService(DebuggerService).GetMasterBreakpointDict()
index = 0
for fileName in bps.keys():
shortFile = os.path.basename(fileName)
lines = bps[fileName]
if lines:
for line in lines:
list.InsertStringItem(index, shortFile)
list.SetStringItem(index, 1, str(line))
list.SetStringItem(index, 2, fileName)
def OnListRightClick(self, event):
menu = wx.Menu()
item = wx.MenuItem(menu, self.clearBPID, "Clear Breakpoint")
menu.AppendItem(item)
item = wx.MenuItem(menu, self.syncLineID, "Goto Source Line")
menu.AppendItem(item)
self.PopupMenu(menu, event.GetPosition())
menu.Destroy()
def SyncBPLine(self, event):
if self.currentItem != -1:
list = self._bpListCtrl
fileName = list.GetItem(self.currentItem, 2).GetText()
lineNumber = list.GetItem(self.currentItem, 1).GetText()
self._ui.SynchCurrentLine( fileName, int(lineNumber) , noArrow=True)
def ClearBreakPoint(self, event):
if self.currentItem >= 0:
list = self._bpListCtrl
fileName = list.GetItem(self.currentItem, 2).GetText()
lineNumber = list.GetItem(self.currentItem, 1).GetText()
wx.GetApp().GetService(DebuggerService).OnToggleBreakpoint(None, line=int(lineNumber) -1, fileName=fileName )
def ListItemSelected(self, event):
self.currentItem = event.m_itemIndex
def ListItemDeselected(self, event):
self.currentItem = -1
class Watch:
CODE_ALL_FRAMES = 1
CODE_THIS_BLOCK = 2
CODE_THIS_LINE = 4
CODE_RUN_ONCE = 8
def __init__(self, name, command, show_code=CODE_ALL_FRAMES):
self._name = name
self._command = command
self._show_code = show_code
class WatchDialog(wx.Dialog):
WATCH_ALL_FRAMES = "Watch in all frames"
WATCH_THIS_FRAME = "Watch in this frame only"
WATCH_ONCE = "Watch once and delete"
def __init__(self, parent, title, chain):
wx.Dialog.__init__(self, parent, -1, title, style=wx.DEFAULT_DIALOG_STYLE)
self._chain = chain
self.label_2 = wx.StaticText(self, -1, "Watch Name:")
self._watchNameTextCtrl = wx.TextCtrl(self, -1, "")
self.label_3 = wx.StaticText(self, -1, "eval(", style=wx.ALIGN_RIGHT)
self._watchValueTextCtrl = wx.TextCtrl(self, -1, "")
self.label_4 = wx.StaticText(self, -1, ",frame.f_globals, frame.f_locals)")
self.radio_box_1 = wx.RadioBox(self, -1, "Watch Information", choices=[WatchDialog.WATCH_ALL_FRAMES, WatchDialog.WATCH_THIS_FRAME, WatchDialog.WATCH_ONCE], majorDimension=0, style=wx.RA_SPECIFY_ROWS)
self._okButton = wx.Button(self, wx.ID_OK, "OK")
self._okButton.SetDefault()
self._okButton.SetHelpText(_("The OK button completes the dialog"))
def OnOkClick(event):
if self._watchNameTextCtrl.GetValue() == "":
wx.MessageBox(_("You must enter a name for the watch."), _("Add Watch"))
return
if self._watchValueTextCtrl.GetValue() == "":
wx.MessageBox(_("You must enter some code to run for the watch."), _("Add Watch"))
return
self.EndModal(wx.ID_OK)
self.Bind(wx.EVT_BUTTON, OnOkClick, self._okButton)
self._cancelButton = wx.Button(self, wx.ID_CANCEL, _("Cancel"))
self._cancelButton.SetHelpText(_("The Cancel button cancels the dialog."))
self.__set_properties()
self.__do_layout()
def GetSettings(self):
return self._watchNameTextCtrl.GetValue(), self._watchValueTextCtrl.GetValue(), self.GetSendFrame(), self.GetRunOnce()
def GetSendFrame(self):
return (WatchDialog.WATCH_ALL_FRAMES != self.radio_box_1.GetStringSelection())
def GetRunOnce(self):
return (WatchDialog.WATCH_ONCE == self.radio_box_1.GetStringSelection())
def __set_properties(self):
self.SetTitle("Add a Watch")
#self.SetSize((400, 250))
self.radio_box_1.SetSelection(0)
def __do_layout(self):
sizer_1 = wx.BoxSizer(wx.VERTICAL)
grid_sizer_4 = wx.FlexGridSizer(1, 3, 5, 5)
grid_sizer_2 = wx.FlexGridSizer(1, 2, 5, 5)
grid_sizer_2.Add(self.label_2, 0, wx.ALIGN_CENTER_VERTICAL|wx.FIXED_MINSIZE, 0)
grid_sizer_2.Add(self._watchNameTextCtrl, 0, wx.EXPAND, 0)
grid_sizer_2.AddGrowableCol(1)
sizer_1.Add(grid_sizer_2, 1, wx.EXPAND, 0)
grid_sizer_4.Add(self.label_3, 0, wx.ALIGN_CENTER_VERTICAL|wx.FIXED_MINSIZE, 0)
grid_sizer_4.Add(self._watchValueTextCtrl, 0, wx.EXPAND, 0)
grid_sizer_4.AddGrowableCol(1)
grid_sizer_4.Add(self.label_4, 0, wx.ALIGN_CENTER_VERTICAL|wx.FIXED_MINSIZE, 0)
sizer_1.Add(grid_sizer_4, 0, wx.EXPAND, 0)
sizer_1.Add(self.radio_box_1, 0, wx.EXPAND, 0)
box = wx.BoxSizer(wx.HORIZONTAL)
box.Add(self._okButton, 0, wx.ALIGN_RIGHT|wx.ALL, 5)
box.Add(self._cancelButton, 0, wx.ALIGN_RIGHT|wx.ALL, 5)
sizer_1.Add(box, 1, wx.EXPAND, 0)
self.SetSizer(sizer_1)
self.Layout()
class BaseFramesUI(wx.SplitterWindow):
def __init__(self, parent, id, ui):
wx.SplitterWindow.__init__(self, parent, id, style = wx.SP_3D)
self._ui = ui
self._p1 = p1 = wx.ScrolledWindow(self, -1)
sizer = wx.BoxSizer(wx.HORIZONTAL)
framesLabel = wx.StaticText(self, -1, "Stack Frame:")
sizer.Add(framesLabel, 0, flag=wx.ALIGN_CENTER_VERTICAL|wx.ALIGN_LEFT|wx.LEFT, border=2)
self._framesChoiceCtrl = wx.Choice(p1, -1, choices=[" "])
sizer.Add(self._framesChoiceCtrl, 1, wx.ALIGN_LEFT|wx.ALL|wx.EXPAND, 1)
self._framesChoiceCtrl.Bind(wx.EVT_LIST_ITEM_RIGHT_CLICK, self.OnListRightClick)
self.Bind(wx.EVT_CHOICE, self.ListItemSelected, self._framesChoiceCtrl)
sizer2 = wx.BoxSizer(wx.VERTICAL)
p1.SetSizer(sizer2)
self._treeCtrl = wx.gizmos.TreeListCtrl(p1, -1, style=wx.TR_DEFAULT_STYLE| wx.TR_FULL_ROW_HIGHLIGHT)
self._treeCtrl.Bind(wx.EVT_TREE_ITEM_RIGHT_CLICK, self.OnRightClick)
sizer2.Add(sizer, 0, wx.ALIGN_LEFT|wx.ALL|wx.EXPAND, 1)
sizer2.Add(self._treeCtrl,1, wx.ALIGN_LEFT|wx.ALL|wx.EXPAND, 1)
tree = self._treeCtrl
tree.AddColumn("Thing")
tree.AddColumn("Value")
tree.SetMainColumn(0) # the one with the tree in it...
tree.SetColumnWidth(0, 175)
tree.SetColumnWidth(1, 355)
self._root = tree.AddRoot("Frame")
tree.SetPyData(self._root, "root")
tree.SetItemText(self._root, "", 1)
tree.Bind(wx.EVT_TREE_ITEM_EXPANDING, self.IntrospectCallback)
self._p2 = p2 = wx.Window(self, -1)
sizer3 = wx.BoxSizer(wx.HORIZONTAL)
p2.SetSizer(sizer3)
p2.Bind(wx.EVT_SIZE, self.OnSize)
self._notebook = wx.Notebook(p2, -1, size=(20,20))
self._notebook.Hide()
sizer3.Add(self._notebook, 1, wx.ALIGN_LEFT|wx.ALL|wx.EXPAND, 1)
self.consoleTab = self.MakeConsoleTab(self._notebook, wx.NewId())
self.inspectConsoleTab = self.MakeInspectConsoleTab(self._notebook, wx.NewId())
self.breakPointsTab = self.MakeBreakPointsTab(self._notebook, wx.NewId())
self._notebook.AddPage(self.consoleTab, "Output")
self._notebook.AddPage(self.inspectConsoleTab, "Interact")
self._notebook.AddPage(self.breakPointsTab, "Break Points")
self.SetMinimumPaneSize(20)
self.SplitVertically(p1, p2, 550)
self.currentItem = None
self._notebook.Show(True)
def PopulateBPList(self):
self.breakPointsTab.PopulateBPList()
def OnSize(self, event):
self._notebook.SetSize(self._p2.GetSize())
def OnDoubleClick(self, event):
# Looking for a stack trace line.
lineText, pos = self._textCtrl.GetCurLine()
fileBegin = lineText.find("File \"")
fileEnd = lineText.find("\", line ")
lineEnd = lineText.find(", in ")
if lineText == "\n" or fileBegin == -1 or fileEnd == -1 or lineEnd == -1:
# Check the line before the one that was clicked on
lineNumber = self._textCtrl.GetCurrentLine()
if(lineNumber == 0):
return
lineText = self._textCtrl.GetLine(lineNumber - 1)
fileBegin = lineText.find("File \"")
fileEnd = lineText.find("\", line ")
lineEnd = lineText.find(", in ")
if lineText == "\n" or fileBegin == -1 or fileEnd == -1 or lineEnd == -1:
return
filename = lineText[fileBegin + 6:fileEnd]
lineNum = int(lineText[fileEnd + 8:lineEnd])
foundView = None
openDocs = wx.GetApp().GetDocumentManager().GetDocuments()
for openDoc in openDocs:
if openDoc.GetFilename() == filename:
foundView = openDoc.GetFirstView()
break
if not foundView:
doc = wx.GetApp().GetDocumentManager().CreateDocument(filename, wx.lib.docview.DOC_SILENT)
foundView = doc.GetFirstView()
if foundView:
foundView.GetFrame().SetFocus()
foundView.Activate()
foundView.GotoLine(lineNum)
startPos = foundView.PositionFromLine(lineNum)
lineText = foundView.GetCtrl().GetLine(lineNum - 1)
foundView.SetSelection(startPos, startPos + len(lineText.rstrip("\n")))
import OutlineService
wx.GetApp().GetService(OutlineService.OutlineService).LoadOutline(foundView, position=startPos)
def MakeConsoleTab(self, parent, id):
panel = wx.Panel(parent, id)
sizer = wx.BoxSizer(wx.HORIZONTAL)
self._textCtrl = STCTextEditor.TextCtrl(panel, wx.NewId())
sizer.Add(self._textCtrl, 1, wx.ALIGN_LEFT|wx.ALL|wx.EXPAND, 2)
self._textCtrl.SetViewLineNumbers(False)
self._textCtrl.SetReadOnly(True)
if wx.Platform == '__WXMSW__':
font = "Courier New"
else:
font = "Courier"
self._textCtrl.SetFont(wx.Font(9, wx.DEFAULT, wx.NORMAL, wx.NORMAL, faceName = font))
self._textCtrl.SetFontColor(wx.BLACK)
self._textCtrl.StyleClearAll()
wx.stc.EVT_STC_DOUBLECLICK(self._textCtrl, self._textCtrl.GetId(), self.OnDoubleClick)
panel.SetSizer(sizer)
#sizer.Fit(panel)
return panel
def ExecuteCommand(self, command):
assert False, "ExecuteCommand not overridden"
def MakeInspectConsoleTab(self, parent, id):
def handleCommand():
cmdStr = self._cmdInput.GetValue()
if cmdStr:
self._cmdList.append(cmdStr)
self._cmdIndex = len(self._cmdList)
self._cmdInput.Clear()
self._cmdOutput.SetDefaultStyle(style=self._cmdOutputTextStyle)
self._cmdOutput.AppendText(">>> " + cmdStr + "\n")
self._cmdOutput.SetDefaultStyle(style=self._defaultOutputTextStyle)
self.ExecuteCommand(cmdStr)
return
def OnCmdButtonPressed(event):
handleCommand()
return
def OnKeyPressed(event):
key = event.KeyCode()
if key == wx.WXK_RETURN:
handleCommand()
elif key == wx.WXK_UP:
if len(self._cmdList) < 1 or self._cmdIndex < 1:
return
self._cmdInput.Clear()
self._cmdInput.AppendText(self._cmdList[self._cmdIndex - 1])
self._cmdIndex = self._cmdIndex - 1
elif key == wx.WXK_DOWN:
if len(self._cmdList) < 1 or self._cmdIndex >= len(self._cmdList):
return
self._cmdInput.Clear()
self._cmdInput.AppendText(self._cmdList[self._cmdIndex - 1])
self._cmdIndex = self._cmdIndex + 1
else:
event.Skip()
return
def OnClrButtonPressed(event):
self._cmdOutput.Clear()
panel = wx.Panel(parent, id)
cmdLabel = wx.StaticText(panel, -1, "Cmd: ")
self._cmdInput = wx.TextCtrl(panel)
cmdButton = wx.Button(panel, label="Execute")
clrButton = wx.Button(panel, label="Clear")
self._cmdOutput = wx.TextCtrl(panel, style=wx.TE_MULTILINE | wx.HSCROLL | wx.TE_READONLY | wx.TE_RICH2)
hbox = wx.BoxSizer()
hbox.Add(cmdLabel, proportion=0, flag=wx.LEFT|wx.ALIGN_CENTER_VERTICAL)
hbox.Add(self._cmdInput, proportion=1, flag=wx.EXPAND)
hbox.Add(cmdButton, proportion=0, flag=wx.RIGHT)
hbox.Add(clrButton, proportion=0, flag=wx.RIGHT)
vbox = wx.BoxSizer(wx.VERTICAL)
vbox.Add(hbox, proportion=0, flag=wx.EXPAND | wx.ALL, border=2)
vbox.Add(self._cmdOutput, proportion=1, flag=wx.EXPAND | wx.LEFT, border=2)
panel.SetSizer(vbox)
cmdButton.Bind(wx.EVT_BUTTON, OnCmdButtonPressed)
clrButton.Bind(wx.EVT_BUTTON, OnClrButtonPressed)
wx.EVT_KEY_DOWN(self._cmdInput, OnKeyPressed)
fixedFont = wx.Font(self._cmdInput.GetFont().GetPointSize(), family=wx.TELETYPE, style=wx.NORMAL, weight=wx.NORMAL)
self._defaultOutputTextStyle = wx.TextAttr("BLACK", wx.NullColour, fixedFont)
self._cmdOutputTextStyle = wx.TextAttr("RED", wx.NullColour, fixedFont)
self._cmdOutput.SetDefaultStyle(style=self._defaultOutputTextStyle)
self._cmdList = []
self._cmdIndex = 0
panel.Show()
return panel
def MakeBreakPointsTab(self, parent, id):
panel = BreakpointsUI(parent, id, self._ui)
return panel
def OnRightClick(self, event):
assert False, "OnRightClick not overridden"
def ClearWhileRunning(self):
list = self._framesChoiceCtrl
list.Clear()
list.Enable(False)
tree = self._treeCtrl
root = self._root
tree.DeleteChildren(root)
self._cmdInput.Enable(False)
self._cmdOutput.Enable(False)
def OnListRightClick(self, event):
if not hasattr(self, "syncFrameID"):
self.syncFrameID = wx.NewId()
self.Bind(wx.EVT_MENU, self.OnSyncFrame, id=self.syncFrameID)
menu = wx.Menu()
item = wx.MenuItem(menu, self.syncFrameID, "Goto Source Line")
menu.AppendItem(item)
self.PopupMenu(menu, event.GetPosition())
menu.Destroy()
def OnSyncFrame(self, event):
assert False, "OnSyncFrame not overridden"
def LoadFramesList(self, framesXML):
assert False, "LoadFramesList not overridden"
def ListItemSelected(self, event):
assert False, "ListItemSelected not overridden"
def PopulateTreeFromFrameMessage(self, message):
assert False, "PopulateTreeFromFrameMessage not overridden"
def IntrospectCallback(self, event):
assert False, "IntrospectCallback not overridden"
def AppendText(self, text):
self._textCtrl.SetReadOnly(False)
self._textCtrl.AddText(text)
self._textCtrl.ScrollToLine(self._textCtrl.GetLineCount())
self._textCtrl.SetReadOnly(True)
def AppendErrorText(self, text):
self._textCtrl.SetReadOnly(False)
self._textCtrl.SetFontColor(wx.RED)
self._textCtrl.StyleClearAll()
self._textCtrl.AddText(text)
self._textCtrl.ScrollToLine(self._textCtrl.GetLineCount())
self._textCtrl.SetFontColor(wx.BLACK)
self._textCtrl.StyleClearAll()
self._textCtrl.SetReadOnly(True)
def ClearOutput(self, event):
self._textCtrl.SetReadOnly(False)
self._textCtrl.ClearAll()
self._textCtrl.SetReadOnly(True)
def SwitchToOutputTab(self):
self._notebook.SetSelection(0)
class PHPFramesUI(BaseFramesUI):
def __init__(self, parent, id, ui):
BaseFramesUI.__init__(self, parent, id, ui)
def LoadFramesList(self, stackList):
wx.GetApp().GetTopWindow().SetCursor(wx.StockCursor(wx.CURSOR_WAIT))
self._cmdInput.Enable(True)
self._cmdOutput.Enable(True)
index = 0
self._stack = stackList
list = self._framesChoiceCtrl
list.Clear()
if len(stackList) > 0:
self._displayVariableTreeRootNode()
for stackFrame in stackList:
message = stackFrame.getDisplayStr(stackList)
list.Append(message)
self.currentItem = index
list.SetSelection(index)
list.Enable(True)
self.OnSyncFrame(None)
self._p1.FitInside()
wx.GetApp().GetTopWindow().SetCursor(wx.StockCursor(wx.CURSOR_DEFAULT))
def PopulateTreeFromStackFrame(self, frameNode):
vars = frameNode.getVariables()
tree = self._treeCtrl
rootTreeNode = self._root
#
# Build a new sub variable tree from the root node.
#
tree.DeleteChildren(rootTreeNode)
for var in vars:
aTreeNode = self.AppendSubTreeFromAVariable(tree, var, rootTreeNode)
#
# No need to expand the node here, as the IntrospectCallback() has
# already called it.
#
self._p2.FitInside()
def AppendSubTreeFromAVariable(self, tree, var, parentTreeNode, previousOne = None):
varName = var.getName()
varValueStr = var.getValueString()
#
# If previously we already have this item in the tree, replace it.
# Otherwise, insert a new one.
#
if previousOne:
newNode = tree.InsertItem(parentTreeNode, previousOne, varName)
else:
newNode = tree.AppendItem(parentTreeNode, varName)
#
# Associate this variable object with this newNode.
#
tree.SetPyData(newNode, var)
#
# Set this variable's value string (for displaying).
#
if varValueStr and len(varValueStr) > 0:
tree.SetItemText(newNode, varValueStr, 1)
#
# If this variable has child variables, recursively build the sub
# variable tree.
#
if var.hasChildren():
childrenVarList = var.getChildrenVariables()
for childVar in childrenVarList:
self.AppendSubTreeFromAVariable(tree, childVar, newNode)
#
# If its child variables are sortable, sort it.
#
if var.childrenIsSortable():
tree.SortChildren(newNode)
return newNode
def IntrospectCallback(self, event):
tree = self._treeCtrl
item = event.GetItem()
#
# Only when the introspection happens to root, we get the whole
# variable tree. For all the individual nodes, we have populated
# the subtree already, so don't need to do anything.
#
if tree.GetPyData(item) == "root" and self._stack and self._stack[self.currentItem]:
stackFrame = self._stack[self.currentItem]
self.PopulateTreeFromStackFrame(stackFrame)
event.Skip()
def OnSyncFrame(self, event):
stackFrame = self._stack[self.currentItem]
fileName = stackFrame.getFileName()
lineNo = stackFrame.getLineNo()
if _VERBOSE:
print "OnSyncFrame(): about to sync: fileName: %s, lineNo: %d" % (fileName, lineNo)
self._ui.SynchCurrentLine(fileName, lineNo)
if _VERBOSE:
print "OnSyncFrame(): sync done"
def ListItemSelected(self, event):
selectedStackFrameStr = event.GetString()
if not self._stack or len(self._stack) < 1:
return
found = False
for stackFrame in self._stack:
if stackFrame.getDisplayStr() == selectedStackFrameStr:
self.currentItem = stackFrame.getFrameIndex()
found = True
break
if found:
self._displayVariableTreeRootNode()
self.OnSyncFrame(None)
return
def _displayVariableTreeRootNode(self):
#
# Add a dummy item to rootTreeNode so that it will be shown as
# expandable. Only do real tree population on the fly when the
# rootTreeNode is expanded in OnIntrospection().
#
tree = self._treeCtrl
rootTreeNode = self._root
dummyNode = tree.AppendItem(rootTreeNode, "dummy")
tree.Collapse(rootTreeNode)
return
class PythonFramesUI(BaseFramesUI):
def __init__(self, parent, id, ui):
BaseFramesUI.__init__(self, parent, id, ui)
def ExecuteCommand(self, command):
retval = self._ui._callback._debuggerServer.execute_in_frame(self._framesChoiceCtrl.GetStringSelection(), command)
self._cmdOutput.AppendText(str(retval) + "\n")
# Refresh the tree view in case this command resulted in changes there. TODO: Need to reopen tree items.
self.PopulateTreeFromFrameMessage(self._framesChoiceCtrl.GetStringSelection())
def OnRightClick(self, event):
#Refactor this...
self._introspectItem = event.GetItem()
self._parentChain = self.GetItemChain(event.GetItem())
watchOnly = len(self._parentChain) < 1
if not _WATCHES_ON and watchOnly:
return
menu = wx.Menu()
if _WATCHES_ON:
if not hasattr(self, "watchID"):
self.watchID = wx.NewId()
self.Bind(wx.EVT_MENU, self.OnWatch, id=self.watchID)
item = wx.MenuItem(menu, self.watchID, "Create a Watch")
menu.AppendItem(item)
menu.AppendSeparator()
if not watchOnly:
if not hasattr(self, "viewID"):
self.viewID = wx.NewId()
self.Bind(wx.EVT_MENU, self.OnView, id=self.viewID)
item = wx.MenuItem(menu, self.viewID, "View in Dialog")
menu.AppendItem(item)
if not hasattr(self, "toInteractID"):
self.toInteractID = wx.NewId()
self.Bind(wx.EVT_MENU, self.OnSendToInteract, id=self.toInteractID)
item = wx.MenuItem(menu, self.toInteractID, "Send to Interact")
menu.AppendItem(item)
offset = wx.Point(x=0, y=20)
menuSpot = event.GetPoint() + offset
self._treeCtrl.PopupMenu(menu, menuSpot)
menu.Destroy()
self._parentChain = None
self._introspectItem = None
def GetItemChain(self, item):
parentChain = []
if item:
if _VERBOSE: print 'Exploding: %s' % self._treeCtrl.GetItemText(item, 0)
while item != self._root:
text = self._treeCtrl.GetItemText(item, 0)
if _VERBOSE: print "Appending ", text
parentChain.append(text)
item = self._treeCtrl.GetItemParent(item)
parentChain.reverse()
return parentChain
def OnView(self, event):
title = self._treeCtrl.GetItemText(self._introspectItem,0)
value = self._treeCtrl.GetItemText(self._introspectItem,1)
dlg = wx.lib.dialogs.ScrolledMessageDialog(self, value, title, style=wx.DD_DEFAULT_STYLE | wx.RESIZE_BORDER)
dlg.Show()
def OnSendToInteract(self, event):
value = ""
prevItem = ""
for item in self._parentChain:
if item.find(prevItem + '[') != -1:
value += item[item.find('['):]
continue
if value != "":
value = value + '.'
if item == 'globals':
item = 'globals()'
if item != 'locals':
value += item
prevItem = item
print value
self.ExecuteCommand(value)
def OnWatch(self, event):
try:
if hasattr(self, '_parentChain'):
wd = WatchDialog(wx.GetApp().GetTopWindow(), "Add a Watch", self._parentChain)
else:
wd = WatchDialog(wx.GetApp().GetTopWindow(), "Add a Watch", None)
wd.CenterOnParent()
if wd.ShowModal() == wx.ID_OK:
name, text, send_frame, run_once = wd.GetSettings()
if send_frame:
frameNode = self._stack[int(self.currentItem)]
message = frameNode.getAttribute("message")
else:
message = ""
binType = self._ui._callback._debuggerServer.add_watch(name, text, message, run_once)
xmldoc = bz2.decompress(binType.data)
domDoc = parseString(xmldoc)
nodeList = domDoc.getElementsByTagName('watch')
if len(nodeList) == 1:
watchValue = nodeList.item(0).getAttribute("message")
wd.Destroy()
except:
tp, val, tb = sys.exc_info()
traceback.print_exception(tp, val, tb)
def OnIntrospect(self, event):
wx.GetApp().GetTopWindow().SetCursor(wx.StockCursor(wx.CURSOR_WAIT))
try:
try:
list = self._framesChoiceCtrl
frameNode = self._stack[int(self.currentItem)]
message = frameNode.getAttribute("message")
binType = self._ui._callback._debuggerServer.attempt_introspection(message, self._parentChain)
xmldoc = bz2.decompress(binType.data)
domDoc = parseString(xmldoc)
nodeList = domDoc.getElementsByTagName('replacement')
replacementNode = nodeList.item(0)
if len(replacementNode.childNodes):
thingToWalk = replacementNode.childNodes.item(0)
tree = self._treeCtrl
parent = tree.GetItemParent(self._introspectItem)
treeNode = self.AppendSubTreeFromNode(thingToWalk, thingToWalk.getAttribute('name'), parent, insertBefore=self._introspectItem)
if thingToWalk.getAttribute('name').find('[') == -1:
self._treeCtrl.SortChildren(treeNode)
self._treeCtrl.Expand(treeNode)
tree.Delete(self._introspectItem)
except:
tp,val,tb = sys.exc_info()
traceback.print_exception(tp, val, tb)
finally:
wx.GetApp().GetTopWindow().SetCursor(wx.StockCursor(wx.CURSOR_DEFAULT))
def OnSyncFrame(self, event):
list = self._framesChoiceCtrl
frameNode = self._stack[int(self.currentItem)]
file = frameNode.getAttribute("file")
line = frameNode.getAttribute("line")
self._ui.SynchCurrentLine( file, int(line) )
def LoadFramesList(self, framesXML):
wx.GetApp().GetTopWindow().SetCursor(wx.StockCursor(wx.CURSOR_WAIT))
try:
self._cmdInput.Enable(True)
self._cmdOutput.Enable(True)
try:
domDoc = parseString(framesXML)
list = self._framesChoiceCtrl
list.Clear()
self._stack = []
nodeList = domDoc.getElementsByTagName('frame')
frame_count = -1
for index in range(0, nodeList.length):
frameNode = nodeList.item(index)
message = frameNode.getAttribute("message")
list.Append(message)
self._stack.append(frameNode)
frame_count += 1
index = len(self._stack) - 1
list.SetSelection(index)
node = self._stack[index]
self.currentItem = index
self.PopulateTreeFromFrameNode(node)
self.OnSyncFrame(None)
self._p1.FitInside()
frameNode = nodeList.item(index)
file = frameNode.getAttribute("file")
line = frameNode.getAttribute("line")
self._ui.SynchCurrentLine( file, int(line) )
except:
tp,val,tb=sys.exc_info()
traceback.print_exception(tp, val, tb)
finally:
wx.GetApp().GetTopWindow().SetCursor(wx.StockCursor(wx.CURSOR_DEFAULT))
def ListItemSelected(self, event):
self.PopulateTreeFromFrameMessage(event.GetString())
self.OnSyncFrame(None)
def PopulateTreeFromFrameMessage(self, message):
index = 0
for node in self._stack:
if node.getAttribute("message") == message:
binType = self._ui._callback._debuggerServer.request_frame_document(message)
xmldoc = bz2.decompress(binType.data)
domDoc = parseString(xmldoc)
nodeList = domDoc.getElementsByTagName('frame')
self.currentItem = index
if len(nodeList):
self.PopulateTreeFromFrameNode(nodeList[0])
return
index = index + 1
def PopulateTreeFromFrameNode(self, frameNode):
list = self._framesChoiceCtrl
list.Enable(True)
tree = self._treeCtrl
#tree.Show(True)
root = self._root
tree.DeleteChildren(root)
children = frameNode.childNodes
firstChild = None
for index in range(0, children.length):
subNode = children.item(index)
treeNode = self.AppendSubTreeFromNode(subNode, subNode.getAttribute('name'), root)
if not firstChild:
firstChild = treeNode
tree.Expand(root)
if firstChild:
tree.Expand(firstChild)
self._p2.FitInside()
def IntrospectCallback(self, event):
tree = self._treeCtrl
item = event.GetItem()
if _VERBOSE:
print "In introspectCallback item is %s, pydata is %s" % (event.GetItem(), tree.GetPyData(item))
if tree.GetPyData(item) != "Introspect":
event.Skip()
return
self._introspectItem = item
self._parentChain = self.GetItemChain(item)
self.OnIntrospect(event)
event.Skip()
def AppendSubTreeFromNode(self, node, name, parent, insertBefore=None):
tree = self._treeCtrl
if insertBefore != None:
treeNode = tree.InsertItem(parent, insertBefore, name)
else:
treeNode = tree.AppendItem(parent, name)
children = node.childNodes
intro = node.getAttribute('intro')
if intro == "True":
tree.SetItemHasChildren(treeNode, True)
tree.SetPyData(treeNode, "Introspect")
if node.getAttribute("value"):
tree.SetItemText(treeNode, self.StripOuterSingleQuotes(node.getAttribute("value")), 1)
for index in range(0, children.length):
subNode = children.item(index)
if self.HasChildren(subNode):
self.AppendSubTreeFromNode(subNode, subNode.getAttribute("name"), treeNode)
else:
name = subNode.getAttribute("name")
value = self.StripOuterSingleQuotes(subNode.getAttribute("value"))
n = tree.AppendItem(treeNode, name)
tree.SetItemText(n, value, 1)
intro = subNode.getAttribute('intro')
if intro == "True":
tree.SetItemHasChildren(n, True)
tree.SetPyData(n, "Introspect")
if name.find('[') == -1:
self._treeCtrl.SortChildren(treeNode)
return treeNode
def StripOuterSingleQuotes(self, string):
if string.startswith("'") and string.endswith("'"):
retval = string[1:-1]
elif string.startswith("\"") and string.endswith("\""):
retval = string[1:-1]
else:
retval = string
if retval.startswith("u'") and retval.endswith("'"):
retval = retval[1:]
return retval
def HasChildren(self, node):
try:
return node.childNodes.length > 0
except:
tp,val,tb=sys.exc_info()
return False
class DebuggerView(Service.ServiceView):
#----------------------------------------------------------------------------
# Overridden methods
#----------------------------------------------------------------------------
def __init__(self, service):
Service.ServiceView.__init__(self, service)
def _CreateControl(self, parent, id):
return None
#------------------------------------------------------------------------------
# Event handling
#-----------------------------------------------------------------------------
def OnToolClicked(self, event):
self.GetFrame().ProcessEvent(event)
#------------------------------------------------------------------------------
# Class methods
#-----------------------------------------------------------------------------
class Interaction:
def __init__(self, message, framesXML, info=None, quit=False):
self._framesXML = framesXML
self._message = message
self._info = info
self._quit = quit
def getFramesXML(self):
return self._framesXML
def getMessage(self):
return self._message
def getInfo(self):
return self._info
def getQuit(self):
return self._quit
class AGXMLRPCServer(SimpleXMLRPCServer.SimpleXMLRPCServer):
def __init__(self, address, logRequests=0):
SimpleXMLRPCServer.SimpleXMLRPCServer.__init__(self, address, logRequests=logRequests)
class RequestHandlerThread(threading.Thread):
def __init__(self, queue, address):
threading.Thread.__init__(self)
self._keepGoing = True
self._queue = queue
self._address = address
self._server = AGXMLRPCServer(self._address,logRequests=0)
self._server.register_function(self.interaction)
self._server.register_function(self.quit)
self._server.register_function(self.dummyOperation)
if _VERBOSE: print "RequestHandlerThread on fileno %s" % str(self._server.fileno())
def run(self):
while self._keepGoing:
try:
self._server.handle_request()
except:
tp, val, tb = sys.exc_info()
traceback.print_exception(tp, val, tb)
self._keepGoing = False
if _VERBOSE: print "Exiting Request Handler Thread."
def interaction(self, message, frameXML, info):
if _VERBOSE: print "In RequestHandlerThread.interaction -- adding to queue"
interaction = Interaction(message, frameXML, info)
self._queue.put(interaction)
return ""
def quit(self):
interaction = Interaction(None, None, info=None, quit=True)
self._queue.put(interaction)
return ""
def dummyOperation(self):
return ""
def AskToStop(self):
self._keepGoing = False
if type(self._server) is not types.NoneType:
try:
# This is a really ugly way to make sure this thread isn't blocked in
# handle_request.
url = 'http://' + self._address[0] + ':' + str(self._address[1]) + '/'
tempServer = xmlrpclib.ServerProxy(url, allow_none=1)
tempServer.dummyOperation()
except:
tp, val, tb = sys.exc_info()
traceback.print_exception(tp, val, tb)
self._server.server_close()
class RequestBreakThread(threading.Thread):
def __init__(self, server, interrupt=False, pushBreakpoints=False, breakDict=None, kill=False):
threading.Thread.__init__(self)
self._server = server
self._interrupt = interrupt
self._pushBreakpoints = pushBreakpoints
self._breakDict = breakDict
self._kill = kill
def run(self):
try:
if _VERBOSE: print "RequestBreakThread, before call"
if self._interrupt:
self._server.break_requested()
if self._pushBreakpoints:
self._server.update_breakpoints(xmlrpclib.Binary(pickle.dumps(self._breakDict)))
if self._kill:
try:
self._server.die()
except:
pass
if _VERBOSE: print "RequestBreakThread, after call"
except:
tp,val,tb = sys.exc_info()
traceback.print_exception(tp, val, tb)
class DebuggerOperationThread(threading.Thread):
def __init__(self, function):
threading.Thread.__init__(self)
self._function = function
def run(self):
if _VERBOSE: print "In DOT, before call"
try:
self._function()
except:
tp,val,tb = sys.exc_info()
traceback.print_exception(tp, val, tb)
if _VERBOSE:
print "In DOT, after call"
class BaseDebuggerCallback(object):
def Start(self):
assert False, "Start not overridden"
def ShutdownServer(self):
assert False, "ShutdownServer not overridden"
def BreakExecution(self):
assert False, "BreakExecution not overridden"
def SingleStep(self):
assert False, "SingleStep not overridden"
def Next(self):
assert False, "Next not overridden"
def Continue(self):
assert False, "Start not overridden"
def Return(self):
assert False, "Return not overridden"
def PushBreakpoints(self):
assert False, "PushBreakpoints not overridden"
class PythonDebuggerCallback(BaseDebuggerCallback):
def __init__(self, host, port, debugger_url, break_url, debuggerUI, autoContinue=False):
if _VERBOSE: print "+++++++ Creating server on port, ", str(port)
self._timer = None
self._queue = Queue.Queue(50)
self._host = host
self._port = int(port)
threading._VERBOSE = _VERBOSE
self._serverHandlerThread = RequestHandlerThread(self._queue, (self._host, self._port))
self._debugger_url = debugger_url
self._debuggerServer = None
self._waiting = False
self._service = wx.GetApp().GetService(DebuggerService)
self._debuggerUI = debuggerUI
self._break_url = break_url
self._breakServer = None
self._firstInteraction = True
self._pendingBreak = False
self._autoContinue = autoContinue
def Start(self):
self._serverHandlerThread.start()
def ShutdownServer(self):
#rbt = RequestBreakThread(self._breakServer, kill=True)
#rbt.start()
self._waiting = False
if self._serverHandlerThread:
self._serverHandlerThread.AskToStop()
self._serverHandlerThread = None
def BreakExecution(self):
rbt = RequestBreakThread(self._breakServer, interrupt=True)
rbt.start()
def SingleStep(self):
self._debuggerUI.DisableWhileDebuggerRunning()
self._debuggerServer.set_step() # Figure out where to set allowNone
self.WaitForRPC()
def Next(self):
self._debuggerUI.DisableWhileDebuggerRunning()
self._debuggerServer.set_next()
self.WaitForRPC()
def Continue(self):
self._debuggerUI.DisableWhileDebuggerRunning()
self._debuggerServer.set_continue()
self.WaitForRPC()
def Return(self):
self._debuggerUI.DisableWhileDebuggerRunning()
self._debuggerServer.set_return()
self.WaitForRPC()
def ReadQueue(self):
if self._queue.qsize():
try:
item = self._queue.get_nowait()
if item.getQuit():
self.interaction(None, None, None, True)
else:
data = bz2.decompress(item.getFramesXML().data)
self.interaction(item.getMessage().data, data, item.getInfo(), False)
except Queue.Empty:
pass
def PushBreakpoints(self):
rbt = RequestBreakThread(self._breakServer, pushBreakpoints=True, breakDict=self._service.GetMasterBreakpointDict())
rbt.start()
def WaitForRPC(self):
self._waiting = True
while self._waiting:
try:
self.ReadQueue()
import time
time.sleep(0.02)
except:
tp, val, tb = sys.exc_info()
traceback.print_exception(tp, val, tb)
wx.GetApp().Yield(True)
if _VERBOSE: print "Exiting WaitForRPC."
def interaction(self, message, frameXML, info, quit):
#This method should be hit as the debugger starts.
if self._firstInteraction:
self._firstInteraction = False
self._debuggerServer = xmlrpclib.ServerProxy(self._debugger_url, allow_none=1)
self._breakServer = xmlrpclib.ServerProxy(self._break_url, allow_none=1)
self.PushBreakpoints()
self._waiting = False
if _VERBOSE: print "+"*40
if(quit):
self._debuggerUI.StopExecution(None)
return ""
if(info != ""):
if _VERBOSE: print "Hit interaction with exception"
#self._debuggerUI.StopExecution(None)
#self._debuggerUI.SetStatusText("Got exception: " + str(info))
self._debuggerUI.SwitchToOutputTab()
else:
if _VERBOSE: print "Hit interaction no exception"
#if not self._autoContinue:
self._debuggerUI.SetStatusText(message)
if not self._autoContinue:
self._debuggerUI.LoadPythonFramesList(frameXML)
self._debuggerUI.EnableWhileDebuggerStopped()
if self._autoContinue:
self._timer = wx.PyTimer(self.DoContinue)
self._autoContinue = False
self._timer.Start(250)
if _VERBOSE: print "+"*40
def DoContinue(self):
self._timer.Stop()
dbgService = wx.GetApp().GetService(DebuggerService)
evt = DebugInternalWebServer()
evt.SetId(self._debuggerUI.CONTINUE_ID)
wx.PostEvent(self._debuggerUI, evt)
if _VERBOSE: print "Event Continue posted"
evt = DebugInternalWebServer()
evt.SetId(DebuggerService.DEBUG_WEBSERVER_NOW_RUN_PROJECT_ID)
wx.PostEvent(dbgService._frame, evt)
if _VERBOSE: print "Event RunProject posted"
def SendRunEvent(self):
class SendEventThread(threading.Thread):
def __init__(self):
threading.Thread.__init__(self)
def run(self):
dbgService = wx.GetApp().GetService(DebuggerService)
evt = DebugInternalWebServer()
evt.SetId(DebuggerService.DEBUG_WEBSERVER_NOW_RUN_PROJECT_ID)
wx.PostEvent(dbgService._frame, evt)
print "Event posted"
set = SendEventThread()
set.start()
class DebuggerService(Service.Service):
#----------------------------------------------------------------------------
# Constants
#----------------------------------------------------------------------------
TOGGLE_BREAKPOINT_ID = wx.NewId()
CLEAR_ALL_BREAKPOINTS = wx.NewId()
RUN_ID = wx.NewId()
DEBUG_ID = wx.NewId()
RUN_LAST_ID = wx.NewId()
DEBUG_LAST_ID = wx.NewId()
DEBUG_WEBSERVER_ID = wx.NewId()
RUN_WEBSERVER_ID = wx.NewId()
DEBUG_WEBSERVER_CONTINUE_ID = wx.NewId()
DEBUG_WEBSERVER_NOW_RUN_PROJECT_ID = wx.NewId()
def ComparePaths(first, second):
one = DebuggerService.ExpandPath(first)
two = DebuggerService.ExpandPath(second)
if _WINDOWS:
return one.lower() == two.lower()
else:
return one == two
ComparePaths = staticmethod(ComparePaths)
# Make sure we're using an expanded path on windows.
def ExpandPath(path):
if _WINDOWS:
try:
return win32api.GetLongPathName(path)
except:
if _VERBOSE:
print "Cannot get long path for %s" % path
return path
ExpandPath = staticmethod(ExpandPath)
#----------------------------------------------------------------------------
# Overridden methods
#----------------------------------------------------------------------------
def __init__(self, serviceName, embeddedWindowLocation = wx.lib.pydocview.EMBEDDED_WINDOW_LEFT):
Service.Service.__init__(self, serviceName, embeddedWindowLocation)
self.BREAKPOINT_DICT_STRING = "MasterBreakpointDict"
config = wx.ConfigBase_Get()
pickledbps = config.Read(self.BREAKPOINT_DICT_STRING)
if pickledbps:
try:
self._masterBPDict = pickle.loads(pickledbps.encode('ascii'))
except:
tp, val, tb = sys.exc_info()
traceback.print_exception(tp,val,tb)
self._masterBPDict = {}
else:
self._masterBPDict = {}
self._frame = None
self.projectPath = None
self.fileToDebug = None
self.phpDbgParam = None
self.dbgLanguage = projectmodel.LANGUAGE_DEFAULT
def OnCloseFrame(self, event):
# IS THIS THE RIGHT PLACE?
try:
config = wx.ConfigBase_Get()
config.Write(self.BREAKPOINT_DICT_STRING, pickle.dumps(self._masterBPDict))
except:
tp,val,tb = sys.exc_info()
traceback.print_exception(tp, val, tb)
return True
def _CreateView(self):
return DebuggerView(self)
#----------------------------------------------------------------------------
# Service specific methods
#----------------------------------------------------------------------------
def InstallControls(self, frame, menuBar = None, toolBar = None, statusBar = None, document = None):
#Service.Service.InstallControls(self, frame, menuBar, toolBar, statusBar, document)
self._frame = frame
config = wx.ConfigBase_Get()
debuggerMenu = wx.Menu()
if not menuBar.FindItemById(DebuggerService.CLEAR_ALL_BREAKPOINTS):
debuggerMenu.Append(DebuggerService.RUN_ID, _("&Run...\tCtrl+R"), _("Runs a file"))
wx.EVT_MENU(frame, DebuggerService.RUN_ID, frame.ProcessEvent)
wx.EVT_UPDATE_UI(frame, DebuggerService.RUN_ID, frame.ProcessUpdateUIEvent)
debuggerMenu.Append(DebuggerService.DEBUG_ID, _("&Debug...\tCtrl+D"), _("Debugs a file"))
wx.EVT_MENU(frame, DebuggerService.DEBUG_ID, frame.ProcessEvent)
wx.EVT_UPDATE_UI(frame, DebuggerService.DEBUG_ID, frame.ProcessUpdateUIEvent)
debuggerMenu.Append(DebuggerService.RUN_LAST_ID, _("&Run Using Last Settings\tF5"), _("Runs a file using previous settings"))
wx.EVT_MENU(frame, DebuggerService.RUN_LAST_ID, frame.ProcessEvent)
wx.EVT_UPDATE_UI(frame, DebuggerService.RUN_LAST_ID, frame.ProcessUpdateUIEvent)
debuggerMenu.Append(DebuggerService.DEBUG_LAST_ID, _("&Debug Using Last Settings\tF8"), _("Debugs a file using previous settings"))
wx.EVT_MENU(frame, DebuggerService.DEBUG_LAST_ID, frame.ProcessEvent)
wx.EVT_UPDATE_UI(frame, DebuggerService.DEBUG_LAST_ID, frame.ProcessUpdateUIEvent)
if not ACTIVEGRID_BASE_IDE:
debuggerMenu.AppendSeparator()
debuggerMenu.Append(DebuggerService.DEBUG_WEBSERVER_ID, _("Debug Internal Web Server"), _("Debugs the internal webservier"))
wx.EVT_MENU(frame, DebuggerService.DEBUG_WEBSERVER_ID, frame.ProcessEvent)
wx.EVT_UPDATE_UI(frame, DebuggerService.DEBUG_WEBSERVER_ID, frame.ProcessUpdateUIEvent)
debuggerMenu.Append(DebuggerService.RUN_WEBSERVER_ID, _("Restart Internal Web Server"), _("Restarts the internal webservier"))
wx.EVT_MENU(frame, DebuggerService.RUN_WEBSERVER_ID, frame.ProcessEvent)
wx.EVT_UPDATE_UI(frame, DebuggerService.RUN_WEBSERVER_ID, frame.ProcessUpdateUIEvent)
frame.Bind(EVT_DEBUG_INTERNAL, frame.ProcessEvent)
debuggerMenu.AppendSeparator()
debuggerMenu.Append(DebuggerService.TOGGLE_BREAKPOINT_ID, _("&Toggle Breakpoint\tCtrl+B"), _("Toggle a breakpoint"))
wx.EVT_MENU(frame, DebuggerService.TOGGLE_BREAKPOINT_ID, self.ProcessEvent)
wx.EVT_UPDATE_UI(frame, DebuggerService.TOGGLE_BREAKPOINT_ID, self.ProcessUpdateUIEvent)
debuggerMenu.Append(DebuggerService.CLEAR_ALL_BREAKPOINTS, _("&Clear All Breakpoints"), _("Clear All Breakpoints"))
wx.EVT_MENU(frame, DebuggerService.CLEAR_ALL_BREAKPOINTS, self.ProcessEvent)
wx.EVT_UPDATE_UI(frame, DebuggerService.CLEAR_ALL_BREAKPOINTS, self.ProcessUpdateUIEvent)
viewMenuIndex = menuBar.FindMenu(_("&Project"))
menuBar.Insert(viewMenuIndex + 1, debuggerMenu, _("&Run"))
toolBar.AddSeparator()
toolBar.AddTool(DebuggerService.RUN_LAST_ID, getRunningManBitmap(), shortHelpString = _("Run Using Last Settings"), longHelpString = _("Run Using Last Settings"))
toolBar.AddTool(DebuggerService.DEBUG_LAST_ID, getDebuggingManBitmap(), shortHelpString = _("Debug Using Last Settings"), longHelpString = _("Debug Using Last Settings"))
toolBar.Realize()
return True
#----------------------------------------------------------------------------
# Event Processing Methods
#----------------------------------------------------------------------------
def ProcessEventBeforeWindows(self, event):
return False
def ProcessEvent(self, event):
if Service.Service.ProcessEvent(self, event):
return True
an_id = event.GetId()
if an_id == DebuggerService.TOGGLE_BREAKPOINT_ID:
self.OnToggleBreakpoint(event)
return True
elif an_id == DebuggerService.CLEAR_ALL_BREAKPOINTS:
self.ClearAllBreakpoints()
return True
elif an_id == DebuggerService.RUN_ID:
self.OnRunProject(event)
return True
elif an_id == DebuggerService.DEBUG_ID:
self.OnDebugProject(event)
return True
elif an_id == DebuggerService.RUN_LAST_ID:
self.OnRunProject(event, showDialog=False)
return True
elif an_id == DebuggerService.DEBUG_LAST_ID:
self.OnDebugProject(event, showDialog=False)
return True
elif an_id == DebuggerService.DEBUG_WEBSERVER_ID:
self.OnDebugWebServer(event)
return True
elif an_id == DebuggerService.DEBUG_WEBSERVER_CONTINUE_ID:
self.OnDebugWebServerContinue(event)
return True
elif an_id == DebuggerService.DEBUG_WEBSERVER_NOW_RUN_PROJECT_ID:
self.WaitDebuggerThenRunProject()
return True
elif an_id == DebuggerService.RUN_WEBSERVER_ID:
self.OnRunWebServer(event)
return True
return False
def ProcessUpdateUIEvent(self, event):
if Service.Service.ProcessUpdateUIEvent(self, event):
return True
an_id = event.GetId()
if an_id == DebuggerService.TOGGLE_BREAKPOINT_ID:
currentView = self.GetDocumentManager().GetCurrentView()
event.Enable(isinstance(currentView, PythonEditor.PythonView))
return True
elif an_id == DebuggerService.CLEAR_ALL_BREAKPOINTS:
event.Enable(self.HasBreakpointsSet())
return True
elif (an_id == DebuggerService.RUN_ID
or an_id == DebuggerService.RUN_LAST_ID
or an_id == DebuggerService.DEBUG_ID
or an_id == DebuggerService.DEBUG_LAST_ID):
event.Enable(self.HasAnyFiles())
return True
else:
return False
#----------------------------------------------------------------------------
# Class Methods
#----------------------------------------------------------------------------
def OnDebugProject(self, event, showDialog=True):
if _WINDOWS and not _PYWIN32_INSTALLED:
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."))
return
if not Executor.GetPythonExecutablePath():
return
if BaseDebuggerUI.DebuggerRunning():
wx.MessageBox(_("A debugger is already running. Please shut down the other debugger first."), _("Debugger Running"))
return
config = wx.ConfigBase_Get()
host = config.Read("DebuggerHostName", DEFAULT_HOST)
if not host:
wx.MessageBox(_("No debugger host set. Please go to Tools->Options->Debugger and set one."), _("No Debugger Host"))
return
self.ShowWindow(True)
projectService = wx.GetApp().GetService(ProjectEditor.ProjectService)
try:
dlg = CommandPropertiesDialog(self.GetView().GetFrame(), 'Debug File', projectService, None, okButtonName="Debug", debugging=True)
except:
return
dlg.CenterOnParent()
if not showDialog:
showDialog = dlg.MustShowDialog()
if showDialog and dlg.ShowModal() == wx.ID_OK:
projectPath, fileToDebug, initialArgs, startIn, isPython, environment = dlg.GetSettings()
elif not showDialog:
projectPath, fileToDebug, initialArgs, startIn, isPython, environment = dlg.GetSettings()
else:
dlg.Destroy()
return
dlg.Destroy()
self.PromptToSaveFiles()
shortFile = os.path.basename(fileToDebug)
fileToDebug = DebuggerService.ExpandPath(fileToDebug)
if fileToDebug.endswith('.bpel'):
self.projectPath = projectPath
self.fileToDebug = fileToDebug
#
# TODO: merge getting project stuff and save the results for
# WaitDebuggerThenRunProject() which currently does it again.
#
projects = projectService.FindProjectByFile(projectPath)
if not projects:
return
project = projects[0]
lang = project.GetAppInfo().language
if lang:
self.dbgLanguage = lang
dbgService = wx.GetApp().GetService(DebuggerService)
evt = DebugInternalWebServer()
evt.SetId(DebuggerService.DEBUG_WEBSERVER_CONTINUE_ID)
wx.PostEvent(dbgService._frame, evt)
if lang == projectmodel.LANGUAGE_PHP:
evt = DebugInternalWebServer()
evt.SetId(DebuggerService.DEBUG_WEBSERVER_NOW_RUN_PROJECT_ID)
wx.PostEvent(dbgService._frame, evt)
return
elif fileToDebug.endswith('.php'):
page = PHPDebuggerUI(Service.ServiceView.bottomTab, -1, str(fileToDebug), self)
count = Service.ServiceView.bottomTab.GetPageCount()
Service.ServiceView.bottomTab.AddPage(page, _("Debugging: ") + shortFile)
Service.ServiceView.bottomTab.SetSelection(count)
fullPhpScriptPath = os.path.normpath(fileToDebug)
environment["REDIRECT_STATUS"] = "200"
environment["REDIRECT_URL"] = fullPhpScriptPath
environment["SERVER_SOFTWARE"] = "AG PHP Debugger 1.7"
environment["SERVER_NAME"] = "localhost"
environment["SERVER_ADDR"] = "127.0.0.1"
environment["SERVER_PORT"] = "80"
environment["REMOTE_ADDR"] = "127.0.0.1"
environment["SCRIPT_FILENAME"] = "php"
environment["GATEWAY_INTERFACE"] = "CGI/1.1"
environment["SERVER_PROTOCOL"] = "HTTP/1.1"
environment["REQUEST_METHOD"] = "GET"
environment["REQUEST_URI"] = fullPhpScriptPath
environment["PATH_INFO"] = fullPhpScriptPath
environment["PATH_TRANSLATED"] = fullPhpScriptPath
environment["HTTP_COOKIE"] = "DBGSESSID=11439636363807700001@clienthost:10001"
page.Execute(initialArgs, startIn, environment)
else:
try:
page = PythonDebuggerUI(Service.ServiceView.bottomTab, -1, str(fileToDebug), self)
count = Service.ServiceView.bottomTab.GetPageCount()
Service.ServiceView.bottomTab.AddPage(page, _("Debugging: ") + shortFile)
Service.ServiceView.bottomTab.SetSelection(count)
page.Execute(initialArgs, startIn, environment)
except:
pass
def WaitDebuggerThenRunProject(self):
import time
#while not BaseDebuggerUI.DebuggerPastAutoContinue():
# time.sleep(0.2)
# wx.GetApp().Yield(True)
# print "After Yield"
time.sleep(2.0)
projectService = wx.GetApp().GetService(ProjectEditor.ProjectService)
projects = projectService.FindProjectByFile(self.projectPath)
if not projects:
return
project = projects[0]
try:
deployFilePath = project.GenerateDeployment()
except ProjectEditor.DataServiceExistenceException, e:
dataSourceName = str(e)
projectService.PromptForMissingDataSource(dataSourceName)
return
projectService.RunProcessModel(self.fileToDebug, project.GetAppInfo().language, deployFilePath)
def OnDebugWebServerContinue(self, event):
self.OnDebugWebServer(event, autoContinue=True)
def OnDebugWebServer(self, event, autoContinue=False):
#print "xxxxx debugging OnDebugWebServer"
if _WINDOWS and not _PYWIN32_INSTALLED:
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."))
return
if not Executor.GetPythonExecutablePath():
return
if BaseDebuggerUI.DebuggerRunning():
wx.MessageBox(_("A debugger is already running. Please shut down the other debugger first."), _("Debugger Running"))
return
import WebServerService
wsService = wx.GetApp().GetService(WebServerService.WebServerService)
fileName, args = wsService.StopAndPrepareToDebug()
#print "xxxxx OnDebugWebServer: fileName=%s, args=%s" % (repr(fileName), repr(args))
config = wx.ConfigBase_Get()
host = config.Read("DebuggerHostName", DEFAULT_HOST)
if not host:
wx.MessageBox(_("No debugger host set. Please go to Tools->Options->Debugger and set one."), _("No Debugger Host"))
return
try:
if self.dbgLanguage == projectmodel.LANGUAGE_PHP:
page = PHPDebuggerUI(Service.ServiceView.bottomTab, -1, fileName, self)
else:
page = PythonDebuggerUI(Service.ServiceView.bottomTab, -1, fileName, self, autoContinue)
count = Service.ServiceView.bottomTab.GetPageCount()
Service.ServiceView.bottomTab.AddPage(page, _("Debugging: Internal WebServer"))
Service.ServiceView.bottomTab.SetSelection(count)
page.Execute(args, startIn=sysutilslib.mainModuleDir, environment=os.environ, onWebServer = True)
except:
pass
def OnRunWebServer(self, event):
if not Executor.GetPythonExecutablePath():
return
import WebServerService
wsService = wx.GetApp().GetService(WebServerService.WebServerService)
wsService.ShutDownAndRestart()
def HasAnyFiles(self):
docs = wx.GetApp().GetDocumentManager().GetDocuments()
return len(docs) > 0
def PromptToSaveFiles(self, running=True):
filesModified = False
docs = wx.GetApp().GetDocumentManager().GetDocuments()
for doc in docs:
if doc.IsModified():
filesModified = True
break
if filesModified:
frame = self.GetView().GetFrame()
if running:
yesNoMsg = wx.MessageDialog(frame,
_("Files have been modified.\nWould you like to save all files before running?"),
_("Run"),
wx.YES_NO|wx.ICON_QUESTION
)
else:
yesNoMsg = wx.MessageDialog(frame,
_("Files have been modified.\nWould you like to save all files before debugging?"),
_("Debug"),
wx.YES_NO|wx.ICON_QUESTION
)
yesNoMsg.CenterOnParent()
if yesNoMsg.ShowModal() == wx.ID_YES:
docs = wx.GetApp().GetDocumentManager().GetDocuments()
for doc in docs:
doc.Save()
yesNoMsg.Destroy()
def OnExit(self):
BaseDebuggerUI.ShutdownAllDebuggers()
RunCommandUI.ShutdownAllRunners()
def OnRunProject(self, event, showDialog=True):
if _WINDOWS and not _PYWIN32_INSTALLED:
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."))
return
if not Executor.GetPythonExecutablePath():
return
projectService = wx.GetApp().GetService(ProjectEditor.ProjectService)
try:
dlg = CommandPropertiesDialog(self.GetView().GetFrame(), 'Run', projectService, None)
except:
return
dlg.CenterOnParent()
if not showDialog:
showDialog = dlg.MustShowDialog()
if showDialog and dlg.ShowModal() == wx.ID_OK:
projectPath, fileToRun, initialArgs, startIn, isPython, environment = dlg.GetSettings()
elif not showDialog:
projectPath, fileToRun, initialArgs, startIn, isPython, environment = dlg.GetSettings()
else:
dlg.Destroy()
return
dlg.Destroy()
self.PromptToSaveFiles()
if fileToRun.endswith('bpel'):
projects = projectService.FindProjectByFile(projectPath)
if not projects:
return
project = projects[0]
try:
deployFilePath = project.GenerateDeployment()
except ProjectEditor.DataServiceExistenceException, e:
dataSourceName = str(e)
projectService.PromptForMissingDataSource(dataSourceName)
return
projectService.RunProcessModel(fileToRun, project.GetAppInfo().language, deployFilePath)
return
self.ShowWindow(True)
shortFile = os.path.basename(fileToRun)
page = RunCommandUI(Service.ServiceView.bottomTab, -1, str(fileToRun))
count = Service.ServiceView.bottomTab.GetPageCount()
Service.ServiceView.bottomTab.AddPage(page, "Running: " + shortFile)
Service.ServiceView.bottomTab.SetSelection(count)
page.Execute(initialArgs, startIn, environment, onWebServer = True)
def OnToggleBreakpoint(self, event, line=-1, fileName=None):
if not fileName:
view = wx.GetApp().GetDocumentManager().GetCurrentView()
# Test to make sure we aren't the project view.
if not hasattr(view, 'MarkerExists'):
return
fileName = wx.GetApp().GetDocumentManager().GetCurrentDocument().GetFilename()
if line < 0:
line = view.GetCtrl().GetCurrentLine()
else:
view = None
if self.BreakpointSet(fileName, line + 1):
self.ClearBreak(fileName, line + 1)
if view:
view.GetCtrl().Refresh()
else:
self.SetBreak(fileName, line + 1)
if view:
view.GetCtrl().Refresh()
# Now refresh all the markers icons in all the open views.
self.ClearAllBreakpointMarkers()
self.SetAllBreakpointMarkers()
def SilentToggleBreakpoint(self, fileName, line):
found = False
for lineNumber in self.GetBreakpointList(fileName):
if int(lineNumber) == int(line):
found = True
break
if found:
self.SetBreak(fileName, line)
else:
self.ClearBreak(fileName, line)
def SetBreak(self, fileName, line):
expandedName = DebuggerService.ExpandPath(fileName)
if not self._masterBPDict.has_key(expandedName):
self._masterBPDict[expandedName] = [line]
else:
self._masterBPDict[expandedName] += [line]
# If we're already debugging, pass this bp off to the PythonDebuggerCallback
self.NotifyDebuggersOfBreakpointChange()
def NotifyDebuggersOfBreakpointChange(self):
BaseDebuggerUI.NotifyDebuggersOfBreakpointChange()
def GetBreakpointList(self, fileName):
expandedName = DebuggerService.ExpandPath(fileName)
if not self._masterBPDict.has_key(expandedName):
return []
else:
return self._masterBPDict[expandedName]
def SetBreakpointList(self, fileName, bplist):
expandedName = DebuggerService.ExpandPath(fileName)
self._masterBPDict[expandedName] = bplist
def BreakpointSet(self, fileName, line):
expandedName = DebuggerService.ExpandPath(fileName)
if not self._masterBPDict.has_key(expandedName):
return False
else:
newList = []
for number in self._masterBPDict[expandedName]:
if(int(number) == int(line)):
return True
return False
def ClearBreak(self, fileName, line):
expandedName = DebuggerService.ExpandPath(fileName)
if not self._masterBPDict.has_key(expandedName):
print "In ClearBreak: no key"
return
else:
newList = []
for number in self._masterBPDict[expandedName]:
if(int(number) != int(line)):
newList.append(number)
self._masterBPDict[expandedName] = newList
self.NotifyDebuggersOfBreakpointChange()
def HasBreakpointsSet(self):
for key, value in self._masterBPDict.items():
if len(value) > 0:
return True
return False
def ClearAllBreakpoints(self):
self._masterBPDict = {}
self.NotifyDebuggersOfBreakpointChange()
self.ClearAllBreakpointMarkers()
def ClearAllBreakpointMarkers(self):
openDocs = wx.GetApp().GetDocumentManager().GetDocuments()
for openDoc in openDocs:
if isinstance(openDoc, CodeEditor.CodeDocument):
openDoc.GetFirstView().MarkerDeleteAll(CodeEditor.CodeCtrl.BREAKPOINT_MARKER_NUM)
def UpdateBreakpointsFromMarkers(self, view, fileName):
newbpLines = view.GetMarkerLines(CodeEditor.CodeCtrl.BREAKPOINT_MARKER_NUM)
self.SetBreakpointList(fileName, newbpLines)
def GetMasterBreakpointDict(self):
return self._masterBPDict
def SetAllBreakpointMarkers(self):
openDocs = wx.GetApp().GetDocumentManager().GetDocuments()
for openDoc in openDocs:
if(isinstance(openDoc, CodeEditor.CodeDocument)):
self.SetCurrentBreakpointMarkers(openDoc.GetFirstView())
def SetCurrentBreakpointMarkers(self, view):
if isinstance(view, CodeEditor.CodeView) and hasattr(view, 'GetDocument'):
view.MarkerDeleteAll(CodeEditor.CodeCtrl.BREAKPOINT_MARKER_NUM)
for linenum in self.GetBreakpointList(view.GetDocument().GetFilename()):
view.MarkerAdd(lineNum=int(linenum) - 1, marker_index=CodeEditor.CodeCtrl.BREAKPOINT_MARKER_NUM)
def GetPhpDbgParam(self):
return self.phpDbgParam
def SetPhpDbgParam(self, value = None):
self.phpDbgParam = value
class DebuggerOptionsPanel(wx.Panel):
def __init__(self, parent, id):
wx.Panel.__init__(self, parent, id)
SPACE = 10
config = wx.ConfigBase_Get()
localHostStaticText = wx.StaticText(self, -1, _("Local Host Name:"))
self._LocalHostTextCtrl = wx.TextCtrl(self, -1, config.Read("DebuggerHostName", DEFAULT_HOST), size = (150, -1))
portNumberStaticText = wx.StaticText(self, -1, _("Port Range:"))
dashStaticText = wx.StaticText(self, -1, _("through to"))
startingPort=config.ReadInt("DebuggerStartingPort", DEFAULT_PORT)
self._PortNumberTextCtrl = wx.lib.intctrl.IntCtrl(self, -1, startingPort, size = (50, -1))
self._PortNumberTextCtrl.SetMin(1)#What are real values?
self._PortNumberTextCtrl.SetMax(65514) #What are real values?
self.Bind(wx.lib.intctrl.EVT_INT, self.MinPortChange, self._PortNumberTextCtrl)
self._EndPortNumberTextCtrl = wx.lib.intctrl.IntCtrl(self, -1, startingPort + PORT_COUNT, size = (50, -1))
self._EndPortNumberTextCtrl.SetMin(22)#What are real values?
self._EndPortNumberTextCtrl.SetMax(65535)#What are real values?
self._EndPortNumberTextCtrl.Enable( False )
debuggerPanelBorderSizer = wx.BoxSizer(wx.VERTICAL)
debuggerPanelSizer = wx.GridBagSizer(hgap = 5, vgap = 5)
debuggerPanelSizer.Add( localHostStaticText, (0,0), flag=wx.ALIGN_CENTER_VERTICAL|wx.ALIGN_LEFT)
debuggerPanelSizer.Add( self._LocalHostTextCtrl, (0,1), (1,3), flag=wx.EXPAND|wx.ALIGN_CENTER)
debuggerPanelSizer.Add( portNumberStaticText, (1,0), flag=wx.ALIGN_LEFT|wx.ALIGN_CENTER_VERTICAL)
debuggerPanelSizer.Add( self._PortNumberTextCtrl, (1,1), flag=wx.ALIGN_CENTER)
debuggerPanelSizer.Add( dashStaticText, (1,2), flag=wx.ALIGN_CENTER)
debuggerPanelSizer.Add( self._EndPortNumberTextCtrl, (1,3), flag=wx.ALIGN_CENTER)
FLUSH_PORTS_ID = wx.NewId()
self._flushPortsButton = wx.Button(self, FLUSH_PORTS_ID, "Reset Port List")
wx.EVT_BUTTON(parent, FLUSH_PORTS_ID, self.FlushPorts)
debuggerPanelSizer.Add(self._flushPortsButton, (2,2), (1,2), flag=wx.ALIGN_RIGHT)
debuggerPanelBorderSizer.Add(debuggerPanelSizer, 0, wx.ALL, SPACE)
self.SetSizer(debuggerPanelBorderSizer)
self.Layout()
parent.AddPage(self, _("Debugger"))
def FlushPorts(self, event):
if self._PortNumberTextCtrl.IsInBounds():
config = wx.ConfigBase_Get()
config.WriteInt("DebuggerStartingPort", self._PortNumberTextCtrl.GetValue())
PythonDebuggerUI.NewPortRange()
else:
wx.MessageBox(_("The starting port is not valid. Please change the value and try again.", "Invalid Starting Port Number"))
def MinPortChange(self, event):
self._EndPortNumberTextCtrl.Enable( True )
self._EndPortNumberTextCtrl.SetValue( self._PortNumberTextCtrl.GetValue() + PORT_COUNT)
self._EndPortNumberTextCtrl.Enable( False )
def OnOK(self, optionsDialog):
config = wx.ConfigBase_Get()
config.Write("DebuggerHostName", self._LocalHostTextCtrl.GetValue())
if self._PortNumberTextCtrl.IsInBounds():
config.WriteInt("DebuggerStartingPort", self._PortNumberTextCtrl.GetValue())
def GetIcon(self):
return getContinueIcon()
class CommandPropertiesDialog(wx.Dialog):
def __init__(self, parent, title, projectService, currentProjectDocument, okButtonName="Run", debugging=False):
self._projService = projectService
self._pmext = None
self._pyext = '.py'
self._phpext = '.php'
for template in self._projService.GetDocumentManager().GetTemplates():
if not ACTIVEGRID_BASE_IDE and template.GetDocumentType() == ProcessModelEditor.ProcessModelDocument:
self._pmext = template.GetDefaultExtension()
break
self._currentProj = projectService.GetCurrentProject()
self._projectNameList, self._projectDocumentList, selectedIndex = self.GetProjectList()
if not self._projectNameList:
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"))
raise Exception("Nothing to Run or Debug.")
wx.Dialog.__init__(self, parent, -1, title)
projStaticText = wx.StaticText(self, -1, _("Project:"))
fileStaticText = wx.StaticText(self, -1, _("File:"))
argsStaticText = wx.StaticText(self, -1, _("Arguments:"))
startInStaticText = wx.StaticText(self, -1, _("Start in:"))
pythonPathStaticText = wx.StaticText(self, -1, _("PYTHONPATH:"))
postpendStaticText = _("Postpend win32api path")
cpPanelBorderSizer = wx.BoxSizer(wx.VERTICAL)
self._projList = wx.Choice(self, -1, choices=self._projectNameList)
self.Bind(wx.EVT_CHOICE, self.EvtListBox, self._projList)
HALF_SPACE = 5
GAP = HALF_SPACE
if wx.Platform == "__WXMAC__":
GAP = 10
flexGridSizer = wx.GridBagSizer(GAP, GAP)
flexGridSizer.Add(projStaticText, (0,0), flag=wx.ALIGN_CENTER_VERTICAL|wx.ALIGN_LEFT)
flexGridSizer.Add(self._projList, (0,1), (1,2), flag=wx.EXPAND)
flexGridSizer.Add(fileStaticText, (1,0), flag=wx.ALIGN_CENTER_VERTICAL|wx.ALIGN_LEFT)
self._fileList = wx.Choice(self, -1)
self.Bind(wx.EVT_CHOICE, self.OnFileSelected, self._fileList)
flexGridSizer.Add(self._fileList, (1,1), (1,2), flag=wx.EXPAND)
config = wx.ConfigBase_Get()
self._lastArguments = config.Read(self.GetKey("LastRunArguments"))
self._argsEntry = wx.TextCtrl(self, -1, str(self._lastArguments))
self._argsEntry.SetToolTipString(str(self._lastArguments))
flexGridSizer.Add(argsStaticText, (2,0), flag=wx.ALIGN_CENTER_VERTICAL|wx.ALIGN_LEFT)
flexGridSizer.Add(self._argsEntry, (2,1), (1,2), flag=wx.EXPAND)
flexGridSizer.Add(startInStaticText, (3,0), flag=wx.ALIGN_CENTER_VERTICAL|wx.ALIGN_LEFT)
self._lastStartIn = config.Read(self.GetKey("LastRunStartIn"))
if not self._lastStartIn:
self._lastStartIn = str(os.getcwd())
self._startEntry = wx.TextCtrl(self, -1, self._lastStartIn)
self._startEntry.SetToolTipString(self._lastStartIn)
flexGridSizer.Add(self._startEntry, (3,1), flag=wx.EXPAND)
self._findDir = wx.Button(self, -1, _("Browse..."))
self.Bind(wx.EVT_BUTTON, self.OnFindDirClick, self._findDir)
flexGridSizer.Add(self._findDir, (3,2))
flexGridSizer.Add(pythonPathStaticText, (4,0), flag=wx.ALIGN_CENTER_VERTICAL|wx.ALIGN_LEFT)
if os.environ.has_key('PYTHONPATH'):
startval = os.environ['PYTHONPATH']
else:
startval = ""
self._lastPythonPath = config.Read(self.GetKey("LastPythonPath"), startval)
self._pythonPathEntry = wx.TextCtrl(self, -1, self._lastPythonPath)
self._pythonPathEntry.SetToolTipString(self._lastPythonPath)
flexGridSizer.Add(self._pythonPathEntry, (4,1), (1,2), flag=wx.EXPAND)
if debugging and _WINDOWS:
self._postpendCheckBox = wx.CheckBox(self, -1, postpendStaticText)
checked = bool(config.ReadInt(self.GetKey("PythonPathPostpend"), 1))
self._postpendCheckBox.SetValue(checked)
flexGridSizer.Add(self._postpendCheckBox, (5,1), flag=wx.EXPAND)
cpPanelBorderSizer.Add(flexGridSizer, 0, flag=wx.ALL, border=10)
box = wx.StdDialogButtonSizer()
self._okButton = wx.Button(self, wx.ID_OK, okButtonName)
self._okButton.SetDefault()
self._okButton.SetHelpText(_("The ") + okButtonName + _(" button completes the dialog"))
box.AddButton(self._okButton)
self.Bind(wx.EVT_BUTTON, self.OnOKClick, self._okButton)
btn = wx.Button(self, wx.ID_CANCEL, _("Cancel"))
btn.SetHelpText(_("The Cancel button cancels the dialog."))
box.AddButton(btn)
box.Realize()
cpPanelBorderSizer.Add(box, 0, flag=wx.ALIGN_RIGHT|wx.ALL, border=5)
self.SetSizer(cpPanelBorderSizer)
# Set up selections based on last values used.
self._fileNameList = None
self._selectedFileIndex = -1
lastProject = config.Read(self.GetKey("LastRunProject"))
lastFile = config.Read(self.GetKey("LastRunFile"))
self._mustShow = not lastFile
if lastProject in self._projectNameList:
selectedIndex = self._projectNameList.index(lastProject)
elif selectedIndex < 0:
selectedIndex = 0
self._projList.Select(selectedIndex)
self._selectedProjectIndex = selectedIndex
self._selectedProjectDocument = self._projectDocumentList[selectedIndex]
self.PopulateFileList(self._selectedProjectDocument, lastFile)
cpPanelBorderSizer.Fit(self)
def MustShowDialog(self):
return self._mustShow
def GetKey(self, lastPart):
if self._currentProj:
return "%s/%s/%s" % (ProjectEditor.PROJECT_KEY, self._currentProj.GetFilename().replace(os.sep, '|'), lastPart)
def OnOKClick(self, event):
startIn = self._startEntry.GetValue()
fileToRun = self._fileList.GetStringSelection()
if not fileToRun:
wx.MessageBox(_("You must select a file to proceed. Note that not all projects have files that can be run or debugged."))
return
isPython = fileToRun.endswith(self._pyext)
if isPython and not os.path.exists(startIn):
wx.MessageBox(_("Starting directory does not exist. Please change this value."))
return
config = wx.ConfigBase_Get()
config.Write(self.GetKey("LastRunProject"), self._projectNameList[self._selectedProjectIndex])
config.Write(self.GetKey("LastRunFile"), fileToRun)
# Don't update the arguments or starting directory unless we're runing python.
if isPython:
config.Write(self.GetKey("LastRunArguments"), self._argsEntry.GetValue())
config.Write(self.GetKey("LastRunStartIn"), self._startEntry.GetValue())
config.Write(self.GetKey("LastPythonPath"),self._pythonPathEntry.GetValue())
if hasattr(self, "_postpendCheckBox"):
config.WriteInt(self.GetKey("PythonPathPostpend"), int(self._postpendCheckBox.GetValue()))
self.EndModal(wx.ID_OK)
def GetSettings(self):
projectPath = self._selectedProjectDocument.GetFilename()
filename = self._fileNameList[self._selectedFileIndex]
args = self._argsEntry.GetValue()
startIn = self._startEntry.GetValue()
isPython = filename.endswith(self._pyext)
env = os.environ
if hasattr(self, "_postpendCheckBox"):
postpend = self._postpendCheckBox.GetValue()
else:
postpend = False
if postpend:
env['PYTHONPATH'] = self._pythonPathEntry.GetValue() + os.pathsep + os.path.join(os.getcwd(), "3rdparty", "pywin32")
else:
env['PYTHONPATH'] = self._pythonPathEntry.GetValue()
return projectPath, filename, args, startIn, isPython, env
def OnFileSelected(self, event):
self._selectedFileIndex = self._fileList.GetSelection()
self.EnableForFileType(event.GetString())
def EnableForFileType(self, fileName):
show = fileName.endswith(self._pyext) or fileName.endswith(self._phpext)
self._startEntry.Enable(show)
self._findDir.Enable(show)
self._argsEntry.Enable(show)
if not show:
self._lastStartIn = self._startEntry.GetValue()
self._startEntry.SetValue("")
self._lastArguments = self._argsEntry.GetValue()
self._argsEntry.SetValue("")
else:
if fileName.endswith(self._phpext):
self._startEntry.SetValue(os.path.dirname(fileName))
else:
self._startEntry.SetValue(self._lastStartIn)
self._argsEntry.SetValue(self._lastArguments)
def OnFindDirClick(self, event):
dlg = wx.DirDialog(self, "Choose a starting directory:", self._startEntry.GetValue(),
style=wx.DD_DEFAULT_STYLE|wx.DD_NEW_DIR_BUTTON)
dlg.CenterOnParent()
if dlg.ShowModal() == wx.ID_OK:
self._startEntry.SetValue(dlg.GetPath())
dlg.Destroy()
def EvtListBox(self, event):
if event.GetString():
index = self._projectNameList.index(event.GetString())
self._selectedProjectDocument = self._projectDocumentList[index]
self._selectedProjectIndex = index
self.PopulateFileList(self._selectedProjectDocument)
def FilterFileList(self, list):
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)
return files
def PopulateFileList(self, project, shortNameToSelect=None):
self._fileNameList = self.FilterFileList(project.GetFiles()[:])
self._fileList.Clear()
if not self._fileNameList:
return
self._fileNameList.sort(lambda a, b: cmp(os.path.basename(a).lower(), os.path.basename(b).lower()))
strings = map(lambda file: os.path.basename(file), self._fileNameList)
for index in range(0, len(strings)):
if shortNameToSelect == strings[index]:
self._selectedFileIndex = index
break
self._fileList.Hide()
self._fileList.AppendItems(strings)
self._fileList.Show()
if self._selectedFileIndex not in range(0, len(strings)):
# Pick first bpel file if there is one.
for index in range(0, len(strings)):
if strings[index].endswith('.bpel'):
self._selectedFileIndex = index
break
# Still no selected file, use first file.
if self._selectedFileIndex not in range(0, len(strings)):
self._selectedFileIndex = 0
self._fileList.SetSelection(self._selectedFileIndex)
self.EnableForFileType(strings[self._selectedFileIndex])
def GetProjectList(self):
docList = []
nameList = []
found = False
index = -1
count = 0
for document in self._projService.GetDocumentManager().GetDocuments():
if document.GetDocumentTemplate().GetDocumentType() == ProjectEditor.ProjectDocument and len(document.GetFiles()):
docList.append(document)
nameList.append(os.path.basename(document.GetFilename()))
if document == self._currentProj:
found = True
index = count
count += 1
#Check for open files not in any of these projects and add them to a default project
def AlreadyInProject(fileName):
for projectDocument in docList:
if projectDocument.IsFileInProject(fileName):
return True
return False
unprojectedFiles = []
for document in self._projService.GetDocumentManager().GetDocuments():
if not ACTIVEGRID_BASE_IDE and type(document) == ProcessModelEditor.ProcessModelDocument:
if not AlreadyInProject(document.GetFilename()):
unprojectedFiles.append(document.GetFilename())
if type(document) == PythonEditor.PythonDocument or type(document) == PHPEditor.PHPDocument:
if not AlreadyInProject(document.GetFilename()):
unprojectedFiles.append(document.GetFilename())
if unprojectedFiles:
unprojProj = ProjectEditor.ProjectDocument()
unprojProj.SetFilename(_("Not in any Project"))
unprojProj.AddFiles(unprojectedFiles)
docList.append(unprojProj)
nameList.append(_("Not in any Project"))
return nameList, docList, index
#----------------------------------------------------------------------
from wx import ImageFromStream, BitmapFromImage
import cStringIO
#----------------------------------------------------------------------
def getBreakData():
return \
'\x89PNG\r\n\x1a\n\x00\x00\x00\rIHDR\x00\x00\x00\x10\x00\x00\x00\x10\x08\x02\
\x00\x00\x00\x90\x91h6\x00\x00\x00\x03sBIT\x08\x08\x08\xdb\xe1O\xe0\x00\x00\
\x00\x85IDAT(\x91\xbd\x92A\x16\x03!\x08CI\xdf\xdc\x0b\x8e\xe6\xd1\xe0d\xe9\
\x82\xd6\xc7(\x9di7\xfd\xab<\x14\x13Q\xb8\xbb\xfc\xc2\xe3\xd3\x82\x99\xb9\
\xe9\xaeq\xe1`f)HF\xc4\x8dC2\x06\xbf\x8a4\xcf\x1e\x03K\xe5h\x1bH\x02\x98\xc7\
\x03\x98\xa9z\x07\x00%\xd6\xa9\xd27\x90\xac\xbbk\xe5\x15I\xcdD$\xdc\xa7\xceT\
5a\xce\xf3\xe4\xa0\xaa\x8bO\x12\x11\xabC\xcb\x9c}\xd57\xef\xb0\xf3\xb7\x86p\
\x97\xf7\xb5\xaa\xde\xb9\xfa|-O\xbdjN\x9b\xf8\x06A\xcb\x00\x00\x00\x00IEND\
\xaeB`\x82'
def getBreakBitmap():
return BitmapFromImage(getBreakImage())
def getBreakImage():
stream = cStringIO.StringIO(getBreakData())
return ImageFromStream(stream)
def getBreakIcon():
return wx.IconFromBitmap(getBreakBitmap())
#----------------------------------------------------------------------
def getClearOutputData():
return \
'\x89PNG\r\n\x1a\n\x00\x00\x00\rIHDR\x00\x00\x00\x10\x00\x00\x00\x10\x08\x06\
\x00\x00\x00\x1f\xf3\xffa\x00\x00\x00\x04sBIT\x08\x08\x08\x08|\x08d\x88\x00\
\x00\x00\xb7IDAT8\x8d\xa5\x93\xdd\x11\xc3 \x0c\x83%`\xa3\xee\xd4\xaeA\xc6\
\xe8N\xedF%\xea\x03\t\x81\xf0\x97\xbb\xf8%G\xce\xfe\x90eC\x1a\x8b;\xe1\xf2\
\x83\xd6\xa0Q2\x8de\xf5oW\xa05H\xea\xd7\x93\x84$\x18\xeb\n\x88;\'.\xd5\x1d\
\x80\x07\xe1\xa1\x1d\xa2\x1cbF\x92\x0f\x80\xe0\xd1 \xb7\x14\x8c \x00*\x15\
\x97\x14\x8c\x8246\x1a\xf8\x98\'/\xdf\xd8Jn\xe65\xc0\xa7\x90_L"\x01\xde\x9d\
\xda\xa7\x92\xfb\xc5w\xdf\t\x07\xc4\x05ym{\xd0\x1a\xe3\xb9xS\x81\x04\x18\x05\
\xc9\x04\xc9a\x00Dc9\x9d\x82\xa4\xbc\xe8P\xb2\xb5P\xac\xf2\x0c\xd4\xf5\x00\
\x88>\xac\xe17\x84\xe4\xb9G\x8b7\x9f\xf3\x1fsUl^\x7f\xe7y\x0f\x00\x00\x00\
\x00IEND\xaeB`\x82'
def getClearOutputBitmap():
return BitmapFromImage(getClearOutputImage())
def getClearOutputImage():
stream = cStringIO.StringIO(getClearOutputData())
return ImageFromStream(stream)
def getClearOutputIcon():
return wx.IconFromBitmap(getClearOutputBitmap())
#----------------------------------------------------------------------
def getCloseData():
return \
'\x89PNG\r\n\x1a\n\x00\x00\x00\rIHDR\x00\x00\x00\x10\x00\x00\x00\x10\x08\x02\
\x00\x00\x00\x90\x91h6\x00\x00\x00\x03sBIT\x08\x08\x08\xdb\xe1O\xe0\x00\x00\
\x00\xedIDAT(\x91\xa5\x90!\xae\x840\x10\x86g_\xd6"*kz\x82j\xb0h\x1c\t\' x\
\x92Z\xc2\x05\x10\x95\x18\x0e\x00\x02M\x82 \xe1\nMF#jz\x80\xea&+\x9a\x10\x96\
\xdd}\xfb\xc8\x1b\xd7?\xdf\x97\xfe3\xb7u]\xe1\xca\xfc\\\xa2\xff- \xe24M\xc7\
\xc49wJ\xee\xc7G]\xd7\x8c1\xc6\x18\xe7\xdc\'B\x08k\xed1y\xfaa\x1cG\xad\xb5\
\x94\x12\x11\x9dsy\x9e+\xa5\x84\x10;\r\x00\xb7\xd3\x95\x8c1UU\x05A\x00\x00\
\xd6\xda,\xcb\x92$\xf9\xb8\x03\x00PJ\x85\x10Zk\xa5\xd4+\xfdF\x00\x80\xae\xeb\
\x08!\x84\x90y\x9e\x11\xf1\x8bP\x96\xa5\xef\xdd\xb6\xad\xb5VJ\xf9\x9b\xe0\
\xe9\xa6i8\xe7\xbe\xdb\xb6mi\x9a\x0e\xc3\xf0F\x88\xe3\x18\x00\xfa\xbe\x0f\
\xc3\xd0\'\x9c\xf3eY\xa2(*\x8ab\xc7\x9e\xaed\x8c\xa1\x94\xben\xf5\xb1\xd2W\
\xfa,\xfce.\x0b\x0f\xb8\x96e\x90gS\xe0v\x00\x00\x00\x00IEND\xaeB`\x82'
def getCloseBitmap():
return BitmapFromImage(getCloseImage())
def getCloseImage():
stream = cStringIO.StringIO(getCloseData())
return ImageFromStream(stream)
def getCloseIcon():
return wx.IconFromBitmap(getCloseBitmap())
#----------------------------------------------------------------------
def getContinueData():
return \
'\x89PNG\r\n\x1a\n\x00\x00\x00\rIHDR\x00\x00\x00\x10\x00\x00\x00\x10\x08\x06\
\x00\x00\x00\x1f\xf3\xffa\x00\x00\x00\x04sBIT\x08\x08\x08\x08|\x08d\x88\x00\
\x00\x00\xcdIDAT8\x8d\xa5\x93\xd1\r\xc20\x0cD\xef\xec,\xc0b\x88\x8d`$\x06Cb\
\x81\xc6\xc7GI\xeb\x94RZq?U"\xdby\xe7SIs\xfc#\xfbU\xa0\xa8\xba\xc6\xa0og\xee\
!P\xd4y\x80\x04\xf3\xc2U\x82{\x9ct\x8f\x93\xb0\xa2\xdbm\xf5\xba\'h\xcdg=`\
\xeeTT\xd1\xc6o& \t\x9a\x13\x00J\x9ev\xb1\'\xa3~\x14+\xbfN\x12\x92\x00@\xe6\
\x85\xdd\x00\x000w\xe6\xe2\xde\xc7|\xdf\x08\xba\x1d(\xaa2n+\xca\xcd\x8d,\xea\
\x98\xc4\x07\x01\x00D\x1dd^\xa8\xa8j\x9ew\xed`\xa9\x16\x99\xde\xa6G\x8b\xd3Y\
\xe6\x85]\n\r\x7f\x99\xf5\x96Jnlz#\xab\xdb\xc1\x17\x19\xb0XV\xc2\xdf\xa3)\
\x85<\xe4\x88\x85.F\x9a\xf3H3\xb0\xf3g\xda\xd2\x0b\xc5_|\x17\xe8\xf5R\xd6\
\x00\x00\x00\x00IEND\xaeB`\x82'
def getContinueBitmap():
return BitmapFromImage(getContinueImage())
def getContinueImage():
stream = cStringIO.StringIO(getContinueData())
return ImageFromStream(stream)
def getContinueIcon():
return wx.IconFromBitmap(getContinueBitmap())
#----------------------------------------------------------------------
def getNextData():
return \
'\x89PNG\r\n\x1a\n\x00\x00\x00\rIHDR\x00\x00\x00\x10\x00\x00\x00\x10\x08\x06\
\x00\x00\x00\x1f\xf3\xffa\x00\x00\x00\x04sBIT\x08\x08\x08\x08|\x08d\x88\x00\
\x00\x00\x8eIDAT8\x8d\xa5SA\x12\xc4 \x08K\xb0\xff\xde\xe9\xbf\xb7\xa6\x87\
\x1d:\xba\xa2tZn(\x84`"i\x05obk\x13\xd5CmN+\xcc\x00l\xd6\x0c\x00\xf5\xf8\x0e\
gK\x06\x00 \xa5=k\x00\x00\xb0\xb2]\xd4?5f\xb1\xdb\xaf\xc6\xa2\xcb\xa8\xf0?\
\x1c\x98\xae\x82\xbf\x81\xa4\x8eA\x16\xe1\n\xd1\xa4\x19\xb3\xe9\n\xce\xe8\
\xf1\n\x9eg^\x18\x18\x90\xec<\x11\xf9#\x04XMZ\x19\xaac@+\x94\xd4\x99)SeP\xa1\
)\xd6\x1dI\xe7*\xdc\xf4\x03\xdf~\xe7\x13T^Q?:X\x19d\x00\x00\x00\x00IEND\xaeB\
`\x82'
def getNextBitmap():
return BitmapFromImage(getNextImage())
def getNextImage():
stream = cStringIO.StringIO(getNextData())
return ImageFromStream(stream)
def getNextIcon():
return wx.IconFromBitmap(getNextBitmap())
#----------------------------------------------------------------------
def getStepInData():
return \
'\x89PNG\r\n\x1a\n\x00\x00\x00\rIHDR\x00\x00\x00\x10\x00\x00\x00\x10\x08\x06\
\x00\x00\x00\x1f\xf3\xffa\x00\x00\x00\x04sBIT\x08\x08\x08\x08|\x08d\x88\x00\
\x00\x00\x87IDAT8\x8d\xadSA\x12\x84 \x0ck\x8a\xffv\xfc\xb74{X\xeb0P@\x07s\
\x84\xa4$\x01\x00M\xb2\x02]R\x8b\xc86\xda\xdc\xedd\xb4~\xe8\x86\xc6\x01-\x93\
\x96\xd9#\xf6\x06\xc3;p1I\xd1\x14\x0b#|\x17aF\xec\r\xeeF\xa0eB\xd34\xca\xd0A\
]j\x84\xa6\x03\x00""\xb7\xb0tRZ\xf7x\xb7\x83\x91]\xcb\x7fa\xd9\x89\x0fC\xfd\
\x94\x9d|9\x99^k\x13\xa1 \xb3\x16\x0f#\xd4\x88N~\x14\xe1-\x96\x7f\xe3\x0f\
\x11\x91UC\x0cX\'\x1e\x00\x00\x00\x00IEND\xaeB`\x82'
def getStepInBitmap():
return BitmapFromImage(getStepInImage())
def getStepInImage():
stream = cStringIO.StringIO(getStepInData())
return ImageFromStream(stream)
def getStepInIcon():
return wx.IconFromBitmap(getStepInBitmap())
#----------------------------------------------------------------------
def getStopData():
return \
'\x89PNG\r\n\x1a\n\x00\x00\x00\rIHDR\x00\x00\x00\x10\x00\x00\x00\x10\x08\x06\
\x00\x00\x00\x1f\xf3\xffa\x00\x00\x00\x04sBIT\x08\x08\x08\x08|\x08d\x88\x00\
\x00\x00QIDAT8\x8d\xdd\x93A\n\xc00\x08\x04g\xb5\xff\x7fq\x13sn\xda&\x01\x0b\
\xa5]\xf0"\xec(.J\xe6dd)\xf7\x13\x80\xadoD-12\xc8\\\xd3\r\xe2\xa6\x00j\xd9\
\x0f\x03\xde\xbf\xc1\x0f\x00\xa7\x18\x01t\xd5\\\x05\xc8\\}T#\xe9\xfb\xbf\x90\
\x064\xd8\\\x12\x1fQM\xf5\xd9\x00\x00\x00\x00IEND\xaeB`\x82'
def getStopBitmap():
return BitmapFromImage(getStopImage())
def getStopImage():
stream = cStringIO.StringIO(getStopData())
return ImageFromStream(stream)
def getStopIcon():
return wx.IconFromBitmap(getStopBitmap())
#----------------------------------------------------------------------
def getStepReturnData():
return \
"\x89PNG\r\n\x1a\n\x00\x00\x00\rIHDR\x00\x00\x00\x10\x00\x00\x00\x10\x08\x06\
\x00\x00\x00\x1f\xf3\xffa\x00\x00\x00\x04sBIT\x08\x08\x08\x08|\x08d\x88\x00\
\x00\x00\x8dIDAT8\x8d\xa5S\xd1\x0e\xc4 \x08\xa3\xb0\xff\xbe\xdc\x7fO\xba'6\
\xf1\xf44\xb3O$Phk\x04\xd4d\x07\xba\xc5\x16\x91#\nza\xdb\x84\x1a\xa2\xfe\xf8\
\x99\xfa_=p+\xe8\x91ED\xbc<\xa4 \xb4\x0b\x01\xb5{\x01\xf9\xbbG-\x13\x87\x16f\
\x84\xbf\x16V\xb0l\x01@\no\x86\xae\x82Q\xa8=\xa4\x0c\x80\xe70\xbd\x10jh\xbd\
\x07R\x06#\xc9^N\xb6\xde\x03)\x83\x18\xaeU\x90\x9c>a\xb2P\r\xb3&/Y\xa8\xd1^^\
\xb6\xf0\x16\xdb\xbf\xf1\x02\x81\xa5TK\x1d\x07\xde\x92\x00\x00\x00\x00IEND\
\xaeB`\x82"
def getStepReturnBitmap():
return BitmapFromImage(getStepReturnImage())
def getStepReturnImage():
stream = cStringIO.StringIO(getStepReturnData())
return ImageFromStream(stream)
def getStepReturnIcon():
return wx.IconFromBitmap(getStepReturnBitmap())
#----------------------------------------------------------------------
def getAddWatchData():
return \
'\x89PNG\r\n\x1a\n\x00\x00\x00\rIHDR\x00\x00\x00\x10\x00\x00\x00\x10\x08\x06\
\x00\x00\x00\x1f\xf3\xffa\x00\x00\x00\x04sBIT\x08\x08\x08\x08|\x08d\x88\x00\
\x00\x00\x85IDAT8\x8dc`\x18h\xc0\x88.\xd0\xc0\xf0\xff?*\x9f\x11C\rN\x80\xae\
\x19\x97\x18\xd1\x9a\x896\x84\x18[p\xa9aA\xe6\xfc7f\xc0P\xc4x\x163\x9cp\x1a0\
\xeb,!w\x100 \x1dK\xac\x10\r\x08\x05".yFL\x85\x8c\x18b\xa8|Ty\xa2\x13\x92\'\
\xc3\xe4\xff\x9f\x18\x1e3\xb82t\xa2\x88\x13\xedg.\x06aa&\x06VV\x7f\x86\xb9\
\xcfU\x19\xbc\xb0\xba\x86h\xe0\xc8\xd0\xfc\xbf\x80\xe1>q)\x94\xe6\x00\x00\
\x85\x923_\xd22\xa4\xcd\x00\x00\x00\x00IEND\xaeB`\x82'
def getAddWatchBitmap():
return BitmapFromImage(getAddWatchImage())
def getAddWatchImage():
stream = cStringIO.StringIO(getAddWatchData())
return ImageFromStream(stream)
def getAddWatchIcon():
return wx.IconFromBitmap(getAddWatchBitmap())
#----------------------------------------------------------------------
def getRunningManData():
return \
'\x89PNG\r\n\x1a\n\x00\x00\x00\rIHDR\x00\x00\x00\x10\x00\x00\x00\x10\x08\x06\
\x00\x00\x00\x1f\xf3\xffa\x00\x00\x00\x04sBIT\x08\x08\x08\x08|\x08d\x88\x00\
\x00\x01\x86IDAT8\x8d\xa5\x93\xb1K\x02Q\x1c\xc7\xbf\xcf\x9a\x1bZl\x88\xb4\
\x04\x83\x10\xa2\x96\xc0A\xa8\x96\x96\xf4h\xe9\xf0\x1f\xd0\xcd(Bpi\x13nH\xb2\
%\x9d\x1a"\xb9)\xb4\x16i\x10\n\x13MA\x84\xa3&\xa1\xa1A\xa1E\xbdw\x97\xa2\xbd\
\x06\xf1(\xef,\xac\xef\xf6x\xdf\xf7}\x9f\xdf\x97\xf7\x081M\xe0?\x9a\xfc\xcd \
\\\xdc2\x99\xb6A[\x14\x91C\x9e\x8c\x1d\x00\x00\xd5\xa7*\x9a\x8a\xfa7\x82u\
\xfb\x14dj\x03mQ\xc3}\xf2\xb5\x83\xc7B\x9e\x89\xf7/\xda\xba\xd1\x94\x01\x00j\
CF\xe2t\xef\x1b>\x1f\x8c3Q\xf0\x11\xd3p\xa2yf\x1a\xbc\xcb\n\xdee\x85\xdd>\
\x07\xb5!C\xe9\xb4\xb1\xe9=b\x03\x8fc\xc3\xcf\xbcN\xb3\x9e`@\x11\xb9\xaa`\
\x7fg\x19\'\x97y\xd8\x96\xfa\xf8\x95\xf23d\xa5O4\xbfh\x87(\xf8\x88a\xc0 $|~\
\x87n\xf7\x03\xaa\xf2\x8e\xc0\xee\n\x00 \x91\xab\xc3\xeb4\xc3\xed\xe1\xb4qF\
\x96\xb8`\xb3h\xb7\xa6Jo\xa0\x9d\x1eD\xc1G\xc4!\x9f\xae\x03\x00\xa8\xd5jh4e\
\r\xb9\xf0P\x82T,\x83\xf3\x0bl\xd8k\x18\xe0\xf6p\x84vz\xa0M\x8aB\xf2\x98\x84\
\x03[\xb0.XP\xcafu^m\x04>\x18\xd7\x9aM\xe4\xea\xba\xc0x\xec\x8c\xa9\xca*^\
\xa5\x1b}\xc0u*\xc9B\xd14\x12\xe8\x97%\x15\xcbF`\xdaH\xba\x80P4\r)\x13#R\xc6\
\xf0\xdc\x8f2\x01\x80\x94\x89\xe9>\xc9(\xcd:\xb6\xd9\x1aw\xa0\x95i\xf8\x0e\
\xc6\xd1\'\'\x86\xa2\xd5\x8d \xbe@\x00\x00\x00\x00IEND\xaeB`\x82'
def getRunningManBitmap():
return BitmapFromImage(getRunningManImage())
def getRunningManImage():
stream = cStringIO.StringIO(getRunningManData())
return ImageFromStream(stream)
def getRunningManIcon():
icon = EmptyIcon()
icon.CopyFromBitmap(getRunningManBitmap())
return icon
#----------------------------------------------------------------------
def getDebuggingManData():
return \
'\x89PNG\r\n\x1a\n\x00\x00\x00\rIHDR\x00\x00\x00\x10\x00\x00\x00\x10\x08\x06\
\x00\x00\x00\x1f\xf3\xffa\x00\x00\x00\x04sBIT\x08\x08\x08\x08|\x08d\x88\x00\
\x00\x01\xafIDAT8\x8d\x8d\x93\xbfK[Q\x14\xc7?7\n:\t\xb5SA\xc1?@\xc1A\x9c,%\
\xd0\xa9\x83\xb5\x98!(b\t\xbc\xa7q("m\x1c\n5V]D\xd4-\xf8\x83\xa7\xa2\t\xa1\
\xa6\xed$8\x08\x92\xa1\x8b\x14A\xd0YB"\xa4\xf4\x87\x90\x97K\xa8\xcb\xed\xf0\
\xc8m\xae\xfa\xd4\x03\x07.\xe7\x9e\xf3\xfd\x9e\x9f\x88@\x1d\xb5\xba\x94\xca\
\xaa\xeb\xb6\xbb4\xc0\x03d&\xb1\xa7\xfc\xfe\x0c\x80L\xdaQ\xd2\xad\x90I;F\x80\
++\xbe\xe0bve\xdf\xd7y\xfemH\xc4\x162\xaa\xbb\xa5D(\x1c\x11\xb7\x02\x88@\x9d\
f?*4\xd1\xf6\xa2\x0f\x80\x93\xf4\x8e\xe1\xb8\xf2\xf1\xb5\x18\x9cH(\x80\xe4bT\
\x83\xd5W\x1f\xa1pD\x8c|\xd8T\x00\xdf\xd6\xd7\xe8\x1f\xb3tp\xf1\n^\xfe\xf8\
\xa5^u7\x00P\x1eYP\xd2\x95\x1c\xa4\xa6\x84\x18\x8do\xab*C&\xed\xa8\xafG\x7f\
\xe9\x1f\xb3x\xdc\x08\xad\x8f \x7f\tg%\xf8Y\x82\xe3\x8de\x86\x82\xcdF9\xba\
\x84\xc1\x89\x84*K\t\xc0\xf0\xbbq:\x9f\xfcO\x7f?\xe7\x01\x9c\xff\x86Br\x8e\
\x83\xd4\x94\x06\xd0SH.F\xc5P\xb0\x19\xe9z \xf9KOmkN\x07\x03\x14/r\xb4?\x8b\
\xe8\xc6\xeb\x1e\x00l\x1f\xfe\xd15\x17\xaf<\xdb\xd37\xef\xd9\x9d\xb4\xe9\x8a\
\xadj\xbfx\xb4\x878(#\x03\x00\xe9JF{[\xf92\xeb\xb1V\x99\xbbb\xab|\x9f\xb7\
\x8d\xa9\x9cf\x1dq\x9au\xc4\x8dM\x0c\x85#\xa2x\x91cw\xd2\xd6i\x83\trk\x13\
\x9f\x0fL\xab\xda\xe6\xd4\xd6Y+\xf1h\x8f\xb9T~G\xd2\x11\xb4\xd4\xe7O[\xf7\
\x1e\xd6\x9d\xc7\xe4\xb7\xbe\x86\xf8\xb1?\xf4\x9c\xff\x01\xbe\xe9\xaf\x96\
\xf0\x7fPA\x00\x00\x00\x00IEND\xaeB`\x82'
def getDebuggingManBitmap():
return BitmapFromImage(getDebuggingManImage())
def getDebuggingManImage():
stream = cStringIO.StringIO(getDebuggingManData())
return ImageFromStream(stream)
def getDebuggingManIcon():
icon = EmptyIcon()
icon.CopyFromBitmap(getDebuggingManBitmap())
return icon
#----------------------------------------------------------------------