Package empro :: Package toolkit :: Package profiler
[frames] | no frames]

Source Code for Package empro.toolkit.profiler

  1  # Copyright 1983-2016 Keysight Technologies, Inc  
2 -class ProfilerData():
3 - def __init__(self):
4 self.profileScriptName = "" 5 self.profileScriptFileName = "" 6 self.profileResults = []
7
8 -class ProfilerToolBar():
9 - def __init__(self):
10 import empro 11 self.profilerToolBar = empro.gui.ToolBar("Profiler Tools","Profile") 12 self.profileAction = empro.gui.Action("Profile") 13 self.profileAction.onTriggered = _profileCurrentFile 14 self.profileAction.icon = empro.gui.Icon(":/scripting/ScriptProfile.ico") 15 self.profilerToolBar.addAction(self.profileAction) 16 self.checkConflictingWhiteSpaceAction = empro.gui.Action("Scan Script") 17 self.checkConflictingWhiteSpaceAction.icon = empro.gui.Icon(":/xmag.ico") 18 self.checkConflictingWhiteSpaceAction.onTriggered = checkCurrentFile
19
20 - def getToolBar(self):
21 return self.profilerToolBar
22
23 -class ProfilerWidget():
24 - def __init__(self,profilerData):
25 import empro 26 self._profilerData = profilerData 27 self._profilerDialog = empro.gui.SimpleDialog(empro.gui.Close) 28 self._profilerDialog.title = self._profilerData.profileScriptName 29 self._profilerTable = empro.gui.TableView() 30 self._profilerTable.alternatingRowColors = False 31 self._profilerTable.hideVerticalHeader() 32 self._profilerTable.addStyleSheet('QHeaderView::section {background-color: rgb(36,75,130); color: rgb(255,255,255)}') 33 self._profilerTable.selectionBehavior = empro.gui.TableView.SelectRows 34 self._profilerTable.selectionMode = empro.gui.TableView.SingleSelection 35 self._profilerTable.onSelectionChanged = self.refreshProfilerTable 36 self._profilerTable.onLayoutChanged = self.onProfilerTableClicked 37 self._profilerTable.onClicked = self.onProfilerTableClicked 38 self._profilerDialog.onFinished = self.onProfilerFinished 39 self.tableRows = [] 40 for data in self._profilerData.profileResults: 41 try: 42 if not data.code.co_name == "<module>": 43 row = [data.code.co_name,data.code.co_firstlineno,data.callcount,data.totaltime,data.inlinetime] 44 self.tableRows.append(row) 45 else: 46 row = [self._profilerData.profileScriptName,None,data.callcount,data.totaltime,data.inlinetime] 47 self.tableRows.append(row) 48 except: 49 if not data.code == "<method 'disable' of '_lsprof.Profiler' objects>": 50 row = [data.code,None,data.callcount,data.totaltime,data.inlinetime] 51 self.tableRows.append(row) 52 if self.tableRows: 53 for index,row in enumerate(self.tableRows): 54 self._profilerTable.setRow(index,row) 55 if row[0] == self._profilerData.profileScriptName: 56 for i in range(len(row)): 57 self._profilerTable.setBoldFont(index,i) 58 self._profilerTable.headers = ["Name","Line No.","Call Count","Total Time (Secs.)","Self Time (Secs.)"] 59 self._profilerTable.resizeRowsToContents() 60 #self._profilerTable.resizeColumnsToContents() 61 self._callCountLabel = empro.gui.Label("<b>Call Count :</b> The Number of times this was called.") 62 self._totalTimeLabel = empro.gui.Label("<b>Total Time :</b> The total time spent in this call including all the subcalls that were made.") 63 self._selfTimeLabel = empro.gui.Label("<b>Self Time :</b> The total time spent in this call excluding all the subcalls that were made.") 64 self._saveStatsButton = empro.gui.PushButton("Save") 65 self._saveStatsButton.onClicked = self.onSaveButtonClicked 66 self._profilerDialog.layout.add(self._profilerTable) 67 self._profilerDialog.layout.add(self._callCountLabel) 68 self._profilerDialog.layout.add(self._totalTimeLabel) 69 self._profilerDialog.layout.add(self._selfTimeLabel) 70 self._profilerDialog.addButton(self._saveStatsButton,3)
71
72 - def onProfilerTableClicked(self,row=None,column=None):
73 import empro 74 selectedRow = self._profilerTable.selectedRows()[0] 75 lineNoData = self._profilerTable.data(selectedRow,1) 76 if lineNoData: 77 fileName = self._profilerData.profileScriptName 78 sw = empro.gui.activeScriptWindow() 79 sw.removeHighlightMarkFromAllEditors() 80 sw.highlightScriptLine(fileName,lineNoData) 81 sw.activateWindow() 82 else: 83 sw = empro.gui.activeScriptWindow() 84 sw.removeHighlightMarkFromAllEditors() 85 sw.activateWindow()
86
87 - def onProfilerFinished(self,result):
88 import empro 89 sw = empro.gui.activeScriptWindow() 90 sw.removeHighlightMarkFromAllEditors() 91 sw.activateWindow()
92
93 - def onSaveButtonClicked(self,ignore):
94 import empro 95 import csv 96 import os 97 sw = empro.gui.activeScriptWindow() 98 sw.removeHighlightMarkFromAllEditors() 99 sw.activateWindow() 100 self._profilerTable.selectAll(False) 101 if self.tableRows: 102 saveFileName,saveFileExtension = empro.gui.getSaveFileNameExSelectedFilter("Save Name for the Report","","*.csv",0) 103 if saveFileName: 104 outputFile = os.path.splitext(saveFileName)[0] 105 with open(outputFile+".csv","wb") as saveFile: 106 writer = csv.DictWriter(saveFile, fieldnames = ["Name","Line No.","Call Count","Total Time (Secs.)","Self Time (Secs.)"]) 107 writer.writeheader() 108 for row in self.tableRows: 109 writer.writerow({'Name':row[0],'Line No.':row[1],'Call Count':row[2],'Total Time (Secs.)':row[3],'Self Time (Secs.)':row[4]})
110
111 - def refreshProfilerTable(self):
112 w,h = self._profilerTable.size() 113 self._profilerTable.resize(w+1,h) 114 self._profilerTable.resize(w,h)
115
116 - def show(self):
117 w,h = self._profilerTable.size() 118 self._profilerDialog.resize(w,h) 119 self._profilerDialog.show(False)
120
121 -class ErrorMessage():
122 - def __init__(self,excInfo):
123 import empro 124 self.dialog = empro.gui.SimpleDialog(empro.gui.Ok) 125 self.dialog.resize(800,100) 126 self.dialog.maximumWidth = 800 127 self.dialog.minimumWidth = 800 128 self.dialog.maximumHeight= 400 129 self.dialog.title = "Error" 130 w = empro.gui.Widget() 131 w.layout = empro.gui.HBoxLayout() 132 w.layout.contentsMargin =[0,0,0,0] 133 w.layout.spacing = 0 134 typeBox = self. _typeBox(excInfo) 135 descriptionBox = self._descriptionBox(excInfo) 136 foundBox = self._foundBox(excInfo) 137 w.layout.addLayout(typeBox) 138 w.layout.addLayout(descriptionBox) 139 if foundBox: 140 w.layout.addLayout(foundBox) 141 self.dialog.layout.add(w)
142
143 - def _typeBox(self,excInfo):
144 import empro 145 typeLayout = empro.gui.VBoxLayout() 146 typeLayout.contentsMargin =[0,0,0,0] 147 self.typeLabel = empro.gui.Label("Type") 148 self.typeLabel.frameStyle = empro.gui.Frame.StyledPanel 149 self.typeLabel.addStyleSheet('QLabel {background-color: rgb(36,75,130); color: rgb(255,255,255)}') 150 type = str(excInfo[0]).split("'")[1].split('.')[1] 151 self.typeColumn = empro.gui.TextEdit(type) 152 self.typeColumn.text = type 153 self.typeColumn.readOnly = True 154 typeLayout.addWidget(self.typeLabel) 155 typeLayout.addWidget(self.typeColumn) 156 return typeLayout
157
158 - def _descriptionBox(self,excInfo):
159 import empro 160 descriptionLayout = empro.gui.VBoxLayout() 161 descriptionLayout.contentsMargin =[0,0,0,0] 162 self.descriptionLabel= empro.gui.Label("Description") 163 self.descriptionLabel.frameStyle = empro.gui.Frame.StyledPanel 164 self.descriptionLabel.addStyleSheet('QLabel {background-color: rgb(36,75,130); color: rgb(255,255,255)}') 165 description = str(excInfo[1]) 166 self.descriptionColumn = empro.gui.TextEdit(description) 167 self.descriptionColumn.readOnly = True 168 descriptionLayout.addWidget(self.descriptionLabel) 169 descriptionLayout.addWidget(self.descriptionColumn) 170 return descriptionLayout
171
172 - def _foundBox(self,excInfo):
173 import os 174 import traceback 175 import empro 176 foundLayout = empro.gui.VBoxLayout() 177 foundLayout.contentsMargin =[0,0,0,0] 178 self.foundLabel = empro.gui.Label("Found at") 179 self.foundLabel.frameStyle = empro.gui.Frame.StyledPanel 180 self.foundLabel.addStyleSheet('QLabel {background-color: rgb(36,75,130); color: rgb(255,255,255)}') 181 self.foundColumn = empro.gui.TableView() 182 self.foundColumn.alternatingRowColors = False 183 self.foundColumn.hideVerticalHeader() 184 self.foundColumn.hideHorizontalHeader() 185 self.foundColumn.selectionMode = empro.gui.TableView.NoSelection 186 tb = excInfo[2] 187 errorLines = traceback.format_tb(tb) 188 errorLines = errorLines[3:] 189 errorLines = errorLines[::-1] 190 lineInfo = [] 191 for line in errorLines: 192 errorLineFileName = line.split('"',2)[1] 193 errorLineFileName = os.path.basename(errorLineFileName) 194 errorLineNo = line.split('"',2)[-1].split(",")[1].strip() 195 sw = empro.gui.activeScriptWindow() 196 lineNo = errorLineNo.split(" ")[1] 197 sw.showErrorMark(errorLineFileName,int(lineNo),True) 198 sw.activateWindow() 199 info ="%s in %s "%(errorLineNo, errorLineFileName) 200 lineInfo.append(info) 201 self.foundColumn.setColumn(0,lineInfo) 202 self.foundColumn.resizeRowsToContents() 203 self.foundColumn.resizeColumnsToContents() 204 self.refreshListWidget(self.foundColumn) 205 self.foundColumn.onClicked = self.foundColumnClicked 206 foundLayout.addWidget(self.foundLabel) 207 foundLayout.addWidget(self.foundColumn) 208 return foundLayout
209
210 - def refreshListWidget(self,listWidget):
211 w,h = listWidget.size() 212 listWidget.resize(w+1,h) 213 listWidget.resize(w,h)
214
215 - def foundColumnClicked(self,row,column):
216 import empro 217 data = self.foundColumn.data(row,column) 218 if data: 219 data = data.split(" ",3) 220 lineno = int(data[1]) 221 fileName = data[-1] 222 fileName = fileName.strip() 223 sw = empro.gui.activeScriptWindow() 224 sw.removeHighlightMarkFromAllEditors() 225 sw.highlightScriptLine(fileName,lineno) 226 sw.activateWindow()
227
228 - def show(self):
229 self.dialog.show(True)
230
231 -class GetChoice ():
232 - def __init__(self,funcName,listOfDict):
233 import os 234 import empro 235 self.choice = None 236 self.data = listOfDict 237 self.dialog = empro.gui.SimpleDialog(empro.gui.Ok) 238 self.dialog.title = funcName 239 self.dialog.resize(400, 200) 240 self.dialog.maximumWidth = 400 241 subjectText = "More than one instance of the <strong> %s</strong> function definition has be found in the loaded scripts.<br> Please select the script which has the required function definition."%(funcName) 242 fields = [os.path.basename(x['_fileName']) for x in self.data] 243 self.subject = empro.gui.Label(subjectText) 244 self.listWidget = empro.gui.TableView() 245 self.listWidget.alternatingRowColors = False 246 self.listWidget.hideHorizontalHeader() 247 self.listWidget.hideVerticalHeader() 248 self.listWidget.selectionMode = empro.gui.TableView.SingleSelection 249 self.listWidget.setColumn(0,fields) 250 self.listWidget.resizeColumnsToContents() 251 self.listWidget.resizeRowsToContents() 252 self.refreshListWidget() 253 self.listWidget.onClicked = self.listWidgetClicked 254 listBox = empro.gui.HBoxLayout() 255 listBox.addWidget(self.listWidget) 256 listBox.addStretch(1) 257 w = empro.gui.Widget() 258 w.layout = empro.gui.VBoxLayout() 259 w.layout.contentsMargin = [0,0,0,0] 260 w.layout.addWidget(self.subject) 261 w.layout.addStretch(1) 262 w.layout.addLayout(listBox) 263 self.dialog.layout.add(w) 264 self.dialog.onClicked = self.onClicked 265 self.dialog.show(True)
266
267 - def refreshListWidget(self):
268 w, h = self.listWidget.size() 269 self.listWidget.resize(w + 1, h) 270 self.listWidget.resize(w, h)
271
272 - def listWidgetClicked(self,iRow,iColumn):
273 import os 274 import empro 275 data = self.data[iRow] 276 fileName = os.path.basename(data['_fileName']) 277 sw = empro.gui.activeScriptWindow() 278 sw.removeHighlightMarkFromAllEditors() 279 sw.activateWindow() 280 for n in range(data['_firstLineNo'],data['_lastLineNo']+1): 281 sw.highlightScriptLine(fileName,n) 282 sw.activateWindow()
283
284 - def onClicked(self,iButton):
285 if (iButton.text == "OK"): 286 import empro 287 sw = empro.gui.activeScriptWindow() 288 sw.removeHighlightMarkFromAllEditors() 289 sw.activateWindow() 290 selectedRow = self.listWidget.selectedRows() 291 if selectedRow : 292 self.choice = selectedRow[0]
293
294 - def getValue (self):
295 return self.choice
296
297 -class Profiler():
298 - def __init__(self,profileData):
299 import empro 300 import cProfile 301 self._profileData= profileData 302 self._profileToolBar = ProfilerToolBar() 303 self._profiler = cProfile.Profile()
304
305 - def _addProfileMenuBar(self):
306 import empro 307 sw = empro.gui.activeScriptWindow() 308 sw._addProfilerAction(self._profileToolBar.profileAction) 309 sw._addCheckWhiteSpaceAction(self._profileToolBar.checkConflictingWhiteSpaceAction)
310 311
312 - def _addProfileToolBar(self):
313 import empro 314 profileToolBar = self._profileToolBar.getToolBar() 315 sw = empro.gui.activeScriptWindow() 316 sw.addToolBar(8,profileToolBar)
317
318 - def _profileScript(self,scriptName,scriptFileName):
319 import empro 320 import os 321 import sys 322 import ast 323 324 globals_ = {"__name__": "__main__", "__file__": scriptFileName} 325 locals_ = globals_ 326 emproCodeObj = compile("import empro","<string>","single") 327 self._profiler.runctx(emproCodeObj, globals_, locals_) 328 try_again = True 329 while try_again: 330 try: 331 try_again = False 332 sw = empro.gui.activeScriptWindow() 333 scriptListObj = empro.activeProject.scriptList() 334 sw.makeTab(scriptListObj.at(scriptName),True) 335 sw.activateWindow() 336 cmd = sw.scriptContent(scriptName) 337 scriptCodeObj = compile(cmd,scriptFileName,"exec") 338 self._profiler.clear() 339 self._profiler.runctx(scriptCodeObj, globals_, locals_) 340 except NameError as e: 341 actualErrorInfo = sys.exc_info() 342 try_again = True 343 try: 344 tempVar = str(e).split("'")[1] 345 except: 346 try_again = False 347 errorWindow = ErrorMessage(actualErrorInfo) 348 errorWindow.show() 349 break 350 sw = empro.gui.activeScriptWindow() 351 scriptNames = list(sw.loadedScripts()) 352 scriptNametoStoredNameDict = _generateScriptNametoStoredNameDict() 353 data ={} 354 for sName in scriptNames: 355 text = sw.scriptContent(sName) 356 try: 357 tree = ast.parse(text,scriptNametoStoredNameDict[sName],'exec') 358 except: 359 continue 360 for func in tree.body: 361 if isinstance(func,ast.FunctionDef): 362 lastBody = func.body[-1] 363 while isinstance(lastBody,(ast.For,ast.While,ast.If)) : 364 lastBody = lastBody.body[-1] 365 lastLine = lastBody.lineno 366 data.setdefault(func.name,[]).append({'_func':func,'_fileName':sName,'_firstLineNo':func.lineno,'_lastLineNo':lastLine}) 367 if tempVar in data.keys(): 368 i = 0 369 if len (data[tempVar]) > 1: 370 i = GetChoice(tempVar,data[tempVar]).getValue() 371 if i == None: 372 quitProfiler = empro.gui.MessageBox.question("Exit Profiler","No File Selected.\nDo you want to stop Profiling?", 16384 + 65536, 16384) == 16384 373 if quitProfiler: 374 print "Profiler Stopped" 375 try_again = False 376 break 377 else: 378 continue 379 wrapped = ast.Interactive(body = [data[tempVar][i]['_func']]) 380 wrapped = ast.fix_missing_locations(wrapped) 381 codeObj = compile(wrapped,data[tempVar][i]['_fileName'],'single') 382 self._profiler.runctx(codeObj, globals_, locals_) 383 else: 384 try_again = False 385 errorWindow = ErrorMessage(actualErrorInfo) 386 errorWindow.show() 387 except: 388 try_again = False 389 errorWindow = ErrorMessage(sys.exc_info()) 390 errorWindow.show() 391 finally: 392 if not try_again: 393 results = self._profiler.getstats() 394 self._profileData.profileScriptName = scriptName 395 self._profileData.profileScriptFileName = scriptFileName 396 self._profileData.profileResults = results 397 self._profilerWidget = ProfilerWidget(self._profileData) 398 self._profilerWidget.show()
399
400 -def checkCurrentFile(ignore):
401 import empro 402 sw = empro.gui.activeScriptWindow() 403 sw.saveAllTabs() 404 scriptName = sw.currentScript() 405 if not scriptName: 406 return 407 scriptCode = sw.scriptContent(scriptName) 408 status = _conflictingWhiteSpace(scriptCode) 409 if not status: 410 status = "There are no conflicting white spaces." 411 print status
412
413 -def _conflictingWhiteSpace(code):
414 import tabnanny 415 import tokenize 416 import StringIO 417 418 try: 419 tabnanny.process_tokens(tokenize.generate_tokens(StringIO.StringIO(code).readline)) 420 except tokenize.TokenError, tokenError: 421 errorMsg = map(str,tokenError) 422 return " ".join(errorMsg) 423 except tabnanny.NannyNag, nannyNag: 424 msg = "Tabs and spaces mixed at line number %s, in the line '%s'." %(nannyNag.get_lineno(),nannyNag.get_line().strip()) 425 return msg 426 except IndentationError, indentError: 427 errorArgs = indentError.args 428 msg = errorArgs[0], "at line number %s, in the line '%s'."%(indentError.lineno,indentError.text.strip()) 429 return " ".join(msg) 430 except: 431 import sys 432 error = sys.exc_info()[1] 433 return error
434
435 -def _updateProfileToolTip (editorName = None):
436 import empro 437 sw = empro.gui.activeScriptWindow() 438 scriptName = sw.currentScript() 439 if scriptName: 440 empro.internal.presentProfiler._profileToolBar.profileAction.text = "Profile '%s'"%(scriptName) 441 else: 442 empro.internal.presentProfiler._profileToolBar.profileAction.text = "Profile"
443
444 -def _generateScriptNametoStoredNameDict():
445 import empro 446 sw = empro.gui.activeScriptWindow() 447 loadedScripts = sw.loadedScripts() 448 loadedScriptsStoredName = sw.loadedScriptsStoredName() 449 scriptNametoStoredNameDict = dict(zip(loadedScripts,loadedScriptsStoredName)) 450 return scriptNametoStoredNameDict
451
452 -def _profileCurrentFile(ignore):
453 import empro 454 sw = empro.gui.activeScriptWindow() 455 sw.removeErrorMarkFromAllEditors() 456 sw.saveAllTabs() 457 sw.activateWindow() 458 scriptNametoStoredNameDict = _generateScriptNametoStoredNameDict() 459 scriptName = sw.currentScript() 460 scriptFileName = scriptNametoStoredNameDict[scriptName] 461 empro.internal.presentProfiler._profileScript(scriptName,scriptFileName)
462
463 -def _activateProfiler():
464 import empro 465 empro.internal.presentProfiler = None 466 try: 467 empro.internal.profileToolbar.visible = False 468 del empro.internal.profileToolbar 469 except: 470 pass 471 finally: 472 profileData = ProfilerData() 473 empro.internal.presentProfiler = Profiler(profileData) 474 empro.internal.presentProfiler._addProfileToolBar() 475 empro.internal.presentProfiler._addProfileMenuBar() 476 sw = empro.gui.activeScriptWindow() 477 sw._onActiveScriptChanged = empro.toolkit.profiler._updateProfileToolTip 478 sw.activateWindow()
479