fastled 1.4.34__py3-none-any.whl → 1.4.36__py3-none-any.whl
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/__version__.py +1 -1
- fastled/app.py +26 -0
- fastled/args.py +5 -0
- fastled/client_server.py +21 -16
- fastled/docker_manager.py +12 -6
- fastled/emoji_util.py +12 -0
- fastled/install/vscode_config.py +186 -9
- fastled/parse_args.py +9 -1
- fastled/select_sketch_directory.py +36 -6
- fastled/test/examples.py +7 -5
- fastled/web_compile.py +13 -3
- {fastled-1.4.34.dist-info → fastled-1.4.36.dist-info}/METADATA +2 -1
- {fastled-1.4.34.dist-info → fastled-1.4.36.dist-info}/RECORD +17 -17
- {fastled-1.4.34.dist-info → fastled-1.4.36.dist-info}/WHEEL +0 -0
- {fastled-1.4.34.dist-info → fastled-1.4.36.dist-info}/entry_points.txt +0 -0
- {fastled-1.4.34.dist-info → fastled-1.4.36.dist-info}/licenses/LICENSE +0 -0
- {fastled-1.4.34.dist-info → fastled-1.4.36.dist-info}/top_level.txt +0 -0
fastled/__version__.py
CHANGED
@@ -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.36"
|
5
5
|
|
6
6
|
__version_url_latest__ = "https://raw.githubusercontent.com/zackees/fastled-wasm/refs/heads/main/src/fastled/__version__.py"
|
fastled/app.py
CHANGED
@@ -12,6 +12,7 @@ from fastled.compile_server import CompileServer
|
|
12
12
|
from fastled.emoji_util import EMO
|
13
13
|
from fastled.filewatcher import file_watcher_set
|
14
14
|
from fastled.parse_args import Args, parse_args
|
15
|
+
from fastled.settings import DEFAULT_URL
|
15
16
|
from fastled.sketch import find_sketch_directories, looks_like_fastled_repo
|
16
17
|
|
17
18
|
|
@@ -53,6 +54,31 @@ def main() -> int:
|
|
53
54
|
|
54
55
|
args = parse_args()
|
55
56
|
|
57
|
+
if args.emsdk_headers:
|
58
|
+
import httpx
|
59
|
+
|
60
|
+
out_path = args.emsdk_headers
|
61
|
+
base_url = args.web if isinstance(args.web, str) else DEFAULT_URL
|
62
|
+
try:
|
63
|
+
response = httpx.get(f"{base_url}/headers/emsdk")
|
64
|
+
if response.status_code == 200:
|
65
|
+
Path(out_path).parent.mkdir(parents=True, exist_ok=True)
|
66
|
+
with open(out_path, "wb") as f:
|
67
|
+
f.write(response.content)
|
68
|
+
print(f"{EMO('✅','SUCCESS:')} EMSDK headers exported to {out_path}")
|
69
|
+
return 0
|
70
|
+
else:
|
71
|
+
print(
|
72
|
+
f"{EMO('❌','ERROR:')} Failed to export EMSDK headers: HTTP {response.status_code}"
|
73
|
+
)
|
74
|
+
return 1
|
75
|
+
except KeyboardInterrupt:
|
76
|
+
print("\nExiting from main...")
|
77
|
+
return 1
|
78
|
+
except Exception as e:
|
79
|
+
print(f"{EMO('❌','ERROR:')} Exception: {e}")
|
80
|
+
return 1
|
81
|
+
|
56
82
|
# Handle --install command early
|
57
83
|
if args.install:
|
58
84
|
from fastled.install.main import fastled_install
|
fastled/args.py
CHANGED
@@ -29,6 +29,7 @@ class Args:
|
|
29
29
|
install: bool = False # Install FastLED development environment
|
30
30
|
dry_run: bool = False # Dry run mode for testing
|
31
31
|
no_interactive: bool = False # Non-interactive mode
|
32
|
+
emsdk_headers: str | None = None # Path to export EMSDK headers ZIP
|
32
33
|
|
33
34
|
@staticmethod
|
34
35
|
def from_namespace(args: argparse.Namespace) -> "Args":
|
@@ -84,6 +85,9 @@ class Args:
|
|
84
85
|
assert isinstance(
|
85
86
|
args.no_interactive, bool
|
86
87
|
), f"expected bool, got {type(args.no_interactive)}"
|
88
|
+
assert isinstance(
|
89
|
+
args.emsdk_headers, str | None
|
90
|
+
), f"expected str | None, got {type(args.emsdk_headers)}"
|
87
91
|
|
88
92
|
init: bool | str = False
|
89
93
|
if args.init is None:
|
@@ -115,5 +119,6 @@ class Args:
|
|
115
119
|
ram_disk_size=args.ram_disk_size,
|
116
120
|
install=args.install,
|
117
121
|
dry_run=args.dry_run,
|
122
|
+
emsdk_headers=args.emsdk_headers,
|
118
123
|
no_interactive=args.no_interactive,
|
119
124
|
)
|
fastled/client_server.py
CHANGED
@@ -276,28 +276,30 @@ def _try_make_compile_server(
|
|
276
276
|
|
277
277
|
|
278
278
|
def _background_update_docker_image() -> None:
|
279
|
-
"""Perform docker image update in the background."""
|
279
|
+
"""Perform docker image update in the background silently."""
|
280
280
|
try:
|
281
|
-
|
281
|
+
# Only attempt update if Docker is installed and running
|
282
|
+
if not DockerManager.is_docker_installed():
|
283
|
+
return
|
284
|
+
|
282
285
|
docker_manager = DockerManager()
|
283
|
-
|
286
|
+
docker_running, _ = docker_manager.is_running()
|
287
|
+
if not docker_running:
|
288
|
+
return
|
289
|
+
|
290
|
+
# Silently update the docker image
|
291
|
+
docker_manager.validate_or_download_image(
|
284
292
|
image_name=IMAGE_NAME, tag="latest", upgrade=True
|
285
293
|
)
|
286
|
-
if updated:
|
287
|
-
print(
|
288
|
-
f"{EMO('✅', 'SUCCESS:')} Background docker image update completed successfully."
|
289
|
-
)
|
290
|
-
else:
|
291
|
-
print(f"{EMO('ℹ️', 'INFO:')} Docker image was already up to date.")
|
292
294
|
except KeyboardInterrupt:
|
293
|
-
print(
|
294
|
-
f"{EMO('⚠️', 'WARNING:')} Background docker image update interrupted by user."
|
295
|
-
)
|
296
295
|
import _thread
|
297
296
|
|
298
297
|
_thread.interrupt_main()
|
299
298
|
except Exception as e:
|
300
|
-
|
299
|
+
# Log warning but don't disrupt user experience
|
300
|
+
import warnings
|
301
|
+
|
302
|
+
warnings.warn(f"Background docker image update failed: {e}")
|
301
303
|
|
302
304
|
|
303
305
|
def _is_local_host(url: str) -> bool:
|
@@ -370,7 +372,7 @@ def run_client(
|
|
370
372
|
# Auto-detect libcompile capability on first call
|
371
373
|
from fastled.sketch import looks_like_fastled_repo
|
372
374
|
|
373
|
-
allow_libcompile = looks_like_fastled_repo(Path(".").resolve())
|
375
|
+
allow_libcompile = is_local_host and looks_like_fastled_repo(Path(".").resolve())
|
374
376
|
|
375
377
|
try:
|
376
378
|
|
@@ -416,11 +418,14 @@ def run_client(
|
|
416
418
|
app=app,
|
417
419
|
)
|
418
420
|
else:
|
419
|
-
|
421
|
+
if result.success:
|
422
|
+
print("\nCompilation successful.")
|
423
|
+
else:
|
424
|
+
print("\nCompilation failed.")
|
420
425
|
if compile_server:
|
421
426
|
print("Shutting down compile server...")
|
422
427
|
compile_server.stop()
|
423
|
-
return 0
|
428
|
+
return 0 if result.success else 1
|
424
429
|
|
425
430
|
if not keep_running or shutdown.is_set():
|
426
431
|
if http_proc:
|
fastled/docker_manager.py
CHANGED
@@ -509,9 +509,12 @@ class DockerManager:
|
|
509
509
|
# Quick check for latest version
|
510
510
|
with Spinner(f"Pulling newer version of {image_name}:{tag}..."):
|
511
511
|
cmd_list = ["docker", "pull", f"{image_name}:{tag}"]
|
512
|
-
|
513
|
-
|
514
|
-
|
512
|
+
subprocess.run(
|
513
|
+
cmd_list,
|
514
|
+
check=True,
|
515
|
+
stdout=subprocess.DEVNULL,
|
516
|
+
stderr=subprocess.DEVNULL,
|
517
|
+
)
|
515
518
|
print(f"Updated to newer version of {image_name}:{tag}")
|
516
519
|
local_image_hash = self.client.images.get(f"{image_name}:{tag}").id
|
517
520
|
assert local_image_hash is not None
|
@@ -524,9 +527,12 @@ class DockerManager:
|
|
524
527
|
with Spinner("Loading "):
|
525
528
|
# We use docker cli here because it shows the download.
|
526
529
|
cmd_list = ["docker", "pull", f"{image_name}:{tag}"]
|
527
|
-
|
528
|
-
|
529
|
-
|
530
|
+
subprocess.run(
|
531
|
+
cmd_list,
|
532
|
+
check=True,
|
533
|
+
stdout=subprocess.DEVNULL,
|
534
|
+
stderr=subprocess.DEVNULL,
|
535
|
+
)
|
530
536
|
try:
|
531
537
|
local_image = self.client.images.get(f"{image_name}:{tag}")
|
532
538
|
local_image_hash = local_image.id
|
fastled/emoji_util.py
CHANGED
@@ -13,3 +13,15 @@ def EMO(emoji: str, fallback: str) -> str:
|
|
13
13
|
return emoji
|
14
14
|
except (UnicodeEncodeError, AttributeError):
|
15
15
|
return fallback
|
16
|
+
|
17
|
+
|
18
|
+
def safe_print(text: str) -> None:
|
19
|
+
"""Print text safely, handling Unicode/emoji encoding issues on Windows cmd.exe"""
|
20
|
+
try:
|
21
|
+
print(text)
|
22
|
+
except UnicodeEncodeError:
|
23
|
+
# Replace problematic characters with safe alternatives
|
24
|
+
safe_text = text.encode(
|
25
|
+
sys.stdout.encoding or "utf-8", errors="replace"
|
26
|
+
).decode(sys.stdout.encoding or "utf-8")
|
27
|
+
print(safe_text)
|
fastled/install/vscode_config.py
CHANGED
@@ -130,20 +130,195 @@ def update_vscode_settings_for_fastled() -> None:
|
|
130
130
|
return
|
131
131
|
settings_json_path = Path.cwd() / ".vscode" / "settings.json"
|
132
132
|
|
133
|
-
# FastLED repository-specific settings
|
133
|
+
# FastLED repository-specific settings - updated to match the official FastLED repo
|
134
134
|
fastled_settings = {
|
135
|
+
# Terminal configuration
|
136
|
+
"terminal.integrated.defaultProfile.windows": "Git Bash",
|
137
|
+
"terminal.integrated.shellIntegration.enabled": False,
|
138
|
+
"terminal.integrated.profiles.windows": {
|
139
|
+
"Command Prompt": {"path": "C:\\Windows\\System32\\cmd.exe"},
|
140
|
+
"Git Bash": {
|
141
|
+
"path": "C:\\Program Files\\Git\\bin\\bash.exe",
|
142
|
+
"args": ["--cd=."],
|
143
|
+
},
|
144
|
+
},
|
145
|
+
# File settings
|
146
|
+
"files.eol": "\n", # Unix line endings
|
147
|
+
"files.autoDetectEol": False, # Prevent VS Code from auto-detecting and changing EOL
|
148
|
+
"files.insertFinalNewline": True, # Ensure files end with a newline
|
149
|
+
"files.trimFinalNewlines": True, # Remove extra newlines at the end
|
150
|
+
"editor.tabSize": 4,
|
151
|
+
"editor.insertSpaces": True,
|
152
|
+
"editor.detectIndentation": True,
|
153
|
+
"editor.formatOnSave": False, # Disabled to prevent conflicts
|
154
|
+
# Debugger defaults - ensure C++ debugger is used for C++ files
|
155
|
+
"debug.defaultDebuggerType": "cppdbg",
|
156
|
+
"debug.toolBarLocation": "docked",
|
157
|
+
"debug.console.fontSize": 14,
|
158
|
+
"debug.console.lineHeight": 19,
|
159
|
+
# Python configuration (using uv as per project rules)
|
160
|
+
"python.defaultInterpreterPath": "uv",
|
161
|
+
"python.debugger": "debugpy",
|
162
|
+
# File associations for debugger
|
163
|
+
"[cpp]": {
|
164
|
+
"editor.defaultFormatter": "llvm-vs-code-extensions.vscode-clangd",
|
165
|
+
"debug.defaultDebuggerType": "cppdbg",
|
166
|
+
},
|
167
|
+
"[c]": {
|
168
|
+
"editor.defaultFormatter": "ms-vscode.cpptools",
|
169
|
+
"debug.defaultDebuggerType": "cppdbg",
|
170
|
+
},
|
171
|
+
"[ino]": {
|
172
|
+
"editor.defaultFormatter": "ms-vscode.cpptools",
|
173
|
+
"debug.defaultDebuggerType": "cppdbg",
|
174
|
+
},
|
175
|
+
# clangd configuration - enhanced
|
135
176
|
"clangd.arguments": [
|
136
|
-
"--compile-commands-dir=${workspaceFolder}
|
137
|
-
"--header-insertion=never",
|
177
|
+
"--compile-commands-dir=${workspaceFolder}",
|
138
178
|
"--clang-tidy",
|
179
|
+
"--header-insertion=never",
|
180
|
+
"--completion-style=detailed",
|
181
|
+
"--function-arg-placeholders=false",
|
139
182
|
"--background-index",
|
183
|
+
"--pch-storage=memory",
|
184
|
+
],
|
185
|
+
"clangd.fallbackFlags": [
|
186
|
+
"-std=c++17",
|
187
|
+
"-I${workspaceFolder}/src",
|
188
|
+
"-I${workspaceFolder}/tests",
|
189
|
+
"-Wno-global-constructors",
|
140
190
|
],
|
191
|
+
# Disable conflicting IntelliSense to let clangd handle C++ analysis
|
141
192
|
"C_Cpp.intelliSenseEngine": "disabled",
|
142
|
-
"
|
143
|
-
"
|
144
|
-
"
|
145
|
-
"
|
146
|
-
"
|
193
|
+
"C_Cpp.autocomplete": "disabled",
|
194
|
+
"C_Cpp.errorSquiggles": "disabled",
|
195
|
+
"C_Cpp.suggestSnippets": False,
|
196
|
+
"C_Cpp.intelliSenseEngineFallback": "disabled",
|
197
|
+
"C_Cpp.autocompleteAddParentheses": False,
|
198
|
+
"C_Cpp.formatting": "disabled",
|
199
|
+
"C_Cpp.vcpkg.enabled": False,
|
200
|
+
"C_Cpp.configurationWarnings": "disabled",
|
201
|
+
"C_Cpp.intelliSenseCachePath": "",
|
202
|
+
"C_Cpp.intelliSenseCacheSize": 0,
|
203
|
+
"C_Cpp.intelliSenseUpdateDelay": 0,
|
204
|
+
"C_Cpp.workspaceParsingPriority": "lowest",
|
205
|
+
"C_Cpp.disabled": True,
|
206
|
+
# File associations - comprehensive
|
207
|
+
"files.associations": {
|
208
|
+
"*.ino": "cpp",
|
209
|
+
"*.h": "cpp",
|
210
|
+
"*.hpp": "cpp",
|
211
|
+
"*.cpp": "cpp",
|
212
|
+
"*.c": "c",
|
213
|
+
"*.inc": "cpp",
|
214
|
+
"*.tcc": "cpp",
|
215
|
+
"*.embeddedhtml": "html",
|
216
|
+
# Core C++ standard library files
|
217
|
+
"compare": "cpp",
|
218
|
+
"type_traits": "cpp",
|
219
|
+
"cmath": "cpp",
|
220
|
+
"limits": "cpp",
|
221
|
+
"iostream": "cpp",
|
222
|
+
"random": "cpp",
|
223
|
+
"functional": "cpp",
|
224
|
+
"bit": "cpp",
|
225
|
+
"vector": "cpp",
|
226
|
+
"array": "cpp",
|
227
|
+
"string": "cpp",
|
228
|
+
"memory": "cpp",
|
229
|
+
"algorithm": "cpp",
|
230
|
+
"iterator": "cpp",
|
231
|
+
"utility": "cpp",
|
232
|
+
"optional": "cpp",
|
233
|
+
"variant": "cpp",
|
234
|
+
"numeric": "cpp",
|
235
|
+
"chrono": "cpp",
|
236
|
+
"thread": "cpp",
|
237
|
+
"mutex": "cpp",
|
238
|
+
"atomic": "cpp",
|
239
|
+
"future": "cpp",
|
240
|
+
"condition_variable": "cpp",
|
241
|
+
},
|
242
|
+
# Disable Java language support and popups
|
243
|
+
"java.enabled": False,
|
244
|
+
"java.jdt.ls.enabled": False,
|
245
|
+
"java.compile.nullAnalysis.mode": "disabled",
|
246
|
+
"java.configuration.checkProjectSettingsExclusions": False,
|
247
|
+
"java.import.gradle.enabled": False,
|
248
|
+
"java.import.maven.enabled": False,
|
249
|
+
"java.autobuild.enabled": False,
|
250
|
+
"java.maxConcurrentBuilds": 0,
|
251
|
+
"java.recommendations.enabled": False,
|
252
|
+
"java.help.showReleaseNotes": False,
|
253
|
+
"redhat.telemetry.enabled": False,
|
254
|
+
# Java exclusions
|
255
|
+
"java.project.sourcePaths": [],
|
256
|
+
"java.project.referencedLibraries": [],
|
257
|
+
"files.exclude": {
|
258
|
+
"**/.classpath": True,
|
259
|
+
"**/.project": True,
|
260
|
+
"**/.factorypath": True,
|
261
|
+
},
|
262
|
+
# Disable PlatformIO auto-detection for .ino files in FastLED project
|
263
|
+
"platformio.disableToolchainAutoInstaller": True,
|
264
|
+
"platformio-ide.autoRebuildAutocompleteIndex": False,
|
265
|
+
"platformio-ide.activateProjectOnTextEditorChange": False,
|
266
|
+
"platformio-ide.autoOpenPlatformIOIniFile": False,
|
267
|
+
"platformio-ide.autoPreloadEnvTasks": False,
|
268
|
+
"platformio-ide.autoCloseSerialMonitor": False,
|
269
|
+
"platformio-ide.disablePIOHomeStartup": True,
|
270
|
+
# Disable conflicting extensions
|
271
|
+
"extensions.ignoreRecommendations": True,
|
272
|
+
# Semantic token color customizations for better C++ development
|
273
|
+
"editor.semanticTokenColorCustomizations": {
|
274
|
+
"rules": {
|
275
|
+
# Types (classes, structs, enums) - Teal/Cyan
|
276
|
+
"class": "#4EC9B0",
|
277
|
+
"struct": "#4EC9B0",
|
278
|
+
"type": "#4EC9B0",
|
279
|
+
"enum": "#4EC9B0",
|
280
|
+
"enumMember": "#B5CEA8",
|
281
|
+
"typedef": "#4EC9B0",
|
282
|
+
# Variables - Almost pure white for maximum readability
|
283
|
+
"variable": "#FAFAFA",
|
284
|
+
"variable.local": "#FAFAFA",
|
285
|
+
# Parameters - Orange for clear distinction
|
286
|
+
"parameter": "#FF8C42",
|
287
|
+
"variable.parameter": "#FF8C42",
|
288
|
+
# Properties - Light purple/pink
|
289
|
+
"property": "#D197D9",
|
290
|
+
# Functions and methods - Yellow
|
291
|
+
"function": "#DCDCAA",
|
292
|
+
"method": "#DCDCAA",
|
293
|
+
"function.declaration": "#DCDCAA",
|
294
|
+
"method.declaration": "#DCDCAA",
|
295
|
+
# Namespaces - Soft blue
|
296
|
+
"namespace": "#86C5F7",
|
297
|
+
# Constants and readonly - Light green with italic
|
298
|
+
"variable.readonly": {"foreground": "#B5CEA8", "fontStyle": "italic"},
|
299
|
+
"variable.defaultLibrary": "#B5CEA8",
|
300
|
+
# Macros and defines - Muted red/salmon
|
301
|
+
"macro": "#E06C75",
|
302
|
+
# String literals - Peach/salmon
|
303
|
+
"string": "#CE9178",
|
304
|
+
# Numbers - Light green
|
305
|
+
"number": "#B5CEA8",
|
306
|
+
# Keywords - Pink/magenta
|
307
|
+
"keyword": "#C586C0",
|
308
|
+
# Storage specifiers - Bright magenta/pink
|
309
|
+
"keyword.storage": "#FF79C6",
|
310
|
+
"storageClass": "#FF79C6",
|
311
|
+
# Built-in types - Different from user-defined types
|
312
|
+
"type.builtin": "#569CD6",
|
313
|
+
"keyword.type": "#569CD6",
|
314
|
+
# Comments - Green
|
315
|
+
"comment": "#6A9955",
|
316
|
+
"comment.documentation": "#6A9955",
|
317
|
+
}
|
318
|
+
},
|
319
|
+
# Inlay hints - Brighter gray for better visibility
|
320
|
+
"editor.inlayHints.fontColor": "#808080",
|
321
|
+
"editor.inlayHints.background": "#3C3C3C20",
|
147
322
|
}
|
148
323
|
|
149
324
|
if settings_json_path.exists():
|
@@ -164,4 +339,6 @@ def update_vscode_settings_for_fastled() -> None:
|
|
164
339
|
with open(settings_json_path, "w") as f:
|
165
340
|
json.dump(data, f, indent=4)
|
166
341
|
|
167
|
-
print(
|
342
|
+
print(
|
343
|
+
f"✅ Updated {settings_json_path} with comprehensive FastLED development settings"
|
344
|
+
)
|
fastled/parse_args.py
CHANGED
@@ -187,6 +187,12 @@ def parse_args() -> Args:
|
|
187
187
|
action="store_true",
|
188
188
|
help="Run in non-interactive mode (fail instead of prompting for input)",
|
189
189
|
)
|
190
|
+
parser.add_argument(
|
191
|
+
"--emsdk-headers",
|
192
|
+
type=str,
|
193
|
+
default=None,
|
194
|
+
help="Export EMSDK headers ZIP to specified path",
|
195
|
+
)
|
190
196
|
|
191
197
|
build_mode = parser.add_mutually_exclusive_group()
|
192
198
|
build_mode.add_argument("--debug", action="store_true", help="Build in debug mode")
|
@@ -207,8 +213,10 @@ def parse_args() -> Args:
|
|
207
213
|
if args.debug and not args.app:
|
208
214
|
playwright_dir = Path.home() / ".fastled" / "playwright"
|
209
215
|
if playwright_dir.exists() and any(playwright_dir.iterdir()):
|
216
|
+
from fastled.emoji_util import EMO
|
217
|
+
|
210
218
|
print(
|
211
|
-
"
|
219
|
+
f"{EMO('⚠️', 'WARNING:')} Debug mode detected with Playwright installed - automatically enabling app mode"
|
212
220
|
)
|
213
221
|
args.app = True
|
214
222
|
elif not args.no_interactive:
|
@@ -1,10 +1,12 @@
|
|
1
1
|
from pathlib import Path
|
2
2
|
|
3
|
+
from rapidfuzz import fuzz
|
4
|
+
|
3
5
|
from fastled.string_diff import string_diff_paths
|
4
6
|
|
5
7
|
|
6
8
|
def select_sketch_directory(
|
7
|
-
sketch_directories: list[Path], cwd_is_fastled: bool
|
9
|
+
sketch_directories: list[Path], cwd_is_fastled: bool, is_followup: bool = False
|
8
10
|
) -> str | None:
|
9
11
|
if cwd_is_fastled:
|
10
12
|
exclude = ["src", "dev", "tests"]
|
@@ -28,10 +30,38 @@ def select_sketch_directory(
|
|
28
30
|
return str(sketch_directories[index])
|
29
31
|
except (ValueError, IndexError):
|
30
32
|
inputs = [p for p in sketch_directories]
|
31
|
-
|
32
|
-
if
|
33
|
-
|
34
|
-
|
33
|
+
|
34
|
+
if is_followup:
|
35
|
+
# On follow-up, find the closest match by fuzzy distance
|
36
|
+
distances = []
|
37
|
+
for path in inputs:
|
38
|
+
path_str = str(path).replace("\\", "/")
|
39
|
+
dist = fuzz.token_sort_ratio(which.lower(), path_str.lower())
|
40
|
+
distances.append((dist, path))
|
41
|
+
|
42
|
+
# Get the best distance and return the closest match(es)
|
43
|
+
best_distance = max(distances, key=lambda x: x[0])[0]
|
44
|
+
best_matches = [
|
45
|
+
path for dist, path in distances if dist == best_distance
|
46
|
+
]
|
47
|
+
|
48
|
+
if len(best_matches) == 1:
|
49
|
+
example = best_matches[0]
|
50
|
+
return str(example)
|
51
|
+
else:
|
52
|
+
# If still multiple matches with same distance, recurse again
|
53
|
+
return select_sketch_directory(
|
54
|
+
best_matches, cwd_is_fastled, is_followup=True
|
55
|
+
)
|
35
56
|
else:
|
36
|
-
|
57
|
+
# First call - use original fuzzy matching (allows ambiguity)
|
58
|
+
top_hits: list[tuple[float, Path]] = string_diff_paths(which, inputs)
|
59
|
+
if len(top_hits) == 1:
|
60
|
+
example = top_hits[0][1]
|
61
|
+
return str(example)
|
62
|
+
else:
|
63
|
+
# Recursive call with is_followup=True for more precise matching
|
64
|
+
return select_sketch_directory(
|
65
|
+
[p for _, p in top_hits], cwd_is_fastled, is_followup=True
|
66
|
+
)
|
37
67
|
return None
|
fastled/test/examples.py
CHANGED
@@ -2,6 +2,8 @@ from tempfile import TemporaryDirectory
|
|
2
2
|
from time import time
|
3
3
|
from warnings import warn
|
4
4
|
|
5
|
+
from fastled.emoji_util import safe_print
|
6
|
+
|
5
7
|
_FILTER = True
|
6
8
|
|
7
9
|
|
@@ -18,21 +20,21 @@ def test_examples(
|
|
18
20
|
examples.remove("LuminescentGrand")
|
19
21
|
with TemporaryDirectory() as tmpdir:
|
20
22
|
for example in examples:
|
21
|
-
|
23
|
+
safe_print(f"Initializing example: {example}")
|
22
24
|
try:
|
23
25
|
sketch_dir = Api.project_init(example, outputdir=tmpdir, host=host)
|
24
26
|
except Exception as e:
|
25
27
|
warn(f"Failed to initialize example: {example}, error: {e}")
|
26
28
|
out[example] = e
|
27
29
|
continue
|
28
|
-
|
30
|
+
safe_print(f"Project initialized at: {sketch_dir}")
|
29
31
|
start = time()
|
30
|
-
|
32
|
+
safe_print(f"Compiling example: {example}")
|
31
33
|
diff = time() - start
|
32
|
-
|
34
|
+
safe_print(f"Compilation took: {diff:.2f} seconds")
|
33
35
|
result = Api.web_compile(sketch_dir, host=host)
|
34
36
|
if not result.success:
|
35
|
-
|
37
|
+
safe_print(f"Compilation failed for {example}: {result.stdout}")
|
36
38
|
out[example] = Exception(result.stdout)
|
37
39
|
return out
|
38
40
|
|
fastled/web_compile.py
CHANGED
@@ -8,6 +8,7 @@ from pathlib import Path
|
|
8
8
|
|
9
9
|
import httpx
|
10
10
|
|
11
|
+
from fastled.emoji_util import EMO, safe_print
|
11
12
|
from fastled.find_good_connection import find_good_connection
|
12
13
|
from fastled.interruptible_http import make_interruptible_post_request
|
13
14
|
from fastled.settings import AUTH_TOKEN, SERVER_PORT
|
@@ -89,7 +90,7 @@ def _banner(msg: str) -> str:
|
|
89
90
|
|
90
91
|
|
91
92
|
def _print_banner(msg: str) -> None:
|
92
|
-
|
93
|
+
safe_print(_banner(msg))
|
93
94
|
|
94
95
|
|
95
96
|
def _compile_libfastled(
|
@@ -144,7 +145,6 @@ def _send_compile_request(
|
|
144
145
|
build_mode: BuildMode,
|
145
146
|
profile: bool,
|
146
147
|
no_platformio: bool,
|
147
|
-
allow_libcompile: bool,
|
148
148
|
) -> httpx.Response:
|
149
149
|
"""Send the compile request to the server and return the response."""
|
150
150
|
host = _sanitize_host(host)
|
@@ -293,6 +293,11 @@ def _process_compile_response(
|
|
293
293
|
)
|
294
294
|
|
295
295
|
|
296
|
+
def _libcompiled_is_allowed(host: str) -> bool:
|
297
|
+
"""Check if libcompiled is allowed for the given host."""
|
298
|
+
return "localhost" in host or "127.0.0.1" in host or "0.0.0.0" in host
|
299
|
+
|
300
|
+
|
296
301
|
def web_compile(
|
297
302
|
directory: Path | str,
|
298
303
|
host: str | None = None,
|
@@ -312,6 +317,12 @@ def web_compile(
|
|
312
317
|
if not directory.exists():
|
313
318
|
raise FileNotFoundError(f"Directory not found: {directory}")
|
314
319
|
|
320
|
+
if allow_libcompile and not _libcompiled_is_allowed(host):
|
321
|
+
print(
|
322
|
+
f"{EMO('🚫', '[ERROR]')} libcompile is not allowed for host {host}, disabling."
|
323
|
+
)
|
324
|
+
allow_libcompile = False
|
325
|
+
|
315
326
|
# Time the zip creation
|
316
327
|
zip_start_time = time.time()
|
317
328
|
zip_result: ZipResult | Exception = zip_files(directory, build_mode=build_mode)
|
@@ -419,7 +430,6 @@ def web_compile(
|
|
419
430
|
build_mode,
|
420
431
|
profile,
|
421
432
|
no_platformio,
|
422
|
-
False, # allow_libcompile is always False since we handle it manually
|
423
433
|
)
|
424
434
|
sketch_time = time.time() - sketch_start_time
|
425
435
|
|
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.4
|
2
2
|
Name: fastled
|
3
|
-
Version: 1.4.
|
3
|
+
Version: 1.4.36
|
4
4
|
Summary: FastLED Wasm Compiler
|
5
5
|
Home-page: https://github.com/zackees/fastled-wasm
|
6
6
|
Maintainer: Zachary Vorhies
|
@@ -23,6 +23,7 @@ Requires-Dist: flask-cors>=4.0.0
|
|
23
23
|
Requires-Dist: livereload
|
24
24
|
Requires-Dist: disklru>=2.0.4
|
25
25
|
Requires-Dist: playwright>=1.40.0
|
26
|
+
Requires-Dist: websockify>=0.13.0
|
26
27
|
Dynamic: home-page
|
27
28
|
Dynamic: license-file
|
28
29
|
Dynamic: maintainer
|
@@ -1,16 +1,16 @@
|
|
1
1
|
fastled/__init__.py,sha256=LlLu9fO3O4FeB5-wt2wHGIFJW76H9FlhdABytEqg8A4,7717
|
2
2
|
fastled/__main__.py,sha256=OcKv2ER1_iQAsZzLIUb3C8hRC9L2clNOhCrjpshrlf4,336
|
3
|
-
fastled/__version__.py,sha256=
|
4
|
-
fastled/app.py,sha256=
|
5
|
-
fastled/args.py,sha256=
|
3
|
+
fastled/__version__.py,sha256=X18yBR3A2-maAsqadc1UyBbvqCZB-ZSj09nuElN84MY,373
|
4
|
+
fastled/app.py,sha256=fWOH2SA4rxW8BPNgBrKs4xsWvUEMX6RzMWPKyyjBoVM,7539
|
5
|
+
fastled/args.py,sha256=Xa7AYnoMcsuSVQUyM6M2P_8liQtQFJzuuBdPbfw9U-g,4786
|
6
6
|
fastled/cli.py,sha256=drgR2AOxVrj3QEz58iiKscYAumbbin2vIV-k91VCOAA,561
|
7
7
|
fastled/cli_test.py,sha256=W-1nODZrip_JU6BEbYhxOa4ckxduOsiX8zIoRkTyxv4,550
|
8
8
|
fastled/cli_test_interactive.py,sha256=BjNhveZOk5aCffHbcrxPQQjWmAuj4ClVKKcKX5eY6yM,542
|
9
|
-
fastled/client_server.py,sha256=
|
9
|
+
fastled/client_server.py,sha256=RnxVnQSFZ4B6xqDHkde6uu9bB6xpPsH5k39m77yrCZc,24730
|
10
10
|
fastled/compile_server.py,sha256=iGUjteXKp5Dlp7mxAE4eD4s0NWgApRIp4ZjtcAN2iZY,3124
|
11
11
|
fastled/compile_server_impl.py,sha256=jBvLH6Di3y_dKsmStw0JSl30u0esHXtVno-r9-Vr1HA,12624
|
12
|
-
fastled/docker_manager.py,sha256=
|
13
|
-
fastled/emoji_util.py,sha256=
|
12
|
+
fastled/docker_manager.py,sha256=_C-H3_gvT43TTT9yraCXBJmwweBmSe3o_YZOTI_7sfc,41205
|
13
|
+
fastled/emoji_util.py,sha256=z3lROwgfCxpqIIJFzQxehH8gcTwGdf4VLPsUgcbcFBM,849
|
14
14
|
fastled/filewatcher.py,sha256=1EFeOLPEA_aN_V_tzgixS3mDhfleh0arTGUy0vWq6Is,10101
|
15
15
|
fastled/find_good_connection.py,sha256=xnrJjrbwNZUkvSQRn_ZTMoVh5GBWTbO-lEsr_L95xq8,3372
|
16
16
|
fastled/interruptible_http.py,sha256=2QwUsRNJ1qawf_-Lp1l0dBady3TK0SrBFhmnWgM7oqg,4888
|
@@ -18,11 +18,11 @@ fastled/keyboard.py,sha256=UTAsqCn1UMYnB8YDzENiLTj4GeL45tYfEcO7_5fLFEg,3556
|
|
18
18
|
fastled/keyz.py,sha256=LO-8m_7CpNDiZLM-FXhQ30f9gN1bUYz5lOsUPTIbI-c,4020
|
19
19
|
fastled/live_client.py,sha256=GPQf6Vj8mneEs4kc_nrfPlw-OmMMuDiIe2iWrP7FeeQ,3143
|
20
20
|
fastled/open_browser.py,sha256=YgfSd6GRCXzOyMsJ5jV1Zx6dKY7622hZrqs_RWx9H1k,5146
|
21
|
-
fastled/parse_args.py,sha256=
|
21
|
+
fastled/parse_args.py,sha256=QYZLjqGu6j7xtPYwohDN-WpaNwIuhsKXBnGc1V3XUxI,13800
|
22
22
|
fastled/paths.py,sha256=VsPmgu0lNSCFOoEC0BsTYzDygXqy15AHUfN-tTuzDZA,99
|
23
23
|
fastled/print_filter.py,sha256=nc_rqYYdCUPinFycaK7fiQF5PG1up51pmJptR__QyAs,1499
|
24
24
|
fastled/project_init.py,sha256=bBt4DwmW5hZkm9ICt9Qk-0Nr_0JQM7icCgH5Iv-bCQs,3984
|
25
|
-
fastled/select_sketch_directory.py,sha256
|
25
|
+
fastled/select_sketch_directory.py,sha256=K7erbgU7pRppGNKyOoOUhNXaWp2qAzyl_EOb7Ai1Yxo,2721
|
26
26
|
fastled/server_flask.py,sha256=HA0Pqkrr7OZn5TgMjykskXYrB-ACFd9sw7ND1L4RW-Y,17132
|
27
27
|
fastled/server_start.py,sha256=W9yKStkRlRNuXeV6j_6O7HjjFPyVLBHMcF9Uy2QjDWQ,479
|
28
28
|
fastled/settings.py,sha256=8RLN3S0ZK4DMphr0gKPfwPKfwIzOtHiQsqMTpGnX7Xg,1842
|
@@ -32,7 +32,7 @@ fastled/string_diff.py,sha256=oTncu0qYdLlLUtYLLDB4bzdQ2OfzegAR6XNAzwE9fIs,6002
|
|
32
32
|
fastled/types.py,sha256=tBikcoKjbBcCTi36MMCz_TjMEBoa-FppRL-yKAVwXFc,1909
|
33
33
|
fastled/util.py,sha256=TjhXbUNh4p2BGhNAldSeL68B7BBOjsWAXji5gy-vDEQ,1440
|
34
34
|
fastled/version.py,sha256=TpBMiEVdO3_sUZEu6wmwN8Q4AgX2BiCxStCsnPKh6E0,1209
|
35
|
-
fastled/web_compile.py,sha256=
|
35
|
+
fastled/web_compile.py,sha256=VDUTsc6EKc_Ty2KkVddTR6ENaj3renZs66Q1rV_jGsc,16823
|
36
36
|
fastled/zip_files.py,sha256=BgHFjaLJ7wF6mnzjqOgn76VcKDwhwc_-w_qyUG_-aNs,2815
|
37
37
|
fastled/assets/example.txt,sha256=lTBovRjiz0_TgtAtbA1C5hNi2ffbqnNPqkKg6UiKCT8,54
|
38
38
|
fastled/assets/localhost-key.pem,sha256=Q-CNO_UoOd8fFNN4ljcnqwUeCMhzTplRjLO2x0pYRlU,1704
|
@@ -43,17 +43,17 @@ fastled/install/extension_manager.py,sha256=uaK5wLrfz3Vsrmr9gm7aEumaQtE2vFKV6RvD
|
|
43
43
|
fastled/install/main.py,sha256=7a4L082wVB3lT6DEc-YILQwFMGyw4mWqRPViFYmG6DI,5212
|
44
44
|
fastled/install/project_detection.py,sha256=hv9wgBAvSEJ0X8ghrcbP1gRc1AWP72XMHxGQac6Jl5k,4877
|
45
45
|
fastled/install/test_install.py,sha256=_wDPkhk6jCNLTxS1IIRS3CyDFKFm3RAQLGaG2las-Zg,13502
|
46
|
-
fastled/install/vscode_config.py,sha256=
|
46
|
+
fastled/install/vscode_config.py,sha256=8z3w0sXqUpuOT0PxTukqRCsTFzTr6WQ8-mPv50XTPHI,12693
|
47
47
|
fastled/playwright/chrome_extension_downloader.py,sha256=48YyQrsuK1TVXPuAvRGzqkQJnx0991Ka6OVUo1A58zU,7079
|
48
48
|
fastled/playwright/playwright_browser.py,sha256=F58BVDJGlFqxOjakT0wGI3hKwxjwrrM1BlUDd1uT-u8,29449
|
49
49
|
fastled/playwright/resize_tracking.py,sha256=frJOFKTcGOn--lQH_adXhcPc7BNek2hPYVLAAk8QI1o,4500
|
50
50
|
fastled/site/build.py,sha256=2YKU_UWKlJdGnjdbAbaL0co6kceFMSTVYwH1KCmgPZA,13987
|
51
51
|
fastled/site/examples.py,sha256=s6vj2zJc6BfKlnbwXr1QWY1mzuDBMt6j5MEBOWjO_U8,155
|
52
52
|
fastled/test/can_run_local_docker_tests.py,sha256=LEuUbHctRhNNFWcvnz2kEGmjDJeXO4c3kNpizm3yVJs,400
|
53
|
-
fastled/test/examples.py,sha256=
|
54
|
-
fastled-1.4.
|
55
|
-
fastled-1.4.
|
56
|
-
fastled-1.4.
|
57
|
-
fastled-1.4.
|
58
|
-
fastled-1.4.
|
59
|
-
fastled-1.4.
|
53
|
+
fastled/test/examples.py,sha256=M0o-5NIhCuwcUHo7CPQw5llLd3OU3FfPgussVScd8Fs,1741
|
54
|
+
fastled-1.4.36.dist-info/licenses/LICENSE,sha256=b6pOoifSXiUaz_lDS84vWlG3fr4yUKwB8fzkrH9R8bQ,1064
|
55
|
+
fastled-1.4.36.dist-info/METADATA,sha256=nhygXwjdC3xbHrks0x5lXSlyxzvndtqx46LL5E4kz6A,31944
|
56
|
+
fastled-1.4.36.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
57
|
+
fastled-1.4.36.dist-info/entry_points.txt,sha256=RCwmzCSOS4-C2i9EziANq7Z2Zb4KFnEMR1FQC0bBwAw,101
|
58
|
+
fastled-1.4.36.dist-info/top_level.txt,sha256=Bbv5kpJpZhWNCvDF4K0VcvtBSDMa8B7PTOrZa9CezHY,8
|
59
|
+
fastled-1.4.36.dist-info/RECORD,,
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|