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.
Files changed (146) hide show
  1. {fastled-1.4.32 → fastled-1.4.34}/PKG-INFO +1 -1
  2. fastled-1.4.34/chrome_vscode_bridge_design_task.md +195 -0
  3. fastled-1.4.34/requirements.docker.txt +1 -0
  4. {fastled-1.4.32 → fastled-1.4.34}/src/fastled/__init__.py +2 -1
  5. {fastled-1.4.32 → fastled-1.4.34}/src/fastled/__version__.py +1 -1
  6. {fastled-1.4.32 → fastled-1.4.34}/src/fastled/app.py +2 -1
  7. {fastled-1.4.32 → fastled-1.4.34}/src/fastled/client_server.py +56 -20
  8. {fastled-1.4.32 → fastled-1.4.34}/src/fastled/compile_server_impl.py +2 -1
  9. fastled-1.4.34/src/fastled/emoji_util.py +15 -0
  10. {fastled-1.4.32 → fastled-1.4.34}/src/fastled/types.py +4 -0
  11. {fastled-1.4.32 → fastled-1.4.34}/src/fastled/web_compile.py +80 -5
  12. {fastled-1.4.32 → fastled-1.4.34}/src/fastled.egg-info/PKG-INFO +1 -1
  13. {fastled-1.4.32 → fastled-1.4.34}/src/fastled.egg-info/SOURCES.txt +3 -0
  14. fastled-1.4.34/task.md +292 -0
  15. fastled-1.4.34/task2.md +292 -0
  16. fastled-1.4.32/requirements.docker.txt +0 -1
  17. fastled-1.4.32/task.md +0 -733
  18. {fastled-1.4.32 → fastled-1.4.34}/.aiderignore +0 -0
  19. {fastled-1.4.32 → fastled-1.4.34}/.cursorrules +0 -0
  20. {fastled-1.4.32 → fastled-1.4.34}/.dockerignore +0 -0
  21. {fastled-1.4.32 → fastled-1.4.34}/.github/workflows/build_multi_docker_image.yml +0 -0
  22. {fastled-1.4.32 → fastled-1.4.34}/.github/workflows/build_webpage.yml +0 -0
  23. {fastled-1.4.32 → fastled-1.4.34}/.github/workflows/lint.yml +0 -0
  24. {fastled-1.4.32 → fastled-1.4.34}/.github/workflows/publish_release.yml +0 -0
  25. {fastled-1.4.32 → fastled-1.4.34}/.github/workflows/template_build_docker_image.yml +0 -0
  26. {fastled-1.4.32 → fastled-1.4.34}/.github/workflows/test_build_exe.yml +0 -0
  27. {fastled-1.4.32 → fastled-1.4.34}/.github/workflows/test_macos.yml +0 -0
  28. {fastled-1.4.32 → fastled-1.4.34}/.github/workflows/test_ubuntu.yml +0 -0
  29. {fastled-1.4.32 → fastled-1.4.34}/.github/workflows/test_win.yml +0 -0
  30. {fastled-1.4.32 → fastled-1.4.34}/.gitignore +0 -0
  31. {fastled-1.4.32 → fastled-1.4.34}/.pylintrc +0 -0
  32. {fastled-1.4.32 → fastled-1.4.34}/.vscode/launch.json +0 -0
  33. {fastled-1.4.32 → fastled-1.4.34}/.vscode/settings.json +0 -0
  34. {fastled-1.4.32 → fastled-1.4.34}/.vscode/tasks.json +0 -0
  35. {fastled-1.4.32 → fastled-1.4.34}/DEBUGGER.md +0 -0
  36. {fastled-1.4.32 → fastled-1.4.34}/Dockerfile +0 -0
  37. {fastled-1.4.32 → fastled-1.4.34}/FAQ.md +0 -0
  38. {fastled-1.4.32 → fastled-1.4.34}/LICENSE +0 -0
  39. {fastled-1.4.32 → fastled-1.4.34}/MANIFEST.in +0 -0
  40. {fastled-1.4.32 → fastled-1.4.34}/README.md +0 -0
  41. {fastled-1.4.32 → fastled-1.4.34}/RELEASE.md +0 -0
  42. {fastled-1.4.32 → fastled-1.4.34}/TODO.md +0 -0
  43. {fastled-1.4.32 → fastled-1.4.34}/build_exe.py +0 -0
  44. {fastled-1.4.32 → fastled-1.4.34}/build_local_docker.py +0 -0
  45. {fastled-1.4.32 → fastled-1.4.34}/build_site.py +0 -0
  46. {fastled-1.4.32 → fastled-1.4.34}/clean +0 -0
  47. {fastled-1.4.32 → fastled-1.4.34}/compiler/debug.sh +0 -0
  48. {fastled-1.4.32 → fastled-1.4.34}/compiler/run.py +0 -0
  49. {fastled-1.4.32 → fastled-1.4.34}/demo/100dots.html +0 -0
  50. {fastled-1.4.32 → fastled-1.4.34}/demo/demo_threejs.html +0 -0
  51. {fastled-1.4.32 → fastled-1.4.34}/demo/micdemo.html +0 -0
  52. {fastled-1.4.32 → fastled-1.4.34}/demo/mp3upload.html +0 -0
  53. {fastled-1.4.32 → fastled-1.4.34}/demo/webgl_postprocessing_unreal_bloom.html +0 -0
  54. {fastled-1.4.32 → fastled-1.4.34}/docker-compose.yml +0 -0
  55. {fastled-1.4.32 → fastled-1.4.34}/entrypoint.sh +0 -0
  56. {fastled-1.4.32 → fastled-1.4.34}/install +0 -0
  57. {fastled-1.4.32 → fastled-1.4.34}/install_linux.sh +0 -0
  58. {fastled-1.4.32 → fastled-1.4.34}/lint +0 -0
  59. {fastled-1.4.32 → fastled-1.4.34}/pyproject.toml +0 -0
  60. {fastled-1.4.32 → fastled-1.4.34}/requirements.testing.txt +0 -0
  61. {fastled-1.4.32 → fastled-1.4.34}/setup.cfg +0 -0
  62. {fastled-1.4.32 → fastled-1.4.34}/setup.py +0 -0
  63. {fastled-1.4.32 → fastled-1.4.34}/src/fastled/__main__.py +0 -0
  64. {fastled-1.4.32 → fastled-1.4.34}/src/fastled/args.py +0 -0
  65. {fastled-1.4.32 → fastled-1.4.34}/src/fastled/assets/example.txt +0 -0
  66. {fastled-1.4.32 → fastled-1.4.34}/src/fastled/assets/localhost-key.pem +0 -0
  67. {fastled-1.4.32 → fastled-1.4.34}/src/fastled/assets/localhost.pem +0 -0
  68. {fastled-1.4.32 → fastled-1.4.34}/src/fastled/cli.py +0 -0
  69. {fastled-1.4.32 → fastled-1.4.34}/src/fastled/cli_test.py +0 -0
  70. {fastled-1.4.32 → fastled-1.4.34}/src/fastled/cli_test_interactive.py +0 -0
  71. {fastled-1.4.32 → fastled-1.4.34}/src/fastled/compile_server.py +0 -0
  72. {fastled-1.4.32 → fastled-1.4.34}/src/fastled/docker_manager.py +0 -0
  73. {fastled-1.4.32 → fastled-1.4.34}/src/fastled/filewatcher.py +0 -0
  74. {fastled-1.4.32 → fastled-1.4.34}/src/fastled/find_good_connection.py +0 -0
  75. {fastled-1.4.32 → fastled-1.4.34}/src/fastled/install/__init__.py +0 -0
  76. {fastled-1.4.32 → fastled-1.4.34}/src/fastled/install/examples_manager.py +0 -0
  77. {fastled-1.4.32 → fastled-1.4.34}/src/fastled/install/extension_manager.py +0 -0
  78. {fastled-1.4.32 → fastled-1.4.34}/src/fastled/install/main.py +0 -0
  79. {fastled-1.4.32 → fastled-1.4.34}/src/fastled/install/project_detection.py +0 -0
  80. {fastled-1.4.32 → fastled-1.4.34}/src/fastled/install/test_install.py +0 -0
  81. {fastled-1.4.32 → fastled-1.4.34}/src/fastled/install/vscode_config.py +0 -0
  82. {fastled-1.4.32 → fastled-1.4.34}/src/fastled/interruptible_http.py +0 -0
  83. {fastled-1.4.32 → fastled-1.4.34}/src/fastled/keyboard.py +0 -0
  84. {fastled-1.4.32 → fastled-1.4.34}/src/fastled/keyz.py +0 -0
  85. {fastled-1.4.32 → fastled-1.4.34}/src/fastled/live_client.py +0 -0
  86. {fastled-1.4.32 → fastled-1.4.34}/src/fastled/open_browser.py +0 -0
  87. {fastled-1.4.32 → fastled-1.4.34}/src/fastled/parse_args.py +0 -0
  88. {fastled-1.4.32 → fastled-1.4.34}/src/fastled/paths.py +0 -0
  89. {fastled-1.4.32 → fastled-1.4.34}/src/fastled/playwright/chrome_extension_downloader.py +0 -0
  90. {fastled-1.4.32 → fastled-1.4.34}/src/fastled/playwright/playwright_browser.py +0 -0
  91. {fastled-1.4.32 → fastled-1.4.34}/src/fastled/playwright/resize_tracking.py +0 -0
  92. {fastled-1.4.32 → fastled-1.4.34}/src/fastled/print_filter.py +0 -0
  93. {fastled-1.4.32 → fastled-1.4.34}/src/fastled/project_init.py +0 -0
  94. {fastled-1.4.32 → fastled-1.4.34}/src/fastled/select_sketch_directory.py +0 -0
  95. {fastled-1.4.32 → fastled-1.4.34}/src/fastled/server_flask.py +0 -0
  96. {fastled-1.4.32 → fastled-1.4.34}/src/fastled/server_start.py +0 -0
  97. {fastled-1.4.32 → fastled-1.4.34}/src/fastled/settings.py +0 -0
  98. {fastled-1.4.32 → fastled-1.4.34}/src/fastled/site/build.py +0 -0
  99. {fastled-1.4.32 → fastled-1.4.34}/src/fastled/site/examples.py +0 -0
  100. {fastled-1.4.32 → fastled-1.4.34}/src/fastled/sketch.py +0 -0
  101. {fastled-1.4.32 → fastled-1.4.34}/src/fastled/spinner.py +0 -0
  102. {fastled-1.4.32 → fastled-1.4.34}/src/fastled/string_diff.py +0 -0
  103. {fastled-1.4.32 → fastled-1.4.34}/src/fastled/test/can_run_local_docker_tests.py +0 -0
  104. {fastled-1.4.32 → fastled-1.4.34}/src/fastled/test/examples.py +0 -0
  105. {fastled-1.4.32 → fastled-1.4.34}/src/fastled/util.py +0 -0
  106. {fastled-1.4.32 → fastled-1.4.34}/src/fastled/version.py +0 -0
  107. {fastled-1.4.32 → fastled-1.4.34}/src/fastled/zip_files.py +0 -0
  108. {fastled-1.4.32 → fastled-1.4.34}/src/fastled.egg-info/dependency_links.txt +0 -0
  109. {fastled-1.4.32 → fastled-1.4.34}/src/fastled.egg-info/entry_points.txt +0 -0
  110. {fastled-1.4.32 → fastled-1.4.34}/src/fastled.egg-info/requires.txt +0 -0
  111. {fastled-1.4.32 → fastled-1.4.34}/src/fastled.egg-info/top_level.txt +0 -0
  112. {fastled-1.4.32 → fastled-1.4.34}/test +0 -0
  113. {fastled-1.4.32 → fastled-1.4.34}/tests/integration/test_build_examples.py +0 -0
  114. {fastled-1.4.32 → fastled-1.4.34}/tests/integration/test_examples.py +0 -0
  115. {fastled-1.4.32 → fastled-1.4.34}/tests/integration/test_libcompile.py +0 -0
  116. {fastled-1.4.32 → fastled-1.4.34}/tests/integration/test_playwright_integration.py +0 -0
  117. {fastled-1.4.32 → fastled-1.4.34}/tests/unit/html/index.html +0 -0
  118. {fastled-1.4.32 → fastled-1.4.34}/tests/unit/test_api.py +0 -0
  119. {fastled-1.4.32 → fastled-1.4.34}/tests/unit/test_bad_ino.py +0 -0
  120. {fastled-1.4.32 → fastled-1.4.34}/tests/unit/test_banner_string.py +0 -0
  121. {fastled-1.4.32 → fastled-1.4.34}/tests/unit/test_cli.py +0 -0
  122. {fastled-1.4.32 → fastled-1.4.34}/tests/unit/test_cli_no_platformio.py +0 -0
  123. {fastled-1.4.32 → fastled-1.4.34}/tests/unit/test_compile_server.py +0 -0
  124. {fastled-1.4.32 → fastled-1.4.34}/tests/unit/test_debug_fetch_source_files.py +0 -0
  125. {fastled-1.4.32 → fastled-1.4.34}/tests/unit/test_docker_linux_on_windows.py +0 -0
  126. {fastled-1.4.32 → fastled-1.4.34}/tests/unit/test_embedded_data.py +0 -0
  127. {fastled-1.4.32 → fastled-1.4.34}/tests/unit/test_filechanger.py +0 -0
  128. {fastled-1.4.32 → fastled-1.4.34}/tests/unit/test_flask_headers.py +0 -0
  129. {fastled-1.4.32 → fastled-1.4.34}/tests/unit/test_http_server.py +0 -0
  130. {fastled-1.4.32 → fastled-1.4.34}/tests/unit/test_ino/bad/bad.ino +0 -0
  131. {fastled-1.4.32 → fastled-1.4.34}/tests/unit/test_ino/bad_platformio/bad_platformio.ino +0 -0
  132. {fastled-1.4.32 → fastled-1.4.34}/tests/unit/test_ino/bad_platformio/platformio.ini +0 -0
  133. {fastled-1.4.32 → fastled-1.4.34}/tests/unit/test_ino/embedded/data/bigdata.dat +0 -0
  134. {fastled-1.4.32 → fastled-1.4.34}/tests/unit/test_ino/embedded/wasm.ino +0 -0
  135. {fastled-1.4.32 → fastled-1.4.34}/tests/unit/test_ino/wasm/wasm.ino +0 -0
  136. {fastled-1.4.32 → fastled-1.4.34}/tests/unit/test_manual_api_invocation.py +0 -0
  137. {fastled-1.4.32 → fastled-1.4.34}/tests/unit/test_no_platformio_compile.py +0 -0
  138. {fastled-1.4.32 → fastled-1.4.34}/tests/unit/test_project_init.py +0 -0
  139. {fastled-1.4.32 → fastled-1.4.34}/tests/unit/test_server_and_client_seperatly.py +0 -0
  140. {fastled-1.4.32 → fastled-1.4.34}/tests/unit/test_session_compile.py +0 -0
  141. {fastled-1.4.32 → fastled-1.4.34}/tests/unit/test_string_diff.py +0 -0
  142. {fastled-1.4.32 → fastled-1.4.34}/tests/unit/test_string_diff_comprehensive.py +0 -0
  143. {fastled-1.4.32 → fastled-1.4.34}/tests/unit/test_version.py +0 -0
  144. {fastled-1.4.32 → fastled-1.4.34}/tests/unit/test_webcompile.py +0 -0
  145. {fastled-1.4.32 → fastled-1.4.34}/upload_package.sh +0 -0
  146. {fastled-1.4.32 → fastled-1.4.34}/vscode-plugin/readme +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: fastled
