From adae55954a7e71c35c9f5680af67b3c2a8d1ad03 Mon Sep 17 00:00:00 2001 From: Dmitry Trofimov Date: Tue, 26 Aug 2014 00:43:20 +0200 Subject: [PATCH] Command-line after debug with exception breakpoints handling. --- .../configurations/GeneralCommandLine.java | 6 +- python/helpers/pydev/pydevd.py | 77 ++++++++++++++++++- python/helpers/pydev/pydevd_frame.py | 6 ++ .../python/console/PyDebugConsoleBuilder.java | 2 +- .../run/PythonScriptCommandLineState.java | 20 +++-- 5 files changed, 100 insertions(+), 11 deletions(-) diff --git a/platform/platform-api/src/com/intellij/execution/configurations/GeneralCommandLine.java b/platform/platform-api/src/com/intellij/execution/configurations/GeneralCommandLine.java index 939680ea372a..63849959f1c1 100644 --- a/platform/platform-api/src/com/intellij/execution/configurations/GeneralCommandLine.java +++ b/platform/platform-api/src/com/intellij/execution/configurations/GeneralCommandLine.java @@ -197,6 +197,10 @@ public class GeneralCommandLine implements UserDataHolder { * @return single-string representation of this command line. */ public String getCommandLineString(@Nullable final String exeName) { + return ParametersList.join(getCommandLineList(exeName)); + } + + public List getCommandLineList(@Nullable final String exeName) { final List commands = new ArrayList(); if (exeName != null) { commands.add(exeName); @@ -208,7 +212,7 @@ public class GeneralCommandLine implements UserDataHolder { commands.add(""); } commands.addAll(myProgramParams.getList()); - return ParametersList.join(commands); + return commands; } /** diff --git a/python/helpers/pydev/pydevd.py b/python/helpers/pydev/pydevd.py index 67a936ea1b46..0209c8635b28 100644 --- a/python/helpers/pydev/pydevd.py +++ b/python/helpers/pydev/pydevd.py @@ -77,7 +77,7 @@ import pydevd_vm_type import pydevd_tracing import pydevd_io from pydevd_additional_thread_info import PyDBAdditionalThreadInfo -from pydevd_custom_frames import CustomFramesContainer, CustomFramesContainerInit +from pydevd_custom_frames import CustomFramesContainer, CustomFramesContainerInit, addCustomFrame import pydevd_dont_trace import pydevd_traceproperty @@ -1549,6 +1549,64 @@ class PyDB: cmd = self.cmdFactory.makeExitMessage() self.writer.addCommand(cmd) + def wait_for_commands(self, globals): + thread = threading.currentThread() + frame = MyFrame() + frame.f_globals = globals + frame.f_locals = globals + frame.f_lineno = -1 + frame.f_code = FCode(setup['file'], setup['file']) + thread_id = GetThreadId(thread) + # frame_id = addCustomFrame(frame, 'todo', GetThreadId(thread)) + cmd = self.cmdFactory.makeThreadSuspendMessage(thread_id, frame, CMD_CONSOLE_EXEC, '') + self.writer.addCommand(cmd) + while True: + self.processInternalCommands() + time.sleep(0.01) + +class MyFrame: + def __init__( + self, + frame, + template_frame_file=None, + template_frame_line=None): + + if template_frame_file is None: + template_frame_file = get_template_file_name(frame) + + self.back_context = frame.f_locals['context'] + self.f_code = FCode('Django Template', template_frame_file) + + if template_frame_line is None: + template_frame_line = get_template_line(frame, template_frame_file) + self.f_lineno = template_frame_line + + self.f_back = frame + self.f_globals = {} + self.f_locals = self.collect_context() + self.f_trace = None + + def collect_context(self): + res = {} + try: + for d in self.back_context.dicts: + res.update(d) + except AttributeError: + pass + return res + + def changeVariable(self, name, value): + for d in self.back_context.dicts: + if DictContains(d, name): + d[name] = value + self.f_locals[name] = value + + +class FCode: + def __init__(self, name, filename): + self.co_name = name + self.co_filename = filename + def set_debug(setup): setup['DEBUG_RECORD_SOCKET_READS'] = True setup['DEBUG_TRACE_BREAKPOINTS'] = 1 @@ -1566,6 +1624,7 @@ def processCommandLine(argv): setup['multiproc'] = False #Used by PyCharm (reuses connection: ssh tunneling) setup['multiprocess'] = False # Used by PyDev (creates new connection to ide) setup['save-signatures'] = False + setup['cmd-line'] = False i = 0 del argv[0] while (i < len(argv)): @@ -1603,6 +1662,9 @@ def processCommandLine(argv): elif (argv[i] == '--save-signatures'): del argv[i] setup['save-signatures'] = True + elif (argv[i] == '--cmd-line'): + del argv[i] + setup['cmd-line'] = True else: raise ValueError("unexpected option " + argv[i]) return setup @@ -2036,6 +2098,11 @@ if __name__ == '__main__': except: pass # It's ok not having stackless there... + debugger = PyDB() + + if setup['cmd-line']: + debugger.cmd_line = True + if fix_app_engine_debug: sys.stderr.write("pydev debugger: google app engine integration enabled\n") curr_dir = os.path.dirname(__file__) @@ -2048,10 +2115,8 @@ if __name__ == '__main__': sys.argv.insert(3, '--automatic_restart=no') sys.argv.insert(4, '--max_module_instances=1') - debugger = PyDB() # Run the dev_appserver debugger.run(setup['file'], None, None, set_trace=False) - else: # as to get here all our imports are already resolved, the psyco module can be # changed and we'll still get the speedups in the debugger, as those functions @@ -2067,7 +2132,6 @@ if __name__ == '__main__': import pydevd_psyco_stub sys.modules['psyco'] = pydevd_psyco_stub - debugger = PyDB() if setup['save-signatures']: if pydevd_vm_type.GetVmType() == pydevd_vm_type.PydevdVmType.JYTHON: @@ -2085,3 +2149,8 @@ if __name__ == '__main__': connected = True # Mark that we're connected when started from inside ide. debugger.run(setup['file'], None, None) + + # if setup['cmd-line']: + # debugger.wait_for_commands(globals) + + diff --git a/python/helpers/pydev/pydevd_frame.py b/python/helpers/pydev/pydevd_frame.py index b7073678bf66..f1c035002bb5 100644 --- a/python/helpers/pydev/pydevd_frame.py +++ b/python/helpers/pydev/pydevd_frame.py @@ -403,6 +403,12 @@ class PyDBFrame: if stop: self.setSuspend(thread, CMD_SET_BREAK) + if event == 'return': + if main_debugger.cmd_line: + base = basename(back.f_code.co_filename) + if base == 'pydevd.py' and back.f_code.co_name == 'run': + self.setSuspend(thread, CMD_SET_BREAK) # we suspend on exit + # if thread has a suspend flag, we suspend with a busy wait if info.pydev_state == STATE_SUSPEND: self.doWaitSuspend(thread, frame, event, arg) diff --git a/python/src/com/jetbrains/python/console/PyDebugConsoleBuilder.java b/python/src/com/jetbrains/python/console/PyDebugConsoleBuilder.java index a99b9332c00d..7fbd432ebf2c 100644 --- a/python/src/com/jetbrains/python/console/PyDebugConsoleBuilder.java +++ b/python/src/com/jetbrains/python/console/PyDebugConsoleBuilder.java @@ -37,7 +37,7 @@ public class PyDebugConsoleBuilder extends TextConsoleBuilder { public PyDebugConsoleBuilder(final Project project, @Nullable Sdk sdk) { myProject = project; - this.mySdk = sdk; + mySdk = sdk; } public ConsoleView getConsole() { diff --git a/python/src/com/jetbrains/python/run/PythonScriptCommandLineState.java b/python/src/com/jetbrains/python/run/PythonScriptCommandLineState.java index 9ebc5c53afb4..cd92fdb34638 100644 --- a/python/src/com/jetbrains/python/run/PythonScriptCommandLineState.java +++ b/python/src/com/jetbrains/python/run/PythonScriptCommandLineState.java @@ -20,6 +20,7 @@ import com.intellij.execution.*; import com.intellij.execution.configurations.GeneralCommandLine; import com.intellij.execution.configurations.ParametersList; import com.intellij.execution.configurations.ParamsGroup; +import com.intellij.execution.executors.DefaultDebugExecutor; import com.intellij.execution.process.CommandLineArgumentsProvider; import com.intellij.execution.process.OSProcessHandler; import com.intellij.execution.process.ProcessHandler; @@ -61,10 +62,18 @@ public class PythonScriptCommandLineState extends PythonCommandLineState { @Override public ExecutionResult execute(Executor executor, final CommandLinePatcher... patchers) throws ExecutionException { if (myConfig.showCommandLineAfterwards()) { + if (executor.getId() == DefaultDebugExecutor.EXECUTOR_ID) { + return super.execute(executor, ArrayUtil.append(patchers, new CommandLinePatcher() { + @Override + public void patchCommandLine(GeneralCommandLine commandLine) { + commandLine.getParametersList().getParamsGroup(PythonCommandLineState.GROUP_DEBUGGER).addParameterAt(1, "--cmd-line"); + } + })); + } PydevConsoleRunner runner = new PythonScriptWithConsoleRunner(myConfig.getProject(), myConfig.getSdk(), PyConsoleType.PYTHON, myConfig.getWorkingDirectory(), - myConfig.getEnvs(), patchers); + myConfig.getEnvs(), patchers); runner.runSync(); @@ -109,7 +118,9 @@ public class PythonScriptCommandLineState extends PythonCommandLineState { @NotNull Sdk sdk, @NotNull PyConsoleType consoleType, @Nullable String workingDir, - Map environmentVariables, CommandLinePatcher[] patchers, String... statementsToExecute) { + Map environmentVariables, + CommandLinePatcher[] patchers, + String... statementsToExecute) { super(project, sdk, consoleType, workingDir, environmentVariables, statementsToExecute); myPatchers = patchers; } @@ -124,7 +135,6 @@ public class PythonScriptCommandLineState extends PythonCommandLineState { protected CommandLineArgumentsProvider createCommandLineArgumentsProvider(final Sdk sdk, final Map environmentVariables, int[] ports) { - final ArrayList args = new ArrayList(); args.add(sdk.getHomePath()); final String versionString = sdk.getVersionString(); @@ -139,7 +149,8 @@ public class PythonScriptCommandLineState extends PythonCommandLineState { try { GeneralCommandLine cmd = generateCommandLine(myPatchers); args.addAll(cmd.getParametersList().getList()); - } catch (Exception e) { + } + catch (Exception e) { //pass } return new CommandLineArgumentsProvider() { @@ -158,7 +169,6 @@ public class PythonScriptCommandLineState extends PythonCommandLineState { return addDefaultEnvironments(sdk, environmentVariables); } }; - } } }