📄 debuggerservice.py
字号:
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:
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -