# -*- coding: GBK -*-    
 | 
#write:zfl  
 | 
#  
 | 
##@package PyTrackObj.py  
 | 
# Ä£¿éµÄ¼òҪ˵Ã÷:´úÂëÖ´ÐÐÂÊ×·×ÙÄÚ²¿´¢´æÀà  
 | 
# @author:zfl  
 | 
# @date 2010-07-21 11:00  
 | 
# @version 1.4  
 | 
#  
 | 
# ÐÞ¸Äʱ¼ä ÐÞ¸ÄÈË ÐÞ¸ÄÄÚÈÝ  
 | 
# @change: "2010-07-21 11:00" zfl ÐÂÔö½Ó¿Ú£¬¿É»ñµÃºÍÉèÖÃPyObjÀà¡¢FuncObjÀàÐÅÏ¢  
 | 
# @change: "2010-08-03 11:00" zfl ÐÂÔö½Ó¿Ú£¬¿É»ñµÃºÍÉèÖÃPyObjÀà¡¢FuncObjÀàÐÅÏ¢  
 | 
# @change: "2010-08-18 16:00" zfl ÐÂÔö½Ó¿Ú  
 | 
# @change: "2010-11-03 10:00" zfl ÐÂÔöµ¥ÐÐÀ¨ºÅµÄÅÐ¶Ï  
 | 
#  
 | 
# Ä£¿éÏêϸ˵Ã÷:´úÂëÖ´ÐÐÂÊ×·×ÙÄÚ²¿´¢´æÀà  
 | 
#  
 | 
#-------------------------------------------------------------------------------  
 | 
  
 | 
"""Version = 2010-11-03 10:00"""  
 | 
  
 | 
#-------------------------------------------------------------------------------  
 | 
#µ¼Èë  
 | 
import os  
 | 
import time  
 | 
import md5  
 | 
import traceback  
 | 
  
 | 
#-------------------------------------------------------------------------------  
 | 
#È«¾Ö±äÁ¿  
 | 
  
 | 
FORM_NAME = "PyTrackObj"  
 | 
  
 | 
IGNORE_FUNC_LIST = []  
 | 
  
 | 
FILE_TRACK_MODE = 1  # Îļþ×·×Ùģʽ  
 | 
FUNC_TRACK_MODE = 2  # º¯Êý×·×Ùģʽ  
 | 
  
 | 
UI_OUTPUT_MODE = 0  # ½çÃæÊä³öģʽ  
 | 
FILE_OUTPUT_MODE = 1  # ÎļþÊä³öģʽ  
 | 
  
 | 
#---µ÷ÊÔº¯Êý---------------------------------------------------------------------  
 | 
  
 | 
NOW_TIME = 'log%s%s%s%s%s%s.txt'%tuple(['%02d'%time.localtime()[i] for i in range(6)])  
 | 
  
 | 
LOG_PATH = os.getcwd() + "\\log\\"      # log·¾¶  
 | 
  
 | 
## Ð´logº¯Êý  
 | 
#  @param *varlist ²»¶¨²Î  
 | 
#  @return ÎÞ·µ»ØÖµ  
 | 
#  @remarks ½«´«ÈëµÄlogÐÅϢдÈëÖ¸¶¨logÎļþ  
 | 
def LogEx(*varlist):  
 | 
    info = '[%s%s%s%s%s%s]'%tuple(['%02d'%time.localtime()[i] for i in range(6)])  
 | 
    for i in range(1, len(varlist)):  
 | 
        curValue = varlist[i]  
 | 
        info += "( "+str(type(curValue)) + ":" + str(curValue) + " ),"  
 | 
      
 | 
    if not os.path.isdir(LOG_PATH):  
 | 
        os.mkdir(LOG_PATH)  
 | 
          
 | 
    if os.path.isfile(LOG_PATH +  NOW_TIME):  
 | 
        logfile = open(LOG_PATH +  NOW_TIME, 'a')  
 | 
    else:  
 | 
        logfile = file(LOG_PATH +  NOW_TIME, 'w')  
 | 
          
 | 
    logfile.write('\t'*int(varlist[0])+info+'\n')  
 | 
    logfile.close()  
 | 
      
 | 
LogEx(0, "CurPath=%s"%os.getcwd())  
 | 
     
 | 
          
 | 
## ÔÚÖ¸¶¨Ä¿Â¼Ï£¬²éÕÒÎļþ£¬²¢·µ»ØÂ·¾¶  
 | 
#  @param path£ºÂ·¾¶  
 | 
#  @param filename£ºÎļþÃû  
 | 
#  @return ÕÒµ½·µ»ØÂ·¾¶£¬Ã»ÕÒµ½·µ»Ø¿Õ´®  
 | 
#  @remarks º¯ÊýÏêϸ˵Ã÷£ºÔÚÖ¸¶¨Ä¿Â¼Ï£¬²éÕÒÎļþ£¬²¢·µ»ØÂ·¾¶  
 | 
def GetFilePath(path, filename):  
 | 
     
 | 
    for dir in os.listdir(path):  
 | 
        curPath = path + "\\"  + dir  
 | 
          
 | 
        # ÊÇÎļþ  
 | 
        if os.path.isfile(curPath):  
 | 
            # ÕÒµ½  
 | 
            if dir == filename:  
 | 
#                LogEx(2, "%s : GetFilePath = %s"%(filename, path))  
 | 
                return path   
 | 
                  
 | 
        # ÊÇÎļþ¼Ð  
 | 
        if os.path.isdir(curPath):  
 | 
            tempPath = GetFilePath(curPath, filename)  
 | 
            if tempPath != "":  
 | 
                return tempPath  
 | 
            continue  
 | 
              
 | 
    return ""  
 | 
  
 | 
  
 | 
## Ö¸¶¨×Ö·ûÁбí²ð·Ö×Ö·û´®  
 | 
#  @param line: ÐèÒª²ð·ÖµÄ×Ö·û´®  
 | 
#  @param charList: ×Ö·ûÁÐ±í  
 | 
#  @return ·µ»Ø²ð³öµÄµÚÒ»¸ö×Ó´®  
 | 
#  @remarks º¯ÊýÏêϸ˵Ã÷£º  
 | 
def GetSplitFirstByChar(line, charList):  
 | 
      
 | 
    for i in range(len(line)):  
 | 
        if line[i] in charList:  
 | 
            return line[:i]  
 | 
      
 | 
    return line  
 | 
  
 | 
  
 | 
## ÅжÏÖ¸¶¨ÐÐÄÚÈÝÊÇ·ñ¿ÉÒÔºöÂÔ  
 | 
#  @param rowContent: ÐÐÄÚÈÝ  
 | 
#  @return ÊÇ·ñ¿ÉÒÔºöÂÔ  
 | 
#  @remarks º¯ÊýÏêϸ˵Ã÷£º  
 | 
def IsLineNeedIgnore(rowContent):  
 | 
      
 | 
    rowContent = rowContent.split("#")[0].strip()  
 | 
    # ºöÂÔµ¥ÐÐÀ¨ºÅ  
 | 
    if rowContent in ["(", "[", "{"]:  
 | 
        return True  
 | 
      
 | 
    # ºöÂÔµ¥ÐÐÀ¨ºÅ  
 | 
    if rowContent.startswith(")") or rowContent.startswith("]") or rowContent.startswith("}"):  
 | 
        return True  
 | 
      
 | 
    charList = [" ", "\t", "\n"]  
 | 
      
 | 
    # ²ð·Ö×Ö·û´®  
 | 
    rowContent = GetSplitFirstByChar(rowContent, charList)  
 | 
      
 | 
    # ºöÂÔglobal  
 | 
    if rowContent == 'global':  
 | 
        return True  
 | 
          
 | 
#    # ºöÂÔreturn  
 | 
#    if rowContent == 'return':  
 | 
#        return True  
 | 
  
 | 
    # ºöÂÔbreak  
 | 
    if rowContent == 'break':  
 | 
        return True  
 | 
      
 | 
    # ºöÂÔelse  
 | 
    if rowContent == 'else:':  
 | 
        return True  
 | 
          
 | 
    # ºöÂÔpass  
 | 
    if rowContent == 'pass':  
 | 
            return True  
 | 
      
 | 
    # ÎÞÐèºöÂÔµÄÄÚÈÝ      
 | 
    return False  
 | 
  
 | 
  
 | 
## ¶Ôº¯Êý¶ÔÏóµÄÅÅÐò±È½Ïº¯Êý  
 | 
#  @param x: ºóÒ»¸ö  
 | 
#  @param y: Ç°Ò»¸ö  
 | 
#  @return Ð¡ÓÚ£¬µÈÓÚ£¬´óÓÚ£º-1£¬ 0 £¬1  
 | 
#  @remarks º¯ÊýÏêϸ˵Ã÷£º  
 | 
