fastled 1.4.32__tar.gz → 1.4.34__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.
- {fastled-1.4.32 → fastled-1.4.34}/PKG-INFO +1 -1
- fastled-1.4.34/chrome_vscode_bridge_design_task.md +195 -0
- fastled-1.4.34/requirements.docker.txt +1 -0
- {fastled-1.4.32 → fastled-1.4.34}/src/fastled/__init__.py +2 -1
- {fastled-1.4.32 → fastled-1.4.34}/src/fastled/__version__.py +1 -1
- {fastled-1.4.32 → fastled-1.4.34}/src/fastled/app.py +2 -1
- {fastled-1.4.32 → fastled-1.4.34}/src/fastled/client_server.py +56 -20
- {fastled-1.4.32 → fastled-1.4.34}/src/fastled/compile_server_impl.py +2 -1
- fastled-1.4.34/src/fastled/emoji_util.py +15 -0
- {fastled-1.4.32 → fastled-1.4.34}/src/fastled/types.py +4 -0
- {fastled-1.4.32 → fastled-1.4.34}/src/fastled/web_compile.py +80 -5
- {fastled-1.4.32 → fastled-1.4.34}/src/fastled.egg-info/PKG-INFO +1 -1
- {fastled-1.4.32 → fastled-1.4.34}/src/fastled.egg-info/SOURCES.txt +3 -0
- fastled-1.4.34/task.md +292 -0
- fastled-1.4.34/task2.md +292 -0
- fastled-1.4.32/requirements.docker.txt +0 -1
- fastled-1.4.32/task.md +0 -733
- {fastled-1.4.32 → fastled-1.4.34}/.aiderignore +0 -0
- {fastled-1.4.32 → fastled-1.4.34}/.cursorrules +0 -0
- {fastled-1.4.32 → fastled-1.4.34}/.dockerignore +0 -0
- {fastled-1.4.32 → fastled-1.4.34}/.github/workflows/build_multi_docker_image.yml +0 -0
- {fastled-1.4.32 → fastled-1.4.34}/.github/workflows/build_webpage.yml +0 -0
- {fastled-1.4.32 → fastled-1.4.34}/.github/workflows/lint.yml +0 -0
- {fastled-1.4.32 → fastled-1.4.34}/.github/workflows/publish_release.yml +0 -0
- {fastled-1.4.32 → fastled-1.4.34}/.github/workflows/template_build_docker_image.yml +0 -0
- {fastled-1.4.32 → fastled-1.4.34}/.github/workflows/test_build_exe.yml +0 -0
- {fastled-1.4.32 → fastled-1.4.34}/.github/workflows/test_macos.yml +0 -0
- {fastled-1.4.32 → fastled-1.4.34}/.github/workflows/test_ubuntu.yml +0 -0
- {fastled-1.4.32 → fastled-1.4.34}/.github/workflows/test_win.yml +0 -0
- {fastled-1.4.32 → fastled-1.4.34}/.gitignore +0 -0
- {fastled-1.4.32 → fastled-1.4.34}/.pylintrc +0 -0
- {fastled-1.4.32 → fastled-1.4.34}/.vscode/launch.json +0 -0
- {fastled-1.4.32 → fastled-1.4.34}/.vscode/settings.json +0 -0
- {fastled-1.4.32 → fastled-1.4.34}/.vscode/tasks.json +0 -0
- {fastled-1.4.32 → fastled-1.4.34}/DEBUGGER.md +0 -0
- {fastled-1.4.32 → fastled-1.4.34}/Dockerfile +0 -0
- {fastled-1.4.32 → fastled-1.4.34}/FAQ.md +0 -0
- {fastled-1.4.32 → fastled-1.4.34}/LICENSE +0 -0
- {fastled-1.4.32 → fastled-1.4.34}/MANIFEST.in +0 -0
- {fastled-1.4.32 → fastled-1.4.34}/README.md +0 -0
- {fastled-1.4.32 → fastled-1.4.34}/RELEASE.md +0 -0
- {fastled-1.4.32 → fastled-1.4.34}/TODO.md +0 -0
- {fastled-1.4.32 → fastled-1.4.34}/build_exe.py +0 -0
- {fastled-1.4.32 → fastled-1.4.34}/build_local_docker.py +0 -0
- {fastled-1.4.32 → fastled-1.4.34}/build_site.py +0 -0
- {fastled-1.4.32 → fastled-1.4.34}/clean +0 -0
- {fastled-1.4.32 → fastled-1.4.34}/compiler/debug.sh +0 -0
- {fastled-1.4.32 → fastled-1.4.34}/compiler/run.py +0 -0
- {fastled-1.4.32 → fastled-1.4.34}/demo/100dots.html +0 -0
- {fastled-1.4.32 → fastled-1.4.34}/demo/demo_threejs.html +0 -0
- {fastled-1.4.32 → fastled-1.4.34}/demo/micdemo.html +0 -0
- {fastled-1.4.32 → fastled-1.4.34}/demo/mp3upload.html +0 -0
- {fastled-1.4.32 → fastled-1.4.34}/demo/webgl_postprocessing_unreal_bloom.html +0 -0
- {fastled-1.4.32 → fastled-1.4.34}/docker-compose.yml +0 -0
- {fastled-1.4.32 → fastled-1.4.34}/entrypoint.sh +0 -0
- {fastled-1.4.32 → fastled-1.4.34}/install +0 -0
- {fastled-1.4.32 → fastled-1.4.34}/install_linux.sh +0 -0
- {fastled-1.4.32 → fastled-1.4.34}/lint +0 -0
- {fastled-1.4.32 → fastled-1.4.34}/pyproject.toml +0 -0
- {fastled-1.4.32 → fastled-1.4.34}/requirements.testing.txt +0 -0
- {fastled-1.4.32 → fastled-1.4.34}/setup.cfg +0 -0
- {fastled-1.4.32 → fastled-1.4.34}/setup.py +0 -0
- {fastled-1.4.32 → fastled-1.4.34}/src/fastled/__main__.py +0 -0
- {fastled-1.4.32 → fastled-1.4.34}/src/fastled/args.py +0 -0
- {fastled-1.4.32 → fastled-1.4.34}/src/fastled/assets/example.txt +0 -0
- {fastled-1.4.32 → fastled-1.4.34}/src/fastled/assets/localhost-key.pem +0 -0
- {fastled-1.4.32 → fastled-1.4.34}/src/fastled/assets/localhost.pem +0 -0
- {fastled-1.4.32 → fastled-1.4.34}/src/fastled/cli.py +0 -0
- {fastled-1.4.32 → fastled-1.4.34}/src/fastled/cli_test.py +0 -0
- {fastled-1.4.32 → fastled-1.4.34}/src/fastled/cli_test_interactive.py +0 -0
- {fastled-1.4.32 → fastled-1.4.34}/src/fastled/compile_server.py +0 -0
- {fastled-1.4.32 → fastled-1.4.34}/src/fastled/docker_manager.py +0 -0
- {fastled-1.4.32 → fastled-1.4.34}/src/fastled/filewatcher.py +0 -0
- {fastled-1.4.32 → fastled-1.4.34}/src/fastled/find_good_connection.py +0 -0
- {fastled-1.4.32 → fastled-1.4.34}/src/fastled/install/__init__.py +0 -0
- {fastled-1.4.32 → fastled-1.4.34}/src/fastled/install/examples_manager.py +0 -0
- {fastled-1.4.32 → fastled-1.4.34}/src/fastled/install/extension_manager.py +0 -0
- {fastled-1.4.32 → fastled-1.4.34}/src/fastled/install/main.py +0 -0
- {fastled-1.4.32 → fastled-1.4.34}/src/fastled/install/project_detection.py +0 -0
- {fastled-1.4.32 → fastled-1.4.34}/src/fastled/install/test_install.py +0 -0
- {fastled-1.4.32 → fastled-1.4.34}/src/fastled/install/vscode_config.py +0 -0
- {fastled-1.4.32 → fastled-1.4.34}/src/fastled/interruptible_http.py +0 -0
- {fastled-1.4.32 → fastled-1.4.34}/src/fastled/keyboard.py +0 -0
- {fastled-1.4.32 → fastled-1.4.34}/src/fastled/keyz.py +0 -0
- {fastled-1.4.32 → fastled-1.4.34}/src/fastled/live_client.py +0 -0
- {fastled-1.4.32 → fastled-1.4.34}/src/fastled/open_browser.py +0 -0
- {fastled-1.4.32 → fastled-1.4.34}/src/fastled/parse_args.py +0 -0
- {fastled-1.4.32 → fastled-1.4.34}/src/fastled/paths.py +0 -0
- {fastled-1.4.32 → fastled-1.4.34}/src/fastled/playwright/chrome_extension_downloader.py +0 -0
- {fastled-1.4.32 → fastled-1.4.34}/src/fastled/playwright/playwright_browser.py +0 -0
- {fastled-1.4.32 → fastled-1.4.34}/src/fastled/playwright/resize_tracking.py +0 -0
- {fastled-1.4.32 → fastled-1.4.34}/src/fastled/print_filter.py +0 -0
- {fastled-1.4.32 → fastled-1.4.34}/src/fastled/project_init.py +0 -0
- {fastled-1.4.32 → fastled-1.4.34}/src/fastled/select_sketch_directory.py +0 -0
- {fastled-1.4.32 → fastled-1.4.34}/src/fastled/server_flask.py +0 -0
- {fastled-1.4.32 → fastled-1.4.34}/src/fastled/server_start.py +0 -0
- {fastled-1.4.32 → fastled-1.4.34}/src/fastled/settings.py +0 -0
- {fastled-1.4.32 → fastled-1.4.34}/src/fastled/site/build.py +0 -0
- {fastled-1.4.32 → fastled-1.4.34}/src/fastled/site/examples.py +0 -0
- {fastled-1.4.32 → fastled-1.4.34}/src/fastled/sketch.py +0 -0
- {fastled-1.4.32 → fastled-1.4.34}/src/fastled/spinner.py +0 -0
- {fastled-1.4.32 → fastled-1.4.34}/src/fastled/string_diff.py +0 -0
- {fastled-1.4.32 → fastled-1.4.34}/src/fastled/test/can_run_local_docker_tests.py +0 -0
- {fastled-1.4.32 → fastled-1.4.34}/src/fastled/test/examples.py +0 -0
- {fastled-1.4.32 → fastled-1.4.34}/src/fastled/util.py +0 -0
- {fastled-1.4.32 → fastled-1.4.34}/src/fastled/version.py +0 -0
- {fastled-1.4.32 → fastled-1.4.34}/src/fastled/zip_files.py +0 -0
- {fastled-1.4.32 → fastled-1.4.34}/src/fastled.egg-info/dependency_links.txt +0 -0
- {fastled-1.4.32 → fastled-1.4.34}/src/fastled.egg-info/entry_points.txt +0 -0
- {fastled-1.4.32 → fastled-1.4.34}/src/fastled.egg-info/requires.txt +0 -0
- {fastled-1.4.32 → fastled-1.4.34}/src/fastled.egg-info/top_level.txt +0 -0
- {fastled-1.4.32 → fastled-1.4.34}/test +0 -0
- {fastled-1.4.32 → fastled-1.4.34}/tests/integration/test_build_examples.py +0 -0
- {fastled-1.4.32 → fastled-1.4.34}/tests/integration/test_examples.py +0 -0
- {fastled-1.4.32 → fastled-1.4.34}/tests/integration/test_libcompile.py +0 -0
- {fastled-1.4.32 → fastled-1.4.34}/tests/integration/test_playwright_integration.py +0 -0
- {fastled-1.4.32 → fastled-1.4.34}/tests/unit/html/index.html +0 -0
- {fastled-1.4.32 → fastled-1.4.34}/tests/unit/test_api.py +0 -0
- {fastled-1.4.32 → fastled-1.4.34}/tests/unit/test_bad_ino.py +0 -0
- {fastled-1.4.32 → fastled-1.4.34}/tests/unit/test_banner_string.py +0 -0
- {fastled-1.4.32 → fastled-1.4.34}/tests/unit/test_cli.py +0 -0
- {fastled-1.4.32 → fastled-1.4.34}/tests/unit/test_cli_no_platformio.py +0 -0
- {fastled-1.4.32 → fastled-1.4.34}/tests/unit/test_compile_server.py +0 -0
- {fastled-1.4.32 → fastled-1.4.34}/tests/unit/test_debug_fetch_source_files.py +0 -0
- {fastled-1.4.32 → fastled-1.4.34}/tests/unit/test_docker_linux_on_windows.py +0 -0
- {fastled-1.4.32 → fastled-1.4.34}/tests/unit/test_embedded_data.py +0 -0
- {fastled-1.4.32 → fastled-1.4.34}/tests/unit/test_filechanger.py +0 -0
- {fastled-1.4.32 → fastled-1.4.34}/tests/unit/test_flask_headers.py +0 -0
- {fastled-1.4.32 → fastled-1.4.34}/tests/unit/test_http_server.py +0 -0
- {fastled-1.4.32 → fastled-1.4.34}/tests/unit/test_ino/bad/bad.ino +0 -0
- {fastled-1.4.32 → fastled-1.4.34}/tests/unit/test_ino/bad_platformio/bad_platformio.ino +0 -0
- {fastled-1.4.32 → fastled-1.4.34}/tests/unit/test_ino/bad_platformio/platformio.ini +0 -0
- {fastled-1.4.32 → fastled-1.4.34}/tests/unit/test_ino/embedded/data/bigdata.dat +0 -0
- {fastled-1.4.32 → fastled-1.4.34}/tests/unit/test_ino/embedded/wasm.ino +0 -0
- {fastled-1.4.32 → fastled-1.4.34}/tests/unit/test_ino/wasm/wasm.ino +0 -0
- {fastled-1.4.32 → fastled-1.4.34}/tests/unit/test_manual_api_invocation.py +0 -0
- {fastled-1.4.32 → fastled-1.4.34}/tests/unit/test_no_platformio_compile.py +0 -0
- {fastled-1.4.32 → fastled-1.4.34}/tests/unit/test_project_init.py +0 -0
- {fastled-1.4.32 → fastled-1.4.34}/tests/unit/test_server_and_client_seperatly.py +0 -0
- {fastled-1.4.32 → fastled-1.4.34}/tests/unit/test_session_compile.py +0 -0
- {fastled-1.4.32 → fastled-1.4.34}/tests/unit/test_string_diff.py +0 -0
- {fastled-1.4.32 → fastled-1.4.34}/tests/unit/test_string_diff_comprehensive.py +0 -0
- {fastled-1.4.32 → fastled-1.4.34}/tests/unit/test_version.py +0 -0
- {fastled-1.4.32 → fastled-1.4.34}/tests/unit/test_webcompile.py +0 -0
- {fastled-1.4.32 → fastled-1.4.34}/upload_package.sh +0 -0
- {fastled-1.4.32 → fastled-1.4.34}/vscode-plugin/readme +0 -0
@@ -0,0 +1,195 @@
|
|
1
|
+
Here’s a refined `chrome_vscode_bridge_design_task.md` file for your repo. Feel free to adjust paths, placeholders, or formatting to match your project's style.
|
2
|
+
|
3
|
+
---
|
4
|
+
|
5
|
+
# Chrome ↔ VSCode Bridge Design 🛠️
|
6
|
+
|
7
|
+
## Overview
|
8
|
+
|
9
|
+
Design and implement a minimal debugging bridge between a Python backend (using a hypothetical `fastled` library) and a Chrome-based frontend, invokable from VS Code. The goal is to allow:
|
10
|
+
|
11
|
+
* **Step-through debugging** (`step`, `next`, `in`, `out`)
|
12
|
+
* **Program counter**, call stack, local variable inspection
|
13
|
+
* Integration with VS Code Python or Node debugger
|
14
|
+
|
15
|
+
---
|
16
|
+
|
17
|
+
## 📘 Architecture
|
18
|
+
|
19
|
+
```
|
20
|
+
[VS Code] ↔ [Chrome Frontend CLI: Puppeteer + CDP] ↔ HTTP ↔ [Python Debug API (fastled)]
|
21
|
+
```
|
22
|
+
|
23
|
+
1. **Backend** (`Python + Flask`)
|
24
|
+
|
25
|
+
* Exposes endpoints:
|
26
|
+
|
27
|
+
* `POST /start` — begins execution, stops at first pause
|
28
|
+
* `POST /step/next` — advances one logical step
|
29
|
+
* `GET /state` — returns `{ pc, function, locals }`
|
30
|
+
* Internally uses generator-based control flow and `inspect` to snapshot state.
|
31
|
+
2. **Frontend** (`Node.js + Puppeteer`)
|
32
|
+
|
33
|
+
* Launches Chrome with remote-debugging enabled
|
34
|
+
* Serves a minimal UI (e.g. HTML + JS) to send `start`, `step`, and poll `state`
|
35
|
+
* Renders debugging state to the user; future CDP integration for real-time UI
|
36
|
+
3. **VS Code Integration**
|
37
|
+
|
38
|
+
* Launch configuration invokes the frontend script
|
39
|
+
* Stepping and inspection occur in the Chrome UI
|
40
|
+
* Optionally hooks into VS Code Debug Console for unified control
|
41
|
+
|
42
|
+
---
|
43
|
+
|
44
|
+
## 📄 Files
|
45
|
+
|
46
|
+
### 1. `debug_fastled_api.py` (Backend)
|
47
|
+
|
48
|
+
```python
|
49
|
+
import fastled, inspect
|
50
|
+
from flask import Flask, jsonify, request
|
51
|
+
|
52
|
+
app = Flask(__name__)
|
53
|
+
_state, _step_generator = {}, None
|
54
|
+
|
55
|
+
def compute(n):
|
56
|
+
x = n * 2
|
57
|
+
y = fastled.compute(x)
|
58
|
+
yield from report_and_pause()
|
59
|
+
return y
|
60
|
+
|
61
|
+
def report_and_pause():
|
62
|
+
frame = inspect.currentframe().f_back
|
63
|
+
_state.update({
|
64
|
+
"pc": frame.f_lineno,
|
65
|
+
"func": frame.f_code.co_name,
|
66
|
+
"locals": frame.f_locals.copy()
|
67
|
+
})
|
68
|
+
yield True
|
69
|
+
|
70
|
+
@app.route('/start', methods=['POST'])
|
71
|
+
def start():
|
72
|
+
global _step_generator
|
73
|
+
n = request.json.get("n", 5)
|
74
|
+
def runner():
|
75
|
+
gen = compute(n)
|
76
|
+
try: next(gen)
|
77
|
+
except StopIteration: pass
|
78
|
+
_step_generator = runner
|
79
|
+
return jsonify({"status": "started"})
|
80
|
+
|
81
|
+
@app.route('/state', methods=['GET'])
|
82
|
+
def state():
|
83
|
+
return jsonify(_state)
|
84
|
+
|
85
|
+
@app.route('/step/next', methods=['POST'])
|
86
|
+
def step_next():
|
87
|
+
try:
|
88
|
+
_step_generator()
|
89
|
+
return jsonify({"status": "paused", **_state})
|
90
|
+
except Exception:
|
91
|
+
return jsonify({"status": "done"})
|
92
|
+
|
93
|
+
if __name__ == "__main__":
|
94
|
+
app.run(port=5000)
|
95
|
+
```
|
96
|
+
|
97
|
+
---
|
98
|
+
|
99
|
+
### 2. `debug_fastled_frontend.js` (Frontend)
|
100
|
+
|
101
|
+
```js
|
102
|
+
const puppeteer = require('puppeteer-core');
|
103
|
+
const fetch = require('node-fetch');
|
104
|
+
|
105
|
+
(async () => {
|
106
|
+
const browser = await puppeteer.launch({
|
107
|
+
executablePath: '/path/to/chrome',
|
108
|
+
args: ['--remote-debugging-port=9222']
|
109
|
+
});
|
110
|
+
const [page] = await browser.pages();
|
111
|
+
|
112
|
+
const html = `
|
113
|
+
<button id="start">Start</button>
|
114
|
+
<button id="step">Next</button>
|
115
|
+
<pre id="out"></pre>
|
116
|
+
<script>
|
117
|
+
document.getElementById('start').onclick = async () => {
|
118
|
+
await fetch('http://localhost:5000/start', {
|
119
|
+
method: 'POST',
|
120
|
+
headers: { 'Content-Type': 'application/json' },
|
121
|
+
body: JSON.stringify({ n: 10 })
|
122
|
+
});
|
123
|
+
update();
|
124
|
+
};
|
125
|
+
document.getElementById('step').onclick = async () => {
|
126
|
+
await fetch('http://localhost:5000/step/next', { method: 'POST' });
|
127
|
+
update();
|
128
|
+
};
|
129
|
+
async function update() {
|
130
|
+
const res = await fetch('http://localhost:5000/state');
|
131
|
+
document.getElementById('out').textContent = JSON.stringify(await res.json(), null, 2);
|
132
|
+
}
|
133
|
+
</script>
|
134
|
+
`;
|
135
|
+
await page.setContent(html);
|
136
|
+
})();
|
137
|
+
```
|
138
|
+
|
139
|
+
---
|
140
|
+
|
141
|
+
## ⛓️ Integration with VS Code
|
142
|
+
|
143
|
+
Add this to `.vscode/launch.json`:
|
144
|
+
|
145
|
+
```jsonc
|
146
|
+
{
|
147
|
+
"configurations": [
|
148
|
+
{
|
149
|
+
"name": "Chrome-FastLED Debug Bridge",
|
150
|
+
"type": "node",
|
151
|
+
"request": "launch",
|
152
|
+
"program": "${workspaceFolder}/debug_fastled_frontend.js"
|
153
|
+
}
|
154
|
+
]
|
155
|
+
}
|
156
|
+
```
|
157
|
+
|
158
|
+
* Launch this first to start Chrome with debugging enabled
|
159
|
+
* Use the UI to `Start`, `Next`, and inspect state output
|
160
|
+
* Optionally, add CDP logic to highlight lines in VS Code or Chrome DevTools
|
161
|
+
|
162
|
+
---
|
163
|
+
|
164
|
+
## ✅ Roadmap & Next Steps
|
165
|
+
|
166
|
+
| Task | Status |
|
167
|
+
| --------------------------------------- | ------------- |
|
168
|
+
| Generator-based stepping API | ✅ Implemented |
|
169
|
+
| Backend state introspection (PC/locals) | ✅ Implemented |
|
170
|
+
| Frontend stepping UI (buttons + state) | ✅ Implemented |
|
171
|
+
| VS Code `launch.json` integration | ✅ Drafted |
|
172
|
+
| CDP / DevTools integration | 🔲 To Do |
|
173
|
+
| Support for `step in`, `step out` | 🔲 To Do |
|
174
|
+
| Breakpoints, multi-file support | 🔲 To Do |
|
175
|
+
|
176
|
+
---
|
177
|
+
|
178
|
+
## 🔧 Future Enhancements
|
179
|
+
|
180
|
+
* **Full CDP client**: translate HTTP state to actual Chrome DevTools UI breakpoints/stepping
|
181
|
+
* **Rich UI**: live code view, synchronized highlighting, variable inspectors
|
182
|
+
* **Language-agnostic bridge**: plug in Node.js or other backends
|
183
|
+
* **VS Code Extension support**: unify stepping flows and tooltips
|
184
|
+
|
185
|
+
---
|
186
|
+
|
187
|
+
## 📎 Summary
|
188
|
+
|
189
|
+
This bridge provides:
|
190
|
+
|
191
|
+
* A **Python backend** exposing stepping and state via HTTP
|
192
|
+
* A **Node.js/pupeteer frontend** for remote-debug Chrome UI
|
193
|
+
* **VS Code launch config** for seamless integration
|
194
|
+
|
195
|
+
You're all set to explore, refine, or build upon this foundation. Let me know if you'd like help developing CDP integration or full VS Code extension support!
|
@@ -0,0 +1 @@
|
|
1
|
+
fastled-wasm-server>=1.1.38
|
@@ -7,6 +7,7 @@ from typing import Generator
|
|
7
7
|
|
8
8
|
from .__version__ import __version__
|
9
9
|
from .compile_server import CompileServer
|
10
|
+
from .emoji_util import EMO
|
10
11
|
from .live_client import LiveClient
|
11
12
|
from .settings import DOCKER_FILE, IMAGE_NAME
|
12
13
|
from .site.build import build
|
@@ -54,7 +55,7 @@ class Api:
|
|
54
55
|
allow_libcompile = looks_like_fastled_repo(Path(".").resolve())
|
55
56
|
if not allow_libcompile:
|
56
57
|
print(
|
57
|
-
"⚠️ libfastled compilation disabled: not running in FastLED repository"
|
58
|
+
f"{EMO('⚠️', 'WARNING:')} libfastled compilation disabled: not running in FastLED repository"
|
58
59
|
)
|
59
60
|
|
60
61
|
out: CompileResult = web_compile(
|
@@ -1,6 +1,6 @@
|
|
1
1
|
# IMPORTANT! There's a bug in github which will REJECT any version update
|
2
2
|
# that has any other change in the repo. Please bump the version as the
|
3
3
|
# ONLY change in a commit, or else the pypi update and the release will fail.
|
4
|
-
__version__ = "1.4.
|
4
|
+
__version__ = "1.4.34"
|
5
5
|
|
6
6
|
__version_url_latest__ = "https://raw.githubusercontent.com/zackees/fastled-wasm/refs/heads/main/src/fastled/__version__.py"
|
@@ -9,6 +9,7 @@ from pathlib import Path
|
|
9
9
|
|
10
10
|
from fastled.client_server import run_client_server
|
11
11
|
from fastled.compile_server import CompileServer
|
12
|
+
from fastled.emoji_util import EMO
|
12
13
|
from fastled.filewatcher import file_watcher_set
|
13
14
|
from fastled.parse_args import Args, parse_args
|
14
15
|
from fastled.sketch import find_sketch_directories, looks_like_fastled_repo
|
@@ -79,7 +80,7 @@ def main() -> int:
|
|
79
80
|
# Check if Playwright browsers are installed
|
80
81
|
playwright_dir = Path.home() / ".fastled" / "playwright"
|
81
82
|
if playwright_dir.exists() and any(playwright_dir.iterdir()):
|
82
|
-
print(f"🎭 Playwright browsers available at: {playwright_dir}")
|
83
|
+
print(f"{EMO('🎭', '*')} Playwright browsers available at: {playwright_dir}")
|
83
84
|
|
84
85
|
# Resolve some of the last interactive arguments
|
85
86
|
# 1. If interactive is set and the sketch directory is not given,
|
@@ -10,6 +10,7 @@ from pathlib import Path
|
|
10
10
|
|
11
11
|
from fastled.compile_server import CompileServer
|
12
12
|
from fastled.docker_manager import DockerManager
|
13
|
+
from fastled.emoji_util import EMO
|
13
14
|
from fastled.filewatcher import DebouncedFileWatcherProcess, FileWatcherProcess
|
14
15
|
from fastled.find_good_connection import ConnectionResult
|
15
16
|
from fastled.keyboard import SpaceBarWatcher
|
@@ -100,7 +101,7 @@ def _run_web_compiler(
|
|
100
101
|
|
101
102
|
# Guard: libfastled compilation requires volume source mapping
|
102
103
|
if not allow_libcompile:
|
103
|
-
print("⚠️ libfastled compilation disabled.")
|
104
|
+
print(f"{EMO('⚠️', 'WARNING:')} libfastled compilation disabled.")
|
104
105
|
|
105
106
|
start = time.time()
|
106
107
|
web_result = web_compile(
|
@@ -122,14 +123,59 @@ def _run_web_compiler(
|
|
122
123
|
(output_dir / "index.html").write_text(error_html, encoding="utf-8")
|
123
124
|
return web_result
|
124
125
|
|
126
|
+
# Extract zip contents to fastled_js directory
|
127
|
+
extraction_start_time = time.time()
|
128
|
+
output_dir.mkdir(exist_ok=True)
|
129
|
+
with tempfile.TemporaryDirectory() as temp_dir:
|
130
|
+
temp_path = Path(temp_dir)
|
131
|
+
temp_zip = temp_path / "result.zip"
|
132
|
+
temp_zip.write_bytes(web_result.zip_bytes)
|
133
|
+
|
134
|
+
# Clear existing contents
|
135
|
+
shutil.rmtree(output_dir, ignore_errors=True)
|
136
|
+
output_dir.mkdir(exist_ok=True)
|
137
|
+
|
138
|
+
# Extract zip contents
|
139
|
+
shutil.unpack_archive(temp_zip, output_dir, "zip")
|
140
|
+
extraction_time = time.time() - extraction_start_time
|
141
|
+
|
125
142
|
def print_results() -> None:
|
126
143
|
hash_value = (
|
127
144
|
web_result.hash_value
|
128
145
|
if web_result.hash_value is not None
|
129
146
|
else "NO HASH VALUE"
|
130
147
|
)
|
148
|
+
|
149
|
+
# Build timing breakdown
|
150
|
+
timing_breakdown = f" Time: {diff:.2f} (seconds)"
|
151
|
+
if hasattr(web_result, "zip_time"):
|
152
|
+
timing_breakdown += f"\n zip creation: {web_result.zip_time:.2f}"
|
153
|
+
if web_result.libfastled_time > 0:
|
154
|
+
timing_breakdown += (
|
155
|
+
f"\n libfastled: {web_result.libfastled_time:.2f}"
|
156
|
+
)
|
157
|
+
timing_breakdown += (
|
158
|
+
f"\n sketch compile + link: {web_result.sketch_time:.2f}"
|
159
|
+
)
|
160
|
+
if hasattr(web_result, "response_processing_time"):
|
161
|
+
timing_breakdown += f"\n response processing: {web_result.response_processing_time:.2f}"
|
162
|
+
|
163
|
+
# Calculate any unaccounted time
|
164
|
+
accounted_time = (
|
165
|
+
web_result.zip_time
|
166
|
+
+ web_result.libfastled_time
|
167
|
+
+ web_result.sketch_time
|
168
|
+
+ web_result.response_processing_time
|
169
|
+
+ extraction_time
|
170
|
+
)
|
171
|
+
unaccounted_time = diff - accounted_time
|
172
|
+
if extraction_time > 0.01:
|
173
|
+
timing_breakdown += f"\n extraction: {extraction_time:.2f}"
|
174
|
+
if unaccounted_time > 0.01:
|
175
|
+
timing_breakdown += f"\n other overhead: {unaccounted_time:.2f}"
|
176
|
+
|
131
177
|
print(
|
132
|
-
f"\nWeb compilation successful\n
|
178
|
+
f"\nWeb compilation successful\n{timing_breakdown}\n output: {output_dir}\n hash: {hash_value}\n zip size: {len(web_result.zip_bytes)} bytes"
|
133
179
|
)
|
134
180
|
|
135
181
|
# now check to see if the hash value is the same as the last hash value
|
@@ -138,20 +184,6 @@ def _run_web_compiler(
|
|
138
184
|
print_results()
|
139
185
|
return web_result
|
140
186
|
|
141
|
-
# Extract zip contents to fastled_js directory
|
142
|
-
output_dir.mkdir(exist_ok=True)
|
143
|
-
with tempfile.TemporaryDirectory() as temp_dir:
|
144
|
-
temp_path = Path(temp_dir)
|
145
|
-
temp_zip = temp_path / "result.zip"
|
146
|
-
temp_zip.write_bytes(web_result.zip_bytes)
|
147
|
-
|
148
|
-
# Clear existing contents
|
149
|
-
shutil.rmtree(output_dir, ignore_errors=True)
|
150
|
-
output_dir.mkdir(exist_ok=True)
|
151
|
-
|
152
|
-
# Extract zip contents
|
153
|
-
shutil.unpack_archive(temp_zip, output_dir, "zip")
|
154
|
-
|
155
187
|
_chunked_print(web_result.stdout)
|
156
188
|
print_results()
|
157
189
|
return web_result
|
@@ -252,16 +284,20 @@ def _background_update_docker_image() -> None:
|
|
252
284
|
image_name=IMAGE_NAME, tag="latest", upgrade=True
|
253
285
|
)
|
254
286
|
if updated:
|
255
|
-
print(
|
287
|
+
print(
|
288
|
+
f"{EMO('✅', 'SUCCESS:')} Background docker image update completed successfully."
|
289
|
+
)
|
256
290
|
else:
|
257
|
-
print("ℹ️ Docker image was already up to date.")
|
291
|
+
print(f"{EMO('ℹ️', 'INFO:')} Docker image was already up to date.")
|
258
292
|
except KeyboardInterrupt:
|
259
|
-
print(
|
293
|
+
print(
|
294
|
+
f"{EMO('⚠️', 'WARNING:')} Background docker image update interrupted by user."
|
295
|
+
)
|
260
296
|
import _thread
|
261
297
|
|
262
298
|
_thread.interrupt_main()
|
263
299
|
except Exception as e:
|
264
|
-
print(f"⚠️ Background docker image update failed: {e}")
|
300
|
+
print(f"{EMO('⚠️', 'WARNING:')} Background docker image update failed: {e}")
|
265
301
|
|
266
302
|
|
267
303
|
def _is_local_host(url: str) -> bool:
|
@@ -15,6 +15,7 @@ from fastled.docker_manager import (
|
|
15
15
|
RunningContainer,
|
16
16
|
Volume,
|
17
17
|
)
|
18
|
+
from fastled.emoji_util import EMO
|
18
19
|
from fastled.settings import DEFAULT_CONTAINER_NAME, IMAGE_NAME, SERVER_PORT
|
19
20
|
from fastled.sketch import looks_like_fastled_repo
|
20
21
|
from fastled.types import BuildMode, CompileResult, CompileServerError
|
@@ -76,7 +77,7 @@ class CompileServerImpl:
|
|
76
77
|
# If we don't have fastled_src_dir (not in FastLED repo), disable libcompile
|
77
78
|
if allow_libcompile and self.fastled_src_dir is None:
|
78
79
|
print(
|
79
|
-
"⚠️ libfastled compilation disabled: volume source mapping not available"
|
80
|
+
f"{EMO('⚠️', 'WARNING:')} libfastled compilation disabled: volume source mapping not available"
|
80
81
|
)
|
81
82
|
print(" (not running in FastLED repository)")
|
82
83
|
allow_libcompile = False
|
@@ -0,0 +1,15 @@
|
|
1
|
+
"""
|
2
|
+
Emoji utility functions for handling Unicode display issues on Windows cmd.exe
|
3
|
+
"""
|
4
|
+
|
5
|
+
import sys
|
6
|
+
|
7
|
+
|
8
|
+
def EMO(emoji: str, fallback: str) -> str:
|
9
|
+
"""Get emoji with fallback for systems that don't support Unicode properly"""
|
10
|
+
try:
|
11
|
+
# Test if we can encode the emoji properly
|
12
|
+
emoji.encode(sys.stdout.encoding or "utf-8")
|
13
|
+
return emoji
|
14
|
+
except (UnicodeEncodeError, AttributeError):
|
15
|
+
return fallback
|
@@ -196,16 +196,30 @@ def _process_compile_response(
|
|
196
196
|
response: httpx.Response,
|
197
197
|
zip_result: ZipResult,
|
198
198
|
start_time: float,
|
199
|
+
zip_time: float,
|
200
|
+
libfastled_time: float,
|
201
|
+
sketch_time: float,
|
199
202
|
) -> CompileResult:
|
200
203
|
"""Process the compile response and return the final result."""
|
201
204
|
if response.status_code != 200:
|
202
205
|
json_response = response.json()
|
203
206
|
detail = json_response.get("detail", "Could not compile")
|
204
207
|
return CompileResult(
|
205
|
-
success=False,
|
208
|
+
success=False,
|
209
|
+
stdout=detail,
|
210
|
+
hash_value=None,
|
211
|
+
zip_bytes=b"",
|
212
|
+
zip_time=zip_time,
|
213
|
+
libfastled_time=libfastled_time,
|
214
|
+
sketch_time=sketch_time,
|
215
|
+
response_processing_time=0.0, # No response processing in error case
|
206
216
|
)
|
207
217
|
|
208
218
|
print(f"Response status code: {response}")
|
219
|
+
|
220
|
+
# Time the response processing
|
221
|
+
response_processing_start = time.time()
|
222
|
+
|
209
223
|
# Create a temporary directory to extract the zip
|
210
224
|
with tempfile.TemporaryDirectory() as extract_dir:
|
211
225
|
extract_path = Path(extract_dir)
|
@@ -250,14 +264,32 @@ def _process_compile_response(
|
|
250
264
|
relative_path = file_path.relative_to(extract_path)
|
251
265
|
out_zip.write(file_path, relative_path)
|
252
266
|
|
267
|
+
response_processing_time = time.time() - response_processing_start
|
253
268
|
diff_time = time.time() - start_time
|
254
|
-
|
269
|
+
|
270
|
+
# Create detailed timing breakdown
|
271
|
+
unaccounted_time = diff_time - (
|
272
|
+
zip_time + libfastled_time + sketch_time + response_processing_time
|
273
|
+
)
|
274
|
+
msg = f"Compilation success, took {diff_time:.2f} seconds\n"
|
275
|
+
msg += f" zip creation: {zip_time:.2f}\n"
|
276
|
+
if libfastled_time > 0:
|
277
|
+
msg += f" libfastled: {libfastled_time:.2f}\n"
|
278
|
+
msg += f" sketch compile + link: {sketch_time:.2f}\n"
|
279
|
+
msg += f" response processing: {response_processing_time:.2f}\n"
|
280
|
+
if unaccounted_time > 0.01: # Only show if significant
|
281
|
+
msg += f" other overhead: {unaccounted_time:.2f}"
|
282
|
+
|
255
283
|
_print_banner(msg)
|
256
284
|
return CompileResult(
|
257
285
|
success=True,
|
258
286
|
stdout=stdout,
|
259
287
|
hash_value=hash_value,
|
260
288
|
zip_bytes=out_buffer.getvalue(),
|
289
|
+
zip_time=zip_time,
|
290
|
+
libfastled_time=libfastled_time,
|
291
|
+
sketch_time=sketch_time,
|
292
|
+
response_processing_time=response_processing_time,
|
261
293
|
)
|
262
294
|
|
263
295
|
|
@@ -279,17 +311,35 @@ def web_compile(
|
|
279
311
|
auth_token = auth_token or AUTH_TOKEN
|
280
312
|
if not directory.exists():
|
281
313
|
raise FileNotFoundError(f"Directory not found: {directory}")
|
314
|
+
|
315
|
+
# Time the zip creation
|
316
|
+
zip_start_time = time.time()
|
282
317
|
zip_result: ZipResult | Exception = zip_files(directory, build_mode=build_mode)
|
318
|
+
zip_time = time.time() - zip_start_time
|
319
|
+
|
283
320
|
if isinstance(zip_result, Exception):
|
284
321
|
return CompileResult(
|
285
|
-
success=False,
|
322
|
+
success=False,
|
323
|
+
stdout=str(zip_result),
|
324
|
+
hash_value=None,
|
325
|
+
zip_bytes=b"",
|
326
|
+
zip_time=zip_time,
|
327
|
+
libfastled_time=0.0, # No libfastled compilation in zip error case
|
328
|
+
sketch_time=0.0, # No sketch compilation in zip error case
|
329
|
+
response_processing_time=0.0, # No response processing in zip error case
|
286
330
|
)
|
287
331
|
zip_bytes = zip_result.zip_bytes
|
288
332
|
print(f"Web compiling on {host}...")
|
333
|
+
|
334
|
+
# Track timing for each step
|
335
|
+
libfastled_time = 0.0
|
336
|
+
sketch_time = 0.0
|
337
|
+
|
289
338
|
try:
|
290
339
|
# Step 1: Compile libfastled if requested
|
291
340
|
if allow_libcompile:
|
292
341
|
print("Step 1: Compiling libfastled...")
|
342
|
+
libfastled_start_time = time.time()
|
293
343
|
try:
|
294
344
|
libfastled_response = _compile_libfastled(host, auth_token, build_mode)
|
295
345
|
|
@@ -308,6 +358,10 @@ def web_compile(
|
|
308
358
|
stdout=stdout,
|
309
359
|
hash_value=None,
|
310
360
|
zip_bytes=b"",
|
361
|
+
zip_time=zip_time,
|
362
|
+
libfastled_time=libfastled_time,
|
363
|
+
sketch_time=0.0, # No sketch compilation when libfastled fails
|
364
|
+
response_processing_time=0.0, # No response processing when libfastled fails
|
311
365
|
)
|
312
366
|
else:
|
313
367
|
# Check for embedded HTTP status in response content
|
@@ -332,6 +386,10 @@ def web_compile(
|
|
332
386
|
stdout=stdout,
|
333
387
|
hash_value=None,
|
334
388
|
zip_bytes=b"",
|
389
|
+
zip_time=zip_time,
|
390
|
+
libfastled_time=libfastled_time,
|
391
|
+
sketch_time=0.0, # No sketch compilation when libfastled fails
|
392
|
+
response_processing_time=0.0, # No response processing when libfastled fails
|
335
393
|
)
|
336
394
|
# Continue with sketch compilation even if libfastled fails
|
337
395
|
elif embedded_status is None:
|
@@ -343,7 +401,9 @@ def web_compile(
|
|
343
401
|
print("✅ libfastled compilation successful")
|
344
402
|
else:
|
345
403
|
print("✅ libfastled compilation successful")
|
404
|
+
libfastled_time = time.time() - libfastled_start_time
|
346
405
|
except Exception as e:
|
406
|
+
libfastled_time = time.time() - libfastled_start_time
|
347
407
|
print(f"Warning: libfastled compilation failed: {e}")
|
348
408
|
# Continue with sketch compilation even if libfastled fails
|
349
409
|
else:
|
@@ -351,6 +411,7 @@ def web_compile(
|
|
351
411
|
|
352
412
|
# Step 2: Compile the sketch
|
353
413
|
print("Step 2: Compiling sketch...")
|
414
|
+
sketch_start_time = time.time()
|
354
415
|
response = _send_compile_request(
|
355
416
|
host,
|
356
417
|
zip_bytes,
|
@@ -360,8 +421,11 @@ def web_compile(
|
|
360
421
|
no_platformio,
|
361
422
|
False, # allow_libcompile is always False since we handle it manually
|
362
423
|
)
|
424
|
+
sketch_time = time.time() - sketch_start_time
|
363
425
|
|
364
|
-
return _process_compile_response(
|
426
|
+
return _process_compile_response(
|
427
|
+
response, zip_result, start_time, zip_time, libfastled_time, sketch_time
|
428
|
+
)
|
365
429
|
|
366
430
|
except ConnectionError as e:
|
367
431
|
_print_banner(str(e))
|
@@ -370,6 +434,10 @@ def web_compile(
|
|
370
434
|
stdout=str(e),
|
371
435
|
hash_value=None,
|
372
436
|
zip_bytes=b"",
|
437
|
+
zip_time=zip_time,
|
438
|
+
libfastled_time=libfastled_time,
|
439
|
+
sketch_time=sketch_time,
|
440
|
+
response_processing_time=0.0, # No response processing in connection error case
|
373
441
|
)
|
374
442
|
except KeyboardInterrupt:
|
375
443
|
print("Keyboard interrupt")
|
@@ -377,5 +445,12 @@ def web_compile(
|
|
377
445
|
except httpx.HTTPError as e:
|
378
446
|
print(f"Error: {e}")
|
379
447
|
return CompileResult(
|
380
|
-
success=False,
|
448
|
+
success=False,
|
449
|
+
stdout=str(e),
|
450
|
+
hash_value=None,
|
451
|
+
zip_bytes=b"",
|
452
|
+
zip_time=zip_time,
|
453
|
+
libfastled_time=libfastled_time,
|
454
|
+
sketch_time=sketch_time,
|
455
|
+
response_processing_time=0.0, # No response processing in HTTP error case
|
381
456
|
)
|
@@ -14,6 +14,7 @@ TODO.md
|
|
14
14
|
build_exe.py
|
15
15
|
build_local_docker.py
|
16
16
|
build_site.py
|
17
|
+
chrome_vscode_bridge_design_task.md
|
17
18
|
clean
|
18
19
|
docker-compose.yml
|
19
20
|
entrypoint.sh
|
@@ -25,6 +26,7 @@ requirements.docker.txt
|
|
25
26
|
requirements.testing.txt
|
26
27
|
setup.py
|
27
28
|
task.md
|
29
|
+
task2.md
|
28
30
|
test
|
29
31
|
upload_package.sh
|
30
32
|
.github/workflows/build_multi_docker_image.yml
|
@@ -58,6 +60,7 @@ src/fastled/client_server.py
|
|
58
60
|
src/fastled/compile_server.py
|
59
61
|
src/fastled/compile_server_impl.py
|
60
62
|
src/fastled/docker_manager.py
|
63
|
+
src/fastled/emoji_util.py
|
61
64
|
src/fastled/filewatcher.py
|
62
65
|
src/fastled/find_good_connection.py
|
63
66
|
src/fastled/interruptible_http.py
|