mirror of
https://github.com/microsoft/debugpy.git
synced 2025-12-23 08:48:12 +00:00
Fix #1001: Enable controlling shell expansion via "argsCanBeInterpretedByShell"
Fix #357: "argsExpansion" does not do what it says in VSCode Treat non-array "args" in debug config as a request to prevent shell argument escaping and allow shell expansion. Remove "argsExpansion".
This commit is contained in:
parent
6b276e339c
commit
4f6638b0a6
8 changed files with 68 additions and 46 deletions
|
|
@ -49,7 +49,6 @@ class DebugConfig(MutableMapping):
|
|||
"type": (),
|
||||
# Launch
|
||||
"args": [],
|
||||
"argsExpansion": "shell",
|
||||
"code": (),
|
||||
"console": "internal",
|
||||
"cwd": (),
|
||||
|
|
|
|||
|
|
@ -325,9 +325,12 @@ debugpy.connect({(host, port)!r})
|
|||
attach_listen.host = "127.0.0.1"
|
||||
attach_listen.port = net.get_test_server_port(5478, 5600)
|
||||
|
||||
all_launch_terminal = [launch["integratedTerminal"], launch["externalTerminal"]]
|
||||
all_launch_terminal = [
|
||||
launch.with_options(console="integratedTerminal"),
|
||||
launch.with_options(console="externalTerminal"),
|
||||
]
|
||||
|
||||
all_launch = [launch["internalConsole"]] + all_launch_terminal
|
||||
all_launch = [launch.with_options(console="internalConsole")] + all_launch_terminal
|
||||
|
||||
all_attach_listen = [attach_listen["api"], attach_listen["cli"]]
|
||||
|
||||
|
|
|
|||
|
|
@ -490,7 +490,11 @@ class Session(object):
|
|||
def _process_request(self, request):
|
||||
self.timeline.record_request(request, block=False)
|
||||
if request.command == "runInTerminal":
|
||||
args = request("args", json.array(str))
|
||||
args = request("args", json.array(str, vectorize=True))
|
||||
if len(args) > 0 and request("argsCanBeInterpretedByShell", False):
|
||||
# The final arg is a string that contains multiple actual arguments.
|
||||
last_arg = args.pop()
|
||||
args += last_arg.split()
|
||||
cwd = request("cwd", ".")
|
||||
env = request("env", json.object(str))
|
||||
try:
|
||||
|
|
@ -557,6 +561,7 @@ class Session(object):
|
|||
"columnsStartAt1": True,
|
||||
"supportsVariableType": True,
|
||||
"supportsRunInTerminalRequest": True,
|
||||
"supportsArgsCanBeInterpretedByShell": True,
|
||||
},
|
||||
)
|
||||
|
||||
|
|
|
|||
|
|
@ -45,6 +45,14 @@ class Target(object):
|
|||
"""
|
||||
raise NotImplementedError
|
||||
|
||||
@property
|
||||
def argslist(self):
|
||||
args = self.args
|
||||
if isinstance(args, str):
|
||||
return [args]
|
||||
else:
|
||||
return list(args)
|
||||
|
||||
@property
|
||||
def co_filename(self):
|
||||
"""co_filename of code objects created at runtime from the source that this
|
||||
|
|
@ -121,9 +129,11 @@ class Program(Target):
|
|||
|
||||
def cli(self, env):
|
||||
if self._cwd:
|
||||
return [self._get_relative_program()] + list(self.args)
|
||||
cli = [self._get_relative_program()]
|
||||
else:
|
||||
return [self.filename.strpath] + list(self.args)
|
||||
cli = [self.filename.strpath]
|
||||
cli += self.argslist
|
||||
return cli
|
||||
|
||||
|
||||
class Module(Target):
|
||||
|
|
@ -150,7 +160,7 @@ class Module(Target):
|
|||
def cli(self, env):
|
||||
if self.filename is not None:
|
||||
env.prepend_to("PYTHONPATH", self.filename.dirname)
|
||||
return ["-m", self.name] + list(self.args)
|
||||
return ["-m", self.name] + self.argslist
|
||||
|
||||
|
||||
class Code(Target):
|
||||
|
|
@ -176,7 +186,7 @@ class Code(Target):
|
|||
session.config["args"] = self.args
|
||||
|
||||
def cli(self, env):
|
||||
return ["-c", self.code] + list(self.args)
|
||||
return ["-c", self.code] + self.argslist
|
||||
|
||||
@property
|
||||
def co_filename(self):
|
||||
|
|
|
|||
|
|
@ -34,8 +34,11 @@ def test_args(pyfile, target, run):
|
|||
|
||||
@pytest.mark.parametrize("target", targets.all)
|
||||
@pytest.mark.parametrize("run", runners.all_launch)
|
||||
@pytest.mark.parametrize("expansion", ["", "none", "shell"])
|
||||
@pytest.mark.parametrize("expansion", ["preserve", "expand"])
|
||||
def test_shell_expansion(pyfile, target, run, expansion):
|
||||
if expansion == "expand" and run.console == "internalConsole":
|
||||
pytest.skip('Shell expansion is not supported for "internalConsole"')
|
||||
|
||||
@pyfile
|
||||
def code_to_debug():
|
||||
import sys
|
||||
|
|
@ -46,6 +49,8 @@ def test_shell_expansion(pyfile, target, run, expansion):
|
|||
backchannel.send(sys.argv)
|
||||
|
||||
def expand(args):
|
||||
if expansion != "expand":
|
||||
return
|
||||
log.info("Before expansion: {0}", args)
|
||||
for i, arg in enumerate(args):
|
||||
if arg.startswith("$"):
|
||||
|
|
@ -57,17 +62,14 @@ def test_shell_expansion(pyfile, target, run, expansion):
|
|||
expand(args)
|
||||
return super().run_in_terminal(args, cwd, env)
|
||||
|
||||
args = ["0", "$1", "2"]
|
||||
argslist = ["0", "$1", "2"]
|
||||
args = argslist if expansion == "preserve" else " ".join(argslist)
|
||||
with Session() as session:
|
||||
if expansion:
|
||||
session.config["argsExpansion"] = expansion
|
||||
|
||||
backchannel = session.open_backchannel()
|
||||
with run(session, target(code_to_debug, args=args)):
|
||||
pass
|
||||
|
||||
argv = backchannel.receive()
|
||||
|
||||
if session.config["console"] != "internalConsole" and expansion != "none":
|
||||
expand(args)
|
||||
assert argv == [some.str] + args
|
||||
expand(argslist)
|
||||
assert argv == [some.str] + argslist
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue