Implement the chain= argument of traceback.print_exception

This commit is contained in:
Jeff Epler 2022-12-02 10:47:50 -06:00
parent 6e40949f6e
commit b83c42e41a
No known key found for this signature in database
GPG Key ID: D5BF15AB975AB4DE
3 changed files with 31 additions and 14 deletions

View File

@ -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 tb_obj = args[ARG_tb].u_obj;
mp_obj_t limit_obj = args[ARG_limit].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 (args[ARG_file].u_obj != mp_const_none) {
if (!is_print_exception) { 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_exception_t *exc = mp_obj_exception_get_native(value);
mp_obj_traceback_t *trace_backup = exc->traceback; 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) { if (tb_obj == MP_OBJ_NULL) {
/* Print the traceback's exception as is */ /* 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); shared_module_traceback_print_exception(MP_OBJ_TO_PTR(value), print, limit);
exc->traceback = trace_backup; exc->traceback = trace_backup;
#if MICROPY_CPYTHON_EXCEPTION_CHAIN
exc->context = context_backup;
exc->cause = cause_backup;
#endif
} }
//| def format_exception( //| 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 //| these lines are concatenated and printed, exactly the same text is
//| printed as does print_exception(). //| 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 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 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 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 callers frame) if limit is positive. //| :param int limit: Print up to limit stack trace entries (starting from the callers frame) if limit is positive.
//| Otherwise, print the last ``abs(limit)`` entries. If limit is omitted or None, all entries are printed. //| 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) { 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 //| no traceback will be shown. This is compatible with CPython 3.5 and
//| newer. //| 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 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 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. //| :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. //| 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 //| :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. //| 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.
//| //|
//| """ //| """
//| ... //| ...

View File

@ -11,9 +11,9 @@ except:
raise SystemExit raise SystemExit
def print_exc_info(e): def print_exc_info(e, chain=True):
print("-" * 72) print("-" * 72)
traceback.print_exception(None, e, e.__traceback__) traceback.print_exception(None, e, e.__traceback__, chain=chain)
print("-" * 72) print("-" * 72)
print() print()
@ -24,6 +24,7 @@ try:
except Exception as inner: except Exception as inner:
raise RuntimeError() from inner raise RuntimeError() from inner
except Exception as e: except Exception as e:
print_exc_info(e, chain=False)
print_exc_info(e) print_exc_info(e)
print() print()

View File

@ -1,3 +1,9 @@
------------------------------------------------------------------------
Traceback (most recent call last):
File "circuitpython/traceback_test_chained.py", line 25, in <module>
RuntimeError:
------------------------------------------------------------------------
------------------------------------------------------------------------ ------------------------------------------------------------------------
Traceback (most recent call last): Traceback (most recent call last):
File "circuitpython/traceback_test_chained.py", line 23, in <module> File "circuitpython/traceback_test_chained.py", line 23, in <module>
@ -17,39 +23,39 @@ OSError:
The above exception was the direct cause of the following exception: The above exception was the direct cause of the following exception:
Traceback (most recent call last): Traceback (most recent call last):
File "circuitpython/traceback_test_chained.py", line 34, in <module> File "circuitpython/traceback_test_chained.py", line 35, in <module>
RuntimeError: RuntimeError:
------------------------------------------------------------------------ ------------------------------------------------------------------------
------------------------------------------------------------------------ ------------------------------------------------------------------------
Traceback (most recent call last): Traceback (most recent call last):
File "circuitpython/traceback_test_chained.py", line 42, in <module> File "circuitpython/traceback_test_chained.py", line 43, in <module>
ZeroDivisionError: division by zero ZeroDivisionError: division by zero
During handling of the above exception, another exception occurred: During handling of the above exception, another exception occurred:
Traceback (most recent call last): Traceback (most recent call last):
File "circuitpython/traceback_test_chained.py", line 44, in <module> File "circuitpython/traceback_test_chained.py", line 45, in <module>
RuntimeError: RuntimeError:
------------------------------------------------------------------------ ------------------------------------------------------------------------
------------------------------------------------------------------------ ------------------------------------------------------------------------
Traceback (most recent call last): Traceback (most recent call last):
File "circuitpython/traceback_test_chained.py", line 53, in <module> File "circuitpython/traceback_test_chained.py", line 54, in <module>
RuntimeError: RuntimeError:
------------------------------------------------------------------------ ------------------------------------------------------------------------
------------------------------------------------------------------------ ------------------------------------------------------------------------
Traceback (most recent call last): Traceback (most recent call last):
File "circuitpython/traceback_test_chained.py", line 59, in <module> File "circuitpython/traceback_test_chained.py", line 60, in <module>
RuntimeError: RuntimeError:
During handling of the above exception, another exception occurred: During handling of the above exception, another exception occurred:
Traceback (most recent call last): Traceback (most recent call last):
File "circuitpython/traceback_test_chained.py", line 61, in <module> File "circuitpython/traceback_test_chained.py", line 62, in <module>
ZeroDivisionError: division by zero ZeroDivisionError: division by zero
------------------------------------------------------------------------ ------------------------------------------------------------------------