src/eric7/Debugger/DebugUI.py

branch
eric7
changeset 9209
b99e7fd55fd3
parent 8881
54e42bc2437a
child 9221
bf71ee032bb4
equal deleted inserted replaced
9208:3fc8dfeb6ebe 9209:b99e7fd55fd3
1 # -*- coding: utf-8 -*-
2
3 # Copyright (c) 2002 - 2022 Detlev Offenbach <detlev@die-offenbachs.de>
4 #
5
6 """
7 Module implementing the debugger UI.
8 """
9
10 import os
11 import copy
12 import contextlib
13
14 from PyQt6.QtCore import pyqtSignal, pyqtSlot, QObject, Qt, QKeyCombination
15 from PyQt6.QtGui import QKeySequence
16 from PyQt6.QtWidgets import QMenu, QToolBar, QApplication, QDialog
17
18 from EricGui.EricAction import EricAction, createActionGroup
19 from EricWidgets import EricMessageBox
20
21 from UI.Info import Program
22 from UI.NotificationWidget import NotificationTypes
23
24 from .DebugClientCapabilities import (
25 HasDebugger, HasInterpreter, HasProfiler, HasCoverage
26 )
27
28 from Globals import recentNameBreakpointConditions
29
30 import Preferences
31 import Utilities
32 import UI.PixmapCache
33 import UI.Config
34
35 from eric7config import getConfig
36
37
38 class DebugUI(QObject):
39 """
40 Class implementing the debugger part of the UI.
41
42 @signal clientStack(stack, debuggerId) emitted at breaking after a reported
43 exception
44 @signal compileForms() emitted if changed project forms should be compiled
45 @signal compileResources() emitted if changed project resources should be
46 compiled
47 @signal executeMake() emitted if a project specific make run should be
48 performed
49 @signal debuggingStarted(filename) emitted when a debugging session was
50 started
51 @signal resetUI(full) emitted to reset the UI partially or fully
52 @signal exceptionInterrupt() emitted after the execution was interrupted
53 by an exception and acknowledged by the user
54 @signal appendStdout(msg) emitted when the client program has terminated
55 and the display of the termination dialog is suppressed
56 """
57 clientStack = pyqtSignal(list, str)
58 resetUI = pyqtSignal(bool)
59 exceptionInterrupt = pyqtSignal()
60 compileForms = pyqtSignal()
61 compileResources = pyqtSignal()
62 executeMake = pyqtSignal()
63 debuggingStarted = pyqtSignal(str)
64 appendStdout = pyqtSignal(str)
65
66 def __init__(self, ui, vm, debugServer, debugViewer, project):
67 """
68 Constructor
69
70 @param ui reference to the main UI
71 @param vm reference to the viewmanager
72 @param debugServer reference to the debug server
73 @param debugViewer reference to the debug viewer widget
74 @param project reference to the project object
75 """
76 super().__init__(ui)
77
78 self.ui = ui
79 self.viewmanager = vm
80 self.debugServer = debugServer
81 self.debugViewer = debugViewer
82 self.project = project
83
84 # Clear some variables
85 self.projectOpen = False
86 self.editorOpen = False
87
88 # read the saved debug info values
89 self.lastUsedVenvName = Preferences.getSettings().value(
90 'DebugInfo/VirtualEnvironment', '')
91 self.scriptsHistory = Preferences.toList(
92 Preferences.getSettings().value('DebugInfo/ScriptsHistory'))
93 self.argvHistory = Preferences.toList(
94 Preferences.getSettings().value('DebugInfo/ArgumentsHistory'))
95 self.wdHistory = Preferences.toList(
96 Preferences.getSettings().value(
97 'DebugInfo/WorkingDirectoryHistory'))
98 self.envHistory = Preferences.toList(
99 Preferences.getSettings().value('DebugInfo/EnvironmentHistory'))
100 self.excList = Preferences.toList(
101 Preferences.getSettings().value('DebugInfo/Exceptions'))
102 self.excIgnoreList = Preferences.toList(
103 Preferences.getSettings().value('DebugInfo/IgnoredExceptions'))
104 self.exceptions = Preferences.toBool(
105 Preferences.getSettings().value(
106 'DebugInfo/ReportExceptions', True))
107 self.autoClearShell = Preferences.toBool(
108 Preferences.getSettings().value('DebugInfo/AutoClearShell', True))
109 self.tracePython = Preferences.toBool(
110 Preferences.getSettings().value('DebugInfo/TracePython', False))
111 self.autoContinue = Preferences.toBool(
112 Preferences.getSettings().value('DebugInfo/AutoContinue', True))
113 self.enableMultiprocess = Preferences.toBool(
114 Preferences.getSettings().value(
115 'DebugInfo/EnableMultiprocess', False))
116 self.multiprocessNoDebugHistory = Preferences.toList(
117 Preferences.getSettings().value(
118 'DebugInfo/MultiprocessNoDebugHistory'))
119 self.overrideGlobalConfig = {
120 "enable": Preferences.toBool(Preferences.getSettings().value(
121 'DebugInfo/OverrideGlobal', False)),
122 "redirect": Preferences.toBool(Preferences.getSettings().value(
123 'DebugInfo/RedirectStdinStdout', True)),
124 }
125
126 self.lastDebuggedFile = None
127 self.lastStartAction = 0 # 0=None, 1=Script, 2=Project
128 self.clientType = ""
129 self.lastAction = -1
130 self.debugActions = [
131 self.__continue, self.__step, self.__stepOver, self.__stepOut,
132 self.__stepQuit, self.__runToCursor, self.__runUntil,
133 self.__moveInstructionPointer
134 ]
135 self.__localsVarFilterList, self.__globalsVarFilterList = (
136 Preferences.getVarFilters())
137 self.debugViewer.setVariablesFilter(
138 self.__globalsVarFilterList, self.__localsVarFilterList)
139
140 self.__clientDebuggerIds = set()
141
142 # Connect the signals emitted by the debug-server
143 debugServer.clientGone.connect(self.__clientGone)
144 debugServer.clientLine.connect(self.__clientLine)
145 debugServer.clientDisconnected.connect(self.__clientDisconnected)
146 debugServer.clientExit.connect(self.__clientExit)
147 debugServer.lastClientExited.connect(self.__lastClientExited)
148 debugServer.clientSyntaxError.connect(self.__clientSyntaxError)
149 debugServer.clientException.connect(self.__clientException)
150 debugServer.clientSignal.connect(self.__clientSignal)
151 debugServer.clientVariables.connect(self.__clientVariables)
152 debugServer.clientVariable.connect(self.__clientVariable)
153 debugServer.clientBreakConditionError.connect(
154 self.__clientBreakConditionError)
155 debugServer.clientWatchConditionError.connect(
156 self.__clientWatchConditionError)
157 debugServer.passiveDebugStarted.connect(self.__passiveDebugStarted)
158 debugServer.clientThreadSet.connect(self.__clientThreadSet)
159 debugServer.clientDebuggerId.connect(self.__clientDebuggerId)
160
161 # Connect the signals emitted by the viewmanager
162 vm.editorOpened.connect(self.__editorOpened)
163 vm.lastEditorClosed.connect(self.__lastEditorClosed)
164 vm.checkActions.connect(self.__checkActions)
165 vm.cursorChanged.connect(self.__cursorChanged)
166 vm.breakpointToggled.connect(self.__cursorChanged)
167
168 # Connect the signals emitted by the project
169 project.projectOpened.connect(self.__projectOpened)
170 project.newProject.connect(self.__projectOpened)
171 project.projectClosed.connect(self.__projectClosed)
172
173 # Set a flag for the passive debug mode
174 self.passive = Preferences.getDebugger("PassiveDbgEnabled")
175
176 def showNotification(self, notification,
177 kind=NotificationTypes.INFORMATION, timeout=None):
178 """
179 Public method to show some notification message.
180
181 @param notification message to be shown
182 @type str
183 @param kind kind of notification to be shown
184 @type NotificationTypes
185 @param timeout timeout for the notification (None = use configured
186 default, 0 = indefinitely)
187 @type int
188 """
189 self.ui.showNotification(
190 UI.PixmapCache.getPixmap("debug48"),
191 self.tr("Notification"), notification, kind=kind, timeout=timeout)
192
193 def variablesFilter(self, scope):
194 """
195 Public method to get the variables filter for a scope.
196
197 @param scope flag indicating global (True) or local (False) scope
198 @return filters list
199 @rtype list of str
200 """
201 if scope:
202 return self.__globalsVarFilterList[:]
203 else:
204 return self.__localsVarFilterList[:]
205
206 def initActions(self):
207 """
208 Public method defining the user interface actions.
209 """
210 self.actions = []
211
212 self.runAct = EricAction(
213 self.tr('Run Script'),
214 UI.PixmapCache.getIcon("runScript"),
215 self.tr('&Run Script...'),
216 Qt.Key.Key_F2, 0, self, 'dbg_run_script')
217 self.runAct.setStatusTip(self.tr('Run the current Script'))
218 self.runAct.setWhatsThis(self.tr(
219 """<b>Run Script</b>"""
220 """<p>Set the command line arguments and run the script outside"""
221 """ the debugger. If the file has unsaved changes it may be"""
222 """ saved first.</p>"""
223 ))
224 self.runAct.triggered.connect(self.__runScript)
225 self.actions.append(self.runAct)
226
227 self.runProjectAct = EricAction(
228 self.tr('Run Project'),
229 UI.PixmapCache.getIcon("runProject"),
230 self.tr('Run &Project...'),
231 QKeyCombination(Qt.Modifier.SHIFT, Qt.Key.Key_F2),
232 0, self, 'dbg_run_project')
233 self.runProjectAct.setStatusTip(self.tr('Run the current Project'))
234 self.runProjectAct.setWhatsThis(self.tr(
235 """<b>Run Project</b>"""
236 """<p>Set the command line arguments and run the current project"""
237 """ outside the debugger."""
238 """ If files of the current project have unsaved changes they"""
239 """ may be saved first.</p>"""
240 ))
241 self.runProjectAct.triggered.connect(self.__runProject)
242 self.actions.append(self.runProjectAct)
243
244 self.coverageAct = EricAction(
245 self.tr('Coverage run of Script'),
246 UI.PixmapCache.getIcon("coverageScript"),
247 self.tr('Coverage run of Script...'), 0, 0, self,
248 'dbg_coverage_script')
249 self.coverageAct.setStatusTip(
250 self.tr('Perform a coverage run of the current Script'))
251 self.coverageAct.setWhatsThis(self.tr(
252 """<b>Coverage run of Script</b>"""
253 """<p>Set the command line arguments and run the script under"""
254 """ the control of a coverage analysis tool. If the file has"""
255 """ unsaved changes it may be saved first.</p>"""
256 ))
257 self.coverageAct.triggered.connect(self.__coverageScript)
258 self.actions.append(self.coverageAct)
259
260 self.coverageProjectAct = EricAction(
261 self.tr('Coverage run of Project'),
262 UI.PixmapCache.getIcon("coverageProject"),
263 self.tr('Coverage run of Project...'), 0, 0, self,
264 'dbg_coverage_project')
265 self.coverageProjectAct.setStatusTip(
266 self.tr('Perform a coverage run of the current Project'))
267 self.coverageProjectAct.setWhatsThis(self.tr(
268 """<b>Coverage run of Project</b>"""
269 """<p>Set the command line arguments and run the current project"""
270 """ under the control of a coverage analysis tool."""
271 """ If files of the current project have unsaved changes"""
272 """ they may be saved first.</p>"""
273 ))
274 self.coverageProjectAct.triggered.connect(self.__coverageProject)
275 self.actions.append(self.coverageProjectAct)
276
277 self.profileAct = EricAction(
278 self.tr('Profile Script'),
279 UI.PixmapCache.getIcon("profileScript"),
280 self.tr('Profile Script...'), 0, 0, self, 'dbg_profile_script')
281 self.profileAct.setStatusTip(self.tr('Profile the current Script'))
282 self.profileAct.setWhatsThis(self.tr(
283 """<b>Profile Script</b>"""
284 """<p>Set the command line arguments and profile the script."""
285 """ If the file has unsaved changes it may be saved first.</p>"""
286 ))
287 self.profileAct.triggered.connect(self.__profileScript)
288 self.actions.append(self.profileAct)
289
290 self.profileProjectAct = EricAction(
291 self.tr('Profile Project'),
292 UI.PixmapCache.getIcon("profileProject"),
293 self.tr('Profile Project...'), 0, 0, self,
294 'dbg_profile_project')
295 self.profileProjectAct.setStatusTip(
296 self.tr('Profile the current Project'))
297 self.profileProjectAct.setWhatsThis(self.tr(
298 """<b>Profile Project</b>"""
299 """<p>Set the command line arguments and profile the current"""
300 """ project. If files of the current project have unsaved"""
301 """ changes they may be saved first.</p>"""
302 ))
303 self.profileProjectAct.triggered.connect(self.__profileProject)
304 self.actions.append(self.profileProjectAct)
305
306 self.debugAct = EricAction(
307 self.tr('Debug Script'),
308 UI.PixmapCache.getIcon("debugScript"),
309 self.tr('&Debug Script...'), Qt.Key.Key_F5, 0, self,
310 'dbg_debug_script')
311 self.debugAct.setStatusTip(self.tr('Debug the current Script'))
312 self.debugAct.setWhatsThis(self.tr(
313 """<b>Debug Script</b>"""
314 """<p>Set the command line arguments and set the current line"""
315 """ to be the first executable Python statement of the current"""
316 """ editor window. If the file has unsaved changes it may be"""
317 """ saved first.</p>"""
318 ))
319 self.debugAct.triggered.connect(self.__debugScript)
320 self.actions.append(self.debugAct)
321
322 self.debugProjectAct = EricAction(
323 self.tr('Debug Project'),
324 UI.PixmapCache.getIcon("debugProject"),
325 self.tr('Debug &Project...'),
326 QKeyCombination(Qt.Modifier.SHIFT, Qt.Key.Key_F5),
327 0, self, 'dbg_debug_project')
328 self.debugProjectAct.setStatusTip(self.tr(
329 'Debug the current Project'))
330 self.debugProjectAct.setWhatsThis(self.tr(
331 """<b>Debug Project</b>"""
332 """<p>Set the command line arguments and set the current line"""
333 """ to be the first executable Python statement of the main"""
334 """ script of the current project. If files of the current"""
335 """ project have unsaved changes they may be saved first.</p>"""
336 ))
337 self.debugProjectAct.triggered.connect(self.__debugProject)
338 self.actions.append(self.debugProjectAct)
339
340 self.restartAct = EricAction(
341 self.tr('Restart'),
342 UI.PixmapCache.getIcon("debugRestart"),
343 self.tr('Restart'), Qt.Key.Key_F4, 0, self, 'dbg_restart_script')
344 self.restartAct.setStatusTip(self.tr(
345 'Restart the last debugged script'))
346 self.restartAct.setWhatsThis(self.tr(
347 """<b>Restart</b>"""
348 """<p>Set the command line arguments and set the current line"""
349 """ to be the first executable Python statement of the script"""
350 """ that was debugged last. If there are unsaved changes, they"""
351 """ may be saved first.</p>"""
352 ))
353 self.restartAct.triggered.connect(self.__doRestart)
354 self.actions.append(self.restartAct)
355
356 self.stopAct = EricAction(
357 self.tr('Stop'),
358 UI.PixmapCache.getIcon("stopScript"),
359 self.tr('Stop'),
360 QKeyCombination(Qt.Modifier.SHIFT, Qt.Key.Key_F10),
361 0,
362 self, 'dbg_stop_script')
363 self.stopAct.setStatusTip(self.tr("""Stop the running script."""))
364 self.stopAct.setWhatsThis(self.tr(
365 """<b>Stop</b>"""
366 """<p>This stops the script running in the debugger backend.</p>"""
367 ))
368 self.stopAct.triggered.connect(self.__stopScript)
369 self.actions.append(self.stopAct)
370
371 self.debugActGrp = createActionGroup(self)
372
373 act = EricAction(
374 self.tr('Continue'),
375 UI.PixmapCache.getIcon("continue"),
376 self.tr('&Continue'), Qt.Key.Key_F6, 0,
377 self.debugActGrp, 'dbg_continue')
378 act.setStatusTip(
379 self.tr('Continue running the program from the current line'))
380 act.setWhatsThis(self.tr(
381 """<b>Continue</b>"""
382 """<p>Continue running the program from the current line. The"""
383 """ program will stop when it terminates or when a breakpoint"""
384 """ is reached.</p>"""
385 ))
386 act.triggered.connect(self.__continue)
387 self.actions.append(act)
388
389 act = EricAction(
390 self.tr('Continue to Cursor'),
391 UI.PixmapCache.getIcon("continueToCursor"),
392 self.tr('Continue &To Cursor'),
393 QKeyCombination(Qt.Modifier.SHIFT, Qt.Key.Key_F6),
394 0, self.debugActGrp, 'dbg_continue_to_cursor')
395 act.setStatusTip(self.tr(
396 """Continue running the program from the"""
397 """ current line to the current cursor position"""))
398 act.setWhatsThis(self.tr(
399 """<b>Continue To Cursor</b>"""
400 """<p>Continue running the program from the current line to the"""
401 """ current cursor position.</p>"""
402 ))
403 act.triggered.connect(self.__runToCursor)
404 self.actions.append(act)
405
406 act = EricAction(
407 self.tr('Continue Until'),
408 UI.PixmapCache.getIcon("continueUntil"),
409 self.tr('Continue &Until'),
410 QKeyCombination(Qt.Modifier.CTRL, Qt.Key.Key_F6),
411 0,
412 self.debugActGrp, 'dbg_continue_until')
413 act.setStatusTip(self.tr(
414 """Continue running the program from the current line to the"""
415 """ current cursor position or until leaving the current frame"""))
416 act.setWhatsThis(self.tr(
417 """<b>Continue Until</b>"""
418 """<p>Continue running the program from the current line to the"""
419 """ cursor position greater than the current line or until"""
420 """ leaving the current frame.</p>"""
421 ))
422 act.triggered.connect(self.__runUntil)
423 self.actions.append(act)
424
425 act = EricAction(
426 self.tr('Move Instruction Pointer to Cursor'),
427 UI.PixmapCache.getIcon("moveInstructionPointer"),
428 self.tr('&Jump To Cursor'), Qt.Key.Key_F12, 0,
429 self.debugActGrp, 'dbg_jump_to_cursor')
430 act.setStatusTip(self.tr(
431 """Skip the code from the"""
432 """ current line to the current cursor position"""))
433 act.setWhatsThis(self.tr(
434 """<b>Move Instruction Pointer to Cursor</b>"""
435 """<p>Move the Python internal instruction pointer to the"""
436 """ current cursor position without executing the code in"""
437 """ between.</p>"""
438 """<p>It's not possible to jump out of a function or jump"""
439 """ in a code block, e.g. a loop. In these cases, a error"""
440 """ message is printed to the log window.</p>"""
441 ))
442 act.triggered.connect(self.__moveInstructionPointer)
443 self.actions.append(act)
444
445 act = EricAction(
446 self.tr('Single Step'),
447 UI.PixmapCache.getIcon("step"),
448 self.tr('Sin&gle Step'), Qt.Key.Key_F7, 0,
449 self.debugActGrp, 'dbg_single_step')
450 act.setStatusTip(self.tr('Execute a single Python statement'))
451 act.setWhatsThis(self.tr(
452 """<b>Single Step</b>"""
453 """<p>Execute a single Python statement. If the statement"""
454 """ is an <tt>import</tt> statement, a class constructor, or a"""
455 """ method or function call then control is returned to the"""
456 """ debugger at the next statement.</p>"""
457 ))
458 act.triggered.connect(self.__step)
459 self.actions.append(act)
460
461 act = EricAction(
462 self.tr('Step Over'),
463 UI.PixmapCache.getIcon("stepOver"),
464 self.tr('Step &Over'), Qt.Key.Key_F8, 0,
465 self.debugActGrp, 'dbg_step_over')
466 act.setStatusTip(self.tr(
467 """Execute a single Python statement staying"""
468 """ in the current frame"""))
469 act.setWhatsThis(self.tr(
470 """<b>Step Over</b>"""
471 """<p>Execute a single Python statement staying in the same"""
472 """ frame. If the statement is an <tt>import</tt> statement,"""
473 """ a class constructor, or a method or function call then"""
474 """ control is returned to the debugger after the statement"""
475 """ has completed.</p>"""
476 ))
477 act.triggered.connect(self.__stepOver)
478 self.actions.append(act)
479
480 act = EricAction(
481 self.tr('Step Out'),
482 UI.PixmapCache.getIcon("stepOut"),
483 self.tr('Step Ou&t'), Qt.Key.Key_F9, 0,
484 self.debugActGrp, 'dbg_step_out')
485 act.setStatusTip(self.tr(
486 """Execute Python statements until leaving"""
487 """ the current frame"""))
488 act.setWhatsThis(self.tr(
489 """<b>Step Out</b>"""
490 """<p>Execute Python statements until leaving the current"""
491 """ frame. If the statements are inside an <tt>import</tt>"""
492 """ statement, a class constructor, or a method or function"""
493 """ call then control is returned to the debugger after the"""
494 """ current frame has been left.</p>"""
495 ))
496 act.triggered.connect(self.__stepOut)
497 self.actions.append(act)
498
499 act = EricAction(
500 self.tr('Stop'),
501 UI.PixmapCache.getIcon("stepQuit"),
502 self.tr('&Stop'), Qt.Key.Key_F10, 0,
503 self.debugActGrp, 'dbg_stop')
504 act.setStatusTip(self.tr('Stop debugging'))
505 act.setWhatsThis(self.tr(
506 """<b>Stop</b>"""
507 """<p>Stop the running debugging session.</p>"""
508 ))
509 act.triggered.connect(self.__stepQuit)
510 self.actions.append(act)
511
512 self.dbgFilterAct = EricAction(
513 self.tr('Variables Type Filter'),
514 self.tr('Varia&bles Type Filter...'), 0, 0, self,
515 'dbg_variables_filter')
516 self.dbgFilterAct.setStatusTip(self.tr(
517 'Configure variables type filter'))
518 self.dbgFilterAct.setWhatsThis(self.tr(
519 """<b>Variables Type Filter</b>"""
520 """<p>Configure the variables type filter. Only variable types"""
521 """ that are not selected are displayed in the global or local"""
522 """ variables window during a debugging session.</p>"""
523 ))
524 self.dbgFilterAct.triggered.connect(
525 self.__configureVariablesFilters)
526 self.actions.append(self.dbgFilterAct)
527
528 self.excFilterAct = EricAction(
529 self.tr('Exceptions Filter'),
530 self.tr('&Exceptions Filter...'), 0, 0, self,
531 'dbg_exceptions_filter')
532 self.excFilterAct.setStatusTip(self.tr(
533 'Configure exceptions filter'))
534 self.excFilterAct.setWhatsThis(self.tr(
535 """<b>Exceptions Filter</b>"""
536 """<p>Configure the exceptions filter. Only exception types"""
537 """ that are listed are highlighted during a debugging"""
538 """ session.</p><p>Please note, that all unhandled exceptions"""
539 """ are highlighted indepent from the filter list.</p>"""
540 ))
541 self.excFilterAct.triggered.connect(
542 self.__configureExceptionsFilter)
543 self.actions.append(self.excFilterAct)
544
545 self.excIgnoreFilterAct = EricAction(
546 self.tr('Ignored Exceptions'),
547 self.tr('&Ignored Exceptions...'), 0, 0,
548 self, 'dbg_ignored_exceptions')
549 self.excIgnoreFilterAct.setStatusTip(self.tr(
550 'Configure ignored exceptions'))
551 self.excIgnoreFilterAct.setWhatsThis(self.tr(
552 """<b>Ignored Exceptions</b>"""
553 """<p>Configure the ignored exceptions. Only exception types"""
554 """ that are not listed are highlighted during a debugging"""
555 """ session.</p><p>Please note, that unhandled exceptions"""
556 """ cannot be ignored.</p>"""
557 ))
558 self.excIgnoreFilterAct.triggered.connect(
559 self.__configureIgnoredExceptions)
560 self.actions.append(self.excIgnoreFilterAct)
561
562 self.dbgSetBpActGrp = createActionGroup(self)
563
564 self.dbgToggleBpAct = EricAction(
565 self.tr('Toggle Breakpoint'),
566 UI.PixmapCache.getIcon("breakpointToggle"),
567 self.tr('Toggle Breakpoint'),
568 QKeySequence(self.tr("Shift+F11", "Debug|Toggle Breakpoint")),
569 0, self.dbgSetBpActGrp, 'dbg_toggle_breakpoint')
570 self.dbgToggleBpAct.setStatusTip(self.tr('Toggle Breakpoint'))
571 self.dbgToggleBpAct.setWhatsThis(self.tr(
572 """<b>Toggle Breakpoint</b>"""
573 """<p>Toggles a breakpoint at the current line of the"""
574 """ current editor.</p>"""
575 ))
576 self.dbgToggleBpAct.triggered.connect(self.__toggleBreakpoint)
577 self.actions.append(self.dbgToggleBpAct)
578
579 self.dbgEditBpAct = EricAction(
580 self.tr('Edit Breakpoint'),
581 UI.PixmapCache.getIcon("cBreakpointToggle"),
582 self.tr('Edit Breakpoint...'),
583 QKeySequence(self.tr("Shift+F12", "Debug|Edit Breakpoint")), 0,
584 self.dbgSetBpActGrp, 'dbg_edit_breakpoint')
585 self.dbgEditBpAct.setStatusTip(self.tr('Edit Breakpoint'))
586 self.dbgEditBpAct.setWhatsThis(self.tr(
587 """<b>Edit Breakpoint</b>"""
588 """<p>Opens a dialog to edit the breakpoints properties."""
589 """ It works at the current line of the current editor.</p>"""
590 ))
591 self.dbgEditBpAct.triggered.connect(self.__editBreakpoint)
592 self.actions.append(self.dbgEditBpAct)
593
594 self.dbgNextBpAct = EricAction(
595 self.tr('Next Breakpoint'),
596 UI.PixmapCache.getIcon("breakpointNext"),
597 self.tr('Next Breakpoint'),
598 QKeySequence(
599 self.tr("Ctrl+Shift+PgDown", "Debug|Next Breakpoint")), 0,
600 self.dbgSetBpActGrp, 'dbg_next_breakpoint')
601 self.dbgNextBpAct.setStatusTip(self.tr('Next Breakpoint'))
602 self.dbgNextBpAct.setWhatsThis(self.tr(
603 """<b>Next Breakpoint</b>"""
604 """<p>Go to next breakpoint of the current editor.</p>"""
605 ))
606 self.dbgNextBpAct.triggered.connect(self.__nextBreakpoint)
607 self.actions.append(self.dbgNextBpAct)
608
609 self.dbgPrevBpAct = EricAction(
610 self.tr('Previous Breakpoint'),
611 UI.PixmapCache.getIcon("breakpointPrevious"),
612 self.tr('Previous Breakpoint'),
613 QKeySequence(
614 self.tr("Ctrl+Shift+PgUp", "Debug|Previous Breakpoint")),
615 0, self.dbgSetBpActGrp, 'dbg_previous_breakpoint')
616 self.dbgPrevBpAct.setStatusTip(self.tr('Previous Breakpoint'))
617 self.dbgPrevBpAct.setWhatsThis(self.tr(
618 """<b>Previous Breakpoint</b>"""
619 """<p>Go to previous breakpoint of the current editor.</p>"""
620 ))
621 self.dbgPrevBpAct.triggered.connect(self.__previousBreakpoint)
622 self.actions.append(self.dbgPrevBpAct)
623
624 act = EricAction(
625 self.tr('Clear Breakpoints'),
626 self.tr('Clear Breakpoints'),
627 0, 0,
628 self.dbgSetBpActGrp, 'dbg_clear_breakpoint')
629 act.setStatusTip(self.tr('Clear Breakpoints'))
630 act.setWhatsThis(self.tr(
631 """<b>Clear Breakpoints</b>"""
632 """<p>Clear breakpoints of all editors.</p>"""
633 ))
634 act.triggered.connect(self.__clearBreakpoints)
635 self.actions.append(act)
636
637 self.debugActGrp.setEnabled(False)
638 self.dbgSetBpActGrp.setEnabled(False)
639 self.runProjectAct.setEnabled(False)
640 self.profileProjectAct.setEnabled(False)
641 self.coverageProjectAct.setEnabled(False)
642 self.debugProjectAct.setEnabled(False)
643 self.restartAct.setEnabled(False)
644 self.stopAct.setEnabled(False)
645
646 def initMenus(self):
647 """
648 Public slot to initialize the project menu.
649
650 @return the generated menu
651 """
652 dmenu = QMenu(self.tr('&Debug'), self.parent())
653 dmenu.setTearOffEnabled(True)
654 smenu = QMenu(self.tr('Sta&rt'), self.parent())
655 smenu.setTearOffEnabled(True)
656 self.breakpointsMenu = QMenu(self.tr('&Breakpoints'), dmenu)
657
658 smenu.addAction(self.restartAct)
659 smenu.addAction(self.stopAct)
660 smenu.addSeparator()
661 smenu.addAction(self.runAct)
662 smenu.addAction(self.runProjectAct)
663 smenu.addSeparator()
664 smenu.addAction(self.debugAct)
665 smenu.addAction(self.debugProjectAct)
666 smenu.addSeparator()
667 smenu.addAction(self.profileAct)
668 smenu.addAction(self.profileProjectAct)
669 smenu.addSeparator()
670 smenu.addAction(self.coverageAct)
671 smenu.addAction(self.coverageProjectAct)
672
673 dmenu.addActions(self.debugActGrp.actions())
674 dmenu.addSeparator()
675 dmenu.addActions(self.dbgSetBpActGrp.actions())
676 self.menuBreakpointsAct = dmenu.addMenu(self.breakpointsMenu)
677 dmenu.addSeparator()
678 dmenu.addAction(self.dbgFilterAct)
679 dmenu.addAction(self.excFilterAct)
680 dmenu.addAction(self.excIgnoreFilterAct)
681
682 self.breakpointsMenu.aboutToShow.connect(self.__showBreakpointsMenu)
683 self.breakpointsMenu.triggered.connect(self.__breakpointSelected)
684 dmenu.aboutToShow.connect(self.__showDebugMenu)
685
686 return smenu, dmenu
687
688 def initToolbars(self, toolbarManager):
689 """
690 Public slot to initialize the debug toolbars.
691
692 @param toolbarManager reference to a toolbar manager object
693 (EricToolBarManager)
694 @return the generated toolbars (list of QToolBar)
695 """
696 starttb = QToolBar(self.tr("Start"), self.ui)
697 starttb.setIconSize(UI.Config.ToolBarIconSize)
698 starttb.setObjectName("StartToolbar")
699 starttb.setToolTip(self.tr('Start'))
700
701 starttb.addAction(self.restartAct)
702 starttb.addAction(self.stopAct)
703 starttb.addSeparator()
704 starttb.addAction(self.runAct)
705 starttb.addAction(self.runProjectAct)
706 starttb.addSeparator()
707 starttb.addAction(self.debugAct)
708 starttb.addAction(self.debugProjectAct)
709
710 debugtb = QToolBar(self.tr("Debug"), self.ui)
711 debugtb.setIconSize(UI.Config.ToolBarIconSize)
712 debugtb.setObjectName("DebugToolbar")
713 debugtb.setToolTip(self.tr('Debug'))
714
715 debugtb.addActions(self.debugActGrp.actions())
716 debugtb.addSeparator()
717 debugtb.addAction(self.dbgToggleBpAct)
718 debugtb.addAction(self.dbgEditBpAct)
719 debugtb.addAction(self.dbgNextBpAct)
720 debugtb.addAction(self.dbgPrevBpAct)
721
722 toolbarManager.addToolBar(starttb, starttb.windowTitle())
723 toolbarManager.addToolBar(debugtb, debugtb.windowTitle())
724 toolbarManager.addAction(self.profileAct, starttb.windowTitle())
725 toolbarManager.addAction(self.profileProjectAct, starttb.windowTitle())
726 toolbarManager.addAction(self.coverageAct, starttb.windowTitle())
727 toolbarManager.addAction(self.coverageProjectAct,
728 starttb.windowTitle())
729
730 return [starttb, debugtb]
731
732 def setScriptsHistory(self, scriptName, clearHistories=False,
733 history=None):
734 """
735 Public slot to initialize the scripts history.
736
737 @param scriptName script name
738 @type str
739 @param clearHistories flag indicating, that the list should
740 be cleared (defaults to False)
741 @type bool (optional)
742 @param history list of history entries to be set (defaults to None)
743 @type list of str (optional)
744 """
745 if clearHistories:
746 del self.scriptsHistory[1:]
747 elif history is not None:
748 self.scriptsHistory = history[:]
749 else:
750 if scriptName in self.scriptsHistory:
751 self.scriptsHistory.remove(scriptName)
752 self.scriptsHistory.insert(0, scriptName)
753
754 def setArgvHistory(self, argsStr, clearHistories=False, history=None):
755 """
756 Public slot to initialize the argv history.
757
758 @param argsStr the commandline arguments (string)
759 @param clearHistories flag indicating, that the list should
760 be cleared (boolean)
761 @param history list of history entries to be set (list of strings)
762 """
763 if clearHistories:
764 del self.argvHistory[1:]
765 elif history is not None:
766 self.argvHistory = history[:]
767 else:
768 if argsStr in self.argvHistory:
769 self.argvHistory.remove(argsStr)
770 self.argvHistory.insert(0, argsStr)
771
772 def setWdHistory(self, wdStr, clearHistories=False, history=None):
773 """
774 Public slot to initialize the wd history.
775
776 @param wdStr the working directory (string)
777 @param clearHistories flag indicating, that the list should
778 be cleared (boolean)
779 @param history list of history entries to be set (list of strings)
780 """
781 if clearHistories:
782 del self.wdHistory[1:]
783 elif history is not None:
784 self.wdHistory = history[:]
785 else:
786 if wdStr in self.wdHistory:
787 self.wdHistory.remove(wdStr)
788 self.wdHistory.insert(0, wdStr)
789
790 def setEnvHistory(self, envStr, clearHistories=False, history=None):
791 """
792 Public slot to initialize the env history.
793
794 @param envStr the environment settings (string)
795 @param clearHistories flag indicating, that the list should
796 be cleared (boolean)
797 @param history list of history entries to be set (list of strings)
798 """
799 if clearHistories:
800 del self.envHistory[1:]
801 elif history is not None:
802 self.envHistory = history[:]
803 else:
804 if envStr in self.envHistory:
805 self.envHistory.remove(envStr)
806 self.envHistory.insert(0, envStr)
807
808 def setExceptionReporting(self, exceptions):
809 """
810 Public slot to initialize the exception reporting flag.
811
812 @param exceptions flag indicating exception reporting status (boolean)
813 """
814 self.exceptions = exceptions
815
816 def setExcList(self, excList):
817 """
818 Public slot to initialize the exceptions type list.
819
820 @param excList list of exception types (list of strings)
821 """
822 self.excList = excList[:] # keep a copy
823
824 def setExcIgnoreList(self, excIgnoreList):
825 """
826 Public slot to initialize the ignored exceptions type list.
827
828 @param excIgnoreList list of ignored exception types (list of strings)
829 """
830 self.excIgnoreList = excIgnoreList[:] # keep a copy
831
832 def setAutoClearShell(self, autoClearShell):
833 """
834 Public slot to initialize the autoClearShell flag.
835
836 @param autoClearShell flag indicating, that the interpreter window
837 should be cleared (boolean)
838 """
839 self.autoClearShell = autoClearShell
840
841 def setTracePython(self, tracePython):
842 """
843 Public slot to initialize the trace Python flag.
844
845 @param tracePython flag indicating if the Python library should be
846 traced as well (boolean)
847 """
848 self.tracePython = tracePython
849
850 def setAutoContinue(self, autoContinue):
851 """
852 Public slot to initialize the autoContinue flag.
853
854 @param autoContinue flag indicating, that the debugger should not
855 stop at the first executable line (boolean)
856 """
857 self.autoContinue = autoContinue
858
859 def __editorOpened(self, fn):
860 """
861 Private slot to handle the editorOpened signal.
862
863 @param fn filename of the opened editor
864 """
865 self.editorOpen = True
866
867 editor = self.viewmanager.getOpenEditor(fn) if fn else None
868 self.__checkActions(editor)
869
870 def __lastEditorClosed(self):
871 """
872 Private slot to handle the closeProgram signal.
873 """
874 self.editorOpen = False
875 self.debugActGrp.setEnabled(False)
876 self.dbgSetBpActGrp.setEnabled(False)
877 self.lastAction = -1
878 if not self.projectOpen:
879 self.restartAct.setEnabled(False)
880 self.lastDebuggedFile = None
881 self.lastStartAction = 0
882 self.clientType = ""
883
884 def __checkActions(self, editor):
885 """
886 Private slot to check some actions for their enable/disable status.
887
888 @param editor editor window
889 """
890 fn = editor.getFileName() if editor else None
891
892 cap = 0
893 if fn:
894 for language in self.debugServer.getSupportedLanguages():
895 exts = self.debugServer.getExtensions(language)
896 if fn.endswith(exts):
897 cap = self.debugServer.getClientCapabilities(language)
898 break
899 else:
900 if editor.isPy3File():
901 cap = self.debugServer.getClientCapabilities('Python3')
902 elif editor.isRubyFile():
903 cap = self.debugServer.getClientCapabilities('Ruby')
904
905 self.dbgSetBpActGrp.setEnabled(cap & HasDebugger)
906 if editor.curLineHasBreakpoint():
907 self.dbgEditBpAct.setEnabled(True)
908 else:
909 self.dbgEditBpAct.setEnabled(False)
910 if editor.hasBreakpoints():
911 self.dbgNextBpAct.setEnabled(True)
912 self.dbgPrevBpAct.setEnabled(True)
913 else:
914 self.dbgNextBpAct.setEnabled(False)
915 self.dbgPrevBpAct.setEnabled(False)
916 else:
917 self.dbgSetBpActGrp.setEnabled(False)
918
919 def __cursorChanged(self, editor):
920 """
921 Private slot handling the cursorChanged signal of the viewmanager.
922
923 @param editor editor window
924 """
925 if editor is None:
926 return
927
928 if editor.isPyFile() or editor.isRubyFile():
929 if editor.curLineHasBreakpoint():
930 self.dbgEditBpAct.setEnabled(True)
931 else:
932 self.dbgEditBpAct.setEnabled(False)
933 if editor.hasBreakpoints():
934 self.dbgNextBpAct.setEnabled(True)
935 self.dbgPrevBpAct.setEnabled(True)
936 else:
937 self.dbgNextBpAct.setEnabled(False)
938 self.dbgPrevBpAct.setEnabled(False)
939
940 def __projectOpened(self):
941 """
942 Private slot to handle the projectOpened signal.
943 """
944 self.projectOpen = True
945 cap = self.debugServer.getClientCapabilities(
946 self.project.getProjectLanguage())
947 if not self.passive:
948 self.debugProjectAct.setEnabled(cap & HasDebugger)
949 self.runProjectAct.setEnabled(cap & HasInterpreter)
950 self.profileProjectAct.setEnabled(cap & HasProfiler)
951 self.coverageProjectAct.setEnabled(cap & HasCoverage)
952
953 def __projectClosed(self):
954 """
955 Private slot to handle the projectClosed signal.
956 """
957 self.projectOpen = False
958 self.runProjectAct.setEnabled(False)
959 self.profileProjectAct.setEnabled(False)
960 self.coverageProjectAct.setEnabled(False)
961 self.debugProjectAct.setEnabled(False)
962
963 if not self.editorOpen:
964 self.restartAct.setEnabled(False)
965 self.lastDebuggedFile = None
966 self.lastStartAction = 0
967 self.clientType = ""
968
969 def clearHistories(self):
970 """
971 Public method to clear the various debug histories.
972 """
973 self.scriptsHistory = []
974 self.argvHistory = []
975 self.wdHistory = []
976 self.envHistory = []
977 self.multiprocessNoDebugHistory = []
978
979 Preferences.getSettings().setValue(
980 'DebugInfo/ScriptsHistory', self.scriptsHistory)
981 Preferences.getSettings().setValue(
982 'DebugInfo/ArgumentsHistory', self.argvHistory)
983 Preferences.getSettings().setValue(
984 'DebugInfo/WorkingDirectoryHistory', self.wdHistory)
985 Preferences.getSettings().setValue(
986 'DebugInfo/EnvironmentHistory', self.envHistory)
987 Preferences.getSettings().setValue(
988 'DebugInfo/MultiprocessNoDebugHistory',
989 self.multiprocessNoDebugHistory)
990
991 self.debugViewer.breakpointViewer.clearHistories()
992
993 def shutdown(self):
994 """
995 Public method to perform shutdown actions.
996 """
997 # Just save the 10 most recent entries
998 del self.scriptsHistory[10:]
999 del self.argvHistory[10:]
1000 del self.wdHistory[10:]
1001 del self.envHistory[10:]
1002
1003 Preferences.getSettings().setValue(
1004 'DebugInfo/VirtualEnvironment', self.lastUsedVenvName)
1005 Preferences.getSettings().setValue(
1006 'DebugInfo/ScriptsHistory', self.scriptsHistory)
1007 Preferences.getSettings().setValue(
1008 'DebugInfo/ArgumentsHistory', self.argvHistory)
1009 Preferences.getSettings().setValue(
1010 'DebugInfo/WorkingDirectoryHistory', self.wdHistory)
1011 Preferences.getSettings().setValue(
1012 'DebugInfo/EnvironmentHistory', self.envHistory)
1013 Preferences.getSettings().setValue(
1014 'DebugInfo/Exceptions', self.excList)
1015 Preferences.getSettings().setValue(
1016 'DebugInfo/IgnoredExceptions', self.excIgnoreList)
1017 Preferences.getSettings().setValue(
1018 'DebugInfo/ReportExceptions', self.exceptions)
1019 Preferences.getSettings().setValue(
1020 'DebugInfo/AutoClearShell', self.autoClearShell)
1021 Preferences.getSettings().setValue(
1022 'DebugInfo/TracePython', self.tracePython)
1023 Preferences.getSettings().setValue(
1024 'DebugInfo/AutoContinue', self.autoContinue)
1025 Preferences.getSettings().setValue(
1026 'DebugInfo/EnableMultiprocess', self.enableMultiprocess)
1027 Preferences.getSettings().setValue(
1028 'DebugInfo/MultiprocessNoDebugHistory',
1029 self.multiprocessNoDebugHistory)
1030 Preferences.getSettings().setValue(
1031 'DebugInfo/OverrideGlobal',
1032 self.overrideGlobalConfig["enable"])
1033 Preferences.getSettings().setValue(
1034 'DebugInfo/RedirectStdinStdout',
1035 self.overrideGlobalConfig["redirect"])
1036
1037 def shutdownServer(self):
1038 """
1039 Public method to shut down the debug server.
1040
1041 This is needed to cleanly close the sockets on Win OS.
1042
1043 @return always true
1044 """
1045 self.debugServer.shutdownServer()
1046 return True
1047
1048 def __resetUI(self, fullReset=True):
1049 """
1050 Private slot to reset the user interface.
1051
1052 @param fullReset flag indicating a full reset is required
1053 @type bool
1054 """
1055 self.lastAction = -1
1056 self.debugActGrp.setEnabled(False)
1057 self.__clientDebuggerIds.clear()
1058
1059 if not self.passive:
1060 if self.editorOpen:
1061 editor = self.viewmanager.activeWindow()
1062 else:
1063 editor = None
1064 self.__checkActions(editor)
1065
1066 self.debugProjectAct.setEnabled(self.projectOpen)
1067 self.runProjectAct.setEnabled(self.projectOpen)
1068 self.profileProjectAct.setEnabled(self.projectOpen)
1069 self.coverageProjectAct.setEnabled(self.projectOpen)
1070 if (
1071 self.lastDebuggedFile is not None and
1072 (self.editorOpen or self.projectOpen)
1073 ):
1074 self.restartAct.setEnabled(True)
1075 else:
1076 self.restartAct.setEnabled(False)
1077 self.stopAct.setEnabled(False)
1078
1079 self.resetUI.emit(fullReset)
1080
1081 def __clientDebuggerId(self, debuggerId):
1082 """
1083 Private slot to track the list of connected debuggers.
1084
1085 @param debuggerId ID of the debugger backend
1086 @type str
1087 """
1088 self.__clientDebuggerIds.add(debuggerId)
1089
1090 def __clientLine(self, fn, line, debuggerId, threadName, forStack):
1091 """
1092 Private method to handle a change to the current line.
1093
1094 @param fn filename
1095 @type str
1096 @param line linenumber
1097 @type int
1098 @param debuggerId ID of the debugger backend
1099 @type str
1100 @param threadName name of the thread signaling the event
1101 @type str
1102 @param forStack flag indicating this is for a stack dump
1103 @type bool
1104 """
1105 self.ui.raise_()
1106 self.ui.activateWindow()
1107 if self.ui.getViewProfile() != "debug":
1108 self.ui.setDebugProfile()
1109 self.viewmanager.setFileLine(fn, line)
1110 if not forStack:
1111 self.__getThreadList(debuggerId)
1112 self.__getClientVariables(debuggerId)
1113
1114 self.debugActGrp.setEnabled(True)
1115
1116 @pyqtSlot(str)
1117 def __clientDisconnected(self, debuggerId):
1118 """
1119 Private slot to handle a debug client disconnecting its control
1120 socket.
1121
1122 @param debuggerId ID of the debugger backend
1123 @type str
1124 """
1125 self.__clientDebuggerIds.discard(debuggerId)
1126
1127 if len(self.__clientDebuggerIds) == 0:
1128 self.viewmanager.exit()
1129 self.__resetUI(fullReset=False)
1130
1131 @pyqtSlot(str, int, str, bool, str)
1132 def __clientExit(self, program, status, message, quiet, debuggerId):
1133 """
1134 Private slot to handle the debugged program terminating.
1135
1136 @param program name of the exited program
1137 @type str
1138 @param status exit code of the debugged program
1139 @type int
1140 @param message exit message of the debugged program
1141 @type str
1142 @param quiet flag indicating to suppress exit info display
1143 @type bool
1144 @param debuggerId ID of the debugger backend
1145 @type str
1146 """
1147 self.__clientDisconnected(debuggerId)
1148
1149 if not quiet:
1150 if not program:
1151 program = self.ui.currentProg
1152
1153 if message:
1154 info = self.tr("Message: {0}").format(
1155 Utilities.html_uencode(message))
1156 else:
1157 info = ""
1158 if program is None:
1159 msg = self.tr(
1160 '<p>The program has terminated with an exit status of'
1161 ' {0}.</p><p>{1}</p>').format(status, info)
1162 else:
1163 msg = self.tr(
1164 '<p><b>{0}</b> has terminated with an exit status of'
1165 ' {1}.</p><p>{2}</p>').format(
1166 os.path.basename(program), status, info)
1167 if status != 0:
1168 timeout = 0
1169 kind = NotificationTypes.WARNING
1170 else:
1171 timeout = None
1172 kind = NotificationTypes.INFORMATION
1173 self.ui.showNotification(
1174 UI.PixmapCache.getPixmap("debug48"),
1175 self.tr("Program terminated"), msg, kind=kind,
1176 timeout=timeout)
1177
1178 def __lastClientExited(self):
1179 """
1180 Private slot handling the exit of the last client.
1181 """
1182 self.viewmanager.exit()
1183 self.__resetUI()
1184
1185 def __clientSyntaxError(self, message, filename, lineNo, characterNo):
1186 """
1187 Private method to handle a syntax error in the debugged program.
1188
1189 @param message message of the syntax error (string)
1190 @param filename translated filename of the syntax error position
1191 (string)
1192 @param lineNo line number of the syntax error position (integer)
1193 @param characterNo character number of the syntax error position
1194 (integer)
1195 """
1196 self.__resetUI()
1197 self.ui.raise_()
1198 self.ui.activateWindow()
1199
1200 if message is None:
1201 EricMessageBox.critical(
1202 self.ui, Program,
1203 self.tr(
1204 'The program being debugged contains an unspecified'
1205 ' syntax error.'))
1206 return
1207
1208 if not os.path.isabs(filename):
1209 if os.path.exists(os.path.join(self.project.getProjectPath(),
1210 filename)):
1211 filename = os.path.join(self.project.getProjectPath(),
1212 filename)
1213 else:
1214 ms = self.project.getMainScript(normalized=True)
1215 if ms is not None:
1216 d = os.path.dirname(ms)
1217 if os.path.exists(os.path.join(d, filename)):
1218 filename = os.path.join(d, filename)
1219 self.viewmanager.setFileLine(filename, lineNo, True, True)
1220 EricMessageBox.critical(
1221 self.ui, Program,
1222 self.tr('<p>The file <b>{0}</b> contains the syntax error'
1223 ' <b>{1}</b> at line <b>{2}</b>, character <b>{3}</b>.'
1224 '</p>')
1225 .format(filename, message, lineNo, characterNo))
1226
1227 def __clientException(self, exceptionType, exceptionMessage, stackTrace,
1228 debuggerId):
1229 """
1230 Private method to handle an exception of the debugged program.
1231
1232 @param exceptionType type of exception raised
1233 @type str
1234 @param exceptionMessage message given by the exception
1235 @type (str
1236 @param stackTrace list of stack entries
1237 @type list of str
1238 @param debuggerId ID of the debugger backend
1239 @type str
1240 """
1241 self.ui.raise_()
1242 QApplication.processEvents()
1243 if not exceptionType:
1244 EricMessageBox.critical(
1245 self.ui, Program,
1246 self.tr('An unhandled exception occured.'
1247 ' See the shell window for details.'))
1248 return
1249
1250 if (
1251 (self.exceptions and
1252 exceptionType not in self.excIgnoreList and
1253 (not len(self.excList) or
1254 (len(self.excList) and exceptionType in self.excList)
1255 )
1256 ) or exceptionType.startswith('unhandled')
1257 ):
1258 res = None
1259 if stackTrace:
1260 with contextlib.suppress(UnicodeError, OSError):
1261 file, line = stackTrace[0][:2]
1262 source, encoding = Utilities.readEncodedFile(file)
1263 source = source.splitlines(True)
1264 if len(source) >= line:
1265 lineFlags = Utilities.extractLineFlags(
1266 source[line - 1].strip())
1267 with contextlib.suppress(IndexError):
1268 lineFlags += Utilities.extractLineFlags(
1269 source[line].strip(), flagsLine=True)
1270 if "__IGNORE_EXCEPTION__" in lineFlags:
1271 res = EricMessageBox.No
1272 if res != EricMessageBox.No:
1273 self.viewmanager.setFileLine(
1274 stackTrace[0][0], stackTrace[0][1], True)
1275 if res != EricMessageBox.No:
1276 self.ui.activateWindow()
1277 if Preferences.getDebugger("BreakAlways"):
1278 res = EricMessageBox.Yes
1279 else:
1280 if stackTrace:
1281 if exceptionType.startswith('unhandled'):
1282 buttons = EricMessageBox.No | EricMessageBox.Yes
1283 else:
1284 buttons = (EricMessageBox.No |
1285 EricMessageBox.Yes |
1286 EricMessageBox.Ignore)
1287 res = EricMessageBox.critical(
1288 self.ui, Program,
1289 self.tr(
1290 '<p>The debugged program raised the exception'
1291 ' <b>{0}</b><br>"<b>{1}</b>"<br>'
1292 'File: <b>{2}</b>, Line: <b>{3}</b></p>'
1293 '<p>Break here?</p>')
1294 .format(
1295 exceptionType,
1296 Utilities.html_encode(exceptionMessage),
1297 stackTrace[0][0],
1298 stackTrace[0][1]),
1299 buttons,
1300 EricMessageBox.No)
1301 else:
1302 res = EricMessageBox.critical(
1303 self.ui, Program,
1304 self.tr(
1305 '<p>The debugged program raised the exception'
1306 ' <b>{0}</b><br>"<b>{1}</b>"</p>')
1307 .format(
1308 exceptionType,
1309 Utilities.html_encode(exceptionMessage)))
1310 if res == EricMessageBox.Yes:
1311 self.debugServer.setDebugging(True)
1312 self.exceptionInterrupt.emit()
1313 stack = []
1314 for fn, ln, func, args in stackTrace:
1315 stack.append((fn, ln, func, args))
1316 self.clientStack.emit(stack, debuggerId)
1317 self.__getClientVariables(debuggerId)
1318 self.__getClientDisassembly(debuggerId)
1319 self.ui.setDebugProfile()
1320 self.debugActGrp.setEnabled(True)
1321 return
1322 elif (
1323 res == EricMessageBox.Ignore and
1324 exceptionType not in self.excIgnoreList
1325 ):
1326 self.excIgnoreList.append(exceptionType)
1327
1328 if self.lastAction != -1:
1329 if self.lastAction == 2:
1330 self.__specialContinue(debuggerId)
1331 else:
1332 self.debugActions[self.lastAction](debuggerId)
1333 else:
1334 self.__continue(debuggerId)
1335
1336 def __clientSignal(self, message, filename, lineNo, funcName, funcArgs,
1337 debuggerId):
1338 """
1339 Private method to handle a signal generated on the client side.
1340
1341 @param message message of the syntax error
1342 @type str
1343 @param filename translated filename of the syntax error position
1344 @type str
1345 @param lineNo line number of the syntax error position
1346 @type int
1347 @param funcName name of the function causing the signal
1348 @type str
1349 @param funcArgs function arguments
1350 @type str
1351 @param debuggerId ID of the debugger backend
1352 @type str
1353 """
1354 self.ui.raise_()
1355 self.ui.activateWindow()
1356 QApplication.processEvents()
1357 self.viewmanager.setFileLine(filename, lineNo, True)
1358 EricMessageBox.critical(
1359 self.ui, Program,
1360 self.tr("""<p>The program generate the signal "{0}".<br/>"""
1361 """File: <b>{1}</b>, Line: <b>{2}</b></p>""").format(
1362 message, filename, lineNo))
1363
1364 def __clientGone(self, unplanned):
1365 """
1366 Private method to handle the disconnection of the debugger client.
1367
1368 @param unplanned True if the client died, False otherwise
1369 """
1370 self.__resetUI()
1371 if unplanned:
1372 EricMessageBox.information(
1373 self.ui, Program,
1374 self.tr('The program being debugged has terminated'
1375 ' unexpectedly.'))
1376
1377 def __getThreadList(self, debuggerId):
1378 """
1379 Private method to get the list of threads from the client.
1380
1381 @param debuggerId ID of the debugger backend
1382 @type str
1383 """
1384 self.debugServer.remoteThreadList(debuggerId)
1385
1386 def __clientThreadSet(self, debuggerId):
1387 """
1388 Private method to handle a change of the client's current thread.
1389
1390 @param debuggerId ID of the debugger backend
1391 @type str
1392 """
1393 if self.debugServer.isDebugging():
1394 self.debugServer.remoteClientVariables(
1395 debuggerId, 0, self.__localsVarFilterList)
1396
1397 def __getClientVariables(self, debuggerId):
1398 """
1399 Private method to request the global and local variables.
1400
1401 In the first step, the global variables are requested from the client.
1402 Once these have been received, the local variables are requested.
1403 This happens in the method '__clientVariables'.
1404
1405 @param debuggerId ID of the debugger backend
1406 @type str
1407 """
1408 # get globals first
1409 self.debugServer.remoteClientVariables(
1410 debuggerId, 1, self.__globalsVarFilterList)
1411 # the local variables are requested once we have received the globals
1412
1413 def __clientVariables(self, scope, variables, debuggerId):
1414 """
1415 Private method to write the clients variables to the user interface.
1416
1417 @param scope scope of the variables
1418 (-2 = no frame found, -1 = empty locals, 1 = global, 0 = local)
1419 @type int
1420 @param variables the list of variables from the client
1421 @type list
1422 @param debuggerId ID of the debugger backend
1423 @type str
1424 """
1425 if debuggerId == self.getSelectedDebuggerId() and scope > -2:
1426 self.ui.activateDebugViewer()
1427 if scope > 0:
1428 self.debugViewer.showVariables(variables, True)
1429 if scope == 1:
1430 # now get the local variables
1431 self.debugServer.remoteClientVariables(
1432 self.getSelectedDebuggerId(),
1433 0, self.__localsVarFilterList)
1434 elif scope == 0:
1435 self.debugViewer.showVariables(variables, False)
1436 elif scope == -1:
1437 vlist = [
1438 (self.tr('No locals available.'), '', '', False, -2, '')
1439 ]
1440 self.debugViewer.showVariables(vlist, False)
1441
1442 def __clientVariable(self, scope, variables, debuggerId):
1443 """
1444 Private method to write the contents of a clients classvariable to
1445 the user interface.
1446
1447 @param scope scope of the variables (-1 = empty locals, 1 = global,
1448 0 = local)
1449 @type int
1450 @param variables the list of variables from the client
1451 @type list
1452 @param debuggerId ID of the debugger backend
1453 @type str
1454 """
1455 if debuggerId == self.getSelectedDebuggerId():
1456 self.ui.activateDebugViewer()
1457 if scope == 1:
1458 self.debugViewer.showVariable(variables, True)
1459 elif scope == 0:
1460 self.debugViewer.showVariable(variables, False)
1461
1462 def __getClientDisassembly(self, debuggerId):
1463 """
1464 Private method to ask the client for the latest traceback disassembly.
1465
1466 @param debuggerId ID of the debugger backend
1467 @type str
1468 """
1469 self.debugServer.remoteClientDisassembly(debuggerId)
1470
1471 def __clientBreakConditionError(self, filename, lineno, debuggerId):
1472 """
1473 Private method to handle a condition error of a breakpoint.
1474
1475 @param filename filename of the breakpoint
1476 @type str
1477 @param lineno line umber of the breakpoint
1478 @type int
1479 @param debuggerId ID of the debugger backend
1480 @type str
1481 """
1482 EricMessageBox.critical(
1483 self.ui,
1484 self.tr("Breakpoint Condition Error"),
1485 self.tr(
1486 """<p>The condition of the breakpoint <b>{0}, {1}</b>"""
1487 """ contains a syntax error.</p>""")
1488 .format(filename, lineno))
1489
1490 model = self.debugServer.getBreakPointModel()
1491 index = model.getBreakPointIndex(filename, lineno)
1492 if not index.isValid():
1493 return
1494
1495 bp = model.getBreakPointByIndex(index)
1496 if not bp:
1497 return
1498
1499 fn, line, cond, temp, enabled, count = bp[:6]
1500
1501 # get recently used breakpoint conditions
1502 rs = Preferences.Prefs.rsettings.value(
1503 recentNameBreakpointConditions)
1504 condHistory = (
1505 Preferences.toList(rs)[
1506 :Preferences.getDebugger("RecentNumber")]
1507 if rs is not None else
1508 []
1509 )
1510
1511 from .EditBreakpointDialog import EditBreakpointDialog
1512 dlg = EditBreakpointDialog(
1513 (fn, line), (cond, temp, enabled, count),
1514 condHistory, self.ui, modal=True)
1515 if dlg.exec() == QDialog.DialogCode.Accepted:
1516 cond, temp, enabled, count = dlg.getData()
1517 model.setBreakPointByIndex(index, fn, line,
1518 (cond, temp, enabled, count))
1519
1520 if cond:
1521 # save the recently used breakpoint condition
1522 if cond in condHistory:
1523 condHistory.remove(cond)
1524 condHistory.insert(0, cond)
1525 Preferences.Prefs.rsettings.setValue(
1526 recentNameBreakpointConditions, condHistory)
1527 Preferences.Prefs.rsettings.sync()
1528
1529 def __clientWatchConditionError(self, cond, debuggerId):
1530 """
1531 Private method to handle a expression error of a watch expression.
1532
1533 Note: This can only happen for normal watch expressions
1534
1535 @param cond expression of the watch expression
1536 @type str
1537 @param debuggerId ID of the debugger backend
1538 @type str
1539 """
1540 EricMessageBox.critical(
1541 self.ui,
1542 self.tr("Watch Expression Error"),
1543 self.tr("""<p>The watch expression <b>{0}</b>"""
1544 """ contains a syntax error.</p>""")
1545 .format(cond))
1546
1547 model = self.debugServer.getWatchPointModel()
1548 index = model.getWatchPointIndex(cond)
1549 if not index.isValid():
1550 return
1551
1552 wp = model.getWatchPointByIndex(index)
1553 if not wp:
1554 return
1555
1556 cond, special, temp, enabled, count = wp[:5]
1557
1558 from .EditWatchpointDialog import EditWatchpointDialog
1559 dlg = EditWatchpointDialog(
1560 (cond, temp, enabled, count, special), self.ui)
1561 if dlg.exec() == QDialog.DialogCode.Accepted:
1562 cond, temp, enabled, count, special = dlg.getData()
1563
1564 # check for duplicates
1565 idx = model.getWatchPointIndex(cond, special)
1566 duplicate = (idx.isValid() and
1567 idx.internalPointer() != index.internalPointer())
1568 if duplicate:
1569 if not special:
1570 msg = self.tr(
1571 """<p>A watch expression '<b>{0}</b>'"""
1572 """ already exists.</p>"""
1573 ).format(Utilities.html_encode(cond))
1574 else:
1575 msg = self.tr(
1576 """<p>A watch expression '<b>{0}</b>'"""
1577 """ for the variable <b>{1}</b> already"""
1578 """ exists.</p>"""
1579 ).format(special, Utilities.html_encode(cond))
1580 EricMessageBox.warning(
1581 self.ui,
1582 self.tr("Watch expression already exists"),
1583 msg)
1584 model.deleteWatchPointByIndex(index)
1585 else:
1586 model.setWatchPointByIndex(index, cond, special,
1587 (temp, enabled, count))
1588
1589 def __configureVariablesFilters(self):
1590 """
1591 Private slot for displaying the variables filter configuration dialog.
1592 """
1593 from .VariablesFilterDialog import VariablesFilterDialog
1594 dlg = VariablesFilterDialog(self.ui, 'Filter Dialog', True)
1595 dlg.setSelection(self.__localsVarFilterList,
1596 self.__globalsVarFilterList)
1597 if dlg.exec() == QDialog.DialogCode.Accepted:
1598 self.__localsVarFilterList, self.__globalsVarFilterList = (
1599 dlg.getSelection()
1600 )
1601 self.debugViewer.setVariablesFilter(
1602 self.__globalsVarFilterList, self.__localsVarFilterList)
1603
1604 def __configureExceptionsFilter(self):
1605 """
1606 Private slot for displaying the exception filter dialog.
1607 """
1608 from .ExceptionsFilterDialog import ExceptionsFilterDialog
1609 dlg = ExceptionsFilterDialog(self.excList, ignore=False)
1610 if dlg.exec() == QDialog.DialogCode.Accepted:
1611 self.excList = dlg.getExceptionsList()[:] # keep a copy
1612
1613 def __configureIgnoredExceptions(self):
1614 """
1615 Private slot for displaying the ignored exceptions dialog.
1616 """
1617 from .ExceptionsFilterDialog import ExceptionsFilterDialog
1618 dlg = ExceptionsFilterDialog(self.excIgnoreList, ignore=True)
1619 if dlg.exec() == QDialog.DialogCode.Accepted:
1620 self.excIgnoreList = dlg.getExceptionsList()[:] # keep a copy
1621
1622 def __toggleBreakpoint(self):
1623 """
1624 Private slot to handle the 'Set/Reset breakpoint' action.
1625 """
1626 self.viewmanager.activeWindow().menuToggleBreakpoint()
1627
1628 def __editBreakpoint(self):
1629 """
1630 Private slot to handle the 'Edit breakpoint' action.
1631 """
1632 self.viewmanager.activeWindow().menuEditBreakpoint()
1633
1634 def __nextBreakpoint(self):
1635 """
1636 Private slot to handle the 'Next breakpoint' action.
1637 """
1638 self.viewmanager.activeWindow().menuNextBreakpoint()
1639
1640 def __previousBreakpoint(self):
1641 """
1642 Private slot to handle the 'Previous breakpoint' action.
1643 """
1644 self.viewmanager.activeWindow().menuPreviousBreakpoint()
1645
1646 def __clearBreakpoints(self):
1647 """
1648 Private slot to handle the 'Clear breakpoints' action.
1649 """
1650 self.debugServer.getBreakPointModel().deleteAll()
1651
1652 def __showDebugMenu(self):
1653 """
1654 Private method to set up the debug menu.
1655 """
1656 bpCount = self.debugServer.getBreakPointModel().rowCount()
1657 self.menuBreakpointsAct.setEnabled(bpCount > 0)
1658
1659 def __showBreakpointsMenu(self):
1660 """
1661 Private method to handle the show breakpoints menu signal.
1662 """
1663 self.breakpointsMenu.clear()
1664
1665 model = self.debugServer.getBreakPointModel()
1666 for row in range(model.rowCount()):
1667 index = model.index(row, 0)
1668 filename, line, cond = model.getBreakPointByIndex(index)[:3]
1669 formattedCond = " : {0}".format(cond[:20]) if cond else ""
1670 bpSuffix = " : {0:d}{1}".format(line, formattedCond)
1671 act = self.breakpointsMenu.addAction(
1672 "{0}{1}".format(
1673 Utilities.compactPath(
1674 filename,
1675 self.ui.maxMenuFilePathLen - len(bpSuffix)),
1676 bpSuffix))
1677 act.setData([filename, line])
1678
1679 def __breakpointSelected(self, act):
1680 """
1681 Private method to handle the breakpoint selected signal.
1682
1683 @param act reference to the action that triggered (QAction)
1684 """
1685 qvList = act.data()
1686 filename = qvList[0]
1687 line = qvList[1]
1688 self.viewmanager.openSourceFile(filename, line)
1689
1690 def __compileChangedProjectFiles(self):
1691 """
1692 Private method to signal compilation of changed forms and resources
1693 is wanted.
1694 """
1695 if Preferences.getProject("AutoCompileForms"):
1696 self.compileForms.emit()
1697 if Preferences.getProject("AutoCompileResources"):
1698 self.compileResources.emit()
1699 if Preferences.getProject("AutoExecuteMake"):
1700 self.executeMake.emit()
1701 QApplication.processEvents()
1702
1703 def __coverageScript(self):
1704 """
1705 Private slot to handle the coverage of script action.
1706 """
1707 self.doCoverage(False)
1708
1709 def __coverageProject(self):
1710 """
1711 Private slot to handle the coverage of project action.
1712 """
1713 self.__compileChangedProjectFiles()
1714 self.doCoverage(True)
1715
1716 def doCoverage(self, runProject, script=""):
1717 """
1718 Public method to handle the coverage actions.
1719
1720 @param runProject flag indicating coverage of the current project
1721 (True) or script (false)
1722 @type bool
1723 @param script name of a script (optional)
1724 @type str
1725 """
1726 from .StartDialog import StartDialog
1727
1728 self.__resetUI()
1729 doNotStart = False
1730
1731 # Get the command line arguments, the working directory and the
1732 # exception reporting flag.
1733 cap = (
1734 self.tr("Coverage of Project")
1735 if runProject else
1736 self.tr("Coverage of Script")
1737 )
1738 if runProject:
1739 scriptName = self.project.getMainScript(True)
1740 elif script:
1741 scriptName = script
1742 elif self.lastDebuggedFile:
1743 scriptName = self.lastDebuggedFile
1744 else:
1745 scriptName = ""
1746 dlg = StartDialog(
1747 cap, self.lastUsedVenvName, self.argvHistory, self.wdHistory,
1748 self.envHistory, self.exceptions, self.ui, 2,
1749 autoClearShell=self.autoClearShell,
1750 configOverride=self.overrideGlobalConfig,
1751 forProject=runProject, scriptName=scriptName,
1752 scriptsList=self.scriptsHistory)
1753 if dlg.exec() == QDialog.DialogCode.Accepted:
1754 (lastUsedVenvName, scriptName, argv, wd, env, exceptions,
1755 clearShell, console) = dlg.getData()
1756 configOverride = dlg.getGlobalOverrideData()
1757 eraseCoverage = dlg.getCoverageData()
1758
1759 if runProject:
1760 fn = self.project.getMainScript(True)
1761 if fn is None:
1762 EricMessageBox.critical(
1763 self.ui,
1764 self.tr("Coverage of Project"),
1765 self.tr(
1766 "There is no main script defined for the"
1767 " current project. Aborting"))
1768 return
1769
1770 if (
1771 Preferences.getDebugger("Autosave") and
1772 not self.project.saveAllScripts(reportSyntaxErrors=True)
1773 ):
1774 doNotStart = True
1775
1776 # save the info for later use
1777 self.project.setDbgInfo(
1778 lastUsedVenvName, argv, wd, env, exceptions, self.excList,
1779 self.excIgnoreList, clearShell,
1780 configOverride=configOverride
1781 )
1782
1783 self.lastStartAction = 6
1784 self.clientType = self.project.getProjectLanguage()
1785 else:
1786 if scriptName:
1787 fn = scriptName
1788 self.clientType = "Python3"
1789 else:
1790 # run current editor
1791 editor = self.viewmanager.activeWindow()
1792 if editor is None:
1793 return
1794
1795 if (
1796 not self.viewmanager.checkDirty(
1797 editor, Preferences.getDebugger("Autosave")) or
1798 editor.getFileName() is None
1799 ):
1800 return
1801
1802 fn = editor.getFileName()
1803 self.clientType = editor.determineFileType()
1804 self.lastStartAction = 5
1805
1806 # save the filename for use by the restart method
1807 self.lastDebuggedFile = fn
1808 self.restartAct.setEnabled(True)
1809
1810 # save the most recently used virtual environment
1811 self.lastUsedVenvName = lastUsedVenvName
1812
1813 # This moves any previous occurrence of these arguments to the head
1814 # of the list.
1815 self.setScriptsHistory(scriptName)
1816 self.setArgvHistory(argv)
1817 self.setWdHistory(wd)
1818 self.setEnvHistory(env)
1819
1820 # Save the exception flags
1821 self.exceptions = exceptions
1822
1823 # Save the erase coverage flag
1824 self.eraseCoverage = eraseCoverage
1825
1826 # Save the clear interpreter flag
1827 self.autoClearShell = clearShell
1828
1829 # Save the run in console flag
1830 self.runInConsole = console
1831
1832 # Save the global config override data
1833 self.overrideGlobalConfig = copy.deepcopy(configOverride)
1834
1835 # Hide all error highlights
1836 self.viewmanager.unhighlight()
1837
1838 if not doNotStart:
1839 if runProject and self.project.getProjectType() in [
1840 "E7Plugin"]:
1841 argv = '--plugin="{0}" {1}'.format(fn, argv)
1842 fn = os.path.join(getConfig('ericDir'), "eric7.py")
1843
1844 self.debugViewer.initCallStackViewer(runProject)
1845
1846 # Ask the client to open the new program.
1847 self.debugServer.remoteCoverage(
1848 lastUsedVenvName, fn, argv, wd, env,
1849 autoClearShell=self.autoClearShell, erase=eraseCoverage,
1850 forProject=runProject, runInConsole=console,
1851 clientType=self.clientType,
1852 configOverride=self.overrideGlobalConfig)
1853
1854 self.stopAct.setEnabled(True)
1855
1856 if dlg.clearHistories():
1857 self.setScriptsHistory("", clearHistories=True)
1858 self.setArgvHistory("", clearHistories=True)
1859 self.setWdHistory("", clearHistories=True)
1860 self.setEnvHistory("", clearHistories=True)
1861 self.setMultiprocessNoDebugHistory("", clearHistories=True)
1862 elif dlg.historiesModified():
1863 (scriptsHistory, argvHistory, wdHistory, envHistory,
1864 _) = dlg.getHistories()
1865 self.setScriptsHistory("", history=scriptsHistory)
1866 self.setArgvHistory("", history=argvHistory)
1867 self.setWdHistory("", history=wdHistory)
1868 self.setEnvHistory("", history=envHistory)
1869
1870 def __profileScript(self):
1871 """
1872 Private slot to handle the profile script action.
1873 """
1874 self.doProfile(False)
1875
1876 def __profileProject(self):
1877 """
1878 Private slot to handle the profile project action.
1879 """
1880 self.__compileChangedProjectFiles()
1881 self.doProfile(True)
1882
1883 def doProfile(self, runProject, script=""):
1884 """
1885 Public method to handle the profile actions.
1886
1887 @param runProject flag indicating profiling of the current project
1888 (True) or script (False)
1889 @type bool
1890 @param script name of a script (optional)
1891 @type str
1892 """
1893 from .StartDialog import StartDialog
1894
1895 self.__resetUI()
1896 doNotStart = False
1897
1898 # Get the command line arguments, the working directory and the
1899 # exception reporting flag.
1900 cap = (
1901 self.tr("Profile of Project")
1902 if runProject else
1903 self.tr("Profile of Script")
1904 )
1905 if runProject:
1906 scriptName = self.project.getMainScript(True)
1907 elif script:
1908 scriptName = script
1909 elif self.lastDebuggedFile:
1910 scriptName = self.lastDebuggedFile
1911 else:
1912 scriptName = ""
1913 dlg = StartDialog(
1914 cap, self.lastUsedVenvName, self.argvHistory, self.wdHistory,
1915 self.envHistory, self.exceptions, self.ui, 3,
1916 autoClearShell=self.autoClearShell,
1917 configOverride=self.overrideGlobalConfig,
1918 forProject=runProject, scriptName=scriptName,
1919 scriptsList=self.scriptsHistory)
1920 if dlg.exec() == QDialog.DialogCode.Accepted:
1921 (lastUsedVenvName, scriptName, argv, wd, env, exceptions,
1922 clearShell, console) = dlg.getData()
1923 configOverride = dlg.getGlobalOverrideData()
1924 eraseTimings = dlg.getProfilingData()
1925
1926 if runProject:
1927 fn = self.project.getMainScript(True)
1928 if fn is None:
1929 EricMessageBox.critical(
1930 self.ui,
1931 self.tr("Profile of Project"),
1932 self.tr(
1933 "There is no main script defined for the"
1934 " current project. Aborting"))
1935 return
1936
1937 if (
1938 Preferences.getDebugger("Autosave") and
1939 not self.project.saveAllScripts(reportSyntaxErrors=True)
1940 ):
1941 doNotStart = True
1942
1943 # save the info for later use
1944 self.project.setDbgInfo(
1945 lastUsedVenvName, argv, wd, env, exceptions, self.excList,
1946 self.excIgnoreList, clearShell,
1947 configOverride=configOverride
1948 )
1949
1950 self.lastStartAction = 8
1951 self.clientType = self.project.getProjectLanguage()
1952 else:
1953 if scriptName:
1954 fn = scriptName
1955 self.clientType = "Python3"
1956 else:
1957 # run current editor
1958 editor = self.viewmanager.activeWindow()
1959 if editor is None:
1960 return
1961
1962 if (
1963 not self.viewmanager.checkDirty(
1964 editor, Preferences.getDebugger("Autosave")) or
1965 editor.getFileName() is None
1966 ):
1967 return
1968
1969 fn = editor.getFileName()
1970 self.clientType = editor.determineFileType()
1971 self.lastStartAction = 7
1972
1973 # save the filename for use by the restart method
1974 self.lastDebuggedFile = fn
1975 self.restartAct.setEnabled(True)
1976
1977 # save the most recently used virtual environment
1978 self.lastUsedVenvName = lastUsedVenvName
1979
1980 # This moves any previous occurrence of these arguments to the head
1981 # of the list.
1982 self.setScriptsHistory(scriptName)
1983 self.setArgvHistory(argv)
1984 self.setWdHistory(wd)
1985 self.setEnvHistory(env)
1986
1987 # Save the exception flags
1988 self.exceptions = exceptions
1989
1990 # Save the erase timing flag
1991 self.eraseTimings = eraseTimings
1992
1993 # Save the clear interpreter flag
1994 self.autoClearShell = clearShell
1995
1996 # Save the run in console flag
1997 self.runInConsole = console
1998
1999 # Save the global config override data
2000 self.overrideGlobalConfig = copy.deepcopy(configOverride)
2001
2002 # Hide all error highlights
2003 self.viewmanager.unhighlight()
2004
2005 if not doNotStart:
2006 if runProject and self.project.getProjectType() in [
2007 "E7Plugin"]:
2008 argv = '--plugin="{0}" {1}'.format(fn, argv)
2009 fn = os.path.join(getConfig('ericDir'), "eric7.py")
2010
2011 self.debugViewer.initCallStackViewer(runProject)
2012
2013 # Ask the client to open the new program.
2014 self.debugServer.remoteProfile(
2015 lastUsedVenvName, fn, argv, wd, env,
2016 autoClearShell=self.autoClearShell, erase=eraseTimings,
2017 forProject=runProject, runInConsole=console,
2018 clientType=self.clientType,
2019 configOverride=self.overrideGlobalConfig)
2020
2021 self.stopAct.setEnabled(True)
2022
2023 if dlg.clearHistories():
2024 self.setScriptsHistory("", clearHistories=True)
2025 self.setArgvHistory("", clearHistories=True)
2026 self.setWdHistory("", clearHistories=True)
2027 self.setEnvHistory("", clearHistories=True)
2028 self.setMultiprocessNoDebugHistory("", clearHistories=True)
2029 elif dlg.historiesModified():
2030 (scriptsHistory, argvHistory, wdHistory, envHistory,
2031 _) = dlg.getHistories()
2032 self.setScriptsHistory("", history=scriptsHistory)
2033 self.setArgvHistory("", history=argvHistory)
2034 self.setWdHistory("", history=wdHistory)
2035 self.setEnvHistory("", history=envHistory)
2036
2037 def __runScript(self):
2038 """
2039 Private slot to handle the run script action.
2040 """
2041 self.doRun(False)
2042
2043 def __runProject(self):
2044 """
2045 Private slot to handle the run project action.
2046 """
2047 self.__compileChangedProjectFiles()
2048 self.doRun(True)
2049
2050 def doRun(self, runProject, script=""):
2051 """
2052 Public method to handle the run actions.
2053
2054 @param runProject flag indicating running the current project (True)
2055 or script (False)
2056 @type bool
2057 @param script name of a script (optional)
2058 @type str
2059 """
2060 from .StartDialog import StartDialog
2061
2062 self.__resetUI()
2063 doNotStart = False
2064
2065 # Get the command line arguments, the working directory and the
2066 # exception reporting flag.
2067 cap = (
2068 self.tr("Run Project")
2069 if runProject else
2070 self.tr("Run Script")
2071 )
2072 if runProject:
2073 scriptName = self.project.getMainScript(True)
2074 elif script:
2075 scriptName = script
2076 elif self.lastDebuggedFile:
2077 scriptName = self.lastDebuggedFile
2078 else:
2079 scriptName = ""
2080 dlg = StartDialog(
2081 cap, self.lastUsedVenvName, self.argvHistory, self.wdHistory,
2082 self.envHistory, self.exceptions, self.ui, 1,
2083 autoClearShell=self.autoClearShell,
2084 configOverride=self.overrideGlobalConfig,
2085 forProject=runProject, scriptName=scriptName,
2086 scriptsList=self.scriptsHistory)
2087 if dlg.exec() == QDialog.DialogCode.Accepted:
2088 (lastUsedVenvName, scriptName, argv, wd, env, exceptions,
2089 clearShell, console) = dlg.getData()
2090 configOverride = dlg.getGlobalOverrideData()
2091
2092 if runProject:
2093 fn = self.project.getMainScript(True)
2094 if fn is None:
2095 EricMessageBox.critical(
2096 self.ui,
2097 self.tr("Run Project"),
2098 self.tr(
2099 "There is no main script defined for the"
2100 " current project. Aborting"))
2101 return
2102
2103 if (
2104 Preferences.getDebugger("Autosave") and
2105 not self.project.saveAllScripts(reportSyntaxErrors=True)
2106 ):
2107 doNotStart = True
2108
2109 # save the info for later use
2110 self.project.setDbgInfo(
2111 lastUsedVenvName, argv, wd, env, exceptions, self.excList,
2112 self.excIgnoreList, clearShell,
2113 configOverride=configOverride
2114 )
2115
2116 self.lastStartAction = 4
2117 self.clientType = self.project.getProjectLanguage()
2118 else:
2119 if scriptName:
2120 fn = scriptName
2121 self.clientType = "Python3"
2122 else:
2123 # run current editor
2124 editor = self.viewmanager.activeWindow()
2125 if editor is None:
2126 return
2127
2128 if (
2129 not self.viewmanager.checkDirty(
2130 editor,
2131 Preferences.getDebugger("Autosave")) or
2132 editor.getFileName() is None
2133 ):
2134 return
2135
2136 fn = editor.getFileName()
2137 self.clientType = editor.determineFileType()
2138 self.lastStartAction = 3
2139
2140 # save the filename for use by the restart method
2141 self.lastDebuggedFile = fn
2142 self.restartAct.setEnabled(True)
2143
2144 # save the most recently used virtual environment
2145 self.lastUsedVenvName = lastUsedVenvName
2146
2147 # This moves any previous occurrence of these arguments to the head
2148 # of the list.
2149 self.setScriptsHistory(scriptName)
2150 self.setArgvHistory(argv)
2151 self.setWdHistory(wd)
2152 self.setEnvHistory(env)
2153
2154 # Save the exception flags
2155 self.exceptions = exceptions
2156
2157 # Save the clear interpreter flag
2158 self.autoClearShell = clearShell
2159
2160 # Save the run in console flag
2161 self.runInConsole = console
2162
2163 # Save the global config override data
2164 self.overrideGlobalConfig = copy.deepcopy(configOverride)
2165
2166 # Hide all error highlights
2167 self.viewmanager.unhighlight()
2168
2169 if not doNotStart:
2170 if runProject and self.project.getProjectType() in [
2171 "E7Plugin"]:
2172 argv = '--plugin="{0}" {1}'.format(fn, argv)
2173 fn = os.path.join(getConfig('ericDir'), "eric7.py")
2174
2175 self.debugViewer.initCallStackViewer(runProject)
2176
2177 # Ask the client to open the new program.
2178 self.debugServer.remoteRun(
2179 lastUsedVenvName, fn, argv, wd, env,
2180 autoClearShell=self.autoClearShell, forProject=runProject,
2181 runInConsole=console, clientType=self.clientType,
2182 configOverride=self.overrideGlobalConfig)
2183
2184 self.stopAct.setEnabled(True)
2185
2186 if dlg.clearHistories():
2187 self.setScriptsHistory("", clearHistories=True)
2188 self.setArgvHistory("", clearHistories=True)
2189 self.setWdHistory("", clearHistories=True)
2190 self.setEnvHistory("", clearHistories=True)
2191 self.setMultiprocessNoDebugHistory("", clearHistories=True)
2192 elif dlg.historiesModified():
2193 (scriptsHistory, argvHistory, wdHistory, envHistory,
2194 _) = dlg.getHistories()
2195 self.setScriptsHistory("", history=scriptsHistory)
2196 self.setArgvHistory("", history=argvHistory)
2197 self.setWdHistory("", history=wdHistory)
2198 self.setEnvHistory("", history=envHistory)
2199
2200 def __debugScript(self):
2201 """
2202 Private slot to handle the debug script action.
2203 """
2204 self.doDebug(False)
2205
2206 def __debugProject(self):
2207 """
2208 Private slot to handle the debug project action.
2209 """
2210 self.__compileChangedProjectFiles()
2211 self.doDebug(True)
2212
2213 def doDebug(self, debugProject, script=""):
2214 """
2215 Public method to handle the debug actions.
2216
2217 @param debugProject flag indicating debugging the current project
2218 (True) or script (False)
2219 @type bool
2220 @param script name of a script (optional)
2221 @type str
2222 """
2223 from .StartDialog import StartDialog
2224
2225 self.__resetUI()
2226 doNotStart = False
2227
2228 # Get the command line arguments, the working directory and the
2229 # exception reporting flag.
2230 cap = (
2231 self.tr("Debug Project")
2232 if debugProject else
2233 self.tr("Debug Script")
2234 )
2235 if debugProject:
2236 scriptName = self.project.getMainScript(True)
2237 elif script:
2238 scriptName = script
2239 elif self.lastDebuggedFile:
2240 scriptName = self.lastDebuggedFile
2241 else:
2242 scriptName = ""
2243 dlg = StartDialog(
2244 cap, self.lastUsedVenvName, self.argvHistory, self.wdHistory,
2245 self.envHistory, self.exceptions, self.ui, 0,
2246 tracePython=self.tracePython, autoClearShell=self.autoClearShell,
2247 autoContinue=self.autoContinue,
2248 enableMultiprocess=self.enableMultiprocess,
2249 multiprocessNoDebugHistory=self.multiprocessNoDebugHistory,
2250 configOverride=self.overrideGlobalConfig,
2251 forProject=debugProject, scriptName=scriptName,
2252 scriptsList=self.scriptsHistory)
2253 if dlg.exec() == QDialog.DialogCode.Accepted:
2254 (lastUsedVenvName, scriptName, argv, wd, env, exceptions,
2255 clearShell, console) = dlg.getData()
2256 configOverride = dlg.getGlobalOverrideData()
2257 (tracePython, autoContinue, enableMultiprocess,
2258 multiprocessNoDebug) = dlg.getDebugData()
2259
2260 if debugProject:
2261 fn = self.project.getMainScript(True)
2262 if fn is None:
2263 EricMessageBox.critical(
2264 self.ui,
2265 self.tr("Debug Project"),
2266 self.tr(
2267 "There is no main script defined for the"
2268 " current project. No debugging possible."))
2269 return
2270
2271 if (
2272 Preferences.getDebugger("Autosave") and
2273 not self.project.saveAllScripts(reportSyntaxErrors=True)
2274 ):
2275 doNotStart = True
2276
2277 # save the info for later use
2278 self.project.setDbgInfo(
2279 lastUsedVenvName, argv, wd, env, exceptions, self.excList,
2280 self.excIgnoreList, clearShell, tracePython=tracePython,
2281 autoContinue=autoContinue,
2282 enableMultiprocess=enableMultiprocess,
2283 multiprocessNoDebug=multiprocessNoDebug,
2284 configOverride=configOverride
2285 )
2286
2287 self.lastStartAction = 2
2288 self.clientType = self.project.getProjectLanguage()
2289 else:
2290 if scriptName:
2291 fn = scriptName
2292 self.clientType = "Python3"
2293 else:
2294 # debug current editor
2295 editor = self.viewmanager.activeWindow()
2296 if editor is None:
2297 return
2298
2299 if (
2300 not self.viewmanager.checkDirty(
2301 editor, Preferences.getDebugger("Autosave")) or
2302 editor.getFileName() is None
2303 ):
2304 return
2305
2306 fn = editor.getFileName()
2307 self.clientType = editor.determineFileType()
2308 self.lastStartAction = 1
2309
2310 # save the filename for use by the restart method
2311 self.lastDebuggedFile = fn
2312 self.restartAct.setEnabled(True)
2313
2314 # save the most recently used virtual environment
2315 self.lastUsedVenvName = lastUsedVenvName
2316
2317 # This moves any previous occurrence of these arguments to the head
2318 # of the list.
2319 self.setScriptsHistory(scriptName)
2320 self.setArgvHistory(argv)
2321 self.setWdHistory(wd)
2322 self.setEnvHistory(env)
2323
2324 # Save the exception flags
2325 self.exceptions = exceptions
2326
2327 # Save the tracePython flag
2328 self.tracePython = tracePython
2329
2330 # Save the clear interpreter flag
2331 self.autoClearShell = clearShell
2332
2333 # Save the run in console flag
2334 self.runInConsole = console
2335
2336 # Save the auto continue flag
2337 self.autoContinue = autoContinue
2338
2339 # Save the multiprocess debugging data
2340 self.enableMultiprocess = enableMultiprocess
2341 self.setMultiprocessNoDebugHistory(multiprocessNoDebug)
2342
2343 # Save the global config override data
2344 self.overrideGlobalConfig = copy.deepcopy(configOverride)
2345
2346 # Hide all error highlights
2347 self.viewmanager.unhighlight()
2348
2349 if not doNotStart:
2350 if debugProject and self.project.getProjectType() in [
2351 "E7Plugin"]:
2352 argv = '--plugin="{0}" {1}'.format(fn, argv)
2353 fn = os.path.join(getConfig('ericDir'), "eric7.py")
2354 tracePython = True # override flag because it must be true
2355
2356 self.debugViewer.initCallStackViewer(debugProject)
2357
2358 # Ask the client to send call trace info
2359 enableCallTrace = self.debugViewer.isCallTraceEnabled()
2360 self.debugViewer.clearCallTrace()
2361 self.debugViewer.setCallTraceToProjectMode(debugProject)
2362
2363 # Ask the client to open the new program.
2364 self.debugServer.remoteLoad(
2365 lastUsedVenvName, fn, argv, wd, env,
2366 autoClearShell=self.autoClearShell,
2367 tracePython=tracePython,
2368 autoContinue=autoContinue, forProject=debugProject,
2369 runInConsole=console, clientType=self.clientType,
2370 enableCallTrace=enableCallTrace,
2371 enableMultiprocess=enableMultiprocess,
2372 multiprocessNoDebug=multiprocessNoDebug,
2373 configOverride=self.overrideGlobalConfig)
2374
2375 if (
2376 self.debugServer.isClientProcessUp() and
2377 self.debugServer.getClientType() == self.clientType
2378 ):
2379 # Signal that we have started a debugging session
2380 self.debuggingStarted.emit(fn)
2381
2382 self.stopAct.setEnabled(True)
2383
2384 if dlg.clearHistories():
2385 self.setScriptsHistory("", clearHistories=True)
2386 self.setArgvHistory("", clearHistories=True)
2387 self.setWdHistory("", clearHistories=True)
2388 self.setEnvHistory("", clearHistories=True)
2389 self.setMultiprocessNoDebugHistory("", clearHistories=True)
2390 elif dlg.historiesModified():
2391 (scriptsHistory, argvHistory, wdHistory, envHistory,
2392 noDebugHistory) = dlg.getHistories()
2393 self.setScriptsHistory("", history=scriptsHistory)
2394 self.setArgvHistory("", history=argvHistory)
2395 self.setWdHistory("", history=wdHistory)
2396 self.setEnvHistory("", history=envHistory)
2397 self.setMultiprocessNoDebugHistory("", history=noDebugHistory)
2398
2399 def __doRestart(self):
2400 """
2401 Private slot to handle the restart action to restart the last
2402 debugged file.
2403 """
2404 self.__resetUI()
2405 doNotStart = False
2406
2407 # first save any changes
2408 if self.lastStartAction in [1, 3, 5, 7, 9]:
2409 editor = self.viewmanager.getOpenEditor(self.lastDebuggedFile)
2410 if (
2411 editor and
2412 not self.viewmanager.checkDirty(
2413 editor, Preferences.getDebugger("Autosave"))
2414 ):
2415 return
2416 forProject = False
2417 elif self.lastStartAction in [2, 4, 6, 8, 10]:
2418 if (
2419 Preferences.getDebugger("Autosave") and
2420 not self.project.saveAllScripts(reportSyntaxErrors=True)
2421 ):
2422 doNotStart = True
2423 self.__compileChangedProjectFiles()
2424 forProject = True
2425 else:
2426 return # should not happen
2427
2428 # get the saved stuff
2429 venvName = self.lastUsedVenvName
2430 wd = self.wdHistory[0]
2431 argv = self.argvHistory[0]
2432 fn = self.lastDebuggedFile
2433 env = self.envHistory[0]
2434
2435 # Hide all error highlights
2436 self.viewmanager.unhighlight()
2437
2438 if not doNotStart:
2439 if forProject and self.project.getProjectType() in [
2440 "E7Plugin"]:
2441 argv = '--plugin="{0}" {1}'.format(fn, argv)
2442 fn = os.path.join(getConfig('ericDir'), "eric7.py")
2443
2444 self.debugViewer.initCallStackViewer(forProject)
2445
2446 if self.lastStartAction in [1, 2]:
2447 # Ask the client to send call trace info
2448 enableCallTrace = self.debugViewer.isCallTraceEnabled()
2449 self.debugViewer.clearCallTrace()
2450 self.debugViewer.setCallTraceToProjectMode(forProject)
2451 multiprocessNoDebug = self.multiprocessNoDebugHistory[0]
2452
2453 # Ask the client to debug the new program.
2454 self.debugServer.remoteLoad(
2455 venvName, fn, argv, wd, env,
2456 autoClearShell=self.autoClearShell,
2457 tracePython=self.tracePython,
2458 autoContinue=self.autoContinue,
2459 forProject=forProject,
2460 runInConsole=self.runInConsole,
2461 clientType=self.clientType,
2462 enableCallTrace=enableCallTrace,
2463 enableMultiprocess=self.enableMultiprocess,
2464 multiprocessNoDebug=multiprocessNoDebug,
2465 configOverride=self.overrideGlobalConfig)
2466
2467 # Signal that we have started a debugging session
2468 self.debuggingStarted.emit(fn)
2469
2470 elif self.lastStartAction in [3, 4]:
2471 # Ask the client to run the new program.
2472 self.debugServer.remoteRun(
2473 venvName, fn, argv, wd, env,
2474 autoClearShell=self.autoClearShell,
2475 forProject=forProject,
2476 runInConsole=self.runInConsole,
2477 clientType=self.clientType,
2478 configOverride=self.overrideGlobalConfig)
2479
2480 elif self.lastStartAction in [5, 6]:
2481 # Ask the client to coverage run the new program.
2482 self.debugServer.remoteCoverage(
2483 venvName, fn, argv, wd, env,
2484 autoClearShell=self.autoClearShell,
2485 erase=self.eraseCoverage,
2486 forProject=forProject,
2487 runInConsole=self.runInConsole,
2488 clientType=self.clientType,
2489 configOverride=self.overrideGlobalConfig)
2490
2491 elif self.lastStartAction in [7, 8]:
2492 # Ask the client to profile run the new program.
2493 self.debugServer.remoteProfile(
2494 venvName, fn, argv, wd, env,
2495 autoClearShell=self.autoClearShell,
2496 erase=self.eraseTimings,
2497 forProject=forProject,
2498 runInConsole=self.runInConsole,
2499 clientType=self.clientType,
2500 configOverride=self.overrideGlobalConfig)
2501
2502 self.stopAct.setEnabled(True)
2503
2504 def __stopScript(self):
2505 """
2506 Private slot to stop the running script.
2507 """
2508 self.debugServer.startClient(False)
2509
2510 def __passiveDebugStarted(self, fn, exc):
2511 """
2512 Private slot to handle a passive debug session start.
2513
2514 @param fn filename of the debugged script
2515 @param exc flag to enable exception reporting of the IDE (boolean)
2516 """
2517 # Hide all error highlights
2518 self.viewmanager.unhighlight()
2519
2520 # Set filename of script being debugged
2521 self.ui.currentProg = fn
2522
2523 # Set exception reporting
2524 self.setExceptionReporting(exc)
2525
2526 # Signal that we have started a debugging session
2527 self.debuggingStarted.emit(fn)
2528
2529 # Initialize the call stack viewer
2530 self.debugViewer.initCallStackViewer(False)
2531
2532 def __continue(self, debuggerId=""):
2533 """
2534 Private method to handle the Continue action.
2535
2536 @param debuggerId ID of the debugger backend
2537 @type str
2538 """
2539 if not debuggerId:
2540 debuggerId = self.getSelectedDebuggerId()
2541
2542 self.lastAction = 0
2543 self.__enterRemote()
2544 self.debugServer.remoteContinue(debuggerId)
2545
2546 def __specialContinue(self, debuggerId=""):
2547 """
2548 Private method to handle the Special Continue action.
2549
2550 @param debuggerId ID of the debugger backend
2551 @type str
2552 """
2553 if not debuggerId:
2554 debuggerId = self.getSelectedDebuggerId()
2555
2556 self.lastAction = 2
2557 self.__enterRemote()
2558 self.debugServer.remoteContinue(debuggerId, 1)
2559
2560 def __step(self, debuggerId=""):
2561 """
2562 Private method to handle the Step action.
2563
2564 @param debuggerId ID of the debugger backend
2565 @type str
2566 """
2567 if not debuggerId:
2568 debuggerId = self.getSelectedDebuggerId()
2569
2570 self.lastAction = 1
2571 self.__enterRemote()
2572 self.debugServer.remoteStep(debuggerId)
2573
2574 def __stepOver(self, debuggerId=""):
2575 """
2576 Private method to handle the Step Over action.
2577
2578 @param debuggerId ID of the debugger backend
2579 @type str
2580 """
2581 if not debuggerId:
2582 debuggerId = self.getSelectedDebuggerId()
2583
2584 self.lastAction = 2
2585 self.__enterRemote()
2586 self.debugServer.remoteStepOver(debuggerId)
2587
2588 def __stepOut(self, debuggerId=""):
2589 """
2590 Private method to handle the Step Out action.
2591
2592 @param debuggerId ID of the debugger backend
2593 @type str
2594 """
2595 if not debuggerId:
2596 debuggerId = self.getSelectedDebuggerId()
2597
2598 self.lastAction = 3
2599 self.__enterRemote()
2600 self.debugServer.remoteStepOut(debuggerId)
2601
2602 def __stepQuit(self, debuggerId=""):
2603 """
2604 Private method to handle the Step Quit action.
2605
2606 @param debuggerId ID of the debugger backend
2607 @type str
2608 """
2609 if not debuggerId:
2610 debuggerId = self.getSelectedDebuggerId()
2611
2612 self.lastAction = 4
2613 self.__enterRemote()
2614 self.debugServer.remoteStepQuit(debuggerId)
2615 self.__resetUI()
2616
2617 def __runToCursor(self, debuggerId=""):
2618 """
2619 Private method to handle the Run to Cursor action.
2620
2621 @param debuggerId ID of the debugger backend
2622 @type str
2623 """
2624 if not debuggerId:
2625 debuggerId = self.getSelectedDebuggerId()
2626
2627 self.lastAction = 0
2628 aw = self.viewmanager.activeWindow()
2629 line = aw.getCursorPosition()[0] + 1
2630 self.__enterRemote()
2631 self.debugServer.remoteBreakpoint(
2632 self.getSelectedDebuggerId(),
2633 aw.getFileName(), line, 1, None, 1)
2634 self.debugServer.remoteContinue(debuggerId)
2635
2636 def __runUntil(self, debuggerId=""):
2637 """
2638 Private method to handle the Run Until action.
2639
2640 @param debuggerId ID of the debugger backend
2641 @type str
2642 """
2643 if not debuggerId:
2644 debuggerId = self.getSelectedDebuggerId()
2645
2646 self.lastAction = 0
2647 aw = self.viewmanager.activeWindow()
2648 line = aw.getCursorPosition()[0] + 1
2649 self.__enterRemote()
2650 self.debugServer.remoteContinueUntil(debuggerId, line)
2651
2652 def __moveInstructionPointer(self, debuggerId=""):
2653 """
2654 Private method to move the instruction pointer to a different line.
2655
2656 @param debuggerId ID of the debugger backend
2657 @type str
2658 """
2659 if not debuggerId:
2660 debuggerId = self.getSelectedDebuggerId()
2661
2662 self.lastAction = 0
2663 aw = self.viewmanager.activeWindow()
2664 line = aw.getCursorPosition()[0] + 1
2665 self.debugServer.remoteMoveIP(debuggerId, line)
2666
2667 def __enterRemote(self):
2668 """
2669 Private method to update the user interface.
2670
2671 This method is called just prior to executing some of
2672 the program being debugged.
2673 """
2674 # Disable further debug commands from the user.
2675 self.debugActGrp.setEnabled(False)
2676
2677 self.viewmanager.unhighlight(True)
2678
2679 def getActions(self):
2680 """
2681 Public method to get a list of all actions.
2682
2683 @return list of all actions (list of EricAction)
2684 """
2685 return self.actions[:]
2686
2687 def getSelectedDebuggerId(self):
2688 """
2689 Public method to get the currently selected debugger ID.
2690
2691 @return selected debugger ID
2692 @rtype str
2693 """
2694 return self.debugViewer.getSelectedDebuggerId()
2695
2696 def setDebugActionsEnabled(self, enable):
2697 """
2698 Public method to set the enabled state of the debug actions.
2699
2700 @param enable enable state to be set
2701 @type bool
2702 """
2703 self.debugActGrp.setEnabled(enable)
2704
2705 def setMultiprocessNoDebugHistory(self, noDebugList, clearHistories=False,
2706 history=None):
2707 """
2708 Public slot to initialize the no debug list history.
2709
2710 @param noDebugList whitespace separated list of programs not to be
2711 debugged
2712 @type str
2713 @param clearHistories flag indicating, that the list should be cleared
2714 @type bool
2715 @param history list of history entries to be set
2716 @type list of str
2717 """
2718 if clearHistories:
2719 del self.multiprocessNoDebugHistory[1:]
2720 elif history is not None:
2721 self.multiprocessNoDebugHistory = history[:]
2722 else:
2723 if noDebugList in self.multiprocessNoDebugHistory:
2724 self.multiprocessNoDebugHistory.remove(noDebugList)
2725 self.multiprocessNoDebugHistory.insert(0, noDebugList)
2726
2727 def setEnableMultiprocess(self, enableMultiprocess):
2728 """
2729 Public slot to initialize the enableMultiprocess flag.
2730
2731 @param enableMultiprocess flag indicating, that the debugger should be
2732 run in multi process mode
2733 @type bool
2734 """
2735 self.enableMultiprocess = enableMultiprocess
2736
2737 def setEnableGlobalConfigOverride(self, overrideData):
2738 """
2739 Public method to initialize the global config override data.
2740
2741 @param overrideData dictionary containing a flag indicating to enable
2742 global config override and a flag indicating to redirect
2743 stdin/stdout/stderr
2744 @type dict
2745 """
2746 self.overrideGlobalConfig = copy.deepcopy(overrideData)

eric ide

mercurial