add traceback module
This commit is contained in:
parent
fc59a7ac02
commit
f371c0a609
@ -35,11 +35,11 @@ msgid ""
|
||||
"https://github.com/adafruit/circuitpython/issues\n"
|
||||
msgstr ""
|
||||
|
||||
#: py/obj.c
|
||||
#: py/obj.c shared-bindings/traceback/__init__.c
|
||||
msgid " File \"%q\""
|
||||
msgstr ""
|
||||
|
||||
#: py/obj.c
|
||||
#: py/obj.c shared-bindings/traceback/__init__.c
|
||||
msgid " File \"%q\", line %d"
|
||||
msgstr ""
|
||||
|
||||
@ -322,7 +322,7 @@ msgstr ""
|
||||
msgid "*x must be assignment target"
|
||||
msgstr ""
|
||||
|
||||
#: py/obj.c
|
||||
#: py/obj.c shared-bindings/traceback/__init__.c
|
||||
msgid ", in %q\n"
|
||||
msgstr ""
|
||||
|
||||
@ -1185,11 +1185,6 @@ msgstr ""
|
||||
msgid "Input/output error"
|
||||
msgstr ""
|
||||
|
||||
#: ports/raspberrypi/common-hal/rp2pio/StateMachine.c
|
||||
#, c-format
|
||||
msgid "Missing jmp_pin. Instruction %d jumps on pin"
|
||||
msgstr ""
|
||||
|
||||
#: ports/raspberrypi/common-hal/rp2pio/StateMachine.c
|
||||
#, c-format
|
||||
msgid "Instruction %d shifts in more bits than pin count"
|
||||
@ -1506,6 +1501,11 @@ msgstr ""
|
||||
msgid "Missing first_set_pin. Instruction %d sets pin(s)"
|
||||
msgstr ""
|
||||
|
||||
#: ports/raspberrypi/common-hal/rp2pio/StateMachine.c
|
||||
#, c-format
|
||||
msgid "Missing jmp_pin. Instruction %d jumps on pin"
|
||||
msgstr ""
|
||||
|
||||
#: shared-bindings/busio/UART.c shared-bindings/displayio/Group.c
|
||||
msgid "Must be a %q subclass."
|
||||
msgstr ""
|
||||
@ -2227,7 +2227,7 @@ msgstr ""
|
||||
msgid "Touch alarms not available"
|
||||
msgstr ""
|
||||
|
||||
#: py/obj.c
|
||||
#: py/obj.c shared-bindings/traceback/__init__.c
|
||||
msgid "Traceback (most recent call last):\n"
|
||||
msgstr ""
|
||||
|
||||
@ -2525,7 +2525,7 @@ msgid "argument name reused"
|
||||
msgstr ""
|
||||
|
||||
#: py/argcheck.c shared-bindings/_stage/__init__.c
|
||||
#: shared-bindings/digitalio/DigitalInOut.c shared-bindings/gamepad/GamePad.c
|
||||
#: shared-bindings/digitalio/DigitalInOut.c
|
||||
msgid "argument num/types mismatch"
|
||||
msgstr ""
|
||||
|
||||
@ -3089,6 +3089,10 @@ msgstr ""
|
||||
msgid "file must be a file opened in byte mode"
|
||||
msgstr ""
|
||||
|
||||
#: shared-bindings/traceback/__init__.c
|
||||
msgid "file write is not available"
|
||||
msgstr ""
|
||||
|
||||
#: shared-bindings/storage/__init__.c
|
||||
msgid "filesystem must provide mount method"
|
||||
msgstr ""
|
||||
@ -3376,6 +3380,10 @@ msgstr ""
|
||||
msgid "invalid element_size %d, must be, 1, 2, or 4"
|
||||
msgstr ""
|
||||
|
||||
#: shared-bindings/traceback/__init__.c
|
||||
msgid "invalid exception"
|
||||
msgstr ""
|
||||
|
||||
#: extmod/modframebuf.c
|
||||
msgid "invalid format"
|
||||
msgstr ""
|
||||
@ -3457,6 +3465,10 @@ msgstr ""
|
||||
msgid "lhs and rhs should be compatible"
|
||||
msgstr ""
|
||||
|
||||
#: shared-bindings/traceback/__init__.c
|
||||
msgid "limit should be an int"
|
||||
msgstr ""
|
||||
|
||||
#: py/emitnative.c
|
||||
msgid "local '%q' has type '%q' but source is '%q'"
|
||||
msgstr ""
|
||||
@ -3609,10 +3621,6 @@ msgstr ""
|
||||
msgid "no active exception to reraise"
|
||||
msgstr ""
|
||||
|
||||
#: shared-bindings/socket/__init__.c shared-module/network/__init__.c
|
||||
msgid "no available NIC"
|
||||
msgstr ""
|
||||
|
||||
#: py/compile.c
|
||||
msgid "no binding for nonlocal found"
|
||||
msgstr ""
|
||||
@ -4085,6 +4093,10 @@ msgstr ""
|
||||
msgid "source palette too large"
|
||||
msgstr ""
|
||||
|
||||
#: shared-bindings/traceback/__init__.c
|
||||
msgid "stack is not ok"
|
||||
msgstr ""
|
||||
|
||||
#: py/objstr.c
|
||||
msgid "start/end indices"
|
||||
msgstr ""
|
||||
|
@ -19,6 +19,7 @@ CIRCUITPY_PWMIO = 0
|
||||
CIRCUITPY_ROTARYIO = 0
|
||||
CIRCUITPY_RTC = 0
|
||||
CIRCUITPY_USB_MIDI = 0
|
||||
CIRCUITPY_TRACEBACK = 0
|
||||
|
||||
CIRCUITPY_PIXELBUF = 1
|
||||
CIRCUITPY_BUSDEVICE = 1
|
||||
|
@ -293,6 +293,9 @@ endif
|
||||
ifeq ($(CIRCUITPY_TOUCHIO),1)
|
||||
SRC_PATTERNS += touchio/%
|
||||
endif
|
||||
ifeq ($(CIRCUITPY_TRACEBACK),1)
|
||||
SRC_PATTERNS += traceback/%
|
||||
endif
|
||||
ifeq ($(CIRCUITPY_UHEAP),1)
|
||||
SRC_PATTERNS += uheap/%
|
||||
endif
|
||||
@ -544,6 +547,7 @@ SRC_SHARED_MODULE_ALL = \
|
||||
terminalio/Terminal.c \
|
||||
terminalio/__init__.c \
|
||||
time/__init__.c \
|
||||
traceback/__init__.c \
|
||||
uheap/__init__.c \
|
||||
ustack/__init__.c \
|
||||
vectorio/Circle.c \
|
||||
|
@ -763,6 +763,13 @@ extern const struct _mp_obj_module_t touchio_module;
|
||||
#define TOUCHIO_MODULE
|
||||
#endif
|
||||
|
||||
#if CIRCUITPY_TRACEBACK
|
||||
extern const struct _mp_obj_module_t traceback_module;
|
||||
#define TRACEBACK_MODULE { MP_OBJ_NEW_QSTR(MP_QSTR_traceback), (mp_obj_t)&traceback_module },
|
||||
#else
|
||||
#define TRACEBACK_MODULE
|
||||
#endif
|
||||
|
||||
#if CIRCUITPY_UHEAP
|
||||
extern const struct _mp_obj_module_t uheap_module;
|
||||
#define UHEAP_MODULE { MP_OBJ_NEW_QSTR(MP_QSTR_uheap),(mp_obj_t)&uheap_module },
|
||||
@ -917,6 +924,7 @@ extern const struct _mp_obj_module_t msgpack_module;
|
||||
SUPERVISOR_MODULE \
|
||||
SYNTHIO_MODULE \
|
||||
TOUCHIO_MODULE \
|
||||
TRACEBACK_MODULE \
|
||||
UHEAP_MODULE \
|
||||
USB_CDC_MODULE \
|
||||
USB_HID_MODULE \
|
||||
|
@ -324,6 +324,9 @@ CFLAGS += -DCIRCUITPY_TOUCHIO_USE_NATIVE=$(CIRCUITPY_TOUCHIO_USE_NATIVE)
|
||||
CIRCUITPY_TOUCHIO ?= 1
|
||||
CFLAGS += -DCIRCUITPY_TOUCHIO=$(CIRCUITPY_TOUCHIO)
|
||||
|
||||
CIRCUITPY_TRACEBACK ?= 1
|
||||
CFLAGS += -DCIRCUITPY_TRACEBACK=$(CIRCUITPY_TRACEBACK)
|
||||
|
||||
# For debugging.
|
||||
CIRCUITPY_UHEAP ?= 0
|
||||
CFLAGS += -DCIRCUITPY_UHEAP=$(CIRCUITPY_UHEAP)
|
||||
|
19
py/modsys.c
19
py/modsys.c
@ -120,25 +120,6 @@ STATIC mp_obj_t mp_sys_exit(size_t n_args, const mp_obj_t *args) {
|
||||
}
|
||||
MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mp_sys_exit_obj, 0, 1, mp_sys_exit);
|
||||
|
||||
STATIC mp_obj_t mp_sys_print_exception(size_t n_args, const mp_obj_t *args) {
|
||||
#if MICROPY_PY_IO && MICROPY_PY_SYS_STDFILES
|
||||
void *stream_obj = &mp_sys_stdout_obj;
|
||||
if (n_args > 1) {
|
||||
mp_get_stream_raise(args[1], MP_STREAM_OP_WRITE);
|
||||
stream_obj = MP_OBJ_TO_PTR(args[1]);
|
||||
}
|
||||
|
||||
mp_print_t print = {stream_obj, mp_stream_write_adaptor};
|
||||
mp_obj_print_exception(&print, args[0]);
|
||||
#else
|
||||
(void)n_args;
|
||||
mp_obj_print_exception(&mp_plat_print, args[0]);
|
||||
#endif
|
||||
|
||||
return mp_const_none;
|
||||
}
|
||||
MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mp_sys_print_exception_obj, 1, 2, mp_sys_print_exception);
|
||||
|
||||
#if MICROPY_PY_SYS_EXC_INFO
|
||||
STATIC mp_obj_t mp_sys_exc_info(void) {
|
||||
mp_obj_t cur_exc = MP_OBJ_FROM_PTR(MP_STATE_VM(cur_exception));
|
||||
|
171
shared-bindings/traceback/__init__.c
Normal file
171
shared-bindings/traceback/__init__.c
Normal file
@ -0,0 +1,171 @@
|
||||
/*
|
||||
* This file is part of the Micro Python project, http://micropython.org/
|
||||
*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2021 microDev
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "py/stream.h"
|
||||
#include "py/runtime.h"
|
||||
|
||||
#include "supervisor/shared/stack.h"
|
||||
|
||||
//| """Traceback Module
|
||||
//|
|
||||
//| This module provides a standard interface to print stack traces of programs.
|
||||
//| This is useful when you want to print stack traces under program control.
|
||||
//|
|
||||
//| """
|
||||
//| ...
|
||||
//|
|
||||
|
||||
//| def print_exception(etype: Type[BaseException], value: BaseException, tb: TracebackType,
|
||||
//| limit: Optional[int] = None, file: Optional[io.FileIO] = None, chain: Optional[bool] = True) -> None:
|
||||
//|
|
||||
//| """Prints exception information and stack trace entries.
|
||||
//|
|
||||
//| .. note: Setting `chain` will have no effect as chained exceptions are not yet implemented.
|
||||
//|
|
||||
//| :param Type[BaseException] etype: This is ignored and inferred from the type of ``value``.
|
||||
//| :param BaseException value: The exception. Must be an instance of `BaseException`.
|
||||
//| :param TracebackType tb: The traceback object. 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 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.
|
||||
//|
|
||||
//| """
|
||||
//| ...
|
||||
//|
|
||||
STATIC mp_obj_t traceback_print_exception(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
|
||||
enum { ARG_etype, ARG_value, ARG_tb, ARG_limit, ARG_file, ARG_chain };
|
||||
static const mp_arg_t allowed_args[] = {
|
||||
{ MP_QSTR_etype, MP_ARG_OBJ | MP_ARG_REQUIRED },
|
||||
{ MP_QSTR_value, MP_ARG_OBJ | MP_ARG_REQUIRED },
|
||||
{ MP_QSTR_tb, MP_ARG_OBJ | MP_ARG_REQUIRED },
|
||||
{ MP_QSTR_limit, MP_ARG_OBJ, {.u_obj = mp_const_none} },
|
||||
{ MP_QSTR_file, MP_ARG_OBJ, {.u_obj = mp_const_none} },
|
||||
{ MP_QSTR_chain, MP_ARG_BOOL, {.u_bool = true} },
|
||||
};
|
||||
|
||||
mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)];
|
||||
mp_arg_parse_all(n_args, pos_args, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args);
|
||||
|
||||
mp_obj_t exc = args[ARG_value].u_obj;
|
||||
if (!mp_obj_is_exception_instance(exc)) {
|
||||
mp_raise_TypeError(translate("invalid exception"));
|
||||
}
|
||||
|
||||
mp_print_t print = mp_plat_print;
|
||||
if (args[ARG_file].u_obj != mp_const_none) {
|
||||
#if MICROPY_PY_IO && MICROPY_PY_SYS_STDFILES
|
||||
mp_get_stream_raise(args[ARG_file].u_obj, MP_STREAM_OP_WRITE);
|
||||
print.data = MP_OBJ_TO_PTR(args[ARG_file].u_obj);
|
||||
print.print_strn = mp_stream_write_adaptor;
|
||||
#else
|
||||
mp_raise_NotImplementedError(translate("file write is not available"));
|
||||
#endif
|
||||
}
|
||||
|
||||
mp_int_t limit = 0;
|
||||
bool print_tb = true;
|
||||
if (args[ARG_limit].u_obj != mp_const_none) {
|
||||
if (!mp_obj_get_int_maybe(args[ARG_limit].u_obj, &limit)) {
|
||||
mp_raise_TypeError(translate("limit should be an int"));
|
||||
}
|
||||
print_tb = !(limit == 0);
|
||||
}
|
||||
|
||||
if (args[ARG_tb].u_obj != mp_const_none && print_tb) {
|
||||
if (!stack_ok()) {
|
||||
mp_raise_RuntimeError(translate("stack is not ok"));
|
||||
}
|
||||
size_t n, *values;
|
||||
mp_obj_exception_get_traceback(exc, &n, &values);
|
||||
if (n > 0) {
|
||||
assert(n % 3 == 0);
|
||||
// Decompress the format strings
|
||||
const compressed_string_t *traceback = MP_ERROR_TEXT("Traceback (most recent call last):\n");
|
||||
char decompressed[decompress_length(traceback)];
|
||||
decompress(traceback, decompressed);
|
||||
#if MICROPY_ENABLE_SOURCE_LINE
|
||||
const compressed_string_t *frame = MP_ERROR_TEXT(" File \"%q\", line %d");
|
||||
#else
|
||||
const compressed_string_t *frame = MP_ERROR_TEXT(" File \"%q\"");
|
||||
#endif
|
||||
char decompressed_frame[decompress_length(frame)];
|
||||
decompress(frame, decompressed_frame);
|
||||
const compressed_string_t *block_fmt = MP_ERROR_TEXT(", in %q\n");
|
||||
char decompressed_block[decompress_length(block_fmt)];
|
||||
decompress(block_fmt, decompressed_block);
|
||||
|
||||
// Set traceback formatting
|
||||
// Default: Print full traceback
|
||||
int i = n - 3, j;
|
||||
if (limit > 0) {
|
||||
// Print upto limit traceback
|
||||
// from caller's frame
|
||||
limit = n - (limit * 3);
|
||||
} else if (limit < 0) {
|
||||
// Print upto limit traceback
|
||||
// from last
|
||||
i = 0, limit = 3 + (limit * 3);
|
||||
}
|
||||
|
||||
// Print the traceback
|
||||
mp_print_str(&print, decompressed);
|
||||
for (; i >= limit; i -= 3) {
|
||||
j = (i < 0) ? -i : i;
|
||||
#if MICROPY_ENABLE_SOURCE_LINE
|
||||
mp_printf(&print, decompressed_frame, values[j], (int)values[j + 1]);
|
||||
#else
|
||||
mp_printf(&print, decompressed_frame, values[j]);
|
||||
#endif
|
||||
// The block name can be NULL if it's unknown
|
||||
qstr block = values[j + 2];
|
||||
if (block == MP_QSTRnull) {
|
||||
mp_print_str(&print, "\n");
|
||||
} else {
|
||||
mp_printf(&print, decompressed_block, block);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
mp_obj_print_helper(&print, exc, PRINT_EXC);
|
||||
mp_print_str(&print, "\n");
|
||||
return mp_const_none;
|
||||
}
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_KW(traceback_print_exception_obj, 3, traceback_print_exception);
|
||||
|
||||
STATIC const mp_rom_map_elem_t traceback_module_globals_table[] = {
|
||||
// module name
|
||||
{ MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_traceback) },
|
||||
// module functions
|
||||
{ MP_ROM_QSTR(MP_QSTR_print_exception), MP_ROM_PTR(&traceback_print_exception_obj) },
|
||||
};
|
||||
STATIC MP_DEFINE_CONST_DICT(traceback_module_globals, traceback_module_globals_table);
|
||||
|
||||
const mp_obj_module_t traceback_module = {
|
||||
.base = { &mp_type_module },
|
||||
.globals = (mp_obj_dict_t *)&traceback_module_globals,
|
||||
};
|
1
shared-module/traceback/__init__.c
Normal file
1
shared-module/traceback/__init__.c
Normal file
@ -0,0 +1 @@
|
||||
// empty file
|
Loading…
Reference in New Issue
Block a user