CPython and Frozen modules¶
Frozen Modules¶
It is common for Firmwares to include a few (or many) python modules as ‘frozen’ modules. ‘Freezing’ modules is a way to pre-process .py modules so they’re ‘baked-in’ to MicroPython’ s firmware and use less memory. Once the code is frozen it can be quickly loaded and interpreted by MicroPython without as much memory and processing time.
Most OSS firmwares store these frozen modules as part of their repository, which allows us to:
Download the *.py from the (github) repo using
git clone
or a direct downloadExtract and store the ‘unfrozen’ modules (ie the *.py files) in a
_Frozen folder. if there are different port / boards or releases defined , there may be multiple folders such as: stubs/micropython_1_12_frozen
/esp32
/GENERIC
/RELEASE
/TINYPICO
/stm32
/GENERIC
/PYBD_SF2
generate typeshed stubs of these files. (the .pyi files will be stored alongside the .py files)
Include/use them in the configuration
ref: https://learn.adafruit.com/micropython-basics-loading-modules/frozen-modules
Collect Frozen Stubs (micropython)¶
This is run daily though the github action workflow : get-all-frozen in the micropython-stubs repo.
If you want to run this manually
Check out repos side-by-side:
micropython-stubs
micropython-stubber
micropython
micropython-lib
link repos using all_stubs symlink
checkout tag / version in the micropython folder
(for most accurate results should checkout micropython-lib for the same date)run
src/get-frozen.py
run
src/update-stubs.py
create a PR for changes to the stubs repo
Postprocessing¶
You can run postprocessing for all stubs by running either of the two scripts.
There is an optional parameter to specify the location of the stub folder. The default path is ./all_stubs
Powershell:
./scripts/updates_stubs.ps1 [-path ./mystubs]
or python
python ./src/update_stubs.py [./mystubs]
This will generate or update the .pyi
stubs for all new (and existing) stubs in the ./all_stubs
or specified folder.
From version ‘1.3.8’ the .pyi
stubs are generated using stubgen
, before that the make_stub_files.py
script was used.
Stubgen is run on each ‘collected stub folder’ (that contains a modules.json
manifest) using the options : --ignore-errors --include-private
and the resulting .pyi
files are stored in the same folder (foo.py
and foo.pyi
are stored next to each other).
In some cases stubgen
detects duplicate modules in a ‘collected stub folder’, and subsequently does not generate any stubs for any .py
module or script.
then Plan B is to run stubgen for each separate *.py
file in that folder. THis is significantly slower and according to the stubgen documentation the resulting stubs may of lesser quality, but that is better than no stubs at all.
Note: In several cases stubgen
creates folders in inappropriate locations (reason undetermined), which would cause issues when re-running stubgen
at a later time.
to compensate for this behaviour the known-incorrect .pyi files are removed before and after stubgen is run see: cleanup(modules_folder)
in utils.py
Repo structure¶
2 python versions
This and sister repos¶
repo |
Why |
Where |
example |
---|---|---|---|
micropython-stubber |
needed to make stubs |
in your source folder |
develop/micropython-stubber |
micropython |
to collect frozen modules |
submodule of micropython-stubber |
develop/micropython-stubber/micropython |
micropython-lib |
to collect frozen modules |
submodule of micropython-stubber |
develop/micropython-stubber/micropython-lib |
micropython-stubs |
stores collected stubs |
next to the |
develop/micropython-stubs |
Note
recommended is to create a symlink from
develop/micropython-stubber\all-stubs
todevelop/micropython-stubs
Note
For Git submodules please refer to https://git-scm.com/book/en/v2/Git-Tools-Submodules
Structure of this repo¶
The file structure is based on my personal windows environment, but you should be able to adapt that without much hardship to you own preference and OS.
What |
Details |
Where |
---|---|---|
stub root |
symlink to connect the 2 sister-repos |
all_stubs |
firmware stubber |
MicroPython |
board/createstubs.py |
minified firmware stubber |
MicroPython |
minified/createstubs.py |
PC based scripts |
CPython |
src/* |
PC based scripts |
CPython |
process.py |
pytest tests |
test/* |
|
Naming Convention and Stub folder structure¶
What |
Why |
Where |
---|---|---|
stub root |
connect the 2 repos |
all_stubs |
cpython stubs for micropython core |
adapt for differences between CPython and MicroPython |
stubs/cpython-core |
generated stub files |
needed to use stubs |
stubs/{firmware}-{port}-{version}-frozen |
Frozen stub files |
better code intellisense |
stubs/{firmware}-{version}-frozen |
Note: I found that, for me, using submodules caused more problems than it solved. So instead I link the two main repo’s using a symlink.
Note: I in the repo tests I have used the folders TESTREPO-micropython
and TESTREPO-micropython-lib
to avoid conflicts with any development that you might be doing on similar micropython
repos at the potential cost of a little disk space.
cd /develop
git clone https://github.com/josverl/micropython-stubber.git
git clone https://github.com/josverl/micropython-stubs.git
git clone https://github.com/micropython/micropython.git
git clone https://github.com/micropython/micropython.git
Create a symbolic link¶
To create the symbolic link to the ../micropython-stubs/stubs
folder the instructions differ slightly for each OS/
The below examples assume that the micropython-stubs repo is cloned ‘next-to’ your project folder.
please adjust as needed.
Windows 10¶
Requires Developer enabled
or elevated powershell prompt.
# target must be an absolute path, resolve path is used to resolve the relative path to absolute
New-Item -ItemType SymbolicLink -Path "all-stubs" -Target (Resolve-Path -Path ../micropython-stubs/stubs)
or use mklink in an (elevated) command prompt
rem target must be an absolute path
mklink /d all-stubs c:\develop\micropython-stubs\stubs
Linux/Unix/Mac OS¶
# target must be an absolute path
ln -s /path/to/micropython-stubs/stubs all-stubs
Stubs¶
Initially I also stored all the generated subs in the same repo. That turned out to be a bit of a hassle and since then I have moved all the stubs to the micropython-stubs repo
Below are the most relevant stub sources referenced in this project.
Firmware and libraries¶
MicroPython firmware and frozen modules [MIT]¶
https://github.com/micropython/micropython
https://github.com/micropython/micropython-lib
Pycopy firmware and frozen modules [MIT]¶
https://github.com/pfalcon/pycopy
https://github.com/pfalcon/pycopy-lib
LoBoris ESP32 firmware and frozen modules [MIT, Apache 2]¶
https://github.com/loboris/MicroPython_ESP32_psRAM_LoBo
Included custom stubs¶
Github repo |
Contributions |
License |
---|---|---|
pfalcon/micropython-lib |
CPython backports |
MIT |
dastultz/micropython-pyb |
a pyb.py file for use with IDEs in developing a project for the Pyboard |
Apache 2 |
Stub source: MicroPython-lib > CPython backports [MIT, Python]¶
While micropython-lib focuses on MicroPython, sometimes it may be beneficial to run MicroPython code using CPython, e.g. to use code coverage, debugging, etc. tools available for it. To facilitate such usage, micropython-lib also provides re-implementations (“backports”) of MicroPython modules which run on CPython. https://github.com/pfalcon/micropython-lib#cpython-backports
micropython_pyb [Apache 2]¶
This project provides a pyb.py file for use with IDEs in developing a project for the Pyboard. https://github.com/dastultz/micropython-pyb
References¶
Inspiration¶
Thonny - MicroPython _cmd_dump_api_info [MIT License]¶
The createstubs.py
script to create the stubs is based on the work of Aivar Annamaa and the Thonny crew.
It is somewhere deep in the code and is apparently only used during the development cycle but it showed a way how to extract/generate a representation of the MicroPython modules written in C
While the concepts remain, the code has been rewritten to run on a micropython board, rather than on a connected PC running CPython. Please refer to : Thonny code sample
MyPy Stubgen¶
MyPy stubgen is used to generate stubs for the frozen modules and for the *.py
stubs that were generated on a board.
make_stub_files [Public Domain]¶
https://github.com/edreamleo/make-stub-files
This script make_stub_files.py
makes a stub (.pyi) file in the output directory for each source file listed on the command line (wildcard file names are supported).
The script does no type inference. Instead, the user supplies patterns in a configuration file. The script matches these patterns to: The names of arguments in functions and methods and The text of return expressions. Return expressions are the actual text of whatever follows the “return” keyword. The script removes all comments in return expressions and converts all strings to “str”. This preprocessing greatly simplifies pattern matching.
Note
It was found that the stubs / prototypes of some functions with complex arguments were not handled correctly,
resulting in incorrectly formatted stubs (.pyi)
Therefore this functionality has been replaced by MyPy stubgen