Skip to content

Turbo : Let fast native code fall back to plain Python when a board can't run it - #11529

Merged
dhalbert merged 4 commits into
adafruit:mainfrom
mikeysklar:native-optional
Oct 9, 2026
Merged

dhalbert merged 4 commits into
adafruit:mainfrom
mikeysklar:native-optional

Conversation

@mikeysklar

@mikeysklar mikeysklar commented Oct 7, 2026 •

Copy link
Copy Markdown
Collaborator

What

@micropython.native(optional=True)
@micropython.viper(optional=True)

both run as plain Python where native code can't be made

Why

Library authors can ship one .py with turbo code that builds in the bundles and runs on every board.

Where Today With this PR
mpy-cross foo.py (no -march, what bundle CI runs) SyntaxError: invalid arch bytecode foo.mpy
mpy-cross -march=<arch> foo.py native native
.py on a board SyntaxError: invalid micropython decorator runs as bytecode
no optional=True, .py on a board invalid micropython decorator native code not supported on this board
optional= anything but True/False, or other arguments silently ignored invalid micropython decorator

Agreed with @dhalbert on Discord after @todbot asked how a bundle library can use viper.

CircuitPython only; micropython#15615 is the upstream request.

Cost: Metro M0 Express +140 bytes (el, 668 free).

Tests

New tests/micropython/decorator_optional.py and decorator_optional_error.py. CI's unix build has an emitter, so the board fallback is hardware-tested only.

Board arch .py runs bare @viper arch file
Metro RP2040 armv6m yes new error used
Metro M4 Airlift Lite armv7emsp yes new error used
Feather STM32F405 Express armv7emsp yes new error used
Feather nRF52840 Express armv7emsp yes new error used
Metro ESP32-S2 xtensawin yes new error used
Metro ESP32-S3 xtensawin yes new error used
ESP32-C5-DevKitC-1 rv32imc yes new error used
Feather ESP32-C6 rv32imc yes new error used
Metro M0 Express (no native load) None yes new error ignored
Adafruit CircuitPython 11.0.0-alpha.0-60-g8fcf94acf1 on 2026-10-07; Adafruit Metro ESP32S2 with ESP32S2
opt_src    -> /lib/opt_src.py (4950, 1000)
opt_strict -> SyntaxError: native code not supported on this board
opt_bad    -> SyntaxError: invalid micropython decorator
opt_mpy    -> /lib/opt_mpy.mpy (4950, 1000)
opt_arch   -> /lib/opt_arch.xtensawin.mpy (4950, 1000)

AI assistance

Claude was used.

Where native code can't be emitted (on the board, or mpy-cross with no
-march), a function marked optional=True compiles as bytecode. Without
it the board now says "native code not supported on this board" instead
of "invalid micropython decorator".

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
@mikeysklar
mikeysklar requested a review from dhalbert October 7, 2026 23:41

@dhalbert dhalbert left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

small query about possible code size shrink

Comment thread py/compile.c Outdated
mikeysklar and others added 3 commits October 7, 2026 19:51
Reuse the existing "invalid micropython decorator" error and drop the
argument check, so pewpew_lcd fits again. optional=True still compiles
as bytecode where native code can't be emitted; other arguments are
ignored, as before.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>

@dhalbert dhalbert left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

I am just curious why you removed the syntax test.

I tried changing the True test to use mp_parse_const_true(). It is 28 bytes longer. The advantage is that it matches "triush" args like 1. But that's not a big deal.

@dhalbert
dhalbert merged commit d5b2f24 into adafruit:main Oct 9, 2026
14 of 16 checks passed
@mikeysklar

Copy link
Copy Markdown
Collaborator Author

@dhalbert I took out the extra check to save space, so something like optional=1 is now ignored instead of giving an error.

That left the error test with nothing to test, so I removed it.

The test for optional=True is still there.

And I agree, 28 bytes isn't worth it just to accept 1.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants