⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 debuggerservice.py

📁 wxPython的基本示例程序
💻 PY
📖 第 1 页 / 共 5 页
字号:
#----------------------------------------------------------------------------# Name:         DebuggerService.py# Purpose:      Debugger Service for Python and PHP## Author:       Matt Fryer## Created:      12/9/04# CVS-ID:       $Id: DebuggerService.py,v 1.8 2006/04/20 06:26:01 RD Exp $# Copyright:    (c) 2004-2005 ActiveGrid, Inc.# License:      wxWindows License#----------------------------------------------------------------------------import wximport wx.lib.intctrlimport wx.lib.docviewimport wx.lib.dialogsimport wx.gizmosimport wx._coreimport wx.lib.pydocviewimport Serviceimport STCTextEditorimport CodeEditorimport PythonEditorimport PHPEditorimport PHPDebuggerimport activegrid.model.projectmodel as projectmodelfrom IDE import ACTIVEGRID_BASE_IDEif not ACTIVEGRID_BASE_IDE:    import ProcessModelEditorimport wx.lib.scrolledpanel as scrolledimport sysimport timeimport SimpleXMLRPCServerimport xmlrpclibimport osimport threadingimport Queueimport SocketServerimport ProjectEditorimport typesfrom xml.dom.minidom import parse, parseStringimport bz2import pickleimport DebuggerHarnessimport tracebackimport StringIOimport UICommonimport activegrid.util.sysutils as sysutilslibimport subprocessimport shutilif wx.Platform == '__WXMSW__':    try:        import win32api        _PYWIN32_INSTALLED = True    except ImportError:        _PYWIN32_INSTALLED = False    _WINDOWS = Trueelse:    _WINDOWS = Falseif not _WINDOWS or _PYWIN32_INSTALLED:    import process_ = wx.GetTranslation_VERBOSE = False_WATCHES_ON = Falseimport  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 = Falseclass 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._pathclass 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)

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -