RadonMetrics/CyclomaticComplexityDialog.py

branch
eric7
changeset 107
0843dd7239f6
parent 106
6422943b388f
child 109
47df4b69f699
equal deleted inserted replaced
106:6422943b388f 107:0843dd7239f6
72 self.radonService.complexityDone.connect(self.__processResult) 72 self.radonService.complexityDone.connect(self.__processResult)
73 self.radonService.error.connect(self.__processError) 73 self.radonService.error.connect(self.__processError)
74 self.radonService.batchFinished.connect(self.__batchFinished) 74 self.radonService.batchFinished.connect(self.__batchFinished)
75 75
76 self.__isSingle = isSingle 76 self.__isSingle = isSingle
77 self.__batch = False
77 self.cancelled = False 78 self.cancelled = False
78 79
79 self.__project = ericApp().getObject("Project") 80 self.__project = ericApp().getObject("Project")
80 self.__locale = QLocale() 81 self.__locale = QLocale()
81 self.__finished = True 82 self.__finished = True
82 self.__errorItem = None 83 self.__errorItem = None
83 84
84 self.__fileList = [] 85 self.__fileList = []
85 self.filterFrame.setVisible(False) 86 self.filterFrame.setVisible(False)
86 87
88 self.summaryHeader.setText(self.tr("<b>Summary:</b>"))
89 self.explanationHeader.setText(self.tr("<b>Ranking:</b>"))
87 self.explanationLabel.setText( 90 self.explanationLabel.setText(
88 self.tr( 91 self.tr(
89 "<table>" 92 "<table>"
90 "<tr><td colspan=3><b>Ranking:</b></td></tr>"
91 "<tr><td><b>A</b></td><td>1 - 5</td>" 93 "<tr><td><b>A</b></td><td>1 - 5</td>"
92 "<td>(low risk - simple block)</td></tr>" 94 "<td>(low risk - simple block)</td></tr>"
93 "<tr><td><b>B</b></td><td>6 - 10</td>" 95 "<tr><td><b>B</b></td><td>6 - 10</td>"
94 "<td>(low risk - well structured and stable block)</td></tr>" 96 "<td>(low risk - well structured and stable block)</td></tr>"
95 "<tr><td><b>C</b></td><td>11 - 20</td>" 97 "<tr><td><b>C</b></td><td>11 - 20</td>"
101 "<tr><td><b>F</b></td><td>&gt; 40</td>" 103 "<tr><td><b>F</b></td><td>&gt; 40</td>"
102 "<td>(very high risk - error-prone, unstable block)</td></tr>" 104 "<td>(very high risk - error-prone, unstable block)</td></tr>"
103 "</table>" 105 "</table>"
104 ) 106 )
105 ) 107 )
108 self.typeHeader.setText(self.tr("<b>Type:</b>"))
106 self.typeLabel.setText( 109 self.typeLabel.setText(
107 self.tr( 110 self.tr(
108 "<table>" 111 "<table>"
109 "<tr><td colspan=2><b>Type:</b></td></tr>"
110 "<tr><td><b>C</b></td><td>Class</td></tr>" 112 "<tr><td><b>C</b></td><td>Class</td></tr>"
111 "<tr><td><b>F</b></td><td>Function</td></tr>" 113 "<tr><td><b>F</b></td><td>Function</td></tr>"
112 "<tr><td><b>M</b></td><td>Method</td></tr>" 114 "<tr><td><b>M</b></td><td>Method</td></tr>"
113 "</table>" 115 "</table>"
114 ) 116 )
269 self.__minimumRank = self.__data["MinimumRank"] 271 self.__minimumRank = self.__data["MinimumRank"]
270 self.rankComboBox.setCurrentIndex( 272 self.rankComboBox.setCurrentIndex(
271 self.rankComboBox.findText(self.__minimumRank) 273 self.rankComboBox.findText(self.__minimumRank)
272 ) 274 )
273 275
274 def start(self, fn, minRank="D"): 276 def start(self, fn):
275 """ 277 """
276 Public slot to start the cyclomatic complexity determination. 278 Public slot to start the cyclomatic complexity determination.
277 279
278 @param fn file or list of files or directory to show 280 @param fn file or list of files or directory to show
279 the cyclomatic complexity for 281 the cyclomatic complexity for
280 @type str or list of str 282 @type str or list of str
281 @param minRank minimum rank of entries to be shown
282 @type str (one character out of A - F)
283 """ 283 """
284 self.cancelled = False 284 self.cancelled = False
285 self.__errorItem = None 285 self.__errorItem = None
286 self.resultList.clear() 286 self.resultList.clear()
287 self.summaryLabel.clear() 287 self.summaryLabel.clear()
322 self.__ccCount = 0 322 self.__ccCount = 0
323 323
324 self.__minimumRank = self.rankComboBox.currentText() 324 self.__minimumRank = self.rankComboBox.currentText()
325 325
326 if len(self.files) > 0: 326 if len(self.files) > 0:
327 # disable updates of the list for speed
328 self.resultList.setUpdatesEnabled(False)
329 self.resultList.setSortingEnabled(False) 327 self.resultList.setSortingEnabled(False)
330 328
331 self.checkProgress.setMaximum(len(self.files)) 329 self.checkProgress.setMaximum(len(self.files))
332 self.checkProgress.setVisible(len(self.files) > 1) 330 self.checkProgress.setVisible(len(self.files) > 1)
333 QApplication.processEvents() 331 QApplication.processEvents()
339 self.cyclomaticComplexity() 337 self.cyclomaticComplexity()
340 else: 338 else:
341 self.__batch = True 339 self.__batch = True
342 self.cyclomaticComplexityBatch() 340 self.cyclomaticComplexityBatch()
343 341
344 def cyclomaticComplexity(self, codestring=""): 342 def cyclomaticComplexity(self):
345 """ 343 """
346 Public method to start a cyclomatic complexity calculation for one 344 Public method to start a cyclomatic complexity calculation for one
347 Python file. 345 Python file.
348 346
349 The results are reported to the __processResult slot. 347 The results are reported to the __processResult slot.
350
351 @param codestring optional sourcestring
352 @type str
353 """ 348 """
354 if not self.files: 349 if not self.files:
355 self.checkProgress.setMaximum(1) 350 self.checkProgress.setMaximum(1)
356 self.checkProgress.setValue(1) 351 self.checkProgress.setValue(1)
357 self.__finish() 352 self.__finish()
358 return 353 return
359 354
360 self.filename = self.files.pop(0) 355 self.filename = self.files.pop(0)
361 self.checkProgress.setValue(self.progress) 356 self.checkProgress.setValue(self.progress)
362 QApplication.processEvents()
363 357
364 if self.cancelled: 358 if self.cancelled:
365 return 359 return
366 360
367 try: 361 try:
386 self.__lastFileItem = None 380 self.__lastFileItem = None
387 381
388 argumentsList = [] 382 argumentsList = []
389 for progress, filename in enumerate(self.files, start=1): 383 for progress, filename in enumerate(self.files, start=1):
390 self.checkProgress.setValue(progress) 384 self.checkProgress.setValue(progress)
391 QApplication.processEvents()
392 385
393 try: 386 try:
394 source = Utilities.readEncodedFile(filename)[0] 387 source = Utilities.readEncodedFile(filename)[0]
395 source = Utilities.normalizeCode(source) 388 source = Utilities.normalizeCode(source)
396 except (UnicodeError, OSError) as msg: 389 except (UnicodeError, OSError) as msg:
399 392
400 argumentsList.append((filename, source)) 393 argumentsList.append((filename, source))
401 394
402 # reset the progress bar to the checked files 395 # reset the progress bar to the checked files
403 self.checkProgress.setValue(self.progress) 396 self.checkProgress.setValue(self.progress)
404 QApplication.processEvents()
405 397
406 self.__finished = False 398 self.__finished = False
407 self.radonService.cyclomaticComplexityBatch(argumentsList) 399 self.radonService.cyclomaticComplexityBatch(argumentsList)
408 400
409 def __batchFinished(self, type_): 401 def __batchFinished(self, type_):
468 self.__ccSum += result["total_cc"] 460 self.__ccSum += result["total_cc"]
469 for rank in result["summary"]: 461 for rank in result["summary"]:
470 self.__summary[rank] += result["summary"][rank] 462 self.__summary[rank] += result["summary"][rank]
471 463
472 self.progress += 1 464 self.progress += 1
473
474 self.checkProgress.setValue(self.progress) 465 self.checkProgress.setValue(self.progress)
475 QApplication.processEvents()
476 466
477 if not self.__batch: 467 if not self.__batch:
478 self.cyclomaticComplexity() 468 self.cyclomaticComplexity()
479 469
480 def __finish(self): 470 def __finish(self):
484 from radon.complexity import cc_rank 474 from radon.complexity import cc_rank
485 475
486 if not self.__finished: 476 if not self.__finished:
487 self.__finished = True 477 self.__finished = True
488 478
489 # re-enable updates of the list
490 self.resultList.setSortingEnabled(True) 479 self.resultList.setSortingEnabled(True)
491 self.resultList.sortItems(0, Qt.SortOrder.AscendingOrder) 480 self.resultList.sortItems(0, Qt.SortOrder.AscendingOrder)
492 self.resultList.sortItems(1, Qt.SortOrder.AscendingOrder) 481 self.resultList.sortItems(1, Qt.SortOrder.AscendingOrder)
493 self.resultList.setUpdatesEnabled(True)
494 482
495 self.cancelled = True 483 self.cancelled = True
496 self.buttonBox.button(QDialogButtonBox.StandardButton.Close).setEnabled( 484 self.buttonBox.button(QDialogButtonBox.StandardButton.Close).setEnabled(
497 True 485 True
498 ) 486 )
514 502
515 averageCC = float(self.__ccSum) / (self.__ccCount or 1) 503 averageCC = float(self.__ccSum) / (self.__ccCount or 1)
516 504
517 self.summaryLabel.setText( 505 self.summaryLabel.setText(
518 self.tr( 506 self.tr(
519 "<b>Summary:</b><br/>"
520 "{0} blocks (classes, functions, methods) analyzed.<br/>" 507 "{0} blocks (classes, functions, methods) analyzed.<br/>"
521 "Average complexity: {7} ({8})" 508 "Average complexity: {7} ({8})"
522 "<table>" 509 "<table>"
523 "<tr><td width=30><b>A</b></td>" 510 "<tr><td width=30><b>A</b></td>"
524 "<td align='right'>{1} blocks</td></tr>" 511 "<td align='right'>{1} blocks</td></tr>"
546 ) 533 )
547 ) 534 )
548 535
549 self.checkProgress.setVisible(False) 536 self.checkProgress.setVisible(False)
550 537
538 def __cancel(self):
539 """
540 Private method to cancel the current check run.
541 """
542 if self.__batch:
543 self.radonService.cancelComplexityBatch()
544 QTimer.singleShot(1000, self.__finish)
545 else:
546 self.__finish()
547
548 def closeEvent(self, evt):
549 """
550 Protected method to handle a close event.
551
552 @param evt reference to the close event
553 @type QCloseEvent
554 """
555 self.__cancel()
556
551 @pyqtSlot(QAbstractButton) 557 @pyqtSlot(QAbstractButton)
552 def on_buttonBox_clicked(self, button): 558 def on_buttonBox_clicked(self, button):
553 """ 559 """
554 Private slot called by a button of the button box clicked. 560 Private slot called by a button of the button box clicked.
555 561
557 @type QAbstractButton 563 @type QAbstractButton
558 """ 564 """
559 if button == self.buttonBox.button(QDialogButtonBox.StandardButton.Close): 565 if button == self.buttonBox.button(QDialogButtonBox.StandardButton.Close):
560 self.close() 566 self.close()
561 elif button == self.buttonBox.button(QDialogButtonBox.StandardButton.Cancel): 567 elif button == self.buttonBox.button(QDialogButtonBox.StandardButton.Cancel):
562 if self.__batch: 568 self.__cancel()
563 self.radonService.cancelComplexityBatch()
564 QTimer.singleShot(1000, self.__finish)
565 else:
566 self.__finish()
567 569
568 @pyqtSlot() 570 @pyqtSlot()
569 def on_startButton_clicked(self): 571 def on_startButton_clicked(self):
570 """ 572 """
571 Private slot to start a cyclomatic complexity run. 573 Private slot to start a cyclomatic complexity run.
642 lineno = item.data(0, self.LineNumberRole) 644 lineno = item.data(0, self.LineNumberRole)
643 if filename: 645 if filename:
644 vm = ericApp().getObject("ViewManager") 646 vm = ericApp().getObject("ViewManager")
645 vm.openSourceFile(filename, lineno) 647 vm.openSourceFile(filename, lineno)
646 648
647 @pyqtSlot(str) 649 @pyqtSlot(int)
648 def on_rankComboBox_activated(self, rank): 650 def on_rankComboBox_activated(self, index):
649 """ 651 """
650 Private slot to handle the selection of a minimum rank. 652 Private slot to handle the selection of a minimum rank.
651 653
652 @param rank selected minimum rank 654 @param index index of the selected minimum rank
653 @type str 655 @type str
654 """ 656 """
655 if self.__isSingle: 657 if self.__isSingle:
656 self.start(self.__fileList[:]) 658 self.start(self.__fileList[:])

eric ide

mercurial