Skip to content

Commit 73665b9

Browse files
committed
Parse and apply "python" / "pythonPath" in the adapter rather than in the launcher.
Fix errors with missing "args". Add test for "pythonPath".
1 parent 65b8b38 commit 73665b9

File tree

5 files changed

+55
-23
lines changed

5 files changed

+55
-23
lines changed

src/debugpy/adapter/clients.py

Lines changed: 21 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99

1010
import debugpy
1111
from debugpy import adapter, launcher
12-
from debugpy.common import fmt, json, log, messaging, sockets
12+
from debugpy.common import compat, fmt, json, log, messaging, sockets
1313
from debugpy.common.compat import unicode
1414
from debugpy.adapter import components, servers, sessions
1515

@@ -272,6 +272,21 @@ def property_or_debug_option(prop_name, flag_name):
272272

273273
return value
274274

275+
# "pythonPath" is a deprecated legacy spelling. If "python" is missing, then try
276+
# the alternative. But if both are missing, the error message should say "python".
277+
python_key = "python"
278+
if python_key in request:
279+
if "pythonPath" in request:
280+
raise request.isnt_valid(
281+
'"pythonPath" is not valid if "python" is specified'
282+
)
283+
elif "pythonPath" in request:
284+
python_key = "pythonPath"
285+
python = request(python_key, json.array(unicode, vectorize=True, size=(0,)))
286+
if not len(python):
287+
python = [compat.filename(sys.executable)]
288+
request.arguments["pythonArgs"] = python[1:]
289+
275290
program = module = code = ()
276291
if "program" in request:
277292
program = request("program", unicode)
@@ -300,7 +315,7 @@ def property_or_debug_option(prop_name, flag_name):
300315
args_expansion = request("argsExpansion", json.enum("shell", "none", optional=True))
301316
if args_expansion == "shell":
302317
args += request("args", json.array(unicode))
303-
del request.arguments["args"]
318+
request.arguments.pop("args", None)
304319

305320
cwd = request("cwd", unicode, optional=True)
306321
if cwd == ():
@@ -330,6 +345,7 @@ def property_or_debug_option(prop_name, flag_name):
330345
launchers.spawn_debuggee(
331346
self.session,
332347
request,
348+
python,
333349
launcher_path,
334350
adapter_host,
335351
args,
@@ -537,8 +553,9 @@ def notify_of_subprocess(self, conn):
537553
body["name"] = fmt("Subprocess {0}", conn.pid)
538554
body["request"] = "attach"
539555
body["subProcessId"] = conn.pid
540-
body.pop("processName", None)
541-
body.pop("args", None)
556+
557+
for key in "args", "processName", "pythonArgs":
558+
body.pop(key, None)
542559

543560
host = body.pop("host", None)
544561
port = body.pop("port", None)

src/debugpy/adapter/launchers.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,7 @@ def terminate_debuggee(self):
6868
def spawn_debuggee(
6969
session,
7070
start_request,
71+
python,
7172
launcher_path,
7273
adapter_host,
7374
args,
@@ -79,7 +80,8 @@ def spawn_debuggee(
7980
# -E tells sudo to propagate environment variables to the target process - this
8081
# is necessary for launcher to get DEBUGPY_LAUNCHER_PORT and DEBUGPY_LOG_DIR.
8182
cmdline = ["sudo", "-E"] if sudo else []
82-
cmdline += [sys.executable, launcher_path]
83+
cmdline += python
84+
cmdline += [launcher_path]
8385
env = {}
8486

8587
arguments = dict(start_request.arguments)

src/debugpy/launcher/handlers.py

Lines changed: 2 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -39,19 +39,8 @@ def property_or_debug_option(prop_name, flag_name):
3939

4040
return value
4141

42-
# "pythonPath" is a deprecated legacy spelling. If "python" is missing, then try
43-
# the alternative. But if both are missing, the error message should say "python".
44-
python_key = "python"
45-
if python_key in request:
46-
if "pythonPath" in request:
47-
raise request.isnt_valid(
48-
'"pythonPath" is not valid if "python" is specified'
49-
)
50-
elif "pythonPath" in request:
51-
python_key = "pythonPath"
52-
cmdline = request(python_key, json.array(unicode, vectorize=True, size=(0,)))
53-
if not len(cmdline):
54-
cmdline = [compat.filename(sys.executable)]
42+
python_args = request("pythonArgs", json.array(unicode, vectorize=True, size=(0,)))
43+
cmdline = [compat.filename(sys.executable)] + python_args
5544

5645
if not request("noDebug", json.default(False)):
5746
port = request("port", int)

tests/debug/runners.py

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -331,12 +331,9 @@ def spawn_debuggee(occ):
331331
attach_listen.host = "127.0.0.1"
332332
attach_listen.port = net.get_test_server_port(5478, 5600)
333333

334+
all_launch_terminal = [launch["integratedTerminal"], launch["externalTerminal"]]
334335

335-
all_launch = [
336-
launch["internalConsole"],
337-
launch["integratedTerminal"],
338-
launch["externalTerminal"],
339-
]
336+
all_launch = [launch["internalConsole"]] + all_launch_terminal
340337

341338
all_attach_listen = [attach_listen["api"], attach_listen["cli"]]
342339

tests/debugpy/test_run.py

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -135,3 +135,30 @@ def code_to_debug():
135135
# The launcher, however, should use our dummy sudo to spawn the debuggee,
136136
# and the debuggee should report the environment variable accordingly.
137137
assert backchannel.receive() == "1"
138+
139+
140+
@pytest.mark.parametrize("run", runners.all_launch_terminal)
141+
def test_custom_python(pyfile, run, target):
142+
@pyfile
143+
def code_to_debug():
144+
import sys
145+
import debuggee
146+
from debuggee import backchannel
147+
148+
debuggee.setup()
149+
backchannel.send(sys.executable)
150+
151+
class Session(debug.Session):
152+
def run_in_terminal(self, args, cwd, env):
153+
assert args[:2] == ["CUSTOMPY", "-O"]
154+
args[0] = sys.executable
155+
return super(Session, self).run_in_terminal(args, cwd, env)
156+
157+
with Session() as session:
158+
session.config["pythonPath"] = ["CUSTOMPY", "-O"]
159+
160+
backchannel = session.open_backchannel()
161+
with run(session, target(code_to_debug)):
162+
pass
163+
164+
assert backchannel.receive() == sys.executable

0 commit comments

Comments
 (0)