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

📄 debuggerservice.py

📁 Wxpython Implemented on Windows CE, Source code
💻 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 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):

⌨️ 快捷键说明

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