def FuncObjCmp(x, y):  
 | 
      
 | 
    if x.startIndex > y.startIndex:  
 | 
        return 1  
 | 
    elif x.startIndex < y.startIndex:  
 | 
        return -1  
 | 
    else:  
 | 
        return 0  
 | 
  
 | 
          
 | 
## Éú³Éº¯ÊýµÄMD5  
 | 
#  @param contenListt: ´úÂëÄÚÈÝ  
 | 
#  @param execRowList: ¿ÉÖ´ÐÐÐÐÄÚÈÝ  
 | 
#  @param MD5Key: MD5ÃÜÔ¿  
 | 
#  @return ·µ»ØMD5  
 | 
#  @remarks º¯ÊýÏêϸ˵Ã÷£ºÉú³Éº¯ÊýµÄMD5  
 | 
def CalcFuncMD5(contentList, execRowList, MD5Key):  
 | 
    mdstr = ""  
 | 
  
 | 
    # ºÏ³ÉÑéÖ¤×Ö·û´®  
 | 
    for rowInfo in execRowList:  
 | 
        if rowInfo[2] < 2:  
 | 
            mdstr += contentList[rowInfo[0]-1].rstrip(" ")  
 | 
              
 | 
    # ·µ»ØÉú³ÉµÄMD5  
 | 
    return md5.md5(mdstr + MD5Key).hexdigest()  
 | 
  
 | 
       
 | 
## ×Ö·û´®ÄÚÈÝÉú³ÉµÄMD5  
 | 
#  @param reportString: ÄÚÈÝ×Ö·û´®  
 | 
#  @param MD5Key: MD5ÃÜÔ¿  
 | 
#  @return ·µ»ØMD5  
 | 
#  @remarks º¯ÊýÏêϸ˵Ã÷£ºÉú³ÉµÄMD5  
 | 
def CalcStringMD5(reportString, MD5Key):  
 | 
      
 | 
    contentList = reportString.split("\r\n")  
 | 
          
 | 
    # ·µ»ØÉú³ÉµÄMD5  
 | 
    return CalcListMD5(contentList, MD5Key)  
 | 
  
 | 
#t =""  
 | 
  
 | 
## ÁбíÄÚÈÝÉú³ÉµÄMD5  
 | 
#  @param reportList: ÄÚÈÝÁÐ±í  
 | 
#  @param MD5Key: MD5ÃÜÔ¿  
 | 
#  @return ·µ»ØMD5  
 | 
#  @remarks º¯ÊýÏêϸ˵Ã÷£ºÉú³ÉµÄMD  
 | 
def CalcListMD5(reportList, MD5Key):  
 | 
#    global t  
 | 
      
 | 
    mdstr = ""  
 | 
    # ºÏ³ÉÑéÖ¤×Ö·û´®  
 | 
    for line in reportList:  
 | 
        line = line.replace("\n", "")  
 | 
        mdstr += line.replace("\r", "")  
 | 
    
 | 
#     ·µ»ØÉú³ÉµÄMD5  
 | 
    return md5.md5(mdstr + MD5Key).hexdigest()  
 | 
  
 | 
  
 | 
## pyÎļþÀà  
 | 
#  
 | 
# ±»Ö´Ðе½µÄpyµÄ¹ÜÀíÀà  
 | 
class PyObj:  
 | 
      
 | 
    ## ¹¹Ô캯Êý  
 | 
    #  @param pyName: PyÎļþÃû  
 | 
    #  @param MD5Key£ºMD5ÃÜÔ¿  
 | 
    #  @param scriptPath£ºPy·¾¶  
 | 
    #  @param isCreate: ÊÇ·ñ¸ù¾ÝPYÉú³ÉPyObj  
 | 
    #  @return ·µ»ØÖµ  
 | 
    #  @remarks º¯ÊýÏêϸ˵Ã÷£º  
 | 
    def __init__(self, pyName, MD5Key="", scriptPath="", isCreate=True):  
 | 
        self.pyName = pyName         # pyÃû  
 | 
        self.funcObjList = []        # º¯Êý¶ÔÏóÁÐ±í  
 | 
        self.contentList = []        # pyÄÚÈÝÁÐ±í  
 | 
        self.pyExecCount = 0         # pyÒÑÖ´ÐÐÐÐÊý  
 | 
        self.pyTotalCount = 0        # py×ÜÓÐЧÐÐÊý  
 | 
        self.isPyFileExist = True    # Ãû×Ö¶ÔÓ¦µÄpyÎļþÊÇ·ñ´æÔÚ  
 | 
        self.isTracking = False      # ÊÇ·ñÊÇ×·×ÙÖÐ  
 | 
        self.MD5 = ""                # PyÎļþMD5  
 | 
        self.MD5Key = MD5Key         # MD5ÃÜÔ¿  
 | 
  
 | 
        if isCreate:  
 | 
            self.CreateFuncObj(scriptPath)         # ½âÎöPyÎļþÐÅÏ¢  
 | 
      
 | 
      
 | 
    ## Éú³Éº¯Êý¶ÔÏóÁÐ±í    
 | 
    #  @param scriptPath£ºPy·¾¶  
 | 
    #  @return ·µ»ØÖµ  
 | 
    #  @remarks º¯ÊýÏêϸ˵Ã÷£º  
 | 
    def CreateFuncObj(self, scriptPath):  
 | 
#        LogEx(0, "CreateFuncObj(self)")  
 | 
          
 | 
        tempPath = GetFilePath(scriptPath, self.pyName)  
 | 
        # pyÃû¶ÔÓ¦µÄÎļþ²»´æÔÚ  
 | 
        if tempPath == "":  
 | 
            LogEx(1, "self.isPyFileExist = False", scriptPath, self.pyName)  
 | 
            self.isPyFileExist = False  
 | 
            return  
 | 
          
 | 
        # ¶ÁÈ¡Îļþ  
 | 
        file = open(tempPath + "\\" + self.pyName, 'r')  
 | 
        self.contentList = file.readlines()  
 | 
        file.close()  
 | 
          
 | 
        isFindFuncHead = False      # ÊÇ·ñÕÒµ½º¯ÊýÍ·  
 | 
        isFindClassHead = False     # ÊÇ·ñÕÒµ½ÀàÍ·  
 | 
        isFindingComment = False    # ÊÇ·ñÕÒµ½Àà»òº¯Êý×¢ÊÍ  
 | 
        startIndex = 0              # º¯ÊýÍ·µÄÆðʼλÖà  
 | 
        funcName = ""               # ÕÒµ½µÄº¯ÊýÃû  
 | 
        className = ""              # ÕÒµ½µÄÀàÃû  
 | 
        funcComment = ""            # º¯Êý×¢ÊÍ  
 | 
        rowCount = 0            # º¯Êý×ÜÐÐÊý  
 | 
        rowList = []            # º¯ÊýÐÐÐÅÏ¢ÁÐ±í  
 | 
        rowStartIndex = 0       # º¯ÊýÐÐÆðʼ  
 | 
        rowEndIndex = 0         # º¯ÊýÐнáÊø  
 | 
          
 | 
        contentList = self.contentList  
 | 
        #±éÀúÿÐÐ  
 | 
        for i in range(len(contentList)+1):  
 | 
#            print i+1,":",contentList[i]  
 | 
              
 | 
            # Îļþ½áÊø  
 | 
            if i == len(contentList):  
 | 
                if isFindFuncHead:  
 | 
                    # »ñµÃº¯Êý×¢ÊÍ  
 | 
                    for j in range(rowStartIndex-2, 0, -1):  
 | 
                        if contentList[j].lstrip().startswith("##"):  
 | 
                            funcComment = contentList[j]  
 | 
#                            isFindingComment = True           # ÕÒµ½º¯Êý×¢ÊÍ  
 | 
                            break  
 | 
                        if not contentList[j].lstrip().startswith("#"):  
 | 
                            break  
 | 
                    isFindFuncHead = False    
 | 
                    startIndex = 0  
 | 
                      
 | 
                    # ½«º¯ÊýÐÐÊý¼ÓÖÁpy×ÜÐÐÊý  
 | 
                    self.pyTotalCount += rowCount  
 | 
                    # ´´½¨º¯Êý¶ÔÏó  
 | 
