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

📄 debuggerservice.py

📁 Wxpython Implemented on Windows CE, Source code
💻 PY
📖 第 1 页 / 共 5 页
字号:
        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

⌨️ 快捷键说明

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