7 Module implementing the debugger UI. |
7 Module implementing the debugger UI. |
8 """ |
8 """ |
9 |
9 |
10 import os |
10 import os |
11 import copy |
11 import copy |
|
12 import contextlib |
12 |
13 |
13 from PyQt5.QtCore import pyqtSignal, pyqtSlot, QObject, Qt |
14 from PyQt5.QtCore import pyqtSignal, pyqtSlot, QObject, Qt |
14 from PyQt5.QtGui import QKeySequence |
15 from PyQt5.QtGui import QKeySequence |
15 from PyQt5.QtWidgets import QMenu, QToolBar, QApplication, QDialog |
16 from PyQt5.QtWidgets import QMenu, QToolBar, QApplication, QDialog |
16 |
17 |
68 @param vm reference to the viewmanager |
69 @param vm reference to the viewmanager |
69 @param debugServer reference to the debug server |
70 @param debugServer reference to the debug server |
70 @param debugViewer reference to the debug viewer widget |
71 @param debugViewer reference to the debug viewer widget |
71 @param project reference to the project object |
72 @param project reference to the project object |
72 """ |
73 """ |
73 super(DebugUI, self).__init__(ui) |
74 super().__init__(ui) |
74 |
75 |
75 self.ui = ui |
76 self.ui = ui |
76 self.viewmanager = vm |
77 self.viewmanager = vm |
77 self.debugServer = debugServer |
78 self.debugServer = debugServer |
78 self.debugViewer = debugViewer |
79 self.debugViewer = debugViewer |
167 |
168 |
168 # Set a flag for the passive debug mode |
169 # Set a flag for the passive debug mode |
169 self.passive = Preferences.getDebugger("PassiveDbgEnabled") |
170 self.passive = Preferences.getDebugger("PassiveDbgEnabled") |
170 |
171 |
171 def showNotification(self, notification, |
172 def showNotification(self, notification, |
172 kind=NotificationTypes.Information, timeout=None): |
173 kind=NotificationTypes.INFORMATION, timeout=None): |
173 """ |
174 """ |
174 Public method to show some notification message. |
175 Public method to show some notification message. |
175 |
176 |
176 @param notification message to be shown |
177 @param notification message to be shown |
177 @type str |
178 @type str |
835 |
836 |
836 @param fn filename of the opened editor |
837 @param fn filename of the opened editor |
837 """ |
838 """ |
838 self.editorOpen = True |
839 self.editorOpen = True |
839 |
840 |
840 if fn: |
841 editor = self.viewmanager.getOpenEditor(fn) if fn else None |
841 editor = self.viewmanager.getOpenEditor(fn) |
|
842 else: |
|
843 editor = None |
|
844 self.__checkActions(editor) |
842 self.__checkActions(editor) |
845 |
843 |
846 def __lastEditorClosed(self): |
844 def __lastEditorClosed(self): |
847 """ |
845 """ |
848 Private slot to handle the closeProgram signal. |
846 Private slot to handle the closeProgram signal. |
865 """ |
863 """ |
866 Private slot to check some actions for their enable/disable status. |
864 Private slot to check some actions for their enable/disable status. |
867 |
865 |
868 @param editor editor window |
866 @param editor editor window |
869 """ |
867 """ |
870 if editor: |
868 fn = editor.getFileName() if editor else None |
871 fn = editor.getFileName() |
|
872 else: |
|
873 fn = None |
|
874 |
869 |
875 cap = 0 |
870 cap = 0 |
876 if fn: |
871 if fn: |
877 for language in self.debugServer.getSupportedLanguages(): |
872 for language in self.debugServer.getSupportedLanguages(): |
878 exts = self.debugServer.getExtensions(language) |
873 exts = self.debugServer.getExtensions(language) |
1148 '<p><b>{0}</b> has terminated with an exit status of' |
1143 '<p><b>{0}</b> has terminated with an exit status of' |
1149 ' {1}.</p><p>{2}</p>').format( |
1144 ' {1}.</p><p>{2}</p>').format( |
1150 os.path.basename(program), status, info) |
1145 os.path.basename(program), status, info) |
1151 if status != 0: |
1146 if status != 0: |
1152 timeout = 0 |
1147 timeout = 0 |
1153 kind = NotificationTypes.Warning |
1148 kind = NotificationTypes.WARNING |
1154 else: |
1149 else: |
1155 timeout = None |
1150 timeout = None |
1156 kind = NotificationTypes.Information |
1151 kind = NotificationTypes.INFORMATION |
1157 self.ui.showNotification( |
1152 self.ui.showNotification( |
1158 UI.PixmapCache.getPixmap("debug48"), |
1153 UI.PixmapCache.getPixmap("debug48"), |
1159 self.tr("Program terminated"), msg, kind=kind, |
1154 self.tr("Program terminated"), msg, kind=kind, |
1160 timeout=timeout) |
1155 timeout=timeout) |
1161 |
1156 |
1239 ) |
1234 ) |
1240 ) or exceptionType.startswith('unhandled') |
1235 ) or exceptionType.startswith('unhandled') |
1241 ): |
1236 ): |
1242 res = None |
1237 res = None |
1243 if stackTrace: |
1238 if stackTrace: |
1244 try: |
1239 with contextlib.suppress(UnicodeError, OSError): |
1245 file, line = stackTrace[0][:2] |
1240 file, line = stackTrace[0][:2] |
1246 source, encoding = Utilities.readEncodedFile(file) |
1241 source, encoding = Utilities.readEncodedFile(file) |
1247 source = source.splitlines(True) |
1242 source = source.splitlines(True) |
1248 if len(source) >= line: |
1243 if len(source) >= line: |
1249 lineFlags = Utilities.extractLineFlags( |
1244 lineFlags = Utilities.extractLineFlags( |
1250 source[line - 1].strip()) |
1245 source[line - 1].strip()) |
1251 try: |
1246 with contextlib.suppress(IndexError): |
1252 lineFlags += Utilities.extractLineFlags( |
1247 lineFlags += Utilities.extractLineFlags( |
1253 source[line].strip(), flagsLine=True) |
1248 source[line].strip(), flagsLine=True) |
1254 except IndexError: |
|
1255 pass |
|
1256 if "__IGNORE_EXCEPTION__" in lineFlags: |
1249 if "__IGNORE_EXCEPTION__" in lineFlags: |
1257 res = E5MessageBox.No |
1250 res = E5MessageBox.No |
1258 except (UnicodeError, OSError): |
|
1259 pass |
|
1260 if res != E5MessageBox.No: |
1251 if res != E5MessageBox.No: |
1261 self.viewmanager.setFileLine( |
1252 self.viewmanager.setFileLine( |
1262 stackTrace[0][0], stackTrace[0][1], True) |
1253 stackTrace[0][0], stackTrace[0][1], True) |
1263 if res != E5MessageBox.No: |
1254 if res != E5MessageBox.No: |
1264 self.ui.activateWindow() |
1255 self.ui.activateWindow() |
1308 self.__getClientVariables(debuggerId) |
1299 self.__getClientVariables(debuggerId) |
1309 self.__getClientDisassembly(debuggerId) |
1300 self.__getClientDisassembly(debuggerId) |
1310 self.ui.setDebugProfile() |
1301 self.ui.setDebugProfile() |
1311 self.debugActGrp.setEnabled(True) |
1302 self.debugActGrp.setEnabled(True) |
1312 return |
1303 return |
1313 elif res == E5MessageBox.Ignore: |
1304 elif ( |
1314 if exceptionType not in self.excIgnoreList: |
1305 res == E5MessageBox.Ignore and |
1315 self.excIgnoreList.append(exceptionType) |
1306 exceptionType not in self.excIgnoreList |
|
1307 ): |
|
1308 self.excIgnoreList.append(exceptionType) |
1316 |
1309 |
1317 if self.lastAction != -1: |
1310 if self.lastAction != -1: |
1318 if self.lastAction == 2: |
1311 if self.lastAction == 2: |
1319 self.__specialContinue(debuggerId) |
1312 self.__specialContinue(debuggerId) |
1320 else: |
1313 else: |
1631 |
1624 |
1632 model = self.debugServer.getBreakPointModel() |
1625 model = self.debugServer.getBreakPointModel() |
1633 for row in range(model.rowCount()): |
1626 for row in range(model.rowCount()): |
1634 index = model.index(row, 0) |
1627 index = model.index(row, 0) |
1635 filename, line, cond = model.getBreakPointByIndex(index)[:3] |
1628 filename, line, cond = model.getBreakPointByIndex(index)[:3] |
1636 if not cond: |
1629 formattedCond = " : {0}".format(cond[:20]) if cond else "" |
1637 formattedCond = "" |
|
1638 else: |
|
1639 formattedCond = " : {0}".format(cond[:20]) |
|
1640 bpSuffix = " : {0:d}{1}".format(line, formattedCond) |
1630 bpSuffix = " : {0:d}{1}".format(line, formattedCond) |
1641 act = self.breakpointsMenu.addAction( |
1631 act = self.breakpointsMenu.addAction( |
1642 "{0}{1}".format( |
1632 "{0}{1}".format( |
1643 Utilities.compactPath( |
1633 Utilities.compactPath( |
1644 filename, |
1634 filename, |
1695 self.__resetUI() |
1685 self.__resetUI() |
1696 doNotStart = False |
1686 doNotStart = False |
1697 |
1687 |
1698 # Get the command line arguments, the working directory and the |
1688 # Get the command line arguments, the working directory and the |
1699 # exception reporting flag. |
1689 # exception reporting flag. |
1700 if runProject: |
1690 cap = ( |
1701 cap = self.tr("Coverage of Project") |
1691 self.tr("Coverage of Project") |
1702 else: |
1692 if runProject else |
1703 cap = self.tr("Coverage of Script") |
1693 self.tr("Coverage of Script") |
|
1694 ) |
1704 dlg = StartDialog( |
1695 dlg = StartDialog( |
1705 cap, self.lastUsedVenvName, self.argvHistory, self.wdHistory, |
1696 cap, self.lastUsedVenvName, self.argvHistory, self.wdHistory, |
1706 self.envHistory, self.exceptions, self.ui, 2, |
1697 self.envHistory, self.exceptions, self.ui, 2, |
1707 autoClearShell=self.autoClearShell, |
1698 autoClearShell=self.autoClearShell, |
1708 configOverride=self.overrideGlobalConfig) |
1699 configOverride=self.overrideGlobalConfig) |
1839 self.__resetUI() |
1830 self.__resetUI() |
1840 doNotStart = False |
1831 doNotStart = False |
1841 |
1832 |
1842 # Get the command line arguments, the working directory and the |
1833 # Get the command line arguments, the working directory and the |
1843 # exception reporting flag. |
1834 # exception reporting flag. |
1844 if runProject: |
1835 cap = ( |
1845 cap = self.tr("Profile of Project") |
1836 self.tr("Profile of Project") |
1846 else: |
1837 if runProject else |
1847 cap = self.tr("Profile of Script") |
1838 self.tr("Profile of Script") |
|
1839 ) |
1848 dlg = StartDialog( |
1840 dlg = StartDialog( |
1849 cap, self.lastUsedVenvName, self.argvHistory, self.wdHistory, |
1841 cap, self.lastUsedVenvName, self.argvHistory, self.wdHistory, |
1850 self.envHistory, self.exceptions, self.ui, 3, |
1842 self.envHistory, self.exceptions, self.ui, 3, |
1851 autoClearShell=self.autoClearShell, |
1843 autoClearShell=self.autoClearShell, |
1852 configOverride=self.overrideGlobalConfig) |
1844 configOverride=self.overrideGlobalConfig) |
1983 self.__resetUI() |
1975 self.__resetUI() |
1984 doNotStart = False |
1976 doNotStart = False |
1985 |
1977 |
1986 # Get the command line arguments, the working directory and the |
1978 # Get the command line arguments, the working directory and the |
1987 # exception reporting flag. |
1979 # exception reporting flag. |
1988 if runProject: |
1980 cap = ( |
1989 cap = self.tr("Run Project") |
1981 self.tr("Run Project") |
1990 else: |
1982 if runProject else |
1991 cap = self.tr("Run Script") |
1983 self.tr("Run Script") |
|
1984 ) |
1992 dlg = StartDialog( |
1985 dlg = StartDialog( |
1993 cap, self.lastUsedVenvName, self.argvHistory, self.wdHistory, |
1986 cap, self.lastUsedVenvName, self.argvHistory, self.wdHistory, |
1994 self.envHistory, self.exceptions, self.ui, 1, |
1987 self.envHistory, self.exceptions, self.ui, 1, |
1995 autoClearShell=self.autoClearShell, |
1988 autoClearShell=self.autoClearShell, |
1996 configOverride=self.overrideGlobalConfig) |
1989 configOverride=self.overrideGlobalConfig) |
2123 self.__resetUI() |
2116 self.__resetUI() |
2124 doNotStart = False |
2117 doNotStart = False |
2125 |
2118 |
2126 # Get the command line arguments, the working directory and the |
2119 # Get the command line arguments, the working directory and the |
2127 # exception reporting flag. |
2120 # exception reporting flag. |
2128 if debugProject: |
2121 cap = ( |
2129 cap = self.tr("Debug Project") |
2122 self.tr("Debug Project") |
2130 else: |
2123 if debugProject else |
2131 cap = self.tr("Debug Script") |
2124 self.tr("Debug Script") |
|
2125 ) |
2132 dlg = StartDialog( |
2126 dlg = StartDialog( |
2133 cap, self.lastUsedVenvName, self.argvHistory, self.wdHistory, |
2127 cap, self.lastUsedVenvName, self.argvHistory, self.wdHistory, |
2134 self.envHistory, self.exceptions, self.ui, 0, |
2128 self.envHistory, self.exceptions, self.ui, 0, |
2135 tracePython=self.tracePython, autoClearShell=self.autoClearShell, |
2129 tracePython=self.tracePython, autoClearShell=self.autoClearShell, |
2136 autoContinue=self.autoContinue, |
2130 autoContinue=self.autoContinue, |