#                    LogEx(2, "findFunc=" + funcName)  
 | 
                          
 | 
                    # Éú³Éº¯Êýmd5  
 | 
                    MD5 = CalcFuncMD5(contentList, rowList, self.MD5Key)  
 | 
                    tempFuncObj = FuncObj(className, funcName, funcComment, rowList, rowStartIndex, rowEndIndex, MD5)  
 | 
                    self.funcObjList.append(tempFuncObj)  # ½«º¯Êý¶ÔÏó¼ÓÖÁÁÐ±í  
 | 
                    funcName = ''      # ÖØÖú¯ÊýÃû  
 | 
                    rowCount = 0       # ÖØÖÃ×ÜÐÐÊý  
 | 
                    rowList = []       # ÖØÖÃÐÐÄÚÈÝÁÐ±í  
 | 
                    funcComment = ''   # ÖØÖú¯Êý×¢ÊÍ  
 | 
                    rowStartIndex = 0  # ÖØÖú¯ÊýÐÐÆðʼ   
 | 
                    rowEndIndex = 0    # ÖØÖú¯ÊýÐнáÊø  
 | 
                    isFindingComment = False  
 | 
                  
 | 
                break  
 | 
              
 | 
            # ÕÒµ½Àà»òº¯Êý×¢ÊÍ  
 | 
            if contentList[i].strip().startswith("##"):  
 | 
                rowList.append([i + 1, i + 1 - rowStartIndex, 2, contentList[i]])  # ±£´æÐÐÐÅÏ¢  
 | 
                continue  
 | 
              
 | 
            # Çå³ýÊ×β¿ØÖÆ·ûºóµÄÐÐÄÚÈÝ  
 | 
            temp = contentList[i].strip()  
 | 
              
 | 
            # ´¦Àí·ÖÐк÷û"\"  
 | 
            if temp.endswith("\\"):  
 | 
                contentList[i] = contentList[i][:contentList[i].rfind("\\")] + " " + contentList[i + 1].lstrip()  
 | 
                contentList[i + 1] = "\n"  
 | 
                temp = contentList[i].strip()  
 | 
                  
 | 
            # ¿ÕÐÐ  
 | 
            if len(temp) == 0:  
 | 
                if isFindFuncHead:  
 | 
                    rowList.append([i + 1, i + 1 - rowStartIndex, 3, "\n"])  # ±£´æ¿ÕÐÐ  
 | 
                continue  
 | 
              
 | 
            # ÐÐ×¢ÊÍ  
 | 
            if temp.startswith("#"):  
 | 
                rowList.append([i + 1, i + 1 - rowStartIndex, 2, contentList[i]])  # ±£´æÐÐÐÅÏ¢  
 | 
                continue  
 | 
              
 | 
            # ÕÒµ½º¯ÊýÍ·  
 | 
            if temp.startswith("def "):  
 | 
                # »ñµÃº¯Êý×¢ÊÍ  
 | 
                for j in range(rowStartIndex-2, 0, -1):  
 | 
                    if contentList[j].lstrip().startswith("##"):  
 | 
                        funcComment = contentList[j]  
 | 
#                        isFindingComment = True           # ÕÒµ½º¯Êý×¢ÊÍ  
 | 
                        break  
 | 
                    if not contentList[j].lstrip().startswith("#"):  
 | 
                        break  
 | 
                      
 | 
                if isFindFuncHead:  
 | 
                    startIndex = 0  
 | 
                      
 | 
                    # ½«º¯ÊýÐÐÊý¼ÓÖÁpy×ÜÐÐÊý  
 | 
                    self.pyTotalCount += rowCount  
 | 
                    # ´´½¨º¯Êý¶ÔÏó  
 | 
#                    LogEx(2, "findFunc=" + funcName)  
 | 
                          
 | 
                    # Éú³Éº¯Êýmd5  
 | 
                    MD5 = CalcFuncMD5(contentList, rowList, self.MD5Key)  
 | 
                    tempFuncObj = FuncObj(className, funcName, funcComment, rowList, rowStartIndex, rowEndIndex, MD5)  
 | 
                    self.funcObjList.append(tempFuncObj)  # ½«º¯Êý¶ÔÏó¼ÓÖÁÁÐ±í  
 | 
                    funcName = ''      # ÖØÖú¯ÊýÃû  
 | 
                    rowCount = 0       # ÖØÖÃ×ÜÐÐÊý  
 | 
                    rowList = []       # ÖØÖÃÐÐÄÚÈÝÁÐ±í  
 | 
                    funcComment = ''   # ÖØÖú¯Êý×¢ÊÍ  
 | 
                    rowStartIndex = 0  # ÖØÖú¯ÊýÐÐÆðʼ  
 | 
                    rowEndIndex = 0    # ÖØÖú¯ÊýÐнáÊø  
 | 
                    isFindingComment = False  
 | 
                      
 | 
#                if isFindingComment == False:  
 | 
#                    LogEx(1, "No Comment!!!")  
 | 
                      
 | 
                endIndex = temp.find('(')                # º¯ÊýÃû½áβË÷Òý  
 | 
                if temp[4:endIndex] in IGNORE_FUNC_LIST:  
 | 
                    continue  
 | 
                isFindFuncHead = True                     # ÒÑÕÒµ½º¯ÊýÍ·  
 | 
                rowStartIndex = i + 1                     # º¯ÊýÐÐÆðʼ  
 | 
                startIndex = contentList[i].find('def')   # º¯ÊýÍ·µÄÆðʼλÖà  
 | 
                  
 | 
                if startIndex == 0:  
 | 
                    isFindClassHead = False               # ÀඨÒå½áÊø  
 | 
                    className = ""                        # Çå¿ÕÀàÃû  
 | 
                      
 | 
                funcName = temp[4:endIndex]               # º¯ÊýÃû  
 | 
                continue  
 | 
  
 | 
            # ÕÒµ½ÀàÍ·  
 | 
            if contentList[i].startswith("class "):  
 | 
                if isFindFuncHead:  
 | 
                    isFindFuncHead = False  
 | 
                    startIndex = 0  
 | 
                      
 | 
                    # ½«º¯ÊýÐÐÊý¼ÓÖÁpy×ÜÐÐÊý  
 | 
                    self.pyTotalCount += rowCount  
 | 
                    # ´´½¨º¯Êý¶ÔÏó  
 | 
#                    LogEx(2, "findFunc=" + funcName)  
 | 
                    # »ñµÃº¯Êý×¢ÊÍ  
 | 
                    for j in range(rowStartIndex-2, 0, -1):  
 | 
                        if contentList[j].startswith("## "):  
 | 
                            funcComment = contentList[j]  
 | 
                        if not contentList[j].startswith("#"):  
 | 
                            break  
 | 
                          
 | 
                    # Éú³Éº¯Êýmd5  
 | 
                    MD5 = CalcFuncMD5(contentList, rowList, self.MD5Key)  
 | 
                    tempFuncObj = FuncObj(className, funcName, funcComment, rowList, rowStartIndex, rowEndIndex, MD5)  
 | 
                    self.funcObjList.append(tempFuncObj)  # ½«º¯Êý¶ÔÏó¼ÓÖÁÁÐ±í  
 | 
                    funcName = ''      # ÖØÖú¯ÊýÃû  
 | 
                    rowCount = 0       # ÖØÖÃ×ÜÐÐÊý  
 | 
                    rowList = []       # ÖØÖÃÐÐÄÚÈÝÁÐ±í  
 | 
                    funcComment = ''   # ÖØÖú¯Êý×¢ÊÍ  
 | 
                    rowStartIndex = 0  # ÖØÖú¯ÊýÐÐÆðʼ  
 | 
                    rowEndIndex = 0    # ÖØÖú¯ÊýÐнáÊø  
 | 
                    isFindingComment = False  
 | 
                      
 | 
#                if isFindingComment == False:  
 | 
#                    LogEx(1, "No Comment!!!")  
 | 
                      
 | 
                isFindClassHead = True                    # ÒÑÕÒµ½ÀàÍ·  
 | 
                endIndex = temp.find(":")                 # ÀàÃû½áβË÷Òý  
 | 
                className = temp[6:endIndex]              # ÀàÃû  
 | 
                continue  
 | 
              
 | 
            # ÒÑÕÒµ½º¯Êý¶¨Òå´¦  
 | 
            if isFindFuncHead:  
 | 
                # µÚÒ»¸ö·Ç¿Õ×Ö·ûµÄË÷Òý<=±Èº¯ÊýÍ·µÄË÷ÒýС¡ª¡ªÒѵ½±¾º¯Êý½áβ  
 | 
                if contentList[i].find(temp[0]) <= startIndex:  
 | 
                    isFindFuncHead = False    
 | 
                    startIndex = 0  
 | 
                      
 | 
                    # ½«º¯ÊýÐÐÊý¼ÓÖÁpy×ÜÐÐÊý  
 | 
                    self.pyTotalCount += rowCount  
 | 
                    # ´´½¨º¯Êý¶ÔÏó  
 | 
