Repository navigation
Conversation
f-fix
force-pushed
the
master
branch
8 times, most recently
from
October 19, 2026 02:50
2519b1a to
3de421a
Compare
|
The PyPI page is https://pypi.org/project/astpp/ and the github page is https://github.com/f-fix/astpp BTW. The README there has some more detailed examples. |
f-fix
force-pushed
the
master
branch
2 times, most recently
from
October 19, 2026 06:17
3a5b537 to
9574fb8
Compare
Author
|
It's rebased to astpp 0.1.1 which means the micropython library version is now generated without manual editing: astpp -O3 -D_OMIT_MAIN < ~/src/astpp/astpp.py > astpp.py &&
black astpp.py |
The full version of `astpp` on github abd PyPI is a self-inlining
python macro preprocessor & runtime polyfill library. The AST parts
run in big pythons, the runtime parts and the output both run in
micropython too. This PR tries to add just the parts that run inside
micropython as a `mip`-installable library.
The subset here was made by running this, which used the pip-installed
version of astpp running in CPython:
```bash
astpp -O3 -D_OMIT_MAIN < ~/src/astpp/astpp.py > astpp.py &&
black astpp.py
```
This tool grew out of an audio tape archival project, but this
particular piece proved useful enough in other projects to merit
separation into its own standalone package/library.
By adding `astpp` we make it possible to use exactly the same
`const(`...`)` over in big python *and* in micropython, using the same
syntax, and actually working at preprocessor-time when you use the
`astpp` preprocessor - run the preprocessor in big pythons but use its
outputs in all pythons including micropython. It also allows you to
strip out debug code/assertions/docstrings.
The `astpp` preprocessor does a version of `const` compatible with
mpy-cross / micropython, that also works on "big" pythons. In the
preprocessed output the contants' values will be inlined. It also
allows you to do "conditional omission" so that parts of your code
won't end up in the output - this is great if you have some fluffier
features that make sense for "big" python, but you want them gone from
your micropython version.
It also supports -O/-O0/-O1/-O2/-O3/-OO optimization levels which do
stuff like force `__debug__` to be `const(False)`, and strip out
docstrings and such. Again, it's intended to reduce code size and
token size.
It also allows you to optionally replace things, and I use this to
rewrite `@micropython.native` and `@micropython.viper` to `@keep` -
which then gets stripped off by the preprocessor - allowing to easily
build a version which can be mpy-cross compiled generically without
being target CPU specific.
In big python this module includes the preprocessor and a test suite
too, but optimized builds omit the test suite and when you don't have
the `ast` module the preprocessor itself won't be runnable. In any
case, though, preprocessing your code actually gets rid of the `astpp`
imports entirely and replaces the imported ports with small inlined
replacements.
I only tested on the Linux i386 port of micropython, but on that one
it seems to work fine:
```bash
micropython -c '
import mip
mip.install("github:f-fix/astpp/astpp.py")
from astpp import const, micropython
@micropython.native
def foo(bar):
return dict(bar=bar)
_X=const(3)
print(foo(3))
'
```
```
Downloading github:f-fix/astpp/astpp.py to /home/bsittler/.micropython/lib
Copying: /home/bsittler/.micropython/lib/astpp.py
Done
{'bar': 3}
```
Using the local version:
```bash
micropython -c '
from astpp import const, micropython
@micropython.native
def foo(bar):
return dict(bar=bar)
_X=const(3)
print(foo(3))
'
```
```
{'bar': 3}
```
Using the pip-installed version as a preprocessor:
```bash
pipx install astpp && astpp -O3 <( echo '
from astpp import const, micropython
@micropython.native
def foo(bar):
return dict(bar=bar)
_X=const(3)
print(foo(3))
' )
```
```
installed package astpp 0.1.3, installed using Python 3.14.8
These apps are now available
- astpp
done! ✨ 🌟 ✨
try:
from micropython import const
except ImportError:
def const(x):
return x
def keep(obj):
return obj
try:
import micropython as _real_mpy
except ImportError:
_real_mpy = None
if _real_mpy is not None:
micropython = _real_mpy
else:
class _MicroPythonShim:
native = staticmethod(keep)
viper = staticmethod(keep)
micropython = _MicroPythonShim()
@micropython.native
def foo(bar):
return dict(bar=bar)
print(foo(3))
```
Running *that* in micropython:
```
micropython -c '
try:
from micropython import const
except ImportError:
def const(x):
return x
def keep(obj):
return obj
try:
import micropython as _real_mpy
except ImportError:
_real_mpy = None
if _real_mpy is not None:
micropython = _real_mpy
else:
class _MicroPythonShim:
native = staticmethod(keep)
viper = staticmethod(keep)
micropython = _MicroPythonShim()
@micropython.native
def foo(bar):
return dict(bar=bar)
print(foo(3))
'
```
```
{'bar': 3}
```
The current alternative is to use micropython-specific imports and
mpy-cross, but that provides equivalent benefits only on
micropython. Using astpp those same benefits are realized on all
pythons.
I used generative AI tools when creating this PR, but a human has
checked the code and is responsible for the code and the description
above.
Signed-off-by: Benjamin C. Wiley Sittler <bsittler@gmail.com>
Author
|
it's rebased to 0.1.3 with more mpy-cross like constant replacement and fixed |
Author
|
BTW I have been testing it with https://github.com/f-fix/xz_decompressor including on x86 micropython $ LC_ALL=C wc -c < xz_decompressor.py
318878
$ python3 astpp.py -O3 < xz_decompressor.py | LC_ALL=C wc -c
192210
$ python3 astpp.py -O3 -D_IS_DESKTOP_PY=False < xz_decompressor.py | LC_ALL=C wc -c
177125
$ python3 astpp.py -O3 -D_IS_DESKTOP_PY=False -D_OMIT_MAIN < xz_decompressor.py | LC_ALL=C wc -c
162023
$ python3 astpp.py -O3 -D_IS_DESKTOP_PY=False -D_OMIT_MAIN < xz_decompressor.py | mpy-cross -O3 -march=x86 - | LC_ALL=C wc -c
66922
$ python3 astpp.py -O3 -D_IS_DESKTOP_PY=False -D_OMIT_MAIN -Dmicropython.{native,viper}=keep < xz_decompressor.py | mpy-cross -O3 - | LC_ALL=C wc -c
47460
|
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.
Add
astpp, a self-inlining python macro preprocessor & runtime polyfill library (the AST parts run in big pythons, the runtime parts and the output both run in micropython too)Summary
By adding
astppwe make it possible to use exactly the sameconst(...)over in big python and in micropython, using the same syntax, and actually working at preprocessor-time. It also allows you to strip out debug code/assertions/docstrings.The
astpppreprocessor does a version ofconstcompatible with mpy-cross / micropython, that also works on "big" pythons. In the preprocessed output the contants' values will be inlined. It also allows you to do "conditional omission" so that parts of your code won't end up in the output - this is great if you have some fluffier features that make sense for "big" python, but you want them gone from your micropython version.It also supports -O/-O0/-O1/-O2/-O3/-OO optimization levels which do stuff like force
__debug__to beconst(False), and strip out docstrings and such. Again, it's intended to reduce code size and token size.It also allows you to optionally replace things, and I use this to rewrite
@micropython.nativeand@micropython.viperto@keep- which then gets stripped off my the preprocessor - allowing to easily build a version which can be mpy-cross compiled generically without being target CPU specific.In big python this module includes the preprocessor and a test suite too, but optimized builds omit the test suite and when you don't have the
astmodule the preprocessor itself won't be runnable. In any case, though, preprocessing your code actually gets rid of theastppimports entirely and replaces the imported ports with small inlined replacements.Testing
I only tested on the Linux i386 port of micropython, but on that one it seems to work fine:
Trade-offs and Alternatives
The current alternative is to use micropython-specific imports and mpy-cross, but that provides equivalent benefits only on micropython. Using astpp those same benefits are realized on all pythons.
Generative AI
I used generative AI tools when creating this PR, but a human has checked the
code and is responsible for the code and the description above.