picolet 0.0.1__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- picolet-0.0.1/.gitignore +34 -0
- picolet-0.0.1/PKG-INFO +250 -0
- picolet-0.0.1/README.md +224 -0
- picolet-0.0.1/hatch_build.py +77 -0
- picolet-0.0.1/picolet/__init__.py +26 -0
- picolet-0.0.1/picolet/__main__.py +125 -0
- picolet-0.0.1/picolet/_bridge/__init__.py +0 -0
- picolet-0.0.1/picolet/_bridge/picolet-bridge.js +1 -0
- picolet-0.0.1/picolet/_runtime_data/RUNTIME_TAG +1 -0
- picolet-0.0.1/picolet/_runtime_data/__init__.py +0 -0
- picolet-0.0.1/picolet/_runtime_data/mbm.toml +71 -0
- picolet-0.0.1/picolet/_runtime_data/sbom/__init__.py +0 -0
- picolet-0.0.1/picolet/_runtime_data/sbom/runtime.toml +288 -0
- picolet-0.0.1/picolet/cli/RUNTIME_TAG +1 -0
- picolet-0.0.1/picolet/cli/__init__.py +0 -0
- picolet-0.0.1/picolet/cli/_paths.py +144 -0
- picolet-0.0.1/picolet/cli/_targets.py +92 -0
- picolet-0.0.1/picolet/cli/_trailer.py +56 -0
- picolet-0.0.1/picolet/cli/build_cmd.py +981 -0
- picolet-0.0.1/picolet/cli/dev_cmd.py +324 -0
- picolet-0.0.1/picolet/cli/init_cmd.py +225 -0
- picolet-0.0.1/picolet/cli/run_cmd.py +129 -0
- picolet-0.0.1/picolet/cli/runtime_resolver.py +810 -0
- picolet-0.0.1/picolet/cli/sbom_gen.py +873 -0
- picolet-0.0.1/picolet/cli/test_cmd.py +640 -0
- picolet-0.0.1/picolet/cli/validate_cmd.py +61 -0
- picolet-0.0.1/picolet/cli/validator.py +469 -0
- picolet-0.0.1/picolet/templates/__init__.py +0 -0
- picolet-0.0.1/picolet/templates/config-editor/package.json +22 -0
- picolet-0.0.1/picolet/templates/config-editor/picolet.toml +20 -0
- picolet-0.0.1/picolet/templates/config-editor/src/config_store.py +302 -0
- picolet-0.0.1/picolet/templates/config-editor/src/config_validator.py +148 -0
- picolet-0.0.1/picolet/templates/config-editor/src/difflib.py +171 -0
- picolet-0.0.1/picolet/templates/config-editor/src/main.py +74 -0
- picolet-0.0.1/picolet/templates/config-editor/src/micro_yaml.py +265 -0
- picolet-0.0.1/picolet/templates/config-editor/src/tomllib.py +490 -0
- picolet-0.0.1/picolet/templates/config-editor/tsconfig.json +19 -0
- picolet-0.0.1/picolet/templates/config-editor/tsconfig.node.json +10 -0
- picolet-0.0.1/picolet/templates/config-editor/ui/index.html +12 -0
- picolet-0.0.1/picolet/templates/config-editor/ui/public/fonts/JetBrainsMono-Regular.woff2 +0 -0
- picolet-0.0.1/picolet/templates/config-editor/ui/src/App.vue +27 -0
- picolet-0.0.1/picolet/templates/config-editor/ui/src/assets/fonts.css +12 -0
- picolet-0.0.1/picolet/templates/config-editor/ui/src/assets/main.css +367 -0
- picolet-0.0.1/picolet/templates/config-editor/ui/src/env.d.ts +2 -0
- picolet-0.0.1/picolet/templates/config-editor/ui/src/main.ts +7 -0
- picolet-0.0.1/picolet/templates/config-editor/ui/src/picolet.d.ts +26 -0
- picolet-0.0.1/picolet/templates/config-editor/ui/src/router/index.ts +17 -0
- picolet-0.0.1/picolet/templates/config-editor/ui/src/store.ts +46 -0
- picolet-0.0.1/picolet/templates/config-editor/ui/src/views/DiffView.vue +78 -0
- picolet-0.0.1/picolet/templates/config-editor/ui/src/views/EditView.vue +409 -0
- picolet-0.0.1/picolet/templates/config-editor/ui/src/views/PickerView.vue +234 -0
- picolet-0.0.1/picolet/templates/config-editor/vite.config.ts +18 -0
- picolet-0.0.1/picolet/templates/dashboard/package.json +22 -0
- picolet-0.0.1/picolet/templates/dashboard/picolet.toml +20 -0
- picolet-0.0.1/picolet/templates/dashboard/src/main.py +71 -0
- picolet-0.0.1/picolet/templates/dashboard/src/metrics_reader.py +463 -0
- picolet-0.0.1/picolet/templates/dashboard/tsconfig.json +19 -0
- picolet-0.0.1/picolet/templates/dashboard/tsconfig.node.json +10 -0
- picolet-0.0.1/picolet/templates/dashboard/ui/index.html +12 -0
- picolet-0.0.1/picolet/templates/dashboard/ui/public/fonts/Antonio-Bold.woff2 +0 -0
- picolet-0.0.1/picolet/templates/dashboard/ui/public/fonts/Antonio-Regular.woff2 +0 -0
- picolet-0.0.1/picolet/templates/dashboard/ui/public/fonts/DMSans-Medium.woff2 +0 -0
- picolet-0.0.1/picolet/templates/dashboard/ui/public/fonts/DMSans-Regular.woff2 +0 -0
- picolet-0.0.1/picolet/templates/dashboard/ui/public/fonts/JetBrainsMono-Regular.woff2 +0 -0
- picolet-0.0.1/picolet/templates/dashboard/ui/src/App.vue +55 -0
- picolet-0.0.1/picolet/templates/dashboard/ui/src/assets/fonts.css +43 -0
- picolet-0.0.1/picolet/templates/dashboard/ui/src/assets/main.css +401 -0
- picolet-0.0.1/picolet/templates/dashboard/ui/src/components/CpuChart.vue +87 -0
- picolet-0.0.1/picolet/templates/dashboard/ui/src/components/DiskChart.vue +91 -0
- picolet-0.0.1/picolet/templates/dashboard/ui/src/components/MemoryGauge.vue +96 -0
- picolet-0.0.1/picolet/templates/dashboard/ui/src/components/NetworkChart.vue +91 -0
- picolet-0.0.1/picolet/templates/dashboard/ui/src/components/ProcessList.vue +53 -0
- picolet-0.0.1/picolet/templates/dashboard/ui/src/components/SparklineStrip.vue +81 -0
- picolet-0.0.1/picolet/templates/dashboard/ui/src/components/TopStrip.vue +33 -0
- picolet-0.0.1/picolet/templates/dashboard/ui/src/env.d.ts +2 -0
- picolet-0.0.1/picolet/templates/dashboard/ui/src/main.ts +7 -0
- picolet-0.0.1/picolet/templates/dashboard/ui/src/picolet.d.ts +25 -0
- picolet-0.0.1/picolet/templates/dashboard/ui/src/router/index.ts +13 -0
- picolet-0.0.1/picolet/templates/dashboard/ui/src/store.ts +45 -0
- picolet-0.0.1/picolet/templates/dashboard/ui/src/utils/format.ts +51 -0
- picolet-0.0.1/picolet/templates/dashboard/ui/src/utils/svg.ts +84 -0
- picolet-0.0.1/picolet/templates/dashboard/ui/src/views/DashboardView.vue +56 -0
- picolet-0.0.1/picolet/templates/dashboard/vite.config.ts +18 -0
- picolet-0.0.1/picolet/templates/hello-cli/picolet.toml +4 -0
- picolet-0.0.1/picolet/templates/hello-cli/src/main.py +19 -0
- picolet-0.0.1/picolet/templates/hello-lvgl/picolet.toml +15 -0
- picolet-0.0.1/picolet/templates/hello-lvgl/src/main.py +52 -0
- picolet-0.0.1/picolet/templates/hello-vue/package.json +21 -0
- picolet-0.0.1/picolet/templates/hello-vue/picolet.toml +20 -0
- picolet-0.0.1/picolet/templates/hello-vue/src/main.py +40 -0
- picolet-0.0.1/picolet/templates/hello-vue/tsconfig.json +19 -0
- picolet-0.0.1/picolet/templates/hello-vue/tsconfig.node.json +10 -0
- picolet-0.0.1/picolet/templates/hello-vue/ui/index.html +12 -0
- picolet-0.0.1/picolet/templates/hello-vue/ui/src/App.vue +127 -0
- picolet-0.0.1/picolet/templates/hello-vue/ui/src/env.d.ts +2 -0
- picolet-0.0.1/picolet/templates/hello-vue/ui/src/main.ts +4 -0
- picolet-0.0.1/picolet/templates/hello-vue/ui/src/picolet.d.ts +28 -0
- picolet-0.0.1/picolet/templates/hello-vue/vite.config.ts +17 -0
- picolet-0.0.1/picolet/templates/hello-webview/picolet.toml +17 -0
- picolet-0.0.1/picolet/templates/hello-webview/src/main.py +22 -0
- picolet-0.0.1/picolet/templates/hello-webview/ui/app.js +24 -0
- picolet-0.0.1/picolet/templates/hello-webview/ui/index.html +17 -0
- picolet-0.0.1/picolet/templates/hello-webview/ui/style.css +15 -0
- picolet-0.0.1/picolet/templates/notes/package.json +23 -0
- picolet-0.0.1/picolet/templates/notes/picolet.toml +20 -0
- picolet-0.0.1/picolet/templates/notes/src/main.py +70 -0
- picolet-0.0.1/picolet/templates/notes/src/notes_store.py +178 -0
- picolet-0.0.1/picolet/templates/notes/tsconfig.json +19 -0
- picolet-0.0.1/picolet/templates/notes/tsconfig.node.json +10 -0
- picolet-0.0.1/picolet/templates/notes/ui/index.html +12 -0
- picolet-0.0.1/picolet/templates/notes/ui/public/fonts/source-sans-3.woff2 +0 -0
- picolet-0.0.1/picolet/templates/notes/ui/public/fonts/source-serif-4-italic.woff2 +0 -0
- picolet-0.0.1/picolet/templates/notes/ui/public/fonts/source-serif-4-roman.woff2 +0 -0
- picolet-0.0.1/picolet/templates/notes/ui/src/App.vue +15 -0
- picolet-0.0.1/picolet/templates/notes/ui/src/assets/fonts.css +34 -0
- picolet-0.0.1/picolet/templates/notes/ui/src/assets/main.css +459 -0
- picolet-0.0.1/picolet/templates/notes/ui/src/env.d.ts +2 -0
- picolet-0.0.1/picolet/templates/notes/ui/src/main.ts +7 -0
- picolet-0.0.1/picolet/templates/notes/ui/src/picolet.d.ts +25 -0
- picolet-0.0.1/picolet/templates/notes/ui/src/router/index.ts +17 -0
- picolet-0.0.1/picolet/templates/notes/ui/src/views/AboutView.vue +25 -0
- picolet-0.0.1/picolet/templates/notes/ui/src/views/EditView.vue +173 -0
- picolet-0.0.1/picolet/templates/notes/ui/src/views/ListView.vue +108 -0
- picolet-0.0.1/picolet/templates/notes/vite.config.ts +18 -0
- picolet-0.0.1/picolet/templates/pydfu/README.md +109 -0
- picolet-0.0.1/picolet/templates/pydfu/package.json +22 -0
- picolet-0.0.1/picolet/templates/pydfu/picolet.toml +29 -0
- picolet-0.0.1/picolet/templates/pydfu/src/_crc32.py +28 -0
- picolet-0.0.1/picolet/templates/pydfu/src/_dfu_file.py +79 -0
- picolet-0.0.1/picolet/templates/pydfu/src/_pydfu/__init__.py +2 -0
- picolet-0.0.1/picolet/templates/pydfu/src/_pydfu/pydfu.py +462 -0
- picolet-0.0.1/picolet/templates/pydfu/src/_usb/__init__.py +2 -0
- picolet-0.0.1/picolet/templates/pydfu/src/_usb/control.py +10 -0
- picolet-0.0.1/picolet/templates/pydfu/src/_usb/core.py +339 -0
- picolet-0.0.1/picolet/templates/pydfu/src/_usb/libusb-1.0.dll +0 -0
- picolet-0.0.1/picolet/templates/pydfu/src/_usb/util.py +21 -0
- picolet-0.0.1/picolet/templates/pydfu/src/main.py +379 -0
- picolet-0.0.1/picolet/templates/pydfu/src/pydfu_adapter.py +190 -0
- picolet-0.0.1/picolet/templates/pydfu/src/pydfu_mock.py +51 -0
- picolet-0.0.1/picolet/templates/pydfu/tsconfig.json +19 -0
- picolet-0.0.1/picolet/templates/pydfu/tsconfig.node.json +10 -0
- picolet-0.0.1/picolet/templates/pydfu/ui/index.html +12 -0
- picolet-0.0.1/picolet/templates/pydfu/ui/public/fonts/IBMPlexSans-Regular.woff2 +0 -0
- picolet-0.0.1/picolet/templates/pydfu/ui/public/fonts/IBMPlexSans-SemiBold.woff2 +0 -0
- picolet-0.0.1/picolet/templates/pydfu/ui/public/fonts/MonaspaceNeon-Bold.woff2 +0 -0
- picolet-0.0.1/picolet/templates/pydfu/ui/public/fonts/MonaspaceNeon-Regular.woff2 +0 -0
- picolet-0.0.1/picolet/templates/pydfu/ui/src/App.vue +111 -0
- picolet-0.0.1/picolet/templates/pydfu/ui/src/assets/fonts.css +27 -0
- picolet-0.0.1/picolet/templates/pydfu/ui/src/assets/main.css +156 -0
- picolet-0.0.1/picolet/templates/pydfu/ui/src/components/AuditStrip.vue +114 -0
- picolet-0.0.1/picolet/templates/pydfu/ui/src/components/DeviceDetail.vue +202 -0
- picolet-0.0.1/picolet/templates/pydfu/ui/src/components/DeviceList.vue +181 -0
- picolet-0.0.1/picolet/templates/pydfu/ui/src/components/HeaderRail.vue +131 -0
- picolet-0.0.1/picolet/templates/pydfu/ui/src/components/LedDot.vue +54 -0
- picolet-0.0.1/picolet/templates/pydfu/ui/src/env.d.ts +2 -0
- picolet-0.0.1/picolet/templates/pydfu/ui/src/main.ts +7 -0
- picolet-0.0.1/picolet/templates/pydfu/ui/src/picolet.d.ts +24 -0
- picolet-0.0.1/picolet/templates/pydfu/ui/src/router/index.ts +17 -0
- picolet-0.0.1/picolet/templates/pydfu/ui/src/views/FlashView.vue +429 -0
- picolet-0.0.1/picolet/templates/pydfu/ui/src/views/HomeView.vue +29 -0
- picolet-0.0.1/picolet/templates/pydfu/ui/src/views/LogView.vue +68 -0
- picolet-0.0.1/picolet/templates/pydfu/vite.config.ts +18 -0
- picolet-0.0.1/picolet/testing/__init__.py +17 -0
- picolet-0.0.1/picolet/testing/_chromium.py +90 -0
- picolet-0.0.1/picolet/testing/_harness.py +651 -0
- picolet-0.0.1/picolet/testing/_webkit.py +314 -0
- picolet-0.0.1/pyproject.toml +66 -0
picolet-0.0.1/.gitignore
ADDED
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
# Build output
|
|
2
|
+
target/
|
|
3
|
+
build/
|
|
4
|
+
build-*/
|
|
5
|
+
*.exe
|
|
6
|
+
*.pyc
|
|
7
|
+
__pycache__/
|
|
8
|
+
|
|
9
|
+
# Frontend build outputs (Vite dist/) inside examples/
|
|
10
|
+
examples/*/dist/
|
|
11
|
+
|
|
12
|
+
# Cached runtime artifacts downloaded by `picolet build`
|
|
13
|
+
.picolet-cache/
|
|
14
|
+
|
|
15
|
+
# Dependencies / caches
|
|
16
|
+
node_modules/
|
|
17
|
+
.venv/
|
|
18
|
+
.uv-cache/
|
|
19
|
+
|
|
20
|
+
# Editor
|
|
21
|
+
.vscode/
|
|
22
|
+
.idea/
|
|
23
|
+
*.swp
|
|
24
|
+
|
|
25
|
+
# OS
|
|
26
|
+
.DS_Store
|
|
27
|
+
Thumbs.db
|
|
28
|
+
|
|
29
|
+
# Build-hook materialised resources (hatch_build.py copies these in
|
|
30
|
+
# from sibling workspace packages; checked-in copies would drift).
|
|
31
|
+
packages/picolet/picolet/_bridge/picolet-bridge.js
|
|
32
|
+
packages/picolet/picolet/_runtime_data/sbom/runtime.toml
|
|
33
|
+
packages/picolet/picolet/_runtime_data/mbm.toml
|
|
34
|
+
packages/picolet/picolet/_runtime_data/RUNTIME_TAG
|
picolet-0.0.1/PKG-INFO
ADDED
|
@@ -0,0 +1,250 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: picolet
|
|
3
|
+
Version: 0.0.1
|
|
4
|
+
Summary: Compile Python programs to small self-contained native binaries via MicroPython
|
|
5
|
+
Project-URL: Homepage, https://github.com/andrewleech/picolet
|
|
6
|
+
Project-URL: Source, https://github.com/andrewleech/picolet
|
|
7
|
+
Project-URL: Issues, https://github.com/andrewleech/picolet/issues
|
|
8
|
+
Author-email: Andrew Leech <andrew@alelec.net>
|
|
9
|
+
License: MIT
|
|
10
|
+
Keywords: binary,bundler,freeze,lvgl,micropython,webview
|
|
11
|
+
Classifier: Development Status :: 4 - Beta
|
|
12
|
+
Classifier: Intended Audience :: Developers
|
|
13
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
14
|
+
Classifier: Programming Language :: Python :: 3
|
|
15
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
16
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
17
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
18
|
+
Classifier: Topic :: Software Development :: Build Tools
|
|
19
|
+
Requires-Python: >=3.11
|
|
20
|
+
Requires-Dist: mpremote
|
|
21
|
+
Provides-Extra: testing
|
|
22
|
+
Requires-Dist: pillow>=10.0; extra == 'testing'
|
|
23
|
+
Requires-Dist: playwright>=1.40; extra == 'testing'
|
|
24
|
+
Requires-Dist: websockets>=12.0; extra == 'testing'
|
|
25
|
+
Description-Content-Type: text/markdown
|
|
26
|
+
|
|
27
|
+
# Picolet
|
|
28
|
+
|
|
29
|
+
Compile a Python program into a small self-contained native executable. Like PyInstaller, but the binary is hundreds of kilobytes rather than tens of megabytes, starts in milliseconds, and has no runtime Python dependency on the host.
|
|
30
|
+
|
|
31
|
+
## The shape of it
|
|
32
|
+
|
|
33
|
+
A Picolet binary is one file. Inside:
|
|
34
|
+
|
|
35
|
+
- A trimmed MicroPython interpreter (~410–650 KB depending on renderer).
|
|
36
|
+
- Your application's `.py` code, compiled to bytecode and frozen into the binary.
|
|
37
|
+
- Optional bundled assets (HTML, fonts, images, schemas) as a read-only ROM filesystem appended to the executable.
|
|
38
|
+
- Optionally: a GUI renderer (system webview or native LVGL) for HTML/JS or native UIs.
|
|
39
|
+
|
|
40
|
+
The result runs on any matching-OS/arch machine without installing Python.
|
|
41
|
+
|
|
42
|
+
## Three ways to use it
|
|
43
|
+
|
|
44
|
+
### 1. Bundle a single CLI script
|
|
45
|
+
|
|
46
|
+
The simplest case:
|
|
47
|
+
|
|
48
|
+
```bash
|
|
49
|
+
picolet build hello.py
|
|
50
|
+
./hello # Linux ≈ 647 KB
|
|
51
|
+
./hello.exe # Windows ≈ 409 KB
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
`hello.py` becomes a self-contained executable. Sub-second startup. No `python` interpreter needed on the host machine. Roughly 20–50× smaller than the equivalent PyInstaller bundle, with no first-launch unpacking delay.
|
|
55
|
+
|
|
56
|
+
### 2. Manifest-driven build
|
|
57
|
+
|
|
58
|
+
For multi-module apps, drive the build from a MicroPython `manifest.py`:
|
|
59
|
+
|
|
60
|
+
```python
|
|
61
|
+
# manifest.py
|
|
62
|
+
require("argparse") # frozen micropython-lib module
|
|
63
|
+
require("typing")
|
|
64
|
+
freeze("./src", "main.py") # your entry
|
|
65
|
+
freeze("./src/lib", "utils.py") # additional modules
|
|
66
|
+
freeze("./src/lib", "data_model.py")
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
```bash
|
|
70
|
+
picolet build --manifest manifest.py
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
The manifest is the canonical MicroPython mechanism for declaring what's frozen into a build. Picolet uses it directly — everything declared is included.
|
|
74
|
+
|
|
75
|
+
Medium-term: romfs contents (HTML, fonts, etc.) declared in the same manifest, per upstream evolution.
|
|
76
|
+
|
|
77
|
+
### 3. GUI application
|
|
78
|
+
|
|
79
|
+
Add a `picolet.toml` to pick a renderer and bundle UI assets:
|
|
80
|
+
|
|
81
|
+
```toml
|
|
82
|
+
[app]
|
|
83
|
+
name = "my-app"
|
|
84
|
+
entry = "src/main.py"
|
|
85
|
+
|
|
86
|
+
[ui]
|
|
87
|
+
renderer = "webview" # or "lvgl" for native
|
|
88
|
+
root = "ui"
|
|
89
|
+
|
|
90
|
+
[window]
|
|
91
|
+
title = "My App"
|
|
92
|
+
size = [900, 600]
|
|
93
|
+
|
|
94
|
+
[romfs]
|
|
95
|
+
include = ["ui", "assets"]
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
```bash
|
|
99
|
+
picolet build
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
For Vue or other JS framework frontends:
|
|
103
|
+
|
|
104
|
+
```toml
|
|
105
|
+
[ui.frontend]
|
|
106
|
+
framework = "vue" # builds Vite output into romfs automatically
|
|
107
|
+
```
|
|
108
|
+
|
|
109
|
+
The IPC bridge is set up automatically:
|
|
110
|
+
|
|
111
|
+
```javascript
|
|
112
|
+
// JS side
|
|
113
|
+
await window.picolet.invoke('list_items', { filter: 'active' });
|
|
114
|
+
window.picolet.on('progress', e => bar.update(e.pct));
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
```python
|
|
118
|
+
# Python side
|
|
119
|
+
@picolet.command
|
|
120
|
+
async def list_items(args):
|
|
121
|
+
return [...]
|
|
122
|
+
```
|
|
123
|
+
|
|
124
|
+
Four worked examples under `examples/` (`pydfu`, `notes`, `config-editor`, `dashboard`) demonstrate the patterns end-to-end, each with a distinct visual aesthetic.
|
|
125
|
+
|
|
126
|
+
## Caveats
|
|
127
|
+
|
|
128
|
+
Read these before adopting.
|
|
129
|
+
|
|
130
|
+
- **MicroPython, not CPython.** The standard library subset is smaller. Pure-Python code using `os`, `sys`, `json`, `re`, `time`, `asyncio`, `struct`, `io` etc. typically works. Code that depends on C extensions (numpy, pandas, Pillow, lxml, etc.) does not. Picolet cannot make a CPython library "just work" — it would have to be ported or replaced with a MicroPython equivalent.
|
|
131
|
+
|
|
132
|
+
- **`micropython-lib` fills most stdlib gaps.** Modules like `argparse`, `pathlib`, `dataclasses`, `typing`, `unittest` are available via [micropython-lib](https://github.com/micropython/micropython-lib) and are declared with `require("name")` in the manifest.
|
|
133
|
+
|
|
134
|
+
- **Custom C modules are straightforward.** A Picolet binary is a MicroPython build under the hood, so any C module written against the standard MicroPython API works. Drop a directory under `user_c_modules/` and reference it in the manifest. Once [upstream PR #18229](https://github.com/micropython/micropython/pull/18229) lands in the fork, `c_module("./path/to/mymodule")` can declare it directly in the manifest.
|
|
135
|
+
|
|
136
|
+
- **Python C-API extensions (CPython `.so`/`.pyd`) do NOT work.** MicroPython's runtime is binary-incompatible with CPython. Write a MicroPython C module instead.
|
|
137
|
+
|
|
138
|
+
- **Async semantics differ slightly.** MicroPython's `asyncio` is a subset of CPython's. Coroutines, tasks, queues, locks, `gather`, `wait_for` work; `asyncio.run` with policies, debug mode, the `loop.add_signal_handler` interface, and some niche APIs don't. Most app code is unaffected.
|
|
139
|
+
|
|
140
|
+
- **First-class platform support is Linux x64 and Windows x64.** macOS (Intel + Apple Silicon) is source-complete but requires GitHub Actions CI for native builds — local cross-compile from Linux is not supported. ARM Linux and mobile platforms are on the backlog.
|
|
141
|
+
|
|
142
|
+
See [docs/caveats.md](docs/caveats.md) for a full catalogue.
|
|
143
|
+
|
|
144
|
+
## Toolchain expectations
|
|
145
|
+
|
|
146
|
+
- The `picolet` CLI runs on Linux, macOS, or Windows (host).
|
|
147
|
+
- Building Windows binaries from Linux uses [`dockcross`](https://github.com/dockcross/dockcross); Docker is required for that path.
|
|
148
|
+
- Building macOS binaries uses GitHub Actions runners (`macos-13` Intel, `macos-14` Apple Silicon).
|
|
149
|
+
- Node.js + npm are required only when building Vue/React frontends.
|
|
150
|
+
|
|
151
|
+
## Getting started
|
|
152
|
+
|
|
153
|
+
Install the CLI. `uv tool install` is the recommended path (no separate
|
|
154
|
+
package manager needed if you already use `uv`); `pipx` is the fallback
|
|
155
|
+
for environments without `uv`. Plain `pip install` is deliberately not
|
|
156
|
+
listed — most modern distros (PEP 668) block it system-wide.
|
|
157
|
+
|
|
158
|
+
```bash
|
|
159
|
+
uv tool install picolet-cli # recommended
|
|
160
|
+
# or:
|
|
161
|
+
pipx install picolet-cli # fallback
|
|
162
|
+
|
|
163
|
+
picolet init my-app --template hello-cli # see --list-templates for the full set
|
|
164
|
+
cd my-app
|
|
165
|
+
picolet dev # live rebuild on file changes
|
|
166
|
+
picolet build # produce target/<os-arch>/my-app[.exe]
|
|
167
|
+
```
|
|
168
|
+
|
|
169
|
+
Templates: `hello-cli`, `hello-webview`, `hello-lvgl`, `hello-vue`, `pydfu`, `notes`, `config-editor`, `dashboard`.
|
|
170
|
+
|
|
171
|
+
## Examples gallery
|
|
172
|
+
|
|
173
|
+
<table>
|
|
174
|
+
<tr>
|
|
175
|
+
<td align="center">
|
|
176
|
+
<a href="examples/pydfu/">
|
|
177
|
+
<img src="examples/pydfu/screenshots/device-list-populated.png" alt="pydfu screenshot" />
|
|
178
|
+
</a>
|
|
179
|
+
<br>
|
|
180
|
+
<strong>pydfu</strong><br>
|
|
181
|
+
DFU firmware flasher (industrial control-panel aesthetic)
|
|
182
|
+
</td>
|
|
183
|
+
<td align="center">
|
|
184
|
+
<a href="examples/notes/">
|
|
185
|
+
<img src="examples/notes/screenshots/list-populated.png" alt="notes screenshot" />
|
|
186
|
+
</a>
|
|
187
|
+
<br>
|
|
188
|
+
<strong>notes</strong><br>
|
|
189
|
+
Markdown notes (editorial / refined)
|
|
190
|
+
</td>
|
|
191
|
+
</tr>
|
|
192
|
+
<tr>
|
|
193
|
+
<td align="center">
|
|
194
|
+
<a href="examples/config-editor/">
|
|
195
|
+
<img src="examples/config-editor/screenshots/edit-toml.png" alt="config-editor screenshot" />
|
|
196
|
+
</a>
|
|
197
|
+
<br>
|
|
198
|
+
<strong>config-editor</strong><br>
|
|
199
|
+
Schema-driven TOML/YAML/JSON editor (brutalist terminal)
|
|
200
|
+
</td>
|
|
201
|
+
<td align="center">
|
|
202
|
+
<a href="examples/dashboard/">
|
|
203
|
+
<img src="examples/dashboard/screenshots/full-dashboard.png" alt="dashboard screenshot" />
|
|
204
|
+
</a>
|
|
205
|
+
<br>
|
|
206
|
+
<strong>dashboard</strong><br>
|
|
207
|
+
Live system metrics (data-dense)
|
|
208
|
+
</td>
|
|
209
|
+
</tr>
|
|
210
|
+
</table>
|
|
211
|
+
|
|
212
|
+
See [docs/examples.md](docs/examples.md) for a longer tour of each.
|
|
213
|
+
|
|
214
|
+
## Renderers
|
|
215
|
+
|
|
216
|
+
| Renderer | Backed by | Use case | Binary size (typical) |
|
|
217
|
+
|---|---|---|---|
|
|
218
|
+
| (none) | — | CLI tool, no UI | ~647 KB Linux / ~409 KB Windows |
|
|
219
|
+
| `webview` | WebKitGTK 4.1 (Linux), WebView2 (Windows), WKWebView (macOS) | HTML/CSS/JS frontend | ~710 KB Linux / ~525 KB Windows |
|
|
220
|
+
| `lvgl` | [`lv_binding_micropython`](https://github.com/lvgl/lv_binding_micropython) + SDL2 | Native widgets, zero system UI deps | ~1.84 MB Linux / ~2.05 MB Windows |
|
|
221
|
+
|
|
222
|
+
## Repository layout
|
|
223
|
+
|
|
224
|
+
```
|
|
225
|
+
picolet/
|
|
226
|
+
├── packages/
|
|
227
|
+
│ ├── picolet-cli/ # picolet init|dev|build|run|test
|
|
228
|
+
│ ├── picolet-runtime/ # the MicroPython runtime + variants + user_c_modules
|
|
229
|
+
│ ├── picolet-bridge-js/ # JS shim: window.picolet.invoke(...)
|
|
230
|
+
│ ├── picolet-templates/ # `picolet init --template <name>` starter packs
|
|
231
|
+
│ └── picolet-testing/ # AppHarness for autonomous test/screenshot
|
|
232
|
+
├── examples/ # four worked example apps
|
|
233
|
+
├── tests/ # per-phase test suites
|
|
234
|
+
└── docs/ # architecture, caveats, examples, CLI reference
|
|
235
|
+
```
|
|
236
|
+
|
|
237
|
+
## More
|
|
238
|
+
|
|
239
|
+
- [Getting started](docs/getting-started.md) — step-by-step tutorial
|
|
240
|
+
- [`manifest.py` guide](docs/manifest.md) — declaring frozen modules + `require()` from `micropython-lib` and community packages
|
|
241
|
+
- [Architecture](docs/architecture.md) — design decisions
|
|
242
|
+
- [Caveats](docs/caveats.md) — MicroPython compatibility reference
|
|
243
|
+
- [Examples tour](docs/examples.md) — what each example app demonstrates
|
|
244
|
+
- [CLI reference](docs/cli-reference.md) — every `picolet` subcommand
|
|
245
|
+
- [SBOM](docs/sbom.md) — supply-chain documentation
|
|
246
|
+
- [History](docs/history/) — phase artefacts and version-specific specs/plans/audits
|
|
247
|
+
|
|
248
|
+
## License
|
|
249
|
+
|
|
250
|
+
MIT throughout. See [LICENSE](LICENSE).
|
picolet-0.0.1/README.md
ADDED
|
@@ -0,0 +1,224 @@
|
|
|
1
|
+
# Picolet
|
|
2
|
+
|
|
3
|
+
Compile a Python program into a small self-contained native executable. Like PyInstaller, but the binary is hundreds of kilobytes rather than tens of megabytes, starts in milliseconds, and has no runtime Python dependency on the host.
|
|
4
|
+
|
|
5
|
+
## The shape of it
|
|
6
|
+
|
|
7
|
+
A Picolet binary is one file. Inside:
|
|
8
|
+
|
|
9
|
+
- A trimmed MicroPython interpreter (~410–650 KB depending on renderer).
|
|
10
|
+
- Your application's `.py` code, compiled to bytecode and frozen into the binary.
|
|
11
|
+
- Optional bundled assets (HTML, fonts, images, schemas) as a read-only ROM filesystem appended to the executable.
|
|
12
|
+
- Optionally: a GUI renderer (system webview or native LVGL) for HTML/JS or native UIs.
|
|
13
|
+
|
|
14
|
+
The result runs on any matching-OS/arch machine without installing Python.
|
|
15
|
+
|
|
16
|
+
## Three ways to use it
|
|
17
|
+
|
|
18
|
+
### 1. Bundle a single CLI script
|
|
19
|
+
|
|
20
|
+
The simplest case:
|
|
21
|
+
|
|
22
|
+
```bash
|
|
23
|
+
picolet build hello.py
|
|
24
|
+
./hello # Linux ≈ 647 KB
|
|
25
|
+
./hello.exe # Windows ≈ 409 KB
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
`hello.py` becomes a self-contained executable. Sub-second startup. No `python` interpreter needed on the host machine. Roughly 20–50× smaller than the equivalent PyInstaller bundle, with no first-launch unpacking delay.
|
|
29
|
+
|
|
30
|
+
### 2. Manifest-driven build
|
|
31
|
+
|
|
32
|
+
For multi-module apps, drive the build from a MicroPython `manifest.py`:
|
|
33
|
+
|
|
34
|
+
```python
|
|
35
|
+
# manifest.py
|
|
36
|
+
require("argparse") # frozen micropython-lib module
|
|
37
|
+
require("typing")
|
|
38
|
+
freeze("./src", "main.py") # your entry
|
|
39
|
+
freeze("./src/lib", "utils.py") # additional modules
|
|
40
|
+
freeze("./src/lib", "data_model.py")
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
```bash
|
|
44
|
+
picolet build --manifest manifest.py
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
The manifest is the canonical MicroPython mechanism for declaring what's frozen into a build. Picolet uses it directly — everything declared is included.
|
|
48
|
+
|
|
49
|
+
Medium-term: romfs contents (HTML, fonts, etc.) declared in the same manifest, per upstream evolution.
|
|
50
|
+
|
|
51
|
+
### 3. GUI application
|
|
52
|
+
|
|
53
|
+
Add a `picolet.toml` to pick a renderer and bundle UI assets:
|
|
54
|
+
|
|
55
|
+
```toml
|
|
56
|
+
[app]
|
|
57
|
+
name = "my-app"
|
|
58
|
+
entry = "src/main.py"
|
|
59
|
+
|
|
60
|
+
[ui]
|
|
61
|
+
renderer = "webview" # or "lvgl" for native
|
|
62
|
+
root = "ui"
|
|
63
|
+
|
|
64
|
+
[window]
|
|
65
|
+
title = "My App"
|
|
66
|
+
size = [900, 600]
|
|
67
|
+
|
|
68
|
+
[romfs]
|
|
69
|
+
include = ["ui", "assets"]
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
```bash
|
|
73
|
+
picolet build
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
For Vue or other JS framework frontends:
|
|
77
|
+
|
|
78
|
+
```toml
|
|
79
|
+
[ui.frontend]
|
|
80
|
+
framework = "vue" # builds Vite output into romfs automatically
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
The IPC bridge is set up automatically:
|
|
84
|
+
|
|
85
|
+
```javascript
|
|
86
|
+
// JS side
|
|
87
|
+
await window.picolet.invoke('list_items', { filter: 'active' });
|
|
88
|
+
window.picolet.on('progress', e => bar.update(e.pct));
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
```python
|
|
92
|
+
# Python side
|
|
93
|
+
@picolet.command
|
|
94
|
+
async def list_items(args):
|
|
95
|
+
return [...]
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
Four worked examples under `examples/` (`pydfu`, `notes`, `config-editor`, `dashboard`) demonstrate the patterns end-to-end, each with a distinct visual aesthetic.
|
|
99
|
+
|
|
100
|
+
## Caveats
|
|
101
|
+
|
|
102
|
+
Read these before adopting.
|
|
103
|
+
|
|
104
|
+
- **MicroPython, not CPython.** The standard library subset is smaller. Pure-Python code using `os`, `sys`, `json`, `re`, `time`, `asyncio`, `struct`, `io` etc. typically works. Code that depends on C extensions (numpy, pandas, Pillow, lxml, etc.) does not. Picolet cannot make a CPython library "just work" — it would have to be ported or replaced with a MicroPython equivalent.
|
|
105
|
+
|
|
106
|
+
- **`micropython-lib` fills most stdlib gaps.** Modules like `argparse`, `pathlib`, `dataclasses`, `typing`, `unittest` are available via [micropython-lib](https://github.com/micropython/micropython-lib) and are declared with `require("name")` in the manifest.
|
|
107
|
+
|
|
108
|
+
- **Custom C modules are straightforward.** A Picolet binary is a MicroPython build under the hood, so any C module written against the standard MicroPython API works. Drop a directory under `user_c_modules/` and reference it in the manifest. Once [upstream PR #18229](https://github.com/micropython/micropython/pull/18229) lands in the fork, `c_module("./path/to/mymodule")` can declare it directly in the manifest.
|
|
109
|
+
|
|
110
|
+
- **Python C-API extensions (CPython `.so`/`.pyd`) do NOT work.** MicroPython's runtime is binary-incompatible with CPython. Write a MicroPython C module instead.
|
|
111
|
+
|
|
112
|
+
- **Async semantics differ slightly.** MicroPython's `asyncio` is a subset of CPython's. Coroutines, tasks, queues, locks, `gather`, `wait_for` work; `asyncio.run` with policies, debug mode, the `loop.add_signal_handler` interface, and some niche APIs don't. Most app code is unaffected.
|
|
113
|
+
|
|
114
|
+
- **First-class platform support is Linux x64 and Windows x64.** macOS (Intel + Apple Silicon) is source-complete but requires GitHub Actions CI for native builds — local cross-compile from Linux is not supported. ARM Linux and mobile platforms are on the backlog.
|
|
115
|
+
|
|
116
|
+
See [docs/caveats.md](docs/caveats.md) for a full catalogue.
|
|
117
|
+
|
|
118
|
+
## Toolchain expectations
|
|
119
|
+
|
|
120
|
+
- The `picolet` CLI runs on Linux, macOS, or Windows (host).
|
|
121
|
+
- Building Windows binaries from Linux uses [`dockcross`](https://github.com/dockcross/dockcross); Docker is required for that path.
|
|
122
|
+
- Building macOS binaries uses GitHub Actions runners (`macos-13` Intel, `macos-14` Apple Silicon).
|
|
123
|
+
- Node.js + npm are required only when building Vue/React frontends.
|
|
124
|
+
|
|
125
|
+
## Getting started
|
|
126
|
+
|
|
127
|
+
Install the CLI. `uv tool install` is the recommended path (no separate
|
|
128
|
+
package manager needed if you already use `uv`); `pipx` is the fallback
|
|
129
|
+
for environments without `uv`. Plain `pip install` is deliberately not
|
|
130
|
+
listed — most modern distros (PEP 668) block it system-wide.
|
|
131
|
+
|
|
132
|
+
```bash
|
|
133
|
+
uv tool install picolet-cli # recommended
|
|
134
|
+
# or:
|
|
135
|
+
pipx install picolet-cli # fallback
|
|
136
|
+
|
|
137
|
+
picolet init my-app --template hello-cli # see --list-templates for the full set
|
|
138
|
+
cd my-app
|
|
139
|
+
picolet dev # live rebuild on file changes
|
|
140
|
+
picolet build # produce target/<os-arch>/my-app[.exe]
|
|
141
|
+
```
|
|
142
|
+
|
|
143
|
+
Templates: `hello-cli`, `hello-webview`, `hello-lvgl`, `hello-vue`, `pydfu`, `notes`, `config-editor`, `dashboard`.
|
|
144
|
+
|
|
145
|
+
## Examples gallery
|
|
146
|
+
|
|
147
|
+
<table>
|
|
148
|
+
<tr>
|
|
149
|
+
<td align="center">
|
|
150
|
+
<a href="examples/pydfu/">
|
|
151
|
+
<img src="examples/pydfu/screenshots/device-list-populated.png" alt="pydfu screenshot" />
|
|
152
|
+
</a>
|
|
153
|
+
<br>
|
|
154
|
+
<strong>pydfu</strong><br>
|
|
155
|
+
DFU firmware flasher (industrial control-panel aesthetic)
|
|
156
|
+
</td>
|
|
157
|
+
<td align="center">
|
|
158
|
+
<a href="examples/notes/">
|
|
159
|
+
<img src="examples/notes/screenshots/list-populated.png" alt="notes screenshot" />
|
|
160
|
+
</a>
|
|
161
|
+
<br>
|
|
162
|
+
<strong>notes</strong><br>
|
|
163
|
+
Markdown notes (editorial / refined)
|
|
164
|
+
</td>
|
|
165
|
+
</tr>
|
|
166
|
+
<tr>
|
|
167
|
+
<td align="center">
|
|
168
|
+
<a href="examples/config-editor/">
|
|
169
|
+
<img src="examples/config-editor/screenshots/edit-toml.png" alt="config-editor screenshot" />
|
|
170
|
+
</a>
|
|
171
|
+
<br>
|
|
172
|
+
<strong>config-editor</strong><br>
|
|
173
|
+
Schema-driven TOML/YAML/JSON editor (brutalist terminal)
|
|
174
|
+
</td>
|
|
175
|
+
<td align="center">
|
|
176
|
+
<a href="examples/dashboard/">
|
|
177
|
+
<img src="examples/dashboard/screenshots/full-dashboard.png" alt="dashboard screenshot" />
|
|
178
|
+
</a>
|
|
179
|
+
<br>
|
|
180
|
+
<strong>dashboard</strong><br>
|
|
181
|
+
Live system metrics (data-dense)
|
|
182
|
+
</td>
|
|
183
|
+
</tr>
|
|
184
|
+
</table>
|
|
185
|
+
|
|
186
|
+
See [docs/examples.md](docs/examples.md) for a longer tour of each.
|
|
187
|
+
|
|
188
|
+
## Renderers
|
|
189
|
+
|
|
190
|
+
| Renderer | Backed by | Use case | Binary size (typical) |
|
|
191
|
+
|---|---|---|---|
|
|
192
|
+
| (none) | — | CLI tool, no UI | ~647 KB Linux / ~409 KB Windows |
|
|
193
|
+
| `webview` | WebKitGTK 4.1 (Linux), WebView2 (Windows), WKWebView (macOS) | HTML/CSS/JS frontend | ~710 KB Linux / ~525 KB Windows |
|
|
194
|
+
| `lvgl` | [`lv_binding_micropython`](https://github.com/lvgl/lv_binding_micropython) + SDL2 | Native widgets, zero system UI deps | ~1.84 MB Linux / ~2.05 MB Windows |
|
|
195
|
+
|
|
196
|
+
## Repository layout
|
|
197
|
+
|
|
198
|
+
```
|
|
199
|
+
picolet/
|
|
200
|
+
├── packages/
|
|
201
|
+
│ ├── picolet-cli/ # picolet init|dev|build|run|test
|
|
202
|
+
│ ├── picolet-runtime/ # the MicroPython runtime + variants + user_c_modules
|
|
203
|
+
│ ├── picolet-bridge-js/ # JS shim: window.picolet.invoke(...)
|
|
204
|
+
│ ├── picolet-templates/ # `picolet init --template <name>` starter packs
|
|
205
|
+
│ └── picolet-testing/ # AppHarness for autonomous test/screenshot
|
|
206
|
+
├── examples/ # four worked example apps
|
|
207
|
+
├── tests/ # per-phase test suites
|
|
208
|
+
└── docs/ # architecture, caveats, examples, CLI reference
|
|
209
|
+
```
|
|
210
|
+
|
|
211
|
+
## More
|
|
212
|
+
|
|
213
|
+
- [Getting started](docs/getting-started.md) — step-by-step tutorial
|
|
214
|
+
- [`manifest.py` guide](docs/manifest.md) — declaring frozen modules + `require()` from `micropython-lib` and community packages
|
|
215
|
+
- [Architecture](docs/architecture.md) — design decisions
|
|
216
|
+
- [Caveats](docs/caveats.md) — MicroPython compatibility reference
|
|
217
|
+
- [Examples tour](docs/examples.md) — what each example app demonstrates
|
|
218
|
+
- [CLI reference](docs/cli-reference.md) — every `picolet` subcommand
|
|
219
|
+
- [SBOM](docs/sbom.md) — supply-chain documentation
|
|
220
|
+
- [History](docs/history/) — phase artefacts and version-specific specs/plans/audits
|
|
221
|
+
|
|
222
|
+
## License
|
|
223
|
+
|
|
224
|
+
MIT throughout. See [LICENSE](LICENSE).
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
"""Hatch build hook: materialize sibling-package resources into picolet/.
|
|
2
|
+
|
|
3
|
+
The picolet wheel ships three pieces of data that live in sibling workspace
|
|
4
|
+
packages outside packages/picolet/:
|
|
5
|
+
|
|
6
|
+
packages/picolet-bridge-js/dist/picolet-bridge.js
|
|
7
|
+
packages/picolet-runtime/sbom/runtime.toml
|
|
8
|
+
packages/picolet-runtime/mbm.toml
|
|
9
|
+
packages/picolet-runtime/RUNTIME_TAG
|
|
10
|
+
|
|
11
|
+
A ``[tool.hatch.build.targets.wheel.force-include]`` rule with ``../`` paths
|
|
12
|
+
*almost* works — it does when hatch is building directly from the source
|
|
13
|
+
workspace. It fails when uv (or pip) builds the wheel from an extracted
|
|
14
|
+
sdist, because the extracted sdist root has no siblings.
|
|
15
|
+
|
|
16
|
+
This hook runs in ``initialize`` (before file enumeration) and copies the
|
|
17
|
+
sibling files into the picolet/ package tree at:
|
|
18
|
+
|
|
19
|
+
picolet/_bridge/picolet-bridge.js
|
|
20
|
+
picolet/_runtime_data/sbom/runtime.toml
|
|
21
|
+
picolet/_runtime_data/mbm.toml
|
|
22
|
+
picolet/_runtime_data/RUNTIME_TAG
|
|
23
|
+
|
|
24
|
+
Once present in the tree they get enumerated as ordinary package files for
|
|
25
|
+
both sdist and wheel. The sdist therefore contains them, so a downstream
|
|
26
|
+
``pip wheel`` from the sdist works without needing the workspace.
|
|
27
|
+
|
|
28
|
+
The destination files are git-ignored in the repo so they don't drift
|
|
29
|
+
between dev builds and CI rebuilds.
|
|
30
|
+
|
|
31
|
+
When the hook can't find the source files (the workspace root has no
|
|
32
|
+
siblings — e.g. an extracted sdist), it skips silently; the assumption is
|
|
33
|
+
that the files are already in the package tree because the sdist build hook
|
|
34
|
+
already put them there.
|
|
35
|
+
"""
|
|
36
|
+
from __future__ import annotations
|
|
37
|
+
|
|
38
|
+
import shutil
|
|
39
|
+
from pathlib import Path
|
|
40
|
+
|
|
41
|
+
from hatchling.builders.hooks.plugin.interface import BuildHookInterface
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
# (workspace-relative source, package-relative destination)
|
|
45
|
+
_FILE_MAP = (
|
|
46
|
+
("packages/picolet-bridge-js/dist/picolet-bridge.js",
|
|
47
|
+
"picolet/_bridge/picolet-bridge.js"),
|
|
48
|
+
("packages/picolet-runtime/sbom/runtime.toml",
|
|
49
|
+
"picolet/_runtime_data/sbom/runtime.toml"),
|
|
50
|
+
("packages/picolet-runtime/mbm.toml",
|
|
51
|
+
"picolet/_runtime_data/mbm.toml"),
|
|
52
|
+
("packages/picolet-runtime/RUNTIME_TAG",
|
|
53
|
+
"picolet/_runtime_data/RUNTIME_TAG"),
|
|
54
|
+
)
|
|
55
|
+
|
|
56
|
+
|
|
57
|
+
class CustomBuildHook(BuildHookInterface):
|
|
58
|
+
PLUGIN_NAME = "picolet-resources"
|
|
59
|
+
|
|
60
|
+
def initialize(self, version, build_data):
|
|
61
|
+
pkg_root = Path(self.root) # packages/picolet/
|
|
62
|
+
# workspace root: parent.parent from packages/picolet/ → repo root
|
|
63
|
+
repo_root = pkg_root.parent.parent
|
|
64
|
+
|
|
65
|
+
for src_rel, dst_rel in _FILE_MAP:
|
|
66
|
+
src = repo_root / src_rel
|
|
67
|
+
dst = pkg_root / dst_rel
|
|
68
|
+
|
|
69
|
+
if not src.is_file():
|
|
70
|
+
# Likely building from an extracted sdist where siblings
|
|
71
|
+
# don't exist. The sdist build hook should have already
|
|
72
|
+
# placed the file at dst; if it's missing too the build
|
|
73
|
+
# will fail later with a clearer error.
|
|
74
|
+
continue
|
|
75
|
+
|
|
76
|
+
dst.parent.mkdir(parents=True, exist_ok=True)
|
|
77
|
+
shutil.copy2(src, dst)
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
"""Picolet — compile Python programs to small self-contained native binaries.
|
|
2
|
+
|
|
3
|
+
Public surface from the host-installed CLI:
|
|
4
|
+
|
|
5
|
+
picolet.cli — command implementations (build, dev, init, run, test, ...)
|
|
6
|
+
picolet.testing — AppHarness + webview/CDP drivers for autonomous testing
|
|
7
|
+
(requires the [testing] extra: ``pip install picolet[testing]``)
|
|
8
|
+
picolet.templates — starter-app templates discoverable via importlib.resources
|
|
9
|
+
|
|
10
|
+
The ``picolet`` CLI command is exposed via the entry point declared in
|
|
11
|
+
pyproject.toml; ``python -m picolet`` invokes the same main().
|
|
12
|
+
|
|
13
|
+
Note: the in-binary ``import picolet`` inside a compiled MicroPython runtime
|
|
14
|
+
refers to a separate set of frozen modules (the dispatcher, IPC transport,
|
|
15
|
+
system event facade, etc.) that live under packages/picolet-runtime/python/
|
|
16
|
+
and never ship in this wheel.
|
|
17
|
+
"""
|
|
18
|
+
|
|
19
|
+
try:
|
|
20
|
+
from importlib.metadata import PackageNotFoundError, version as _pkg_version
|
|
21
|
+
|
|
22
|
+
__version__ = _pkg_version("picolet")
|
|
23
|
+
except Exception:
|
|
24
|
+
__version__ = "0.0.0-dev"
|
|
25
|
+
|
|
26
|
+
__all__ = ("__version__",)
|