Skip to content

Commit

Permalink
Show cause message on chained exception. Fixes #1024
Browse files Browse the repository at this point in the history
  • Loading branch information
fabioz committed Sep 26, 2022
1 parent 761bace commit c300080
Show file tree
Hide file tree
Showing 3 changed files with 72 additions and 1 deletion.
13 changes: 13 additions & 0 deletions src/debugpy/_vendored/pydevd/_pydevd_bundle/pydevd_comm.py
Original file line number Diff line number Diff line change
Expand Up @@ -1467,6 +1467,19 @@ def build_exception_info_response(dbg, thread_id, request_seq, set_additional_th
source_path = frames[0][0]

stack_str = ''.join(traceback.format_list(frames[-max_frames:]))

try:
stype = frames_list.exc_type.__qualname__
smod = frames_list.exc_type.__module__
if smod not in ("__main__", "builtins"):
if not isinstance(smod, str):
smod = "<unknown>"
stype = smod + '.' + stype
except Exception:
stype = '<unable to get exception type>'
pydev_log.exception('Error getting exception type.')

stack_str += '%s: %s\n' % (stype, frames_list.exc_desc)
stack_str += frames_list.exc_context_msg
stack_str_lst.append(stack_str)

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
def method2():
{}['foo']


def method():
try:
method2()
except Exception as e:
raise Exception('TEST SUCEEDED') from e


method()
48 changes: 47 additions & 1 deletion src/debugpy/_vendored/pydevd/tests_python/test_debugger_json.py
Original file line number Diff line number Diff line change
Expand Up @@ -719,7 +719,6 @@ def test_case_handled_exception_no_break_on_generator(case_setup):
writer.finished_ok = True


@pytest.mark.skipif(not IS_PY36_OR_GREATER, reason='Requires Python 3.')
def test_case_throw_exc_reason(case_setup):

def check_test_suceeded_msg(self, stdout, stderr):
Expand Down Expand Up @@ -771,6 +770,53 @@ def additional_output_checks(writer, stdout, stderr):
writer.finished_ok = True


def test_case_throw_exc_reason_shown(case_setup):

def check_test_suceeded_msg(self, stdout, stderr):
return 'TEST SUCEEDED' in ''.join(stderr)

def additional_output_checks(writer, stdout, stderr):
assert "raise Exception('TEST SUCEEDED') from e" in stderr
assert "{}['foo']" in stderr
assert "KeyError: 'foo'" in stderr

with case_setup.test_file(
'_debugger_case_raise_with_cause_msg.py',
EXPECTED_RETURNCODE=1,
check_test_suceeded_msg=check_test_suceeded_msg,
additional_output_checks=additional_output_checks
) as writer:
json_facade = JsonFacade(writer)

json_facade.write_launch(justMyCode=False)
json_facade.write_set_exception_breakpoints(['uncaught'])
json_facade.write_make_initial_run()

json_hit = json_facade.wait_for_thread_stopped(
reason='exception', line=writer.get_line_index_with_content("raise Exception('TEST SUCEEDED') from e"))

exc_info_request = json_facade.write_request(
pydevd_schema.ExceptionInfoRequest(pydevd_schema.ExceptionInfoArguments(json_hit.thread_id)))
exc_info_response = json_facade.wait_for_response(exc_info_request)

stack_frames = json_hit.stack_trace_response.body.stackFrames
# Note that the additional context doesn't really appear in the stack
# frames, only in the details.
assert [x['name'] for x in stack_frames] == ['method', '<module>']

body = exc_info_response.body
assert body.exceptionId == 'Exception'
assert body.description == 'TEST SUCEEDED'
assert normcase(body.details.kwargs['source']) == normcase(writer.TEST_FILE)

# Check that we have the exception cause in the stack trace.
assert "KeyError: 'foo'" in body.details.stackTrace

json_facade.write_continue()

writer.finished_ok = True


def test_case_handled_exception_breaks(case_setup):
with case_setup.test_file('_debugger_case_exceptions.py') as writer:
json_facade = JsonFacade(writer)
Expand Down

0 comments on commit c300080

Please sign in to comment.