#                    LogEx(2, "findFunc=" + funcName)  
 | 
                    # »ñµÃº¯Êý×¢ÊÍ  
 | 
                    for j in range(rowStartIndex-2, 0, -1):  
 | 
                        if contentList[j].startswith("## "):  
 | 
                            funcComment = contentList[j]  
 | 
                        if not contentList[j].startswith("#"):  
 | 
                            break  
 | 
                          
 | 
                    # Éú³Éº¯Êýmd5  
 | 
                    MD5 = CalcFuncMD5(contentList, rowList, self.MD5Key)  
 | 
                    tempFuncObj = FuncObj(className, funcName, funcComment, rowList, rowStartIndex, rowEndIndex, MD5)  
 | 
                    self.funcObjList.append(tempFuncObj)  # ½«º¯Êý¶ÔÏó¼ÓÖÁÁÐ±í  
 | 
                    funcName = ''      # ÖØÖú¯ÊýÃû  
 | 
                    rowCount = 0       # ÖØÖÃ×ÜÐÐÊý  
 | 
                    rowList = []       # ÖØÖÃÐÐÄÚÈÝÁÐ±í  
 | 
                    funcComment = ''   # ÖØÖú¯Êý×¢ÊÍ  
 | 
                    rowStartIndex = 0  # ÖØÖú¯ÊýÐÐÆðʼ  
 | 
                    rowEndIndex = 0    # ÖØÖú¯ÊýÐнáÊø  
 | 
                    isFindingComment = False  
 | 
                      
 | 
                # Î´µ½º¯Êýµ×  
 | 
                else:  
 | 
                    if isFindClassHead and not isFindFuncHead:  
 | 
                        continue  
 | 
                      
 | 
                    rowEndIndex = i + 1    # º¯ÊýÐнáÊø  
 | 
                      
 | 
                    if IsLineNeedIgnore(temp):  # ÊÇ·ñÐèÒªºöÂÔ±¾ÐÐ  
 | 
                        rowList.append([i + 1, i + 1 - rowStartIndex, 2, contentList[i]])  # ±£´æÐÐÐÅÏ¢  
 | 
                        continue  
 | 
                      
 | 
                    rowCount += 1      # ×ÜÐÐÊý+1  
 | 
                    rowList.append([i + 1, i + 1 - rowStartIndex, 0, contentList[i]])  # ±£´æÐÐÐÅÏ¢  
 | 
      
 | 
      
 | 
    ## ²éѯº¯ÊýÊÇ·ñÒÑÔÚº¯Êý¶ÔÏóÁбíÖÐ  
 | 
    #  @param funcName:º¯ÊýÃû  
 | 
    #  @param className:º¯ÊýËùÊôÀàÃû  
 | 
    #  @return ·µ»ØÖµ  
 | 
    #  @remarks º¯ÊýÏêϸ˵Ã÷£º²éѯ´«²ÎµÄº¯ÊýÃûËùÖ¸º¯ÊýÊÇ·ñÒÑÔÚº¯Êý¶ÔÏóÁбíÖУ¬ÊÇ·µ»Ø¸ÃfuncObj£¬²»ÔÚ·µ»ØNone  
 | 
    def FindFuncObj(self, funcName, className=""):  
 | 
          
 | 
        for funcObj in self.funcObjList:  
 | 
            if funcName == funcObj.funcName:  
 | 
                if className and funcObj.className != className:  
 | 
                    continue  
 | 
                # ÕÒµ½£¬²¢·µ»Ø  
 | 
                return funcObj  
 | 
          
 | 
        # Î´ÕÒµ½£¬·µ»ØNone  
 | 
        return None           
 | 
      
 | 
      
 | 
    ## ¸üк¯Êý״̬  
 | 
    #  @param funcName:º¯ÊýÃû  
 | 
    #  @param rowInfo:ÐÐÐÅÏ¢  
 | 
    #  @return ·µ»ØÖµ  
 | 
    #  @remarks º¯ÊýÏêϸ˵Ã÷£º  
 | 
    def UpdateFuncState(self, funcName, rowIndex, returnValue):  
 | 
#        print 'funcName:%s rowIndex:%s returnValue%s'%(funcName, rowIndex, returnValue)  
 | 
          
 | 
        tempFuncObj = self.FindFuncObj(funcName)  
 | 
        if tempFuncObj:  
 | 
            if tempFuncObj.UpdateRowState(rowIndex, returnValue):  
 | 
                self.pyExecCount += 1  
 | 
#        else:  
 | 
