Show cause message on chained exception. Fixes #1024

This commit is contained in:
Fabio Zadrozny 2022-09-16 11:42:39 -03:00
parent 761bacebb5
commit c300080c62
3 changed files with 72 additions and 1 deletions

View file

@ -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)

View file

@ -0,0 +1,12 @@
def method2():
{}['foo']
def method():
try:
method2()
except Exception as e:
raise Exception('TEST SUCEEDED') from e
method()

View file

@ -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):
@ -771,6 +770,53 @@ def test_case_throw_exc_reason(case_setup):
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)