25 from eric5config import getConfig |
25 from eric5config import getConfig |
26 |
26 |
27 |
27 |
28 ClientDefaultCapabilities = DebugClientCapabilities.HasAll |
28 ClientDefaultCapabilities = DebugClientCapabilities.HasAll |
29 |
29 |
|
30 |
30 def getRegistryData(): |
31 def getRegistryData(): |
31 """ |
32 """ |
32 Module function to get characterising data for the debugger interface. |
33 Module function to get characterising data for the debugger interface. |
33 |
34 |
34 @return list of the following data. Client type (string), client |
35 @return list of the following data. Client type (string), client |
35 capabilities (integer), client type association (list of strings) |
36 capabilities (integer), client type association (list of strings) |
36 """ |
37 """ |
37 exts = [] |
38 exts = [] |
38 for ext in Preferences.getDebugger("Python3Extensions").split(): |
39 for ext in Preferences.getDebugger("Python3Extensions").split(): |
39 if ext.startswith("."): |
40 if ext.startswith("."): |
82 Preferences.getDebugger("PathTranslationLocal") |
84 Preferences.getDebugger("PathTranslationLocal") |
83 self.translate = self.__remoteTranslation |
85 self.translate = self.__remoteTranslation |
84 else: |
86 else: |
85 self.translate = self.__identityTranslation |
87 self.translate = self.__identityTranslation |
86 |
88 |
87 def __identityTranslation(self, fn, remote2local = True): |
89 def __identityTranslation(self, fn, remote2local=True): |
88 """ |
90 """ |
89 Private method to perform the identity path translation. |
91 Private method to perform the identity path translation. |
90 |
92 |
91 @param fn filename to be translated (string) |
93 @param fn filename to be translated (string) |
92 @param remote2local flag indicating the direction of translation |
94 @param remote2local flag indicating the direction of translation |
93 (False = local to remote, True = remote to local [default]) |
95 (False = local to remote, True = remote to local [default]) |
94 @return translated filename (string) |
96 @return translated filename (string) |
95 """ |
97 """ |
96 return fn |
98 return fn |
97 |
99 |
98 def __remoteTranslation(self, fn, remote2local = True): |
100 def __remoteTranslation(self, fn, remote2local=True): |
99 """ |
101 """ |
100 Private method to perform the path translation. |
102 Private method to perform the path translation. |
101 |
103 |
102 @param fn filename to be translated (string) |
104 @param fn filename to be translated (string) |
103 @param remote2local flag indicating the direction of translation |
105 @param remote2local flag indicating the direction of translation |
107 if remote2local: |
109 if remote2local: |
108 return fn.replace(self.translateRemote, self.translateLocal) |
110 return fn.replace(self.translateRemote, self.translateLocal) |
109 else: |
111 else: |
110 return fn.replace(self.translateLocal, self.translateRemote) |
112 return fn.replace(self.translateLocal, self.translateRemote) |
111 |
113 |
112 def __startProcess(self, program, arguments, environment = None): |
114 def __startProcess(self, program, arguments, environment=None): |
113 """ |
115 """ |
114 Private method to start the debugger client process. |
116 Private method to start the debugger client process. |
115 |
117 |
116 @param program name of the executable to start (string) |
118 @param program name of the executable to start (string) |
117 @param arguments arguments to be passed to the program (list of string) |
119 @param arguments arguments to be passed to the program (list of string) |
136 def startRemote(self, port, runInConsole): |
138 def startRemote(self, port, runInConsole): |
137 """ |
139 """ |
138 Public method to start a remote Python interpreter. |
140 Public method to start a remote Python interpreter. |
139 |
141 |
140 @param port portnumber the debug server is listening on (integer) |
142 @param port portnumber the debug server is listening on (integer) |
141 @param runInConsole flag indicating to start the debugger in a |
143 @param runInConsole flag indicating to start the debugger in a |
142 console window (boolean) |
144 console window (boolean) |
143 @return client process object (QProcess) and a flag to indicate |
145 @return client process object (QProcess) and a flag to indicate |
144 a network connection (boolean) |
146 a network connection (boolean) |
145 """ |
147 """ |
146 if Preferences.getDebugger("CustomPython3Interpreter"): |
148 if Preferences.getDebugger("CustomPython3Interpreter"): |
150 else: |
152 else: |
151 interpreter = sys.executable |
153 interpreter = sys.executable |
152 |
154 |
153 debugClientType = Preferences.getDebugger("DebugClientType3") |
155 debugClientType = Preferences.getDebugger("DebugClientType3") |
154 if debugClientType == "standard": |
156 if debugClientType == "standard": |
155 debugClient = os.path.join(getConfig('ericDir'), |
157 debugClient = os.path.join(getConfig('ericDir'), |
156 "DebugClients", "Python3", "DebugClient.py") |
158 "DebugClients", "Python3", "DebugClient.py") |
157 elif debugClientType == "threaded": |
159 elif debugClientType == "threaded": |
158 debugClient = os.path.join(getConfig('ericDir'), |
160 debugClient = os.path.join(getConfig('ericDir'), |
159 "DebugClients", "Python3", "DebugClientThreads.py") |
161 "DebugClients", "Python3", "DebugClientThreads.py") |
160 else: |
162 else: |
229 self.trUtf8("Start Debugger"), |
231 self.trUtf8("Start Debugger"), |
230 self.trUtf8( |
232 self.trUtf8( |
231 """<p>The debugger backend could not be started.</p>""")) |
233 """<p>The debugger backend could not be started.</p>""")) |
232 return process, self.__isNetworked |
234 return process, self.__isNetworked |
233 |
235 |
234 process = self.__startProcess(interpreter, |
236 process = self.__startProcess(interpreter, |
235 [debugClient, noencoding, str(port), redirect, ipaddr], |
237 [debugClient, noencoding, str(port), redirect, ipaddr], |
236 clientEnv) |
238 clientEnv) |
237 if process is None: |
239 if process is None: |
238 E5MessageBox.critical(None, |
240 E5MessageBox.critical(None, |
239 self.trUtf8("Start Debugger"), |
241 self.trUtf8("Start Debugger"), |
240 self.trUtf8("""<p>The debugger backend could not be started.</p>""")) |
242 self.trUtf8("""<p>The debugger backend could not be started.</p>""")) |
243 def startRemoteForProject(self, port, runInConsole): |
245 def startRemoteForProject(self, port, runInConsole): |
244 """ |
246 """ |
245 Public method to start a remote Python interpreter for a project. |
247 Public method to start a remote Python interpreter for a project. |
246 |
248 |
247 @param port portnumber the debug server is listening on (integer) |
249 @param port portnumber the debug server is listening on (integer) |
248 @param runInConsole flag indicating to start the debugger in a |
250 @param runInConsole flag indicating to start the debugger in a |
249 console window (boolean) |
251 console window (boolean) |
250 @return client process object (QProcess) and a flag to indicate |
252 @return client process object (QProcess) and a flag to indicate |
251 a network connection (boolean) |
253 a network connection (boolean) |
252 """ |
254 """ |
253 project = e5App().getObject("Project") |
255 project = e5App().getObject("Project") |
322 self.trUtf8("Start Debugger"), |
324 self.trUtf8("Start Debugger"), |
323 self.trUtf8( |
325 self.trUtf8( |
324 """<p>The debugger backend could not be started.</p>""")) |
326 """<p>The debugger backend could not be started.</p>""")) |
325 return process, self.__isNetworked |
327 return process, self.__isNetworked |
326 |
328 |
327 process = self.__startProcess(interpreter, |
329 process = self.__startProcess(interpreter, |
328 [debugClient, noencoding, str(port), redirect, ipaddr], |
330 [debugClient, noencoding, str(port), redirect, ipaddr], |
329 clientEnv) |
331 clientEnv) |
330 if process is None: |
332 if process is None: |
331 E5MessageBox.critical(None, |
333 E5MessageBox.critical(None, |
332 self.trUtf8("Start Debugger"), |
334 self.trUtf8("Start Debugger"), |
333 self.trUtf8("""<p>The debugger backend could not be started.</p>""")) |
335 self.trUtf8("""<p>The debugger backend could not be started.</p>""")) |
410 |
412 |
411 @param env environment settings (dictionary) |
413 @param env environment settings (dictionary) |
412 """ |
414 """ |
413 self.__sendCommand('{0}{1}\n'.format(RequestEnv, str(env))) |
415 self.__sendCommand('{0}{1}\n'.format(RequestEnv, str(env))) |
414 |
416 |
415 def remoteLoad(self, fn, argv, wd, traceInterpreter = False, autoContinue = True, |
417 def remoteLoad(self, fn, argv, wd, traceInterpreter=False, autoContinue=True, |
416 autoFork = False, forkChild = False): |
418 autoFork=False, forkChild=False): |
417 """ |
419 """ |
418 Public method to load a new program to debug. |
420 Public method to load a new program to debug. |
419 |
421 |
420 @param fn the filename to debug (string) |
422 @param fn the filename to debug (string) |
421 @param argv the commandline arguments to pass to the program (string) |
423 @param argv the commandline arguments to pass to the program (string) |
431 |
433 |
432 wd = self.translate(wd, False) |
434 wd = self.translate(wd, False) |
433 fn = self.translate(os.path.abspath(fn), False) |
435 fn = self.translate(os.path.abspath(fn), False) |
434 self.__sendCommand('{0}{1}\n'.format(RequestForkMode, repr((autoFork, forkChild)))) |
436 self.__sendCommand('{0}{1}\n'.format(RequestForkMode, repr((autoFork, forkChild)))) |
435 self.__sendCommand('{0}{1}|{2}|{3}|{4:d}\n'.format( |
437 self.__sendCommand('{0}{1}|{2}|{3}|{4:d}\n'.format( |
436 RequestLoad, wd, fn, str(Utilities.parseOptionString(argv)), |
438 RequestLoad, wd, fn, str(Utilities.parseOptionString(argv)), |
437 traceInterpreter)) |
439 traceInterpreter)) |
438 |
440 |
439 def remoteRun(self, fn, argv, wd, autoFork = False, forkChild = False): |
441 def remoteRun(self, fn, argv, wd, autoFork=False, forkChild=False): |
440 """ |
442 """ |
441 Public method to load a new program to run. |
443 Public method to load a new program to run. |
442 |
444 |
443 @param fn the filename to run (string) |
445 @param fn the filename to run (string) |
444 @param argv the commandline arguments to pass to the program (string) |
446 @param argv the commandline arguments to pass to the program (string) |
450 fn = self.translate(os.path.abspath(fn), False) |
452 fn = self.translate(os.path.abspath(fn), False) |
451 self.__sendCommand('{0}{1}\n'.format(RequestForkMode, repr((autoFork, forkChild)))) |
453 self.__sendCommand('{0}{1}\n'.format(RequestForkMode, repr((autoFork, forkChild)))) |
452 self.__sendCommand('{0}{1}|{2}|{3}\n'.format( |
454 self.__sendCommand('{0}{1}|{2}|{3}\n'.format( |
453 RequestRun, wd, fn, str(Utilities.parseOptionString(argv)))) |
455 RequestRun, wd, fn, str(Utilities.parseOptionString(argv)))) |
454 |
456 |
455 def remoteCoverage(self, fn, argv, wd, erase = False): |
457 def remoteCoverage(self, fn, argv, wd, erase=False): |
456 """ |
458 """ |
457 Public method to load a new program to collect coverage data. |
459 Public method to load a new program to collect coverage data. |
458 |
460 |
459 @param fn the filename to run (string) |
461 @param fn the filename to run (string) |
460 @param argv the commandline arguments to pass to the program (string) |
462 @param argv the commandline arguments to pass to the program (string) |
461 @param wd the working directory for the program (string) |
463 @param wd the working directory for the program (string) |
462 @keyparam erase flag indicating that coverage info should be |
464 @keyparam erase flag indicating that coverage info should be |
463 cleared first (boolean) |
465 cleared first (boolean) |
464 """ |
466 """ |
465 wd = self.translate(wd, False) |
467 wd = self.translate(wd, False) |
466 fn = self.translate(os.path.abspath(fn), False) |
468 fn = self.translate(os.path.abspath(fn), False) |
467 self.__sendCommand('{0}{1}@@{2}@@{3}@@{4:d}\n'.format( |
469 self.__sendCommand('{0}{1}@@{2}@@{3}@@{4:d}\n'.format( |
468 RequestCoverage, wd, fn, str(Utilities.parseOptionString(argv)), |
470 RequestCoverage, wd, fn, str(Utilities.parseOptionString(argv)), |
469 erase)) |
471 erase)) |
470 |
472 |
471 def remoteProfile(self, fn, argv, wd, erase = False): |
473 def remoteProfile(self, fn, argv, wd, erase=False): |
472 """ |
474 """ |
473 Public method to load a new program to collect profiling data. |
475 Public method to load a new program to collect profiling data. |
474 |
476 |
475 @param fn the filename to run (string) |
477 @param fn the filename to run (string) |
476 @param argv the commandline arguments to pass to the program (string) |
478 @param argv the commandline arguments to pass to the program (string) |
482 self.__sendCommand('{0}{1}|{2}|{3}|{4:d}\n'.format( |
484 self.__sendCommand('{0}{1}|{2}|{3}|{4:d}\n'.format( |
483 RequestProfile, wd, fn, str(Utilities.parseOptionString(argv)), erase)) |
485 RequestProfile, wd, fn, str(Utilities.parseOptionString(argv)), erase)) |
484 |
486 |
485 def remoteStatement(self, stmt): |
487 def remoteStatement(self, stmt): |
486 """ |
488 """ |
487 Public method to execute a Python statement. |
489 Public method to execute a Python statement. |
488 |
490 |
489 @param stmt the Python statement to execute (string). It |
491 @param stmt the Python statement to execute (string). It |
490 should not have a trailing newline. |
492 should not have a trailing newline. |
491 """ |
493 """ |
492 self.__sendCommand('{0}\n'.format(stmt)) |
494 self.__sendCommand('{0}\n'.format(stmt)) |
514 """ |
516 """ |
515 Public method to stop the debugged program. |
517 Public method to stop the debugged program. |
516 """ |
518 """ |
517 self.__sendCommand(RequestStepQuit + '\n') |
519 self.__sendCommand(RequestStepQuit + '\n') |
518 |
520 |
519 def remoteContinue(self, special = False): |
521 def remoteContinue(self, special=False): |
520 """ |
522 """ |
521 Public method to continue the debugged program. |
523 Public method to continue the debugged program. |
522 |
524 |
523 @param special flag indicating a special continue operation |
525 @param special flag indicating a special continue operation |
524 """ |
526 """ |
525 self.__sendCommand('{0}{1:d}\n'.format(RequestContinue, special)) |
527 self.__sendCommand('{0}{1:d}\n'.format(RequestContinue, special)) |
526 |
528 |
527 def remoteBreakpoint(self, fn, line, set, cond = None, temp = False): |
529 def remoteBreakpoint(self, fn, line, set, cond=None, temp=False): |
528 """ |
530 """ |
529 Public method to set or clear a breakpoint. |
531 Public method to set or clear a breakpoint. |
530 |
532 |
531 @param fn filename the breakpoint belongs to (string) |
533 @param fn filename the breakpoint belongs to (string) |
532 @param line linenumber of the breakpoint (int) |
534 @param line linenumber of the breakpoint (int) |
560 """ |
562 """ |
561 fn = self.translate(fn, False) |
563 fn = self.translate(fn, False) |
562 self.__sendCommand('{0}{1},{2:d},{3:d}\n'.format( |
564 self.__sendCommand('{0}{1},{2:d},{3:d}\n'.format( |
563 RequestBreakIgnore, fn, line, count)) |
565 RequestBreakIgnore, fn, line, count)) |
564 |
566 |
565 def remoteWatchpoint(self, cond, set, temp = False): |
567 def remoteWatchpoint(self, cond, set, temp=False): |
566 """ |
568 """ |
567 Public method to set or clear a watch expression. |
569 Public method to set or clear a watch expression. |
568 |
570 |
569 @param cond expression of the watch expression (string) |
571 @param cond expression of the watch expression (string) |
570 @param set flag indicating setting or resetting a watch expression (boolean) |
572 @param set flag indicating setting or resetting a watch expression (boolean) |
591 @param count number of occurrences to ignore (int) |
593 @param count number of occurrences to ignore (int) |
592 """ |
594 """ |
593 # cond is combination of cond and special (s. watch expression viewer) |
595 # cond is combination of cond and special (s. watch expression viewer) |
594 self.__sendCommand('{0}{1},{2:d}\n'.format(RequestWatchIgnore, cond, count)) |
596 self.__sendCommand('{0}{1},{2:d}\n'.format(RequestWatchIgnore, cond, count)) |
595 |
597 |
596 def remoteRawInput(self,s): |
598 def remoteRawInput(self, s): |
597 """ |
599 """ |
598 Public method to send the raw input to the debugged program. |
600 Public method to send the raw input to the debugged program. |
599 |
601 |
600 @param s the raw input (string) |
602 @param s the raw input (string) |
601 """ |
603 """ |
613 |
615 |
614 @param tid id of the thread (integer) |
616 @param tid id of the thread (integer) |
615 """ |
617 """ |
616 self.__sendCommand('{0}{1:d}\n'.format(RequestThreadSet, tid)) |
618 self.__sendCommand('{0}{1:d}\n'.format(RequestThreadSet, tid)) |
617 |
619 |
618 def remoteClientVariables(self, scope, filter, framenr = 0): |
620 def remoteClientVariables(self, scope, filter, framenr=0): |
619 """ |
621 """ |
620 Public method to request the variables of the debugged program. |
622 Public method to request the variables of the debugged program. |
621 |
623 |
622 @param scope the scope of the variables (0 = local, 1 = global) |
624 @param scope the scope of the variables (0 = local, 1 = global) |
623 @param filter list of variable types to filter out (list of int) |
625 @param filter list of variable types to filter out (list of int) |
624 @param framenr framenumber of the variables to retrieve (int) |
626 @param framenr framenumber of the variables to retrieve (int) |
625 """ |
627 """ |
626 self.__sendCommand('{0}{1:d}, {2:d}, {3}\n'.format( |
628 self.__sendCommand('{0}{1:d}, {2:d}, {3}\n'.format( |
627 RequestVariables, framenr, scope, str(filter))) |
629 RequestVariables, framenr, scope, str(filter))) |
628 |
630 |
629 def remoteClientVariable(self, scope, filter, var, framenr = 0): |
631 def remoteClientVariable(self, scope, filter, var, framenr=0): |
630 """ |
632 """ |
631 Public method to request the variables of the debugged program. |
633 Public method to request the variables of the debugged program. |
632 |
634 |
633 @param scope the scope of the variables (0 = local, 1 = global) |
635 @param scope the scope of the variables (0 = local, 1 = global) |
634 @param filter list of variable types to filter out (list of int) |
636 @param filter list of variable types to filter out (list of int) |
768 cf = stack[0] |
770 cf = stack[0] |
769 if self.__autoContinue: |
771 if self.__autoContinue: |
770 self.__autoContinue = False |
772 self.__autoContinue = False |
771 QTimer.singleShot(0, self.remoteContinue) |
773 QTimer.singleShot(0, self.remoteContinue) |
772 else: |
774 else: |
773 self.debugServer.signalClientLine(cf[0], int(cf[1]), |
775 self.debugServer.signalClientLine(cf[0], int(cf[1]), |
774 resp == ResponseStack) |
776 resp == ResponseStack) |
775 self.debugServer.signalClientStack(stack) |
777 self.debugServer.signalClientStack(stack) |
776 continue |
778 continue |
777 |
779 |
778 if resp == ResponseThreadList: |
780 if resp == ResponseThreadList: |