diff --git a/python/helper-image/Dockerfile b/python/helper-image/Dockerfile index ce689b18..ab170f58 100644 --- a/python/helper-image/Dockerfile +++ b/python/helper-image/Dockerfile @@ -30,31 +30,43 @@ FROM python:2.7 as python27 RUN PYTHONUSERBASE=/dbgpy pip install --user ptvsd debugpy RUN PYTHONUSERBASE=/dbgpy/pydevd/python2.7 pip install --user pydevd --no-warn-script-location +COPY pydevd.patch . +RUN patch -p0 -d /dbgpy/pydevd/python2.7/lib/python2.7/site-packages < pydevd.patch RUN PYTHONUSERBASE=/dbgpy/pydevd-pycharm/python2.7 pip install --user pydevd-pycharm --no-warn-script-location FROM python:3.5 as python35 RUN PYTHONUSERBASE=/dbgpy pip install --user ptvsd debugpy RUN PYTHONUSERBASE=/dbgpy/pydevd/python3.5 pip install --user pydevd --no-warn-script-location +COPY pydevd.patch . +RUN patch -p0 -d /dbgpy/pydevd/python3.5/lib/python3.5/site-packages < pydevd.patch RUN PYTHONUSERBASE=/dbgpy/pydevd-pycharm/python3.5 pip install --user pydevd-pycharm --no-warn-script-location FROM python:3.6 as python36 RUN PYTHONUSERBASE=/dbgpy pip install --user ptvsd debugpy RUN PYTHONUSERBASE=/dbgpy/pydevd/python3.6 pip install --user pydevd --no-warn-script-location +COPY pydevd.patch . +RUN patch -p0 -d /dbgpy/pydevd/python3.6/lib/python3.6/site-packages < pydevd.patch RUN PYTHONUSERBASE=/dbgpy/pydevd-pycharm/python3.6 pip install --user pydevd-pycharm --no-warn-script-location FROM python:3.7 as python37 RUN PYTHONUSERBASE=/dbgpy pip install --user ptvsd debugpy RUN PYTHONUSERBASE=/dbgpy/pydevd/python3.7 pip install --user pydevd --no-warn-script-location +COPY pydevd.patch . +RUN patch -p0 -d /dbgpy/pydevd/python3.7/lib/python3.7/site-packages < pydevd.patch RUN PYTHONUSERBASE=/dbgpy/pydevd-pycharm/python3.7 pip install --user pydevd-pycharm --no-warn-script-location FROM python:3.8 as python38 RUN PYTHONUSERBASE=/dbgpy pip install --user ptvsd debugpy RUN PYTHONUSERBASE=/dbgpy/pydevd/python3.8 pip install --user pydevd --no-warn-script-location +COPY pydevd.patch . +RUN patch -p0 -d /dbgpy/pydevd/python3.8/lib/python3.8/site-packages < pydevd.patch RUN PYTHONUSERBASE=/dbgpy/pydevd-pycharm/python3.8 pip install --user pydevd-pycharm --no-warn-script-location FROM python:3.9 as python39 RUN PYTHONUSERBASE=/dbgpy pip install --user ptvsd debugpy RUN PYTHONUSERBASE=/dbgpy/pydevd/python3.9 pip install --user pydevd --no-warn-script-location +COPY pydevd.patch . +RUN patch -p0 -d /dbgpy/pydevd/python3.9/lib/python3.9/site-packages < pydevd.patch RUN PYTHONUSERBASE=/dbgpy/pydevd-pycharm/python3.9 pip install --user pydevd-pycharm --no-warn-script-location FROM golang:1.14.1 as build diff --git a/python/helper-image/launcher/launcher.go b/python/helper-image/launcher/launcher.go index 1986faea..0f3b5a29 100644 --- a/python/helper-image/launcher/launcher.go +++ b/python/helper-image/launcher/launcher.go @@ -308,7 +308,7 @@ func (pc *pythonContext) updateCommandLine(ctx context.Context) error { // Appropriate location to resolve pydevd is set in updateEnv // TODO: check for modules (and fail?) cmdline = append(cmdline, pc.args[0]) - cmdline = append(cmdline, "-m", "pydevd", "--port", strconv.Itoa(int(pc.port)), "--server") + cmdline = append(cmdline, "-m", "pydevd", "--server", "--port", strconv.Itoa(int(pc.port))) if pc.env["WRAPPER_VERBOSE"] != "" { cmdline = append(cmdline, "--DEBUG") } @@ -316,6 +316,9 @@ func (pc *pythonContext) updateCommandLine(ctx context.Context) error { // From the pydevd source, PyCharm wants multiproc cmdline = append(cmdline, "--multiproc") } + if !pc.wait { + cmdline = append(cmdline, "--continue") + } cmdline = append(cmdline, "--file") // --file is expected as last argument cmdline = append(cmdline, pc.args[1:]...) if pc.wait { diff --git a/python/helper-image/launcher/launcher_test.go b/python/helper-image/launcher/launcher_test.go index a1ddb472..7803b527 100644 --- a/python/helper-image/launcher/launcher_test.go +++ b/python/helper-image/launcher/launcher_test.go @@ -275,8 +275,15 @@ func TestLaunch(t *testing.T) { description: "pydevd", pc: pythonContext{debugMode: "pydevd", port: 2345, wait: false, args: []string{"python", "app.py"}, env: nil}, commands: RunCmdOut([]string{"python", "-V"}, "Python 3.7.4\n"). - AndRunCmd([]string{"python", "-m", "pydevd", "--port", "2345", "--server", "--file", "app.py"}), - expected: pythonContext{debugMode: "pydevd", port: 2345, wait: false, args: []string{"python", "-m", "pydevd", "--port", "2345", "--server", "--file", "app.py"}, env: env{"PYTHONPATH": dbgRoot + "/python/pydevd/python3.7/lib/python3.7/site-packages"}}, + AndRunCmd([]string{"python", "-m", "pydevd", "--server", "--port", "2345", "--continue", "--file", "app.py"}), + expected: pythonContext{debugMode: "pydevd", port: 2345, wait: false, args: []string{"python", "-m", "pydevd", "--server", "--port", "2345", "--continue", "--file", "app.py"}, env: env{"PYTHONPATH": dbgRoot + "/python/pydevd/python3.7/lib/python3.7/site-packages"}}, + }, + { + description: "pydevd with wait", + pc: pythonContext{debugMode: "pydevd", port: 2345, wait: true, args: []string{"python", "app.py"}, env: nil}, + commands: RunCmdOut([]string{"python", "-V"}, "Python 3.7.4\n"). + AndRunCmd([]string{"python", "-m", "pydevd", "--server", "--port", "2345", "--file", "app.py"}), + expected: pythonContext{debugMode: "pydevd", port: 2345, wait: true, args: []string{"python", "-m", "pydevd", "--server", "--port", "2345", "--file", "app.py"}, env: env{"PYTHONPATH": dbgRoot + "/python/pydevd/python3.7/lib/python3.7/site-packages"}}, }, } diff --git a/python/helper-image/pydevd.patch b/python/helper-image/pydevd.patch new file mode 100644 index 00000000..989fd3ea --- /dev/null +++ b/python/helper-image/pydevd.patch @@ -0,0 +1,68 @@ +diff --git _pydevd_bundle/pydevd_command_line_handling.py _pydevd_bundle/pydevd_command_line_handling.py +index 2afae09..2985a35 100644 +--- _pydevd_bundle/pydevd_command_line_handling.py ++++ _pydevd_bundle/pydevd_command_line_handling.py +@@ -69,6 +69,7 @@ ACCEPTED_ARG_HANDLERS = [ + ArgHandlerWithParam('client-access-token'), + + ArgHandlerBool('server'), ++ ArgHandlerBool('continue'), + ArgHandlerBool('DEBUG_RECORD_SOCKET_READS'), + ArgHandlerBool('multiproc'), # Used by PyCharm (reuses connection: ssh tunneling) + ArgHandlerBool('multiprocess'), # Used by PyDev (creates new connection to ide) +diff --git pydevd.py pydevd.py +index 4639778..9ecfec0 100644 +--- pydevd.py ++++ pydevd.py +@@ -1376,6 +1376,8 @@ class PyDB(object): + + def run(self): + host = SetupHolder.setup['client'] ++ if host is None: ++ host = '' + port = SetupHolder.setup['port'] + + self._server_socket = create_server_socket(host=host, port=port) +@@ -2240,7 +2242,7 @@ class PyDB(object): + from _pydev_bundle.pydev_monkey import patch_thread_modules + patch_thread_modules() + +- def run(self, file, globals=None, locals=None, is_module=False, set_trace=True): ++ def run(self, file, globals=None, locals=None, is_module=False, set_trace=True, wait=True): + module_name = None + entry_point_fn = '' + if is_module: +@@ -2322,7 +2324,8 @@ class PyDB(object): + sys.path.insert(0, os.path.split(os_path_abspath(file))[0]) + + if set_trace: +- self.wait_for_ready_to_run() ++ if wait: ++ self.wait_for_ready_to_run() + + # call prepare_to_run when we already have all information about breakpoints + self.prepare_to_run() +@@ -3276,14 +3279,21 @@ def main(): + + apply_debugger_options(setup) + ++ wait = True ++ if setup['continue']: ++ wait = False ++ + try: +- debugger.connect(host, port) ++ if wait: ++ debugger.connect(host, port) ++ else: ++ debugger.create_wait_for_connection_thread() + except: + sys.stderr.write("Could not connect to %s: %s\n" % (host, port)) + pydev_log.exception() + sys.exit(1) + +- globals = debugger.run(setup['file'], None, None, is_module) ++ globals = debugger.run(setup['file'], None, None, is_module, wait=wait) + + if setup['cmd-line']: + debugger.wait_for_commands(globals)