3
- Version: 1.4.32
3
+ Version: 1.4.34
4
4
  Summary: FastLED Wasm Compiler
5
5
  Home-page: https://github.com/zackees/fastled-wasm
6
6
  Maintainer: Zachary Vorhies
@@ -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.32"
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 Time: {diff:.2f}\n output: {output_dir}\n hash: {hash_value}\n zip size: {len(web_result.zip_bytes)} bytes"
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("✅ Background docker image update completed successfully.")
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("⚠️ Background docker image update interrupted by user.")
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
@@ -12,6 +12,10 @@ class CompileResult:
12
12
  stdout: str
13
13
  hash_value: str | None
14
14
  zip_bytes: bytes
15
+ zip_time: float
16
+ libfastled_time: float
17
+ sketch_time: float
18
+ response_processing_time: float
15
19
 
16
20
  def __bool__(self) -> bool:
17
21
  return self.success
@@ -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, stdout=detail, hash_value=None, zip_bytes=b""
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
- msg = f"Compilation success, took {diff_time:.2f} seconds"
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, stdout=str(zip_result), hash_value=None, zip_bytes=b""
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(response, zip_result, start_time)
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, stdout=str(e), hash_value=None, zip_bytes=b""
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
  )
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: fastled
3
- Version: 1.4.32
3
+ Version: 1.4.34
4
4
  Summary: FastLED Wasm Compiler
5
5
  Home-page: https://github.com/zackees/fastled-wasm
6
6
  Maintainer: Zachary Vorhies
@@ -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