src/eric7/DataViews/PyProfileDialog.py

branch
eric7
changeset 9221
bf71ee032bb4
parent 9209
b99e7fd55fd3
child 9413
80c06d472826
diff -r e9e7eca7efee -r bf71ee032bb4 src/eric7/DataViews/PyProfileDialog.py
--- a/src/eric7/DataViews/PyProfileDialog.py	Wed Jul 13 11:16:20 2022 +0200
+++ b/src/eric7/DataViews/PyProfileDialog.py	Wed Jul 13 14:55:47 2022 +0200
@@ -8,13 +8,17 @@
 """
 
 import os
-import pickle       # secok
+import pickle  # secok
 import time
 
 from PyQt6.QtCore import Qt
 from PyQt6.QtWidgets import (
-    QDialog, QDialogButtonBox, QMenu, QHeaderView, QTreeWidgetItem,
-    QApplication
+    QDialog,
+    QDialogButtonBox,
+    QMenu,
+    QHeaderView,
+    QTreeWidgetItem,
+    QApplication,
 )
 
 from EricWidgets import EricMessageBox
@@ -28,20 +32,21 @@
     Class implementing a custom QTreeWidgetItem to allow sorting on numeric
     values.
     """
+
     def __getNC(self, itm):
         """
         Private method to get the value to compare on for the first column.
-        
+
         @param itm item to operate on (ProfileTreeWidgetItem)
         @return comparison value for the first column (integer)
         """
         s = itm.text(0)
-        return int(s.split('/')[0])
-        
+        return int(s.split("/")[0])
+
     def __lt__(self, other):
         """
         Special method to check, if the item is less than the other one.
-        
+
         @param other reference to item to compare against
             (ProfileTreeWidgetItem)
         @return true, if this item is less than other (boolean)
@@ -52,65 +57,63 @@
         if column == 6:
             return int(self.text(column)) < int(other.text(column))
         return self.text(column) < other.text(column)
-        
+
 
 class PyProfileDialog(QDialog, Ui_PyProfileDialog):
     """
     Class implementing a dialog to display the results of a profiling run.
     """
+
     def __init__(self, parent=None):
         """
         Constructor
-        
+
         @param parent parent widget (QWidget)
         """
         super().__init__(parent)
         self.setupUi(self)
         self.setWindowFlags(Qt.WindowType.Window)
-        
-        self.buttonBox.button(
-            QDialogButtonBox.StandardButton.Close).setEnabled(False)
-        self.buttonBox.button(
-            QDialogButtonBox.StandardButton.Cancel).setDefault(True)
-        
+
+        self.buttonBox.button(QDialogButtonBox.StandardButton.Close).setEnabled(False)
+        self.buttonBox.button(QDialogButtonBox.StandardButton.Cancel).setDefault(True)
+
         self.cancelled = False
         self.exclude = True
-        self.ericpath = os.path.dirname(
-            os.path.dirname(os.path.abspath(__file__)))
+        self.ericpath = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
         self.pyLibPath = Utilities.getPythonLibPath()
-        
-        self.summaryList.headerItem().setText(
-            self.summaryList.columnCount(), "")
+
+        self.summaryList.headerItem().setText(self.summaryList.columnCount(), "")
         self.resultList.headerItem().setText(self.resultList.columnCount(), "")
-        self.resultList.header().setSortIndicator(
-            0, Qt.SortOrder.DescendingOrder)
-        
+        self.resultList.header().setSortIndicator(0, Qt.SortOrder.DescendingOrder)
+
         self.__menu = QMenu(self)
         self.filterItm = self.__menu.addAction(
-            self.tr('Exclude Python Library'),
-            self.__filter)
+            self.tr("Exclude Python Library"), self.__filter
+        )
         self.__menu.addSeparator()
-        self.__menu.addAction(
-            self.tr('Erase Profiling Info'), self.__eraseProfile)
-        self.__menu.addAction(
-            self.tr('Erase Timing Info'), self.__eraseTiming)
+        self.__menu.addAction(self.tr("Erase Profiling Info"), self.__eraseProfile)
+        self.__menu.addAction(self.tr("Erase Timing Info"), self.__eraseTiming)
         self.__menu.addSeparator()
-        self.__menu.addAction(self.tr('Erase All Infos'), self.__eraseAll)
-        self.resultList.setContextMenuPolicy(
-            Qt.ContextMenuPolicy.CustomContextMenu)
-        self.resultList.customContextMenuRequested.connect(
-            self.__showContextMenu)
-        self.summaryList.setContextMenuPolicy(
-            Qt.ContextMenuPolicy.CustomContextMenu)
-        self.summaryList.customContextMenuRequested.connect(
-            self.__showContextMenu)
-        
-    def __createResultItem(self, calls, totalTime, totalTimePerCall,
-                           cumulativeTime, cumulativeTimePerCall, file, line,
-                           functionName):
+        self.__menu.addAction(self.tr("Erase All Infos"), self.__eraseAll)
+        self.resultList.setContextMenuPolicy(Qt.ContextMenuPolicy.CustomContextMenu)
+        self.resultList.customContextMenuRequested.connect(self.__showContextMenu)
+        self.summaryList.setContextMenuPolicy(Qt.ContextMenuPolicy.CustomContextMenu)
+        self.summaryList.customContextMenuRequested.connect(self.__showContextMenu)
+
+    def __createResultItem(
+        self,
+        calls,
+        totalTime,
+        totalTimePerCall,
+        cumulativeTime,
+        cumulativeTimePerCall,
+        file,
+        line,
+        functionName,
+    ):
         """
         Private method to create an entry in the result list.
