From b83c42e41ab6b67a42f16415ceeb93bd38ea4a79 Mon Sep 17 00:00:00 2001 From: Jeff Epler Date: Fri, 2 Dec 2022 10:47:50 -0600 Subject: [PATCH] Implement the chain= argument of traceback.print_exception --- shared-bindings/traceback/__init__.c | 22 ++++++++++++++----- tests/circuitpython/traceback_test_chained.py | 5 +++-- .../traceback_test_chained.py.exp | 18 ++++++++++----- 3 files changed, 31 insertions(+), 14 deletions(-) diff --git a/shared-bindings/traceback/__init__.c b/shared-bindings/traceback/__init__.c index eeb7bc458d..153587e919 100644 --- a/shared-bindings/traceback/__init__.c +++ b/shared-bindings/traceback/__init__.c @@ -58,6 +58,7 @@ STATIC void traceback_exception_common(bool is_print_exception, mp_print_t *prin } mp_obj_t tb_obj = args[ARG_tb].u_obj; mp_obj_t limit_obj = args[ARG_limit].u_obj; + bool chain = args[ARG_chain].u_bool; if (args[ARG_file].u_obj != mp_const_none) { if (!is_print_exception) { @@ -90,6 +91,15 @@ STATIC void traceback_exception_common(bool is_print_exception, mp_print_t *prin mp_obj_exception_t *exc = mp_obj_exception_get_native(value); mp_obj_traceback_t *trace_backup = exc->traceback; + #if MICROPY_CPYTHON_EXCEPTION_CHAIN + mp_obj_exception_t *context_backup = exc->context; + mp_obj_exception_t *cause_backup = exc->cause; + + if (!chain) { + exc->context = NULL; + exc->cause = NULL; + } + #endif if (tb_obj == MP_OBJ_NULL) { /* Print the traceback's exception as is */ @@ -101,6 +111,10 @@ STATIC void traceback_exception_common(bool is_print_exception, mp_print_t *prin shared_module_traceback_print_exception(MP_OBJ_TO_PTR(value), print, limit); exc->traceback = trace_backup; + #if MICROPY_CPYTHON_EXCEPTION_CHAIN + exc->context = context_backup; + exc->cause = cause_backup; + #endif } //| def format_exception( @@ -128,14 +142,12 @@ STATIC void traceback_exception_common(bool is_print_exception, mp_print_t *prin //| these lines are concatenated and printed, exactly the same text is //| printed as does print_exception(). //| -//| .. note:: Setting ``chain`` will have no effect as chained exceptions are not yet implemented. -//| //| :param exc: The exception. Must be an instance of `BaseException`. Unused if value is specified. //| :param value: If specified, is used in place of ``exc``. //| :param TracebackType tb: When value is alsp specified, ``tb`` is used in place of the exception's own traceback. If `None`, the traceback will not be printed. //| :param int limit: Print up to limit stack trace entries (starting from the caller’s frame) if limit is positive. //| Otherwise, print the last ``abs(limit)`` entries. If limit is omitted or None, all entries are printed. -//| :param bool chain: If `True` then chained exceptions will be printed (note: not yet implemented). +//| :param bool chain: If `True` then chained exceptions will be printed. //| """ //| STATIC mp_obj_t traceback_format_exception(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { @@ -169,8 +181,6 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_KW(traceback_format_exception_obj, 0, traceback_f //| no traceback will be shown. This is compatible with CPython 3.5 and //| newer. //| -//| .. note:: Setting ``chain`` will have no effect as chained exceptions are not yet implemented. -//| //| :param exc: The exception. Must be an instance of `BaseException`. Unused if value is specified. //| :param value: If specified, is used in place of ``exc``. //| :param tb: When value is alsp specified, ``tb`` is used in place of the exception's own traceback. If `None`, the traceback will not be printed. @@ -178,7 +188,7 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_KW(traceback_format_exception_obj, 0, traceback_f //| Otherwise, print the last ``abs(limit)`` entries. If limit is omitted or None, all entries are printed. //| :param io.FileIO file: If file is omitted or `None`, the output goes to `sys.stderr`; otherwise it should be an open //| file or file-like object to receive the output. -//| :param bool chain: If `True` then chained exceptions will be printed (note: not yet implemented). +//| :param bool chain: If `True` then chained exceptions will be printed. //| //| """ //| ... diff --git a/tests/circuitpython/traceback_test_chained.py b/tests/circuitpython/traceback_test_chained.py index 83d0c03466..72336d7495 100644 --- a/tests/circuitpython/traceback_test_chained.py +++ b/tests/circuitpython/traceback_test_chained.py @@ -11,9 +11,9 @@ except: raise SystemExit -def print_exc_info(e): +def print_exc_info(e, chain=True): print("-" * 72) - traceback.print_exception(None, e, e.__traceback__) + traceback.print_exception(None, e, e.__traceback__, chain=chain) print("-" * 72) print() @@ -24,6 +24,7 @@ try: except Exception as inner: raise RuntimeError() from inner except Exception as e: + print_exc_info(e, chain=False) print_exc_info(e) print() diff --git a/tests/circuitpython/traceback_test_chained.py.exp b/tests/circuitpython/traceback_test_chained.py.exp index c874ff707f..5fa40126b3 100644 --- a/tests/circuitpython/traceback_test_chained.py.exp +++ b/tests/circuitpython/traceback_test_chained.py.exp @@ -1,3 +1,9 @@ +------------------------------------------------------------------------ +Traceback (most recent call last): + File "circuitpython/traceback_test_chained.py", line 25, in +RuntimeError: +------------------------------------------------------------------------ + ------------------------------------------------------------------------ Traceback (most recent call last): File "circuitpython/traceback_test_chained.py", line 23, in @@ -17,39 +23,39 @@ OSError: The above exception was the direct cause of the following exception: Traceback (most recent call last): - File "circuitpython/traceback_test_chained.py", line 34, in + File "circuitpython/traceback_test_chained.py", line 35, in RuntimeError: ------------------------------------------------------------------------ ------------------------------------------------------------------------ Traceback (most recent call last): - File "circuitpython/traceback_test_chained.py", line 42, in + File "circuitpython/traceback_test_chained.py", line 43, in ZeroDivisionError: division by zero During handling of the above exception, another exception occurred: Traceback (most recent call last): - File "circuitpython/traceback_test_chained.py", line 44, in + File "circuitpython/traceback_test_chained.py", line 45, in RuntimeError: ------------------------------------------------------------------------ ------------------------------------------------------------------------ Traceback (most recent call last): - File "circuitpython/traceback_test_chained.py", line 53, in + File "circuitpython/traceback_test_chained.py", line 54, in RuntimeError: ------------------------------------------------------------------------ ------------------------------------------------------------------------ Traceback (most recent call last): - File "circuitpython/traceback_test_chained.py", line 59, in + File "circuitpython/traceback_test_chained.py", line 60, in RuntimeError: During handling of the above exception, another exception occurred: Traceback (most recent call last): - File "circuitpython/traceback_test_chained.py", line 61, in + File "circuitpython/traceback_test_chained.py", line 62, in ZeroDivisionError: division by zero ------------------------------------------------------------------------