#            LogEx(0, 'py:%s has no FuncObj:%s'%(self.pyName,funcName))  
 | 
                              
 | 
                      
 | 
    ## »ñµÃPyÃû  
 | 
    #  @param ²ÎÊý  
 | 
    #  @return PyÃû  
 | 
    #  @remarks »ñµÃPyÃû  
 | 
    def GetName(self):  
 | 
          
 | 
        return  self.pyName  
 | 
      
 | 
      
 | 
    ## ÊÇ·ñ×·×ÙÖÐ  
 | 
    #  @param ²ÎÊý  
 | 
    #  @return ÊÇ·ñ×·×ÙÖÐ  
 | 
    #  @remarks º¯ÊýÏêϸ˵Ã÷£º»ñµÃ×·×ÙÇé¿ö  
 | 
    def IsTracking(self):  
 | 
          
 | 
        return self.isTracking  
 | 
      
 | 
          
 | 
    ## ÉèÖÃ×·×Ù  
 | 
    #  @param isTracking:zÊÇ·ñ×·×ÙÖÐ  
 | 
    #  @return ·µ»ØÖµ  
 | 
    #  @remarks º¯ÊýÏêϸ˵Ã÷£ºÉèÖÃ×·×Ù  
 | 
    def SetTrack(self, isTracking):  
 | 
          
 | 
        self.isTracking = isTracking    
 | 
      
 | 
          
 | 
    ## ÉèÖú¯Êý×·×Ù  
 | 
    #  @param isTracking:zÊÇ·ñ×·×ÙÖÐ  
 | 
    #  @return ·µ»ØÖµ  
 | 
    #  @remarks º¯ÊýÏêϸ˵Ã÷£ºÉèÖÃ×·×Ù  
 | 
    def SetAllFuncTrack(self, isTracking):  
 | 
          
 | 
        for funcObj in self.GetFuncObjList():  
 | 
              
 | 
            funcObj.SetTrack(isTracking)  
 | 
              
 | 
          
 | 
    ## »ñÈ¡PyÐÅÏ¢  
 | 
    #  @param ²ÎÊý  
 | 
    #  @return PyÐÅÏ¢  
 | 
    #  @remarks º¯ÊýÏêϸ˵Ã÷£º±¾PyµÄÐÅÏ¢  
 | 
    def GetPyInfo(self):  
 | 
          
 | 
        return (self.pyName,           # pyÃû  
 | 
                self.funcObjList,      # º¯Êý¶ÔÏóÁÐ±í  
 | 
                self.contentList,      # pyÄÚÈÝÁÐ±í  
 | 
                self.pyExecCount,      # pyÒÑÖ´ÐÐÐÐÊý  
 | 
                self.pyTotalCount,     # py×ÜÓÐЧÐÐÊý  
 | 
                self.isPyFileExist,    # Ãû×Ö¶ÔÓ¦µÄpyÎļþÊÇ·ñ´æÔÚ  
 | 
                self.isTracking,       # ÊÇ·ñÊÇ×·×ÙÖÐ  
 | 
                )  
 | 
             
 | 
              
 | 
    ## »ñµÃº¯ÊýÃûÁÐ±í  
 | 
    #  @param ²ÎÊý  
 | 
    #  @return º¯ÊýÃûÁÐ±í  
 | 
    #  @remarks º¯ÊýÏêϸ˵Ã÷£º»ñµÃËùÓк¯ÊýµÄº¯ÊýÃûÁÐ±í  
 | 
    def GetFuncNameList(self):  
 | 
          
 | 
        funcNameList = []  
 | 
        for funcObj in self.funcObjList:  
 | 
            funcNameList.append(funcObj.funcName)  
 | 
              
 | 
        return funcNameList  
 | 
      
 | 
      
 | 
    ## »ñµÃº¯Êý¶ÔÏóÁÐ±í  
 | 
    #  @param ²ÎÊý  
 | 
    #  @return º¯Êý¶ÔÏóÁÐ±í  
 | 
    #  @remarks º¯ÊýÏêϸ˵Ã÷£º»ñµÃËùÓк¯ÊýµÄº¯Êý¶ÔÏóÁÐ±í  
 | 
    def GetFuncObjList(self):  
 | 
              
 | 
        return self.funcObjList  
 | 
      
 | 
      
 | 
    ## ÉèÖÃPyÐÅÏ¢  
 | 
    #  @param pyName: pyÃû  
 | 
    #  @param pyExecCount: pyÒÑÖ´ÐÐÐÐÊý  
 | 
    #  @param pyTotalCount: py×ÜÓÐЧÐÐÊý  
 | 
    #  @param funcObjList: º¯Êý¶ÔÏóÁÐ±í  
 | 
    #  @param contentList: pyÄÚÈÝÁÐ±í  
 | 
    #  @param MD5: PyÎļþMD5  
 | 
    #  @param isPyFileExist: Ãû×Ö¶ÔÓ¦µÄpyÎļþÊÇ·ñ´æÔÚ  
 | 
    #  @param isTracking: ÊÇ·ñÊÇ×·×ÙÖÐ  
 | 
    #  @return ·µ»ØÖµ  
 | 
    #  @remarks º¯ÊýÏêϸ˵Ã÷£ºÉèÖÃPyµÄÐÅÏ¢  
 | 
    def SetPyInfo(self, pyName, pyExecCount, pyTotalCount, funcObjList, contentList, \  
 | 
                  MD5, isPyFileExist=True, isTracking=False):  
 | 
          
 | 
        self.pyName = pyName                 # pyÃû  
 | 
        self.funcObjList = funcObjList       # º¯Êý¶ÔÏóÁÐ±í  
 | 
        self.contentList = contentList       # pyÄÚÈÝÁÐ±í  
 | 
        self.pyExecCount = pyExecCount       # pyÒÑÖ´ÐÐÐÐÊý  
 | 
        self.pyTotalCount = pyTotalCount     # py×ÜÓÐЧÐÐÊý  
 | 
        self.MD5 = MD5                       # PyÎļþMD5  
 | 
        self.pyFileExist = isPyFileExist     # Ãû×Ö¶ÔÓ¦µÄpyÎļþÊÇ·ñ´æÔÚ  
 | 
        self.isTracking = isTracking         # ÊÇ·ñÊÇ×·×ÙÖÐ  
 | 
          
 | 
          
 | 
    ## ¼ÆËãPy¿ÉÖ´ÐÐÐÐÊý£¬ºÍ×ÜÐÐÊý  
 | 
    #  @param ²ÎÊý  
 | 
    #  @return ·µ»ØÖµ  
 | 
    #  @remarks º¯ÊýÏêϸ˵Ã÷£º¼ÆËãPy¿ÉÖ´ÐÐÐÐÊý£¬ºÍ×ÜÐÐÊý  
 | 
    def CalcFuncExecCount(self):  
 | 
          
 | 
        self.pyExecCount = 0                 # pyÒÑÖ´ÐÐÐÐÊý  
 | 
        self.pyTotalCount = 0                # py×ÜÓÐЧÐÐÊý  
 | 
          
 | 
        for funcObj in self.funcObjList:  
 | 
              
 | 
            funcExecCount, funcTotalCount = funcObj.CalcRowExecCount()  
 | 
            self.pyExecCount += funcExecCount   
 | 
            self.pyTotalCount += funcTotalCount   
 | 
              
 | 
        return (self.pyExecCount, self.pyTotalCount)  
 | 
              
 | 
              
 | 
    ## »ñµÃPyÖ´ÐÐÂÊ  
 | 
    #  @param ²ÎÊý  
 | 
    #  @return ·µ»ØÖµ  
 | 
    #  @remarks º¯ÊýÏêϸ˵Ã÷£º»ñµÃPyÖ´ÐÐÂÊ  
 | 
    def GetExecPercent(self):  
 | 
          
 | 
        if self.pyTotalCount == 0:  
 | 
            return 0.0  
 | 
        return  float(self.pyExecCount)/self.pyTotalCount*100  
 | 
              
 | 
              
 | 
    ## »ñµÃPyÖ´ÐÐÐÐÊýÇé¿ö  
 | 
    #  @param ²ÎÊý  
 | 
    #  @return ·µ»ØÖµ (ÒÑÖ´ÐÐÐÐÊý£¬×ÜÐÐÊý)  
 | 
    #  @remarks º¯ÊýÏêϸ˵Ã÷£º»ñµÃPyÖ´ÐÐÐÐÊýÇé¿ö  
 | 
    def GetExecRowCount(self):  
 | 
           
 | 
        return (self.pyExecCount, self.pyTotalCount)  
 | 
      
 | 
          
 | 
    ## PyÖÐÐÂÔöº¯Êý¶ÔÏó  
 | 
    #  @param funcObj: º¯Êý¶ÔÏó  
 | 
    #  @param contentlist: Py´úÂë  
 | 
    #  @return ·µ»ØÖµ  
 | 
    #  @remarks º¯ÊýÏêϸ˵Ã÷£ºPyÖÐÐÂÔöº¯Êý¶ÔÏó  
 | 
    def AddFuncObj(self, funcObj):  
 | 
          
 | 
        if funcObj.funcName in self.GetFuncNameList():  
 | 
            tempObj = self.FindFuncObj(funcObj.funcName, funcObj.className)  
 | 
              
 | 
            # MD5²»Í¬£¬²»ºÏ²¢  
 | 
            if funcObj.GetMD5() != tempObj.GetMD5():  
 | 
                LogEx(1, '%s -> %s:MD5 Differ'%(self.pyName, funcObj.funcName))  
 | 
#                print '%s -> %s:MD5 Differ'%(self.pyName, funcObj.funcName)  
 | 
#                funcObj.MD5 = tempObj.GetMD5()  
 | 
                return  
 | 
              
 | 
            # Èç¹ûÓÐÏÈÇå³ý£¬ÔÙÌí¼Ó  
 | 
            self.pyExecCount -= tempObj.execRowCount  
 | 
            self.pyTotalCount -= tempObj.totalRowCount  
 | 
              
 | 
            # ¼Ç¼º¯ÊýÍ·ÐкŠ 
 | 
            funcStartIndex = tempObj.startIndex  
 | 
            funcEndIndex = tempObj.endIndex  
 | 
            isTracking = tempObj.isTracking  
 | 
              
 | 
            self.funcObjList.remove(tempObj)  
 | 
              
 | 
        else:  
 | 
            funcStartIndex = funcObj.startIndex  
 | 
            funcEndIndex = funcObj.endIndex  
 | 
            isTracking = False  
 | 
          
 | 
        # º¯ÊýÍ·ÐкŲ»Í¬Ê±£¬ÒªÖØÐ¼ÆËãеĺ¯Êý¶ÔÏóµÄÿÐеÄÐкŠ 
 | 
        if funcStartIndex != funcObj.startIndex:  
 | 
            funcObj.startIndex  
 | 
            # ÐкÅÏà¶ÔÆ«ÒÆ  
 | 
            offSet = funcObj.startIndex - funcStartIndex  
 | 
            # ¼ÆËãÐкţ¬²¢Ìæ»»ÐÐ×Öµä  
 | 
            tempRowObjDict = {}  
 | 
            for rowObj in funcObj.rowObjDict.values():  
 | 
                rowInfoList = rowObj.GetRowInfo()  
 | 
                lineIndex = rowInfoList[0] - offSet  
 | 
                tempRowObjDict[lineIndex] = RowObj(lineIndex, rowInfoList[1], rowInfoList[2], rowInfoList[3])  
 | 
                  
 | 
            funcObj.rowObjDict = tempRowObjDict  
 | 
          
 | 
        funcObj.isTracking = isTracking  
 | 
        funcObj.startIndex = funcStartIndex  
 | 
        funcObj.endIndex = funcEndIndex  
 | 
          
 | 
        # ¼ÓÈëPy¶ÔÏó  
 | 
        self.funcObjList.append(funcObj)   
 | 
        self.pyExecCount += funcObj.execRowCount  
 | 
        self.pyTotalCount += funcObj.totalRowCount  
 | 
              
 | 
        # ÖØÐÂÅÅÐò  
 | 
        self.funcObjList.sort(FuncObjCmp)  
 | 
          
 | 
          
 | 
    ##ºÏ²¢Py¶ÔÏó  
 | 
    #  @param pyObj: Py¶ÔÏó  
 | 
    #  @return ·µ»ØÖµ  
 | 
    #  @remarks º¯ÊýÏêϸ˵Ã÷£ººÏ²¢Py¶ÔÏó  
 | 
    def AddPyObj(self, pyObj):  
 | 
          
 | 
        for funcObj in pyObj.funcObjList:  
 | 
            tempFuncObj = self.FindFuncObj(funcObj.funcName, funcObj.className)  
 | 
            if not tempFuncObj:  
 | 
                continue  
 | 
            # ¸²¸ÇÂʸßÓÚµ±Ç°µÄ²ÅºÏ²¢  
 | 
            if funcObj.GetExecPercent() > self.FindFuncObj(funcObj.funcName, funcObj.className).GetExecPercent():  
 | 
                self.AddFuncObj(funcObj)  
 | 
          
 | 
      
 | 
    ## »ñÈ¡²âÊÔÐÅÏ¢  
 | 
    #  @param funcName: º¯ÊýÃû  
 | 
    #  @param trackMode: ×·×Ùģʽ£¬1 Îļþ¡¢2 º¯Êý  
 | 
    #  @param showMode: Êä³öģʽ£¬0 ½çÃæ¡¢1 Îļþ  
 | 
    #  @return ·µ»ØÖµ  
 | 
    #  @remarks º¯ÊýÏêϸ˵Ã÷£º·µ»Ø´ËpyµÄ±»Ö´ÐÐÇé¿ö  
 | 
    def GetTestReport(self, funcName, trackMode, outputMode):  
 | 