-        
+
         @param calls number of calls (integer)
         @param totalTime total time (double)
         @param totalTimePerCall total time per call (double)
@@ -120,59 +123,62 @@
         @param line linenumber (integer)
         @param functionName function name (string)
         """
-        itm = ProfileTreeWidgetItem(self.resultList, [
-            calls,
-            "{0: 8.3f}".format(totalTime),
-            totalTimePerCall,
-            "{0: 8.3f}".format(cumulativeTime),
-            cumulativeTimePerCall,
-            file,
-            str(line),
-            functionName
-        ])
+        itm = ProfileTreeWidgetItem(
+            self.resultList,
+            [
+                calls,
+                "{0: 8.3f}".format(totalTime),
+                totalTimePerCall,
+                "{0: 8.3f}".format(cumulativeTime),
+                cumulativeTimePerCall,
+                file,
+                str(line),
+                functionName,
+            ],
+        )
         for col in [0, 1, 2, 3, 4, 6]:
             itm.setTextAlignment(col, Qt.AlignmentFlag.AlignRight)
-        
+
     def __createSummaryItem(self, label, contents):
         """
         Private method to create an entry in the summary list.
-        
+
         @param label text of the first column (string)
         @param contents text of the second column (string)
         """
         itm = QTreeWidgetItem(self.summaryList, [label, contents])
         itm.setTextAlignment(1, Qt.AlignmentFlag.AlignRight)
-        
+
     def __resortResultList(self):
         """
         Private method to resort the tree.
         """
-        self.resultList.sortItems(self.resultList.sortColumn(),
-                                  self.resultList.header()
-                                  .sortIndicatorOrder())
-        
+        self.resultList.sortItems(
+            self.resultList.sortColumn(), self.resultList.header().sortIndicatorOrder()
+        )
+
     def __populateLists(self, exclude=False):
         """
         Private method used to populate the listviews.
