8000 py/modsys.c: Add sys._exc_traceback. by DavidEGrayson · Pull Request #11244 · micropython/micropython · GitHub
[go: up one dir, main page]

Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 17 additions & 1 deletion py/objexcept.c
Original file line number Diff line number Diff line change
Expand Up @@ -280,7 +280,23 @@ void mp_obj_exception_attr(mp_obj_t self_in, qstr attr, mp_obj_t *dest) {
}
return;
}
if (attr == MP_QSTR_args) {
if (attr == MP_QSTR___traceback__) {
// We expose traceback data via 'exc.__traceback__' to allow
// custom formatting of the traceback by user code.
size_t entry_count = self->traceback_len / TRACEBACK_ENTRY_LEN;
size_t *data = self->traceback_data;
mp_obj_t obj = mp_obj_new_list(entry_count, NULL);
mp_obj_list_t *list = MP_OBJ_TO_PTR(obj);
for (size_t i = 0; i < entry_count; i++) {
size_t *src = &data[i * TRACEBACK_ENTRY_LEN];
mp_obj_t entry[3];
entry[0] = MP_OBJ_NEW_QSTR(src[0]); // filename
entry[1] = MP_OBJ_NEW_SMALL_INT(src[1]); // line number
entry[2] = MP_OBJ_NEW_QSTR(src[2]); // block
list->items[i] = mp_obj_new_tuple(3, entry);
}
dest[0] = obj;
} else if (attr == MP_QSTR_args) {
decompress_error_text_maybe(self);
dest[0] = MP_OBJ_FROM_PTR(self->args);
} else if (attr == MP_QSTR_value || attr == MP_QSTR_errno) {
Expand Down
16 changes: 16 additions & 0 deletions tests/cpydiff/types_exception_traceback.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
"""
categories: Types,Exception
description: The ``__traceback__`` attribute of exceptions is a simple list of tuples.
cause: MicroPython is optimised to reduce code size.
workaround: Check the type of ``__traceback__`` before using it.
"""


def foo():
1 / 0


try:
foo()
except Exception as e:
print(e.__traceback__)
26 changes: 26 additions & 0 deletions tests/micropython/traceback.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
# This comment allows test runners like run_script_on_remote_target
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggest calling this test exc_traceback.py.

And then adding (or changing this comment) to briefly mention what it's testing, eg Test values of BaseException.__traceback__ which are MicroPython specific".

# to safely prepend a line of code without messing up line numbers.


def foo():
1 / 0


def normalize(filename):
if filename == "<stdin>":
return "traceback.py"
return filename.split("/")[-1]


try:
foo()
except Exception as e:
tb = e.__traceback__
for t in tb:
print("%s:%d" % (normalize(t[0]), t[1]), *t[2:])
e.__traceback__ = None
print(e.__traceback__)
try:
e.args = 77
except AttributeError:
print("setting args not allowed")
4 changes: 4 additions & 0 deletions tests/micropython/traceback.py.exp
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
traceback.py:6 foo
traceback.py:16 <module>
[]
setting args not allowed
9 changes: 6 additions & 3 deletions tests/run-tests.py
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,7 @@
"misc/sys_settrace_features.py",
"misc/sys_settrace_generator.py",
"misc/sys_settrace_loop.py",
"micropython/traceback.py",
),
}

Expand Down Expand Up @@ -108,6 +109,8 @@
"micropython/schedule.py",
# These require sys.exc_info().
"misc/sys_exc_info.py",
# These require exception tracebacks.
"micropython/traceback.py",
# These require sys.settrace().
"misc/sys_settrace_cov.py",
"misc/sys_settrace_features.py",
Expand All @@ -125,9 +128,7 @@
"stress/list_sort.py", # watchdog kicks in because it takes too long
),
"minimal": (
"basics/class_inplace_op.py", # all special methods not supported
"basics/subclass_native_init.py", # native subclassing corner cases not support
"micropython/opt_level.py", # don't assume line numbers are stored
"micropython/traceback.py", # no line numbers, no list[N:] syntax
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please don't remove these (see comment below).

),
"nrf": (
"basics/io_buffered_writer.py",
Expand Down Expand Up @@ -827,6 +828,8 @@ def run_tests(pyb, tests, args, result_dir, num_threads=1):

# Skip platform-specific tests.
skip_tests.update(platform_tests_to_skip.get(args.platform, ()))
if args.build == "minimal":
skip_tests.update(platform_tests_to_skip.get(args.build, ()))
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I understand why you made this change, but it's not the right approach. We should not mix up the platform with the build.

If really needed we can add a build_tests_to_skip dict, to mirror platform_tests_to_skip, but for only one test I suggest following 7db50cc and adding the same code at the top of traceback.py to skip that test automatically.


# Some tests are known to fail on 64-bit machines
if pyb is None and platform.architecture()[0] == "64bit":
Expand Down
Loading
0