Skip to content

Add support for auto-attaching debugger with URIs #136

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

Closed
JesseFarebro opened this issue Nov 20, 2023 · 3 comments
Closed

Add support for auto-attaching debugger with URIs #136

JesseFarebro opened this issue Nov 20, 2023 · 3 comments
Labels
feature-request Request for new features or functionality needs community feedback

Comments

@JesseFarebro
Copy link

Hi,

One of my biggest pain points when debugging with vscode is how much of a pain it is to specify CLI arguments. My ideal workflow is always to use the CLI and never have to write any configurations in launch.json. This should be possible through URIs, e.g.,

import subprocess

import portpicker
import debugpy

def attach():
  port = portpicker.pick_unused_port()
  debugpy.listen(port)
  
  subprocess.check_call([
    "code",
    "--open-url",
    f"vscode://ms-python.debugpy/connect?port={port}"
  ])
  debugpy.wait_for_client()

It would be even more ideal if debugpy supported this natively with e.g., python -m debugpy being able to do this automatically.

Is there any reason this hasn't already been implemented? It should be a fairly straightforward URI handler in this plugin to support the example I linked above, and hopefully, you'd see the value in implementing this in debugpy itself.

@github-actions github-actions bot added the triage-needed Needs assignment to the proper sub-team label Nov 20, 2023
@JesseFarebro
Copy link
Author

JesseFarebro commented Nov 20, 2023

It's also worth noting that resolving microsoft/vscode-remote-release#4260 or microsoft/vscode#197586 would be a prerequisite before this could be fully realized as currently, remote sessions don't support --open-url.

@alextremblay
Copy link

alextremblay commented Nov 20, 2023

If you're interested in a horrible, horrible workaround, here's what I'm doing in my repo while i wait for microsoft/vscode#197587 to get merged:

Step 1: install fabiospampinato.vscode-debug-launcher

Step 2:

import os
import socket
import json

def _get_vscode_debug_launcher_url(port: int):
    launch_config = {
        "name": "Python: Remote Attach",
        "type": "python",
        "request": "attach",
        "connect": {"host": "localhost", "port": port},
        "pathMappings": [
            {"localRoot": "${workspaceFolder}", "remoteRoot": os.getcwd()}
        ],
        "justMyCode": False,
    }
    launch_config = json.dumps(launch_config)
    return f"vscode://fabiospampinato.vscode-debug-launcher/launch?args={launch_config}"



def _handle_vscode_remote(vscode_ipc: str, port: int):
    # the VSCode Remote extension does not support `code --open-url {url}` with a `vscode://` extension
    # This may change in the future, but for now we need to bypass this limitation by using the VSCode IPC
    # secket to send the `vscode://` url to the VSCode instance server directly
    import requests

    from urllib3.connection import HTTPConnection
    from urllib3.connectionpool import HTTPConnectionPool
    from requests.adapters import HTTPAdapter

    class VSCodeIPCConnection(HTTPConnection):
        def __init__(self):
            super().__init__("localhost")

        def connect(self):
            self.sock = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
            self.sock.connect(vscode_ipc)

    class VSCodeIPCConnectionPool(HTTPConnectionPool):
        def __init__(self):
            super().__init__("localhost")

        def _new_conn(self):
            return VSCodeIPCConnection()

    class VSCodeIPCAdapter(HTTPAdapter):
        def get_connection(self, url, proxies=None):
            return VSCodeIPCConnectionPool()

    session = requests.Session()
    session.mount("vscode://", VSCodeIPCAdapter())
    session.post(
        "vscode://",
        headers={"content-type": "application/json", "accept": "application/json"},
        json={
            "type": "openExternal",
            "uris": [_get_vscode_debug_launcher_url(port)],
        },
    )

if __name__ == "__main__":
    import debugpy

    # Find an open port to listen on
    s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    s.bind(("localhost", 0))
    s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
    port = s.getsockname()[1]
    s.close()

    debugpy.listen(port)

    # If we're in a local vscode terminal session, we need to tell VSCode to connect to the debug adapter
    # using fabiospampinato.vscode-debug-launcher extension
    if os.environ.get("TERM_PROGRAM") == "vscode":
        vscode_ipc = os.environ.get("VSCODE_IPC_HOOK_CLI")
        if vscode_ipc:
            # If VSCode is running in a remote SSH or container session, this gets pretty complex
            _handle_vscode_remote(vscode_ipc, port)
        else:
            # If VSCode is running locally (ie not using the Remote SSH or Remote Containers extensions),
            # this is pretty straightforward
            import subprocess

            subprocess.run(
                ["code", "--open-url", _get_vscode_debug_launcher_url(port)]
            )

    # If we're not in a VSCode terminal window, we will need to prompt the user to connect to the debug adapter
    # with their preferred editor's debugger
    logger.info(f"Waiting for debugger to attach on port {port}...")
    debugpy.wait_for_client()

This is a horrible hack and should never be used. it depends on internal implementation details of vscode remote (the IPC socket used by the code and browser helper script to talk to the vscode remote server)
But until that PR gets merged, it's the only way to achieve this goal (trigger VSCode's debugger to start and attach to the current running python process)

@eleanorjboyd
Copy link
Member

Thank you for submitting your feature request and everyone who considered it! Unfortunately, this issue did not receive enough votes over the allotted time, and so we are closing the issue. PRs are welcome so you can create a PR that fixes this if you are passionate about getting this feature across the finish line. Thanks!

@eleanorjboyd eleanorjboyd closed this as not planned Won't fix, can't repro, duplicate, stale Jan 7, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
feature-request Request for new features or functionality needs community feedback
Projects
None yet
Development

No branches or pull requests

4 participants