#        LogEx(0, "GetTestReport(funcName=%s, trackMode=%d, outputMode=%d)"%(funcName, trackMode, outputMode))  
 | 
          
 | 
        # Îļþ²»´æÔÚ¡ª¡ª²âÊÔ±¨¸æ·µ»Ø´´½¨±¨¸æÊ§°Ü  
 | 
        if not self.isPyFileExist:  
 | 
            return '¡¾%s¡¿Create Report Fail\r\n'%self.pyName  
 | 
          
 | 
        tempReport = ""  
 | 
#        self.pyExecCount = 0  
 | 
        CRLF = "\r\n"  
 | 
          
 | 
        # µ¥º¯Êý±¨¸æ  
 | 
        if funcName:  
 | 
            funcObj = self.FindFuncObj(funcName)  
 | 
#            LogEx(1, "funcObj.isTracking=%s"%funcObj.isTracking)  
 | 
            if funcObj and (funcObj.isTracking or trackMode == FILE_TRACK_MODE):  
 | 
                # Ìí¼Óÿ¸öº¯Êý·µ»ØµÄ±¨¸æ  
 | 
                funcExecCount, tempReport = funcObj.GetFuncReport(self.contentList, outputMode)  
 | 
                  
 | 
        else:  
 | 
            for funcObj in self.funcObjList:  
 | 
    #            LogEx(1, "funcName=%s, %s, %s)"%(funcObj.funcName, self.isTracking, funcObj.isTracking))  
 | 
                # º¯Êý×·×Ùģʽ  
 | 
                if trackMode == FUNC_TRACK_MODE:  
 | 
                    # Î´×·×ÙµÄpy  
 | 
                    if not self.isTracking:  
 | 
                        continue  
 | 
                    # Î´×·×ٵĺ¯Êý  
 | 
                    if not funcObj.isTracking:  
 | 
                        continue  
 | 
                                  
 | 
                # Ìí¼Óÿ¸öº¯Êý·µ»ØµÄ±¨¸æ  
 | 
                execCount, funReport = funcObj.GetFuncReport(self.contentList, outputMode)  
 | 
                tempReport += funReport  
 | 
#                self.pyExecCount += int(execCount)  
 | 
  
 | 
        # py±¨¸æ     
 | 
        if self.pyTotalCount == 0:  
 | 
            LogEx(1, 'PyTotalRowsCount Zero:%s'%self.pyName)  
 | 
            pyReport = '¡¾%s¡¿ state:[0/0]  percent:[100%%]%s'%(self.pyName, CRLF*2)  
 | 
        else:  
 | 
            pyReport = '¡¾%s¡¿ '%self.pyName  
 | 
            pyReport += 'state:[%s/%s]  '%(self.pyExecCount, self.pyTotalCount)  
 | 
            pyReport += 'percent:[%0.02f%%]  '%(self.GetExecPercent())  
 | 
            pyReport += '%s'%(CRLF*2)  
 | 
          
 | 
        # ¸½¼ÓÐÅÏ¢ºÍMD5ÑéÖ¤Âë  
 | 
        if outputMode == FILE_OUTPUT_MODE:  
 | 
            if not self.MD5:  
 | 
                self.MD5 = CalcListMD5(self.contentList, self.MD5Key)  
 | 
            tempReport += '%sPyÎļþMD5:[%s]'%(CRLF*2, self.MD5)  
 | 
            reportMD5 = CalcStringMD5(pyReport + tempReport + CRLF, self.MD5Key)  
 | 
            tempReport += '%s²âÊÔ±¨¸æMD5:[%s]%s'%(CRLF*2, reportMD5, CRLF*2)  
 | 
            tempReport += '±£´æÊ±¼ä:[%s-%s-%s %s:%s:%s]'%tuple(['%02d'%time.localtime()[i] for i in range(6)])  
 | 
          
 | 
        return pyReport + tempReport      
 | 
      
 | 
      
 | 
    ## Çå³ýPyÖ´ÐÐÐÅÏ¢  
 | 
    #  @param ²ÎÊý  
 | 
    #  @return ·µ»ØÖµ  
 | 
    #  @remarks º¯ÊýÏêϸ˵Ã÷£ºPy  
 | 
    def ClearState(self):  
 | 
            
 | 
        self.pyExecCount = 0  
 | 
        self.isTracking = False  
 | 
          
 | 
        for funcObj in self.funcObjList:  
 | 
            funcObj.ClearState()  
 | 
  
 | 
  
 | 
## º¯ÊýÀà  
 | 
#  
 | 
# ¹ÜÀíº¯ÊýÖÐÿÐеÄÖ´ÐÐÇé¿ö  
 | 
class FuncObj:  
 | 
      
 | 
    ## ¹¹Ôì  
 | 
    #  @param className: ËùÊôÀàÃû  
 | 
    #  @param funcName: º¯ÊýÃû  
 | 
    #  @param funcComment: º¯Êý×¢ÊÍ   
 | 
    #  @param rowInfoList: ËùÓÐÐÐÐÅÏ¢  
 | 
    #  @param startIndex: º¯ÊýÆðʼ  
 | 
    #  @param endIndex: º¯Êý½áÊø  
 | 
    #  @param MD5: º¯ÊýMD5  
 | 
    #  @param returnValue: ·µ»ØÖµ  
 | 
    #  @return ·µ»ØÖµ  
 | 
    #  @remarks º¯ÊýÏêϸ˵Ã÷£º  
 | 
    def __init__(self, className, funcName, funcComment, rowInfoList, startIndex, endIndex, MD5, returnValue=None):  
 | 
        self.className = className         # ËùÊôÀàÃû  
 | 
        self.funcName = funcName           # º¯ÊýÃû  
 | 
        self.funcComment = funcComment     # º¯Êý×¢ÊÍ     
 | 
        self.execRowCount = 0              # ÒÑÖ´ÐÐÐÐÊý   
 | 
        self.totalRowCount = 0             # ×ÜÐÐÊý  
 | 
        self.rowObjDict = {}               # ÐжÔÏóÁÐ±í  
 | 
        self.returnValue = returnValue     # ·µ»ØÖµ  
 | 
        self.startIndex = startIndex       # º¯ÊýÆðʼ  
 | 
        self.endIndex = endIndex           # º¯Êý½áÊø  
 | 
        self.isTracking = False            # ÊÇ·ñÊÇ×·×ÙÖÐ  
 | 
        self.MD5 = MD5     # MD5  
 | 
          
 | 
        self.CreateRowInfo(rowInfoList)    # Éú³ÉÐжÔÏó  
 | 
        self.CalcRowExecCount()            # ¼ÆËãÖ´ÐÐÐÐÊý£¬ºÍ×ÜÐÐÊý  
 | 
      
 | 
      
 | 
    ## Éú³ÉÐжÔÏó  
 | 
    #  @param rowInfo:ÐÐÐÅÏ¢  
 | 
    #  @return ·µ»ØÖµ  
 | 
    #  @remarks º¯ÊýÏêϸ˵Ã÷£º  
 | 
    def CreateRowInfo(self, rowInfo):  
 | 
          
 | 
        for i in rowInfo:  
 | 
            #´´½¨ÐжÔÏó  
 | 
            tempRowObj = RowObj(i[0], i[1], i[2], i[3])  
 | 
            #±£´æÐжÔÏó  
 | 
            self.rowObjDict[i[0]] = tempRowObj  
 | 
              
 | 
              
 | 
    ## ¼ÆË㺯Êý¿ÉÖ´ÐÐÐÐÊý£¬ºÍ×ÜÐÐÊý  
 | 
    #  @param ²ÎÊý  
 | 
    #  @return £¨Ö´ÐÐÐÐÊý£¬×ÜÐÐÊý£©  
 | 
    #  @remarks º¯ÊýÏêϸ˵Ã÷£º¼ÆË㺯Êý¿ÉÖ´ÐÐÐÐÊý£¬ºÍ×ÜÐÐÊý  
 | 
    def CalcRowExecCount(self):  
 | 
          
 | 
        self.execRowCount = 0  
 | 
        self.totalRowCount = 0  
 | 
          
 | 
        for rowObj in self.rowObjDict.values():  
 | 
            if rowObj.GetRowInfo()[2] == 1:  
 | 
                self.execRowCount += 1  
 | 
            if rowObj.GetRowInfo()[2] < 2:  
 | 
                self.totalRowCount += 1  
 | 
                  
 | 
        return (self.execRowCount, self.totalRowCount)  
 | 
      
 | 
      
 | 
    ## ¸üÐÂÐÐ״̬  
 | 
    #  @param rowIndex: ÐкŠ 
 | 
    #  @param returnValue: ·µ»ØÖµ  
 | 
    #  @return ·µ»ØÊÇ·ñ¸Ä±ä  
 | 
    #  @remarks º¯ÊýÏêϸ˵Ã÷£º  
 | 
    def UpdateRowState(self, rowIndex, returnValue):  
 | 
        self.returnValue = returnValue  
 | 
  
 | 
        if self.rowObjDict.has_key(rowIndex):  
 | 
            if self.rowObjDict[rowIndex].ChangeRowState():  
 | 
                self.execRowCount += 1  
 | 
                return True  
 | 
