-
Couldn't load subscription status.
- Fork 30
Add support for pydevd debugging of modules #75
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 4 commits
9e65dd0
81fe612
8632338
ef3a44a
c7dff01
141d5d8
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -52,6 +52,7 @@ import ( | |
| "flag" | ||
| "fmt" | ||
| "io" | ||
| "io/ioutil" | ||
| "os" | ||
| "os/exec" | ||
| "path/filepath" | ||
|
|
@@ -308,16 +309,23 @@ 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") | ||
| } | ||
| if pc.debugMode == ModePydevdPycharm { | ||
| // 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:]...) | ||
|
|
||
| // --file is expected as last pydev argument, but it must be a file, and so launching with | ||
| // a module requires some special handling. | ||
| cmdline = append(cmdline, "--file") | ||
briandealwis marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| file, args, err := handlePydevModule(pc.args[1:]) | ||
| if err != nil { | ||
| return err | ||
| } | ||
| cmdline = append(cmdline, file) | ||
| cmdline = append(cmdline, args...) | ||
| if pc.wait { | ||
| logrus.Warn("pydevd does not support wait-for-client") | ||
| } | ||
|
|
@@ -353,6 +361,47 @@ func determinePythonMajorMinor(ctx context.Context, launcherBin string, env env) | |
| return | ||
| } | ||
|
|
||
| // handlePydevModule applies special pydevd handling for a python module. When a module is | ||
| // found, we write out a python script that uses runpy to invoke the module. | ||
| func handlePydevModule(args []string) (string, []string, error) { | ||
| switch { | ||
| case len(args) == 0: | ||
| return "", nil, fmt.Errorf("no python command-line specified") // shouldn't happen | ||
| case !strings.HasPrefix(args[0], "-"): | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. what if it's something like There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. if I update my entrypoint to this There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. update: I may have been wrong here. running another test. will update this comment There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It does break. That's going to be more involved — I'll do tackle it as a follow-up. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. sg. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. |
||
| // this is a file | ||
| return args[0], args[1:], nil | ||
| case !strings.HasPrefix(args[0], "-m"): | ||
| // this is some other command-line flag | ||
| return "", nil, fmt.Errorf("expected python module: %q", args) | ||
| } | ||
| module := args[0][2:] | ||
| remaining := args[1:] | ||
| if module == "" { | ||
| if len(args) == 1 { | ||
| return "", nil, fmt.Errorf("missing python module: %q", args) | ||
| } | ||
| module = args[1] | ||
| remaining = args[2:] | ||
| } | ||
|
|
||
| snippet := strings.ReplaceAll(`import sys | ||
| import runpy | ||
| runpy.run_module('{module}', run_name="__main__",alter_sys=True) | ||
| `, `{module}`, module) | ||
|
|
||
| // write out the temp location as other locations may not be writable | ||
| d, err := ioutil.TempDir("", "pydevd*") | ||
| if err != nil { | ||
| return "", nil, err | ||
| } | ||
| // use a skaffold-specific file name to ensure no possibility of it matching a user import | ||
| f := filepath.Join(d, "skaffold_pydevd_launch.py") | ||
| if err := ioutil.WriteFile(f, []byte(snippet), 0755); err != nil { | ||
| return "", nil, err | ||
| } | ||
| return f, remaining, nil | ||
| } | ||
|
|
||
| func isEnabled(env env) bool { | ||
| v, found := env["WRAPPER_ENABLED"] | ||
| return !found || (v != "0" && v != "false" && v != "no") | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -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) |
Uh oh!
There was an error while loading. Please reload this page.