Conversation
…ted as success mp_raise_msg_str asserts that the type's make_new is mp_obj_exception_make_new. A Python subclass of Warning has mp_obj_instance_make_new instead, and the assert is compiled out of a release build, so warnings.warn called the wrong function with the exception's arguments and faulted the board. It calls the category and raises what comes back. getpass passed its prompt to mp_printf as the format string, so a prompt containing a percent sign read conversions off the varargs area. os.chdir wrote cwd_path and vfs_cur before the lookup and the proxy call that can fail, with no restore on the raise path, so a chdir to a missing directory raised and left the current directory pointing at it. adafruit_bus_device broke out of its acquire loop when an exception was pending and then returned as though it held the bus; it calls mp_handle_pending(true) now. traceback.print_exception overwrites the live exception's traceback, and its context and cause when chain is false, and restored them only on the path where printing returned.
Author
|
Testing and diagnostic script. |
tannewt
requested changes
Sep 14, 2026
tannewt
left a comment
Member
There was a problem hiding this comment.
Please have your LLM add tests into tests/ that would have failed without these fixes. If the unix port doesn't have these modules then use the zephyr native_sim tests.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Code written by Claude Code, guided and corrected by @peterbay.
The problem
Five places where a failure is reported as a success, or a caller's state is left changed by a call that did not succeed. One of them faults the board.
The changes
warnings.warnbuilt the exception past the category.mp_raise_msg_strasserts that the type'smake_newismp_obj_exception_make_new. A Python subclass ofWarninghasmp_obj_instance_make_newinstead, and the assert is compiled out of a release build, so the wrong function was called with the exception's arguments. It calls the category now and raises what comes back.getpassused its prompt as a format string.mp_printf(print, prompt)reads conversions out of a caller-supplied string, sogetpass("Enter 100% of the key: ")swallowed the%and the character after it and pulled a word off the varargs area for it. Changed tomp_print_str.os.chdircommitted the new directory before the call that can fail.MP_STATE_VM(cwd_path)andvfs_curwere written first, then the lookup and the proxy call, with no restore on the raise path — so achdirto a missing directory raised and left the current directory pointing at it. They are written after the call succeeds.adafruit_bus_devicereturned as though it held the bus when an exception was pending. The acquire loop broke out onmp_hal_is_interrupted()and the function then carried on; the first transfer inside thewithblock ran without the lock. It callsmp_handle_pending(true), which raises what is waiting.traceback.print_exceptiondid not restore what it had overwritten if printing raised. It deliberately replaces the live exception's traceback, and its__context__and__cause__whenchainis false, and puts them back afterwards — but only on the path where printing returned. The restore is on both paths now.Testing
Seeed XIAO nRF52840 Sense, on two builds differing only by these changes.
os.chdir("/no/such/directory")raises, thenos.getcwd()/no/such/directory/, unchangedos.chdir("/lib")on a directory that exists/lib, unchanged either way/libgetpass("Enter 100% of the key: ", stream), prompt as writtenEnter 100of the key:Enter 100% of the key:warn("hello", Warning)undersimplefilter("error")Warning: hello, unchanged either wayWarning: hellowarn("hello", MyWarning), a Python subclassMyWarning: helloThe two
warnrows together are the point: the built-in category works on both builds, because itsmake_newis the one the assert expects. It is only a category defined in Python that reaches the wrong function.Two of the changes are not in that table. Reaching the
tracebackrestore needs printing itself to raise, and nothing I could arrange from Python got it to — thefileargument is checked for writability before anything is overwritten, and a custom__str__that raises is not called on the path that prints. Theadafruit_bus_devicelock needs a bus and an exception pending at the moment the lock is taken.No new translatable strings.