-        
+
         @param exclude flag indicating whether files residing in the
                 Python library should be excluded
         """
         self.resultList.clear()
         self.summaryList.clear()
-        
+
         self.checkProgress.setMaximum(len(self.stats))
         QApplication.processEvents()
-        
+
         total_calls = 0
         prim_calls = 0
         total_tt = 0
-        
+
         try:
             # disable updates of the list for speed
             self.resultList.setUpdatesEnabled(False)
             self.resultList.setSortingEnabled(False)
-            
+
             # now go through all the files
             now = time.monotonic()
             for progress, (func, (cc, nc, tt, ct, _callers)) in enumerate(
@@ -180,24 +186,26 @@
             ):
                 if self.cancelled:
                     return
-                
+
                 if (
-                    not (self.ericpath and
-                         func[0].startswith(self.ericpath)) and
-                    not func[0].startswith("DebugClients") and
-                    func[0] != "profile" and
-                    not (exclude and (func[0].startswith(self.pyLibPath) or
-                                      func[0] == "")
-                         ) and
-                    (self.file is None or
-                     func[0].startswith(self.file) or
-                     func[0].startswith(self.pyLibPath))
+                    not (self.ericpath and func[0].startswith(self.ericpath))
+                    and not func[0].startswith("DebugClients")
+                    and func[0] != "profile"
+                    and not (
+                        exclude
+                        and (func[0].startswith(self.pyLibPath) or func[0] == "")
+                    )
+                    and (
+                        self.file is None
+                        or func[0].startswith(self.file)
+                        or func[0].startswith(self.pyLibPath)
+                    )
                 ):
                     # calculate the totals
                     total_calls += nc
                     prim_calls += cc
                     total_tt += tt
-                    
+
                     if nc != cc:
                         c = "{0:d}/{1:d}".format(nc, cc)
                     else:
@@ -210,9 +218,10 @@
                         cpc = "{0: 8.3f}".format(0.0)
                     else:
                         cpc = "{0: 8.3f}".format(ct / cc)
-                    self.__createResultItem(c, tt, tpc, ct, cpc, func[0],
-                                            func[1], func[2])
-                    
+                    self.__createResultItem(
+                        c, tt, tpc, ct, cpc, func[0], func[1], func[2]
+                    )
+
                 self.checkProgress.setValue(progress)
                 if time.monotonic() - now > 0.01:
                     QApplication.processEvents()
@@ -222,107 +231,98 @@
             self.resultList.setSortingEnabled(True)
             self.resultList.setUpdatesEnabled(True)
         self.__resortResultList()
-        
+
         # now do the summary stuff
-        self.__createSummaryItem(self.tr("function calls"),
-                                 str(total_calls))
+        self.__createSummaryItem(self.tr("function calls"), str(total_calls))
         if total_calls != prim_calls:
-            self.__createSummaryItem(self.tr("primitive calls"),
-                                     str(prim_calls))
-        self.__createSummaryItem(self.tr("CPU seconds"),
-                                 "{0:.3f}".format(total_tt))
-        
+            self.__createSummaryItem(self.tr("primitive calls"), str(prim_calls))
+        self.__createSummaryItem(self.tr("CPU seconds"), "{0:.3f}".format(total_tt))
+
     def start(self, pfn, fn=None):
         """
         Public slot to start the calculation of the profile data.