#        else:  
 | 
#            LogEx(0, 'Func:%s has no row:%s'%(self.funcName,rowIndex))  
 | 
          
 | 
        return False  
 | 
      
 | 
  
 | 
    ## »ñµÃº¯ÊýÃû  
 | 
    #  @param ²ÎÊý  
 | 
    #  @return º¯ÊýÃû  
 | 
    #  @remarks »ñµÃº¯ÊýÃû  
 | 
    def GetName(self):  
 | 
          
 | 
        return  self.funcName  
 | 
                                          
 | 
                      
 | 
    ## »ñµÃº¯ÊýMD5  
 | 
    #  @param ²ÎÊý  
 | 
    #  @return º¯ÊýMD5  
 | 
    #  @remarks »ñµÃº¯ÊýMD5  
 | 
    def GetMD5(self):  
 | 
          
 | 
        return  self.MD5      
 | 
             
 | 
                      
 | 
    ## »ñµÃº¯ÊýÖ´ÐÐÂÊ  
 | 
    #  @param ²ÎÊý  
 | 
    #  @return º¯ÊýÖ´ÐÐÂÊ  
 | 
    #  @remarks»ñµÃº¯ÊýÖ´ÐÐÂÊ  
 | 
    def GetExecPercent(self):  
 | 
          
 | 
        if self.totalRowCount == 0:  
 | 
            return 0.0  
 | 
        return  float(self.execRowCount)/self.totalRowCount*100  
 | 
              
 | 
          
 | 
    ## ÉèÖÃ×·×Ù  
 | 
    #  @param isTracking: ÊÇ·ñ×·×ÙÖÐ  
 | 
    #  @return ·µ»ØÖµ  
 | 
    #  @remarks º¯ÊýÏêϸ˵Ã÷£ºÉèÖÃ×·×Ù  
 | 
    def SetTrack(self, isTracking):  
 | 
          
 | 
        self.isTracking = isTracking     
 | 
      
 | 
      
 | 
    ## »ñÈ¡º¯ÊýÐÅÏ¢  
 | 
    #  @param ²ÎÊý  
 | 
    #  @return º¯ÊýÐÅÏ¢  
 | 
    #  @remarks º¯ÊýÏêϸ˵Ã÷£º±¾º¯ÊýµÄÐÅÏ¢  
 | 
    def GetFuncInfo(self):  
 | 
          
 | 
        return (self.className,        # ËùÊôÀàÃû  
 | 
                self.funcName,         # º¯ÊýÃû  
 | 
                self.funcComment,      # º¯Êý×¢ÊÍ    
 | 
                self.execRowCount,     # ÒÑÖ´ÐÐÐÐÊý  
 | 
                self.totalRowCount,    # ×ÜÐÐÊý  
 | 
                self.rowObjDict,       # ÐжÔÏó×Öµä  
 | 
                self.returnValue,      # ·µ»ØÖµ  
 | 
                self.startIndex,       # º¯ÊýÆðʼ  
 | 
                self.endIndex,         # º¯Êý½áÊø  
 | 
                self.isTracking,       # ÊÇ·ñÊÇ×·×ÙÖÐ  
 | 
                self.MD5               # º¯ÊýMD5  
 | 
                )  
 | 
          
 | 
          
 | 
    ## ÉèÖú¯ÊýÐÅÏ¢  
 | 
    #  @param className: ËùÊôÀàÃû  
 | 
    #  @param funcName: º¯ÊýÃû  
 | 
    #  @param funcComment: º¯Êý×¢ÊÍ  
 | 
    #  @param execRowCount: ÒÑÖ´ÐÐÐÐÊý  
 | 
    #  @param totalRowCount: ×ÜÐÐÊý  
 | 
    #  @param rowObjList: ÐжÔÏóÁÐ±í  
 | 
    #  @param startIndex: º¯ÊýÆðʼ  
 | 
    #  @param endIndex: º¯Êý½áÊø  
 | 
    #  @param MD5: º¯ÊýMD5  
 | 
    #  @param returnValue: ·µ»ØÖµ  
 | 
    #  @param isTracking: ÊÇ·ñÊÇ×·×ÙÖÐ  
 | 
    #  @return PyÐÅÏ¢  
 | 
    #  @remarks º¯ÊýÏêϸ˵Ã÷£ºÉèÖú¯ÊýÐÅÏ¢  
 | 
    def SetFuncInfo(self, className, funcName, funcComment, execRowCount, totalRowCount, \  
 | 
                    rowObjList, startIndex, endIndex, MD5, returnValue=None, isTracking=False):  
 | 
          
 | 
        self.className = className            # ËùÊôÀàÃû  
 | 
        self.funcName = funcName              # º¯ÊýÃû  
 | 
        self.funcComment = funcComment        # º¯Êý×¢ÊÍ     
 | 
        self.execRowCount = execRowCount      # ÒÑÖ´ÐÐÐÐÊý   
 | 
        self.totalRowCount = totalRowCount    # ×ÜÐÐÊý  
 | 
        self.rowObjList = rowObjList          # ÐжÔÏó×Öµä  
 | 
        self.returnValue = returnValue        # ·µ»ØÖµ  
 | 
        self.startIndex = startIndex          # º¯ÊýÆðʼ  
 | 
        self.endIndex = endIndex              # º¯Êý½áÊø  
 | 
        self.MD5 = MD5                        # º¯ÊýMD5  
 | 
        self.isTracking = isTracking          # ÊÇ·ñÊÇ×·×ÙÖÐ  
 | 
      
 | 
      
 | 
    ## »ñÈ¡º¯ÊýÖ´ÐÐÐÅÏ¢  
 | 
    #  @param contentList: PYÄÚÈÝ  
 | 
    #  @param showMode: Êä³öģʽ£¬0 ½çÃæ¡¢1 Îļþ  
 | 
    #  @return ·µ»ØÖµ  
 | 
    #  @remarks º¯ÊýÏêϸ˵Ã÷£º·µ»Øº¯ÊýµÄ±»Ö´ÐÐÇé¿ö  
 | 
    def GetFuncReport(self, contentList, outputMode):  
 | 
#        LogEx(0, "GetFuncReport()")  
 | 
        # º¯ÊýÖ´Ðб¨¸æ  
 | 
        funcReport = ''  
 | 
        CRLF = "\r\n"  
 | 
          
 | 
        # Èç¹ûÓк¯Êý×¢ÊÍ  
 | 
        if self.funcComment:  
 | 
            # Ìí¼Ó×¢ÊÍ  
 | 
            funcReport += self.funcComment.strip('\r\n')  
 | 
        # Ìí¼ÓMD5  
 | 
        funcReport += '    MD5:[%s]'%self.MD5 + CRLF  
 | 
              
 | 
#===============================================================================  
 | 
#        self.execRowCount = 0  # Çå¿ÕÒÑÖ´ÐÐÐÐÊý  
 | 
#        keys = self.rowObjDict.keys()  
 | 
#        keys.sort()  
 | 
#        for key in keys:  
 | 
#            state = self.rowObjDict[key].GetRowInfo()[2]  
 | 
#            #ÒÑÖ´ÐÐÐÐ  
 | 
#            if state == 1:  
 | 
#                self.execRowCount += 1  
 | 
