Skip to content

Commit

Permalink
Don't print twice in evaluation if output is being already redirected.
Browse files Browse the repository at this point in the history
…Fixes microsoft#827
  • Loading branch information
fabioz committed Feb 25, 2022
1 parent 6134532 commit 8c01072
Show file tree
Hide file tree
Showing 6 changed files with 53 additions and 1 deletion.
2 changes: 1 addition & 1 deletion src/debugpy/_vendored/pydevd/_pydevd_bundle/pydevd_comm.py
Original file line number Diff line number Diff line change
Expand Up @@ -1161,7 +1161,7 @@ def internal_evaluate_expression_json(py_db, request, thread_id):
if hasattr(fmt, 'to_dict'):
fmt = fmt.to_dict()

if context == 'repl':
if context == 'repl' and not py_db.is_output_redirected:
ctx = pydevd_io.redirect_stream_to_pydb_io_messages_context()
else:
ctx = NULL
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -389,11 +389,15 @@ def get_variable_presentation(setting, default):
if bool(path_mappings):
pydevd_file_utils.setup_client_server_paths(path_mappings)

redirecting = args.get("isOutputRedirected")
if self._options.redirect_output:
py_db.enable_output_redirection(True, True)
redirecting = True
else:
py_db.enable_output_redirection(False, False)

py_db.is_output_redirected = redirecting

self.api.set_show_return_values(py_db, self._options.show_return_value)

if not self._options.break_system_exit_zero:
Expand Down
3 changes: 3 additions & 0 deletions src/debugpy/_vendored/pydevd/pydevd.py
Original file line number Diff line number Diff line change
Expand Up @@ -639,6 +639,9 @@ def __init__(self, set_as_global=True):
self.show_return_values = False
self.remove_return_values_flag = False
self.redirect_output = False
# Note that besides the `redirect_output` flag, we also need to consider that someone
# else is already redirecting (i.e.: debugpy).
self.is_output_redirected = False

# this flag disables frame evaluation even if it's available
self.use_frame_eval = True
Expand Down
5 changes: 5 additions & 0 deletions src/debugpy/adapter/clients.py
Original file line number Diff line number Diff line change
Expand Up @@ -217,17 +217,22 @@ def handle(self, request):

arguments = request.arguments
if self.launcher:
redirecting = arguments.get("console") == "internalConsole"
if "RedirectOutput" in debug_options:
# The launcher is doing output redirection, so we don't need the
# server to do it, as well.
arguments = dict(arguments)
arguments["debugOptions"] = list(
debug_options - {"RedirectOutput"}
)
redirecting = True

if arguments.get("redirectOutput"):
arguments = dict(arguments)
del arguments["redirectOutput"]
redirecting = True

arguments["isOutputRedirected"] = redirecting

# pydevd doesn't send "initialized", and responds to the start request
# immediately, without waiting for "configurationDone". If it changes
Expand Down
3 changes: 3 additions & 0 deletions tests/debugpy/test_multiproc.py
Original file line number Diff line number Diff line change
Expand Up @@ -135,6 +135,7 @@ def grandchild(q, a):

expected_child_config = expected_subprocess_config(parent_session)
child_config = parent_session.wait_for_next_event("debugpyAttach")
child_config.pop("isOutputRedirected", None)
assert child_config == expected_child_config
parent_session.proceed()

Expand All @@ -144,6 +145,7 @@ def grandchild(q, a):

expected_grandchild_config = expected_subprocess_config(child_session)
grandchild_config = child_session.wait_for_next_event("debugpyAttach")
grandchild_config.pop("isOutputRedirected", None)
assert grandchild_config == expected_grandchild_config

with debug.Session(grandchild_config) as grandchild_session:
Expand Down Expand Up @@ -204,6 +206,7 @@ def parent():

expected_child_config = expected_subprocess_config(parent_session)
child_config = parent_session.wait_for_next_event("debugpyAttach")
child_config.pop("isOutputRedirected", None)
assert child_config == expected_child_config
parent_session.proceed()

Expand Down
37 changes: 37 additions & 0 deletions tests/debugpy/test_output.py
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,43 @@ def code_to_debug():
assert session.output("stdout").startswith("Hello\tWorld")


@pytest.mark.parametrize("redirect_mode", ["internalConsole", "redirectOutput"])
def test_redirect_output_and_eval(pyfile, target, run, redirect_mode):
@pyfile
def code_to_debug():
import debuggee
import sys

debuggee.setup()
sys.stdout.write("line\n")
() # @wait_for_output

with debug.Session() as session:
if redirect_mode == "redirectOutput":
session.config["redirectOutput"] = True
elif redirect_mode == "internalConsole":
session.config["console"] = "internalConsole"
else:
raise AssertionError("Unexpected: " + redirect_mode)

with run(session, target(code_to_debug)):
session.set_breakpoints(code_to_debug, all)

stop = session.wait_for_stop()
session.request(
"evaluate",
{
"expression": "sys.stdout.write('evaluated\\n')",
"frameId": stop.frame_id,
"context": "repl",
},
)

session.request_continue()

assert session.output("stdout") == "line\nevaluated\n"


@pytest.mark.parametrize("run", runners.all)
@pytest.mark.parametrize("redirect", ["enabled", "disabled"])
def test_redirect_output(pyfile, target, run, redirect):
Expand Down

0 comments on commit 8c01072

Please sign in to comment.