Skip to content

Commit 7d2a7a2

Browse files
committed
Fix #463: Enable overriding "pythonPath" in the launcher
Add "debugLauncherPython" debug config property to customize Python interpreter used to spawn the launcher.
1 parent c6dc935 commit 7d2a7a2

File tree

3 files changed

+73
-23
lines changed

3 files changed

+73
-23
lines changed

src/debugpy/adapter/clients.py

+5-1
Original file line numberDiff line numberDiff line change
@@ -319,6 +319,10 @@ def property_or_debug_option(prop_name, flag_name):
319319
request.arguments["pythonArgs"] = python[1:]
320320
request.arguments["python"] = python
321321

322+
launcher_python = request("debugLauncherPython", unicode, optional=True)
323+
if launcher_python == ():
324+
launcher_python = python[0]
325+
322326
program = module = code = ()
323327
if "program" in request:
324328
program = request("program", unicode)
@@ -379,7 +383,7 @@ def property_or_debug_option(prop_name, flag_name):
379383
launchers.spawn_debuggee(
380384
self.session,
381385
request,
382-
python,
386+
[launcher_python],
383387
launcher_path,
384388
adapter_host,
385389
args,

tests/debug/config.py

+4-3
Original file line numberDiff line numberDiff line change
@@ -42,9 +42,6 @@ class DebugConfig(collections.MutableMapping):
4242
"postDebugTask": (),
4343
"preLaunchTask": (),
4444
"pyramid": False,
45-
"python": (),
46-
"pythonArgs": [],
47-
"pythonPath": (),
4845
"redirectOutput": False,
4946
"rules": [],
5047
"showReturnValue": True,
@@ -58,11 +55,15 @@ class DebugConfig(collections.MutableMapping):
5855
"code": (),
5956
"console": "internal",
6057
"cwd": (),
58+
"debugLauncherPython": (),
6159
"env": {},
6260
"gevent": False,
6361
"internalConsoleOptions": "neverOpen",
6462
"module": (),
6563
"program": (),
64+
"python": (),
65+
"pythonArgs": [],
66+
"pythonPath": (),
6667
"stopOnEntry": False,
6768
"sudo": False,
6869
"waitOnNormalExit": False,

tests/debugpy/test_run.py

+64-19
Original file line numberDiff line numberDiff line change
@@ -137,44 +137,90 @@ def code_to_debug():
137137
assert backchannel.receive() == "1"
138138

139139

140-
@pytest.mark.parametrize("run", runners.all_launch)
141-
@pytest.mark.parametrize("python_args", [None, "-B"])
142-
@pytest.mark.parametrize("python", [None, "custompy", "custompy,-O"])
143-
@pytest.mark.parametrize("python_key", ["python", "pythonPath"])
144-
def test_custom_python(pyfile, tmpdir, run, target, python_key, python, python_args):
140+
def make_custompy(tmpdir, id=""):
145141
if sys.platform == "win32":
146-
custompy = tmpdir / "custompy.cmd"
142+
custompy = tmpdir / ("custompy" + id + ".cmd")
147143
script = """@echo off
148-
set DEBUGPY_CUSTOM_PYTHON=1%DEBUGPY_CUSTOM_PYTHON%
144+
set DEBUGPY_CUSTOM_PYTHON=<id>;%DEBUGPY_CUSTOM_PYTHON%
149145
<python> %*
150146
"""
151147
else:
152-
custompy = tmpdir / "custompy.sh"
148+
custompy = tmpdir / ("custompy" + id + ".sh")
153149
script = """#!/bin/sh
154-
env DEBUGPY_CUSTOM_PYTHON=1$DEBUGPY_CUSTOM_PYTHON <python> "$@"
150+
env "DEBUGPY_CUSTOM_PYTHON=<id>;$DEBUGPY_CUSTOM_PYTHON" <python> "$@"
155151
"""
156-
custompy.write(script.replace("<python>", sys.executable))
152+
153+
script = script.replace("<id>", id)
154+
script = script.replace("<python>", sys.executable)
155+
custompy.write(script)
157156
os.chmod(custompy.strpath, 0o777)
158157

158+
return custompy.strpath
159+
160+
161+
@pytest.mark.parametrize("run", runners.all_launch)
162+
@pytest.mark.parametrize("debuggee_custompy", [None, "launcher"])
163+
@pytest.mark.parametrize("launcher_custompy", [None, "debuggee"])
164+
def test_custom_python(
165+
pyfile, tmpdir, run, target, debuggee_custompy, launcher_custompy,
166+
):
159167
@pyfile
160168
def code_to_debug():
161169
import os
170+
171+
import debuggee
172+
from debuggee import backchannel
173+
174+
debuggee.setup()
175+
backchannel.send(os.getenv("DEBUGPY_CUSTOM_PYTHON"))
176+
177+
expected = ""
178+
if debuggee_custompy:
179+
debuggee_custompy = make_custompy(tmpdir, "debuggee")
180+
expected += "debuggee;"
181+
if launcher_custompy:
182+
launcher_custompy = make_custompy(tmpdir, "launcher")
183+
expected += "launcher;"
184+
else:
185+
# If "python" is set, it also becomes the default for "debugLauncherPython"
186+
expected *= 2
187+
if not len(expected):
188+
pytest.skip()
189+
190+
with debug.Session() as session:
191+
session.config.pop("python", None)
192+
if launcher_custompy:
193+
session.config["debugLauncherPython"] = launcher_custompy
194+
if debuggee_custompy:
195+
session.config["python"] = debuggee_custompy
196+
197+
backchannel = session.open_backchannel()
198+
with run(session, target(code_to_debug)):
199+
pass
200+
201+
assert backchannel.receive() == expected
202+
203+
204+
@pytest.mark.parametrize("run", runners.all_launch)
205+
@pytest.mark.parametrize("python_args", [None, "-B"])
206+
@pytest.mark.parametrize("python", [None, "custompy", "custompy,-O"])
207+
@pytest.mark.parametrize("python_key", ["python", "pythonPath"])
208+
def test_custom_python_args(
209+
pyfile, tmpdir, run, target, python_key, python, python_args
210+
):
211+
@pyfile
212+
def code_to_debug():
162213
import sys
163214

164215
import debuggee
165216
from debuggee import backchannel
166217

167218
debuggee.setup()
168-
backchannel.send(
169-
[
170-
os.getenv("DEBUGPY_CUSTOM_PYTHON"),
171-
sys.flags.optimize,
172-
sys.flags.dont_write_bytecode,
173-
]
174-
)
219+
backchannel.send([sys.flags.optimize, sys.flags.dont_write_bytecode])
175220

221+
custompy = make_custompy(tmpdir)
176222
python = [] if python is None else python.split(",")
177-
python = [(custompy.strpath if arg == "custompy" else arg) for arg in python]
223+
python = [(custompy if arg == "custompy" else arg) for arg in python]
178224
python_args = [] if python_args is None else python_args.split(",")
179225
python_cmd = (python if len(python) else [sys.executable]) + python_args
180226

@@ -191,7 +237,6 @@ def code_to_debug():
191237
pass
192238

193239
assert backchannel.receive() == [
194-
"11" if len(python) else None, # one for launcher, one for debuggee
195240
"-O" in python_cmd,
196241
"-B" in python_cmd,
197242
]

0 commit comments

Comments
 (0)