# -*- 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)