-        
+
         @param pfn basename of the profiling file (string)
         @param fn file to display the profiling data for (string)
         """
         self.basename = os.path.splitext(pfn)[0]
-        
+
         fname = "{0}.profile".format(self.basename)
         if not os.path.exists(fname):
             EricMessageBox.warning(
                 self,
                 self.tr("Profile Results"),
-                self.tr("""<p>There is no profiling data"""
-                        """ available for <b>{0}</b>.</p>""")
-                .format(pfn))
+                self.tr(
+                    """<p>There is no profiling data"""
+                    """ available for <b>{0}</b>.</p>"""
+                ).format(pfn),
+            )
             self.close()
             return
         try:
-            with open(fname, 'rb') as f:
-                self.stats = pickle.load(f)     # secok
+            with open(fname, "rb") as f:
+                self.stats = pickle.load(f)  # secok
         except (OSError, pickle.PickleError, EOFError):
             EricMessageBox.critical(
                 self,
                 self.tr("Loading Profiling Data"),
-                self.tr("""<p>The profiling data could not be"""
-                        """ read from file <b>{0}</b>.</p>""")
-                .format(fname))
+                self.tr(
+                    """<p>The profiling data could not be"""
+                    """ read from file <b>{0}</b>.</p>"""
+                ).format(fname),
+            )
             self.close()
             return
-        
+
         self.file = fn
         self.__populateLists()
         self.__finish()
-        
+
     def __finish(self):
         """
         Private slot called when the action finished or the user pressed the
         button.
         """
         self.cancelled = True
-        self.buttonBox.button(
-            QDialogButtonBox.StandardButton.Close).setEnabled(True)
-        self.buttonBox.button(
-            QDialogButtonBox.StandardButton.Cancel).setEnabled(False)
-        self.buttonBox.button(
-            QDialogButtonBox.StandardButton.Close).setDefault(True)
+        self.buttonBox.button(QDialogButtonBox.StandardButton.Close).setEnabled(True)
+        self.buttonBox.button(QDialogButtonBox.StandardButton.Cancel).setEnabled(False)
+        self.buttonBox.button(QDialogButtonBox.StandardButton.Close).setDefault(True)
         QApplication.processEvents()
-        self.resultList.header().resizeSections(
-            QHeaderView.ResizeMode.ResizeToContents)
+        self.resultList.header().resizeSections(QHeaderView.ResizeMode.ResizeToContents)
         self.resultList.header().setStretchLastSection(True)
         self.summaryList.header().resizeSections(
-            QHeaderView.ResizeMode.ResizeToContents)
+            QHeaderView.ResizeMode.ResizeToContents
+        )
         self.summaryList.header().setStretchLastSection(True)
-        
+
     def __unfinish(self):
         """
         Private slot called to revert the effects of the __finish slot.
         """
         self.cancelled = False
-        self.buttonBox.button(
-            QDialogButtonBox.StandardButton.Close).setEnabled(False)
-        self.buttonBox.button(
-            QDialogButtonBox.StandardButton.Cancel).setEnabled(True)
-        self.buttonBox.button(
-            QDialogButtonBox.StandardButton.Cancel).setDefault(True)
-        
+        self.buttonBox.button(QDialogButtonBox.StandardButton.Close).setEnabled(False)
+        self.buttonBox.button(QDialogButtonBox.StandardButton.Cancel).setEnabled(True)
+        self.buttonBox.button(QDialogButtonBox.StandardButton.Cancel).setDefault(True)
+
     def on_buttonBox_clicked(self, button):
         """
         Private slot called by a button of the button box clicked.
-        
+
         @param button button that was clicked (QAbstractButton)
         """
-        if button == self.buttonBox.button(
-            QDialogButtonBox.StandardButton.Close
-        ):
+        if button == self.buttonBox.button(QDialogButtonBox.StandardButton.Close):
             self.close()
-        elif button == self.buttonBox.button(
-            QDialogButtonBox.StandardButton.Cancel
-        ):
+        elif button == self.buttonBox.button(QDialogButtonBox.StandardButton.Cancel):
             self.__finish()
-        
+
     def __showContextMenu(self, coord):
         """
         Private slot to show the context menu of the listview.
-        
+
         @param coord the position of the mouse pointer (QPoint)
         """
         self.__menu.popup(self.mapToGlobal(coord))
-        
+
     def __eraseProfile(self):
         """
         Private slot to handle the Erase Profile context menu action.
@@ -330,7 +330,7 @@
         fname = "{0}.profile".format(self.basename)
         if os.path.exists(fname):
             os.remove(fname)
-        
+
     def __eraseTiming(self):
         """
         Private slot to handle the Erase Timing context menu action.
@@ -338,14 +338,14 @@
         fname = "{0}.timings".format(self.basename)
         if os.path.exists(fname):
             os.remove(fname)
-        
+
     def __eraseAll(self):
         """
         Private slot to handle the Erase All context menu action.
         """
         self.__eraseProfile()
         self.__eraseTiming()
-        
+
     def __filter(self):
         """
         Private slot to handle the Exclude/Include Python Library context menu
@@ -354,10 +354,10 @@
         self.__unfinish()
         if self.exclude:
             self.exclude = False
-            self.filterItm.setText(self.tr('Include Python Library'))
+            self.filterItm.setText(self.tr("Include Python Library"))
             self.__populateLists(True)
         else:
             self.exclude = True
-            self.filterItm.setText(self.tr('Exclude Python Library'))
+            self.filterItm.setText(self.tr("Exclude Python Library"))
             self.__populateLists(False)
         self.__finish()

eric ide

mercurial