diff --git a/python/helpers/pydev/_pydev_bundle/pydev_monkey.py b/python/helpers/pydev/_pydev_bundle/pydev_monkey.py index 79369393dd3f..bdb9fc67c1f6 100644 --- a/python/helpers/pydev/_pydev_bundle/pydev_monkey.py +++ b/python/helpers/pydev/_pydev_bundle/pydev_monkey.py @@ -45,8 +45,13 @@ def _get_host_port(): def _is_managed_arg(arg): - if arg.endswith('pydevd.py'): - return True + return arg.endswith('pydevd.py') + + +def _is_already_patched(args): + for arg in args: + if 'pydevd' in arg: + return True return False @@ -138,6 +143,9 @@ def patch_args(args): ind_c = get_c_option_index(args) if ind_c != -1: + if _is_already_patched(args): + return args + host, port = _get_host_port() if port is not None: diff --git a/python/helpers/pydev/pydevd.py b/python/helpers/pydev/pydevd.py index fc18ce4ad6a3..8e7ffb971d26 100644 --- a/python/helpers/pydev/pydevd.py +++ b/python/helpers/pydev/pydevd.py @@ -1478,15 +1478,19 @@ class DispatchReader(ReaderThread): self.killReceived = True -DISPATCH_APPROACH_NEW_CONNECTION = 1 # Used by PyDev -DISPATCH_APPROACH_EXISTING_CONNECTION = 2 # Used by PyCharm -DISPATCH_APPROACH = DISPATCH_APPROACH_NEW_CONNECTION +def _should_use_existing_connection(setup): + ''' + The new connection dispatch approach is used by PyDev when the `multiprocess` option is set, + the existing connection approach is used by PyCharm when the `multiproc` option is set. + ''' + return setup.get('multiproc', False) + def dispatch(): setup = SetupHolder.setup host = setup['client'] port = setup['port'] - if DISPATCH_APPROACH == DISPATCH_APPROACH_EXISTING_CONNECTION: + if _should_use_existing_connection(setup): dispatcher = Dispatcher() try: dispatcher.connect(host, port) @@ -1616,8 +1620,6 @@ def main(): elif setup['multiproc']: # PyCharm pydev_log.debug("Started in multiproc mode\n") - global DISPATCH_APPROACH - DISPATCH_APPROACH = DISPATCH_APPROACH_EXISTING_CONNECTION dispatcher = Dispatcher() try: diff --git a/python/testData/debug/test_python_subprocess_another_helper.py b/python/testData/debug/test_python_subprocess_another_helper.py new file mode 100644 index 000000000000..d75b5ec6ee75 --- /dev/null +++ b/python/testData/debug/test_python_subprocess_another_helper.py @@ -0,0 +1,5 @@ +def boo(): + x = 42 + print("Hello!") + +boo() \ No newline at end of file diff --git a/python/testData/debug/test_python_subprocess_helper.py b/python/testData/debug/test_python_subprocess_helper.py new file mode 100644 index 000000000000..8e6b840aae50 --- /dev/null +++ b/python/testData/debug/test_python_subprocess_helper.py @@ -0,0 +1,10 @@ +import subprocess +import sys + + +def foo(): + subprocess.call([sys.executable, '-c', "from test_python_subprocess_another_helper import boo"], + stderr=subprocess.PIPE) + return 42 + +foo() diff --git a/python/testData/debug/test_python_subprocess_with_c_parameter.py b/python/testData/debug/test_python_subprocess_with_c_parameter.py new file mode 100644 index 000000000000..4da05724373c --- /dev/null +++ b/python/testData/debug/test_python_subprocess_with_c_parameter.py @@ -0,0 +1,6 @@ +from __future__ import print_function +import subprocess +import sys + +ret = subprocess.call([sys.executable, '-c', "from test_python_subprocess_helper import foo"], stderr=subprocess.PIPE) +print('The subprocess return code is %d' % ret) diff --git a/python/testSrc/com/jetbrains/env/python/PythonDebuggerTest.java b/python/testSrc/com/jetbrains/env/python/PythonDebuggerTest.java index fdf6c758557b..1cd3cad39679 100644 --- a/python/testSrc/com/jetbrains/env/python/PythonDebuggerTest.java +++ b/python/testSrc/com/jetbrains/env/python/PythonDebuggerTest.java @@ -827,6 +827,35 @@ public class PythonDebuggerTest extends PyEnvTestCase { }); } + @Test + public void testPythonSubprocessWithCParameter() { + runPythonTest(new PyDebuggerTask("/debug", "test_python_subprocess_with_c_parameter.py") { + @Override + protected void init() { + setMultiprocessDebug(true); + } + + @Override + public void before() { + toggleBreakpoint(getFilePath("test_python_subprocess_another_helper.py"), 2); + } + + @Override + public void testing() throws Exception { + waitForPause(); + eval("x").hasValue("42"); + resume(); + waitForOutput("Hello!"); + } + + @NotNull + @Override + public Set getTags() { + return ImmutableSet.of("-iron", "-jython"); + } + }); + } + @Test public void testPyQtQThreadInheritor() { Assume.assumeFalse("Don't run under Windows",UsefulTestCase.IS_UNDER_TEAMCITY && SystemInfo.isWindows);