#===============================================================================  
 | 
          
 | 
        # ---ÒÑÖ´ÐÐÐÐÊý/×ÜÐÐÊý¡¢Ö´ÐÐÂÊ¡¢ÆðÖ¹ÐÐÊý¡¢·µ»ØÖµ¡¢·µ»ØÖµÀàÐÍ---  
 | 
        if self.totalRowCount == 0:  
 | 
            LogEx(1, 'FuncRows Zero:%s'%self.funcName)  
 | 
              
 | 
            if self.className:  
 | 
                funcReport += '    [%s]:'%self.className  
 | 
                funcReport += ':<%s>  state:[0/0]  percent:[100%%]  '%(self.funcName)  
 | 
            else:  
 | 
                funcReport += '    [Func]:'  
 | 
                funcReport += ' <%s>  state:[0/0]  percent:[100%%]  '%(self.funcName)  
 | 
                  
 | 
                  
 | 
            funcReport += 'range:[%d:%d]  '%(self.startIndex, self.endIndex)  
 | 
            funcReport += 'returnValue:[%s]  '%(self.returnValue)  
 | 
            funcReport += 'type:[%s]%s'%(type(self.returnValue), CRLF)  
 | 
              
 | 
            return 0, funcReport  
 | 
          
 | 
        if self.className:  
 | 
            funcReport += '    [%s]:'%self.className + ':<%s>  '%self.funcName  
 | 
        else:  
 | 
            funcReport += '    [Func]:' + ' <%s>  '%(self.funcName)  
 | 
          
 | 
        funcReport += 'state:[%s/%s]  '%(self.execRowCount, self.totalRowCount)  
 | 
        funcReport += 'percent:[%0.02f%%]  '%(float(self.execRowCount)/self.totalRowCount*100)  
 | 
        funcReport += 'range:[%d:%d]  '%(self.startIndex, self.endIndex)  
 | 
        funcReport += 'returnValue:[%s]  '%(self.returnValue)  
 | 
        funcReport += 'type:[%s]%s'%(type(self.returnValue), CRLF)  
 | 
  
 | 
        # ¼ÆËãÐкÅλÊý  
 | 
        count = 1  
 | 
        num = len(contentList)/10  
 | 
        while num > 0:  
 | 
            num = num/10  
 | 
            count += 1  
 | 
          
 | 
        formatString = "[%0" + str(count) + "d] %s"  
 | 
          
 | 
        for i in range(self.startIndex, self.endIndex):  
 | 
            # ´úÂë  
 | 
            if self.rowObjDict.has_key(i+1):  
 | 
                state = self.rowObjDict[i + 1].GetRowInfo()[2]  
 | 
                sentance = self.rowObjDict[i + 1].GetRowInfo()[3]  
 | 
                # Ö´Ðйý  
 | 
                if state == 1:  
 | 
                    funcReport += '        ' + (formatString)%(i + 1, sentance.strip('\r\n')) + CRLF  
 | 
  
 | 
                # Î´Ö´Ðйý£¬¼Ó*  
 | 
                elif state == 0:  
 | 
                    funcReport += '*      '  
 | 
                    # Êä³öµ½Îļþ£¬¶à¼ÓÒ»¸ö¿Õ¸ñ  
 | 
                    if outputMode == FILE_OUTPUT_MODE:  
 | 
                        funcReport += ' '  
 | 
                    funcReport += (formatString)%(i + 1, sentance.strip('\r\n')) + CRLF  
 | 
                # ×¢Êͼ°ºöÂÔÏî  
 | 
                elif len(sentance.strip()) > 0:  
 | 
                    funcReport += '        ' + (formatString)%(i + 1, sentance.strip('\r\n')) + CRLF  
 | 
                      
 | 
#===============================================================================  
 | 
#            elif len(contentList[i].strip()) > 0:  
 | 
#                funcReport += '        ' + (formatString)%(i+1, contentList[i].strip('\r\n')) + CRLF  
 | 
#===============================================================================  
 | 
             
 | 
        funcReport += CRLF  
 | 
            
 | 
        return self.execRowCount,funcReport  
 | 
      
 | 
      
 | 
    ## Çå³ýº¯ÊýÖ´ÐÐÐÅÏ¢  
 | 
    #  @param ²ÎÊý  
 | 
    #  @return ·µ»ØÖµ  
 | 
    #  @remarks º¯ÊýÏêϸ˵Ã÷£ºÇå³ý±¾º¯ÊýÖ´ÐÐÇé¿ö  
 | 
    def ClearState(self):  
 | 
            
 | 
        self.execRowCount = 0  
 | 
        self.returnValue = None  
 | 
        self.isTracking = False   
 | 
          
 | 
        for rowObj in self.rowObjDict.values():  
 | 
            rowObj.ClearState()  
 | 
  
 | 
  
 | 
## ÐÐÄÚÈÝÀà  
 | 
#  
 | 
# ¹ÜÀí±¾Ðеı»Ö´ÐÐÇé¿ö  
 | 
class RowObj:  
 | 
      
 | 
    ## ¹¹Ô캯Êý  
 | 
    #  @param rowIndex: ÐкŠ 
 | 
    #  @param rowOffset: ÐкÅÏà¶ÔÓ뺯Êý¶¨ÒåλÖÃµÄÆ«ÒÆ  
 | 
    #  @param rowState: ÐÐÖ´ÐÐ״̬  
 | 
    #  @param content: ÐÐÄÚÈÝ  
 | 
    #  @return ·µ»ØÖµ  
 | 
    #  @remarks º¯ÊýÏêϸ˵Ã÷£º  
 | 
    def __init__(self, rowIndex, rowOffset, rowState, content):  
 | 
        self.index = rowIndex            # ÐкŠ 
 | 
        self.offset = rowOffset          # ÐкÅÏà¶ÔÓ뺯Êý¶¨ÒåλÖÃµÄÆ«ÒÆ  
 | 
        self.state = rowState            # Ö´ÐÐ״̬  
 | 
        self.content = content           # ÐÐÄÚÈÝ  
 | 
      
 | 
      
 | 
    ## ¸üÐÂÐÐ״̬  
 | 
    #  @param ²ÎÊý  
 | 
    #  @return ÊÇ·ñ¸Ä±ä  
 | 
    #  @remarks º¯ÊýÏêϸ˵Ã÷£º  
 | 
    def ChangeRowState(self):  
 | 
        if self.state == 0:  
 | 
            self.state = 1  
 | 
            return True  
 | 
          
 | 
        return False  
 | 
      
 | 
      
 | 
    ## »ñÈ¡ÐÐÖ´ÐÐÐÅÏ¢  
 | 
    #  @param ²ÎÊý  
 | 
    #  @return (rowIndex:ÐкÅ,rowOffset:ÐкÅÏà¶ÔÓ뺯Êý¶¨ÒåλÖÃµÄÆ«ÒÆ,rowState:ÐÐÖ´ÐÐ״̬,self.content:ÐÐÄÚÈÝ)  
 | 
    #  @remarks º¯ÊýÏêϸ˵Ã÷£º±¾ÐÐÄÚÈݵÄÖ´ÐÐÇé¿ö  
 | 
    def GetRowInfo(self):  
 | 
        return (self.index, self.offset, self.state, self.content)  
 | 
      
 | 
      
 | 
    ## Çå³ýÐÐÖ´ÐÐÐÅÏ¢  
 | 
    #  @param ²ÎÊý  
 | 
    #  @return ·µ»ØÖµ  
 | 
    #  @remarks º¯ÊýÏêϸ˵Ã÷£ºÇå³ý±¾ÐÐÖ´ÐÐÇé¿ö  
 | 
    def ClearState(self):  
 | 
        self.state = 0  
 | 
  
 | 
  
 | 
#-------------------------------------------------------------------------------  
 | 
  
 | 
## »ñµÃPyObjʵÀý  
 | 
#  @param pyName: ÎļþÃû  
 | 
#  @param MD5Key£ºMD5ÃÜÔ¿  
 | 
#  @param scriptPath: Py·¾¶  
 | 
#  @param isCreate: ÊÇ·ñ¸ù¾ÝPYÉú³ÉPyObj  
 | 
#  @return ·µ»ØPyObj  
 | 
#  @remarks º¯ÊýÏêϸ˵Ã÷£º  
 | 
def GetPyObj(pyName, MD5Key, scriptPath="", isCreate=True):  
 | 
      
 | 
    return PyObj(pyName, MD5Key, scriptPath, isCreate)  
 | 
  
 | 
  
 | 
## »ñµÃFuncObjʵÀý  
 | 
#  @param className: ËùÊôÀàÃû  
 | 
#  @param funcName: º¯ÊýÃû  
 | 
#  @param funcComment: º¯Êý×¢ÊÍ   
 | 
#  @param rowInfoList: ËùÓÐÐÐÐÅÏ¢  
 | 
#  @param startIndex: º¯ÊýÆðʼ  
 | 
#  @param endIndex: º¯Êý½áÊø  
 | 
#  @param MD5: º¯ÊýMD5  
 | 
#  @param totalRowCount: ·µ»ØÖµ  
 | 
#  @return ·µ»ØFuncObj  
 | 
#  @remarks º¯ÊýÏêϸ˵Ã÷£º  
 | 
def GetFuncObj(className, funcName, funcComment, rowInfoList, startIndex, endIndex, MD5, returnValue=None):  
 | 
      
 | 
    return FuncObj(className, funcName, funcComment, rowInfoList, startIndex, endIndex, MD5, returnValue)  
 | 
  
 |