fastled 1.4.35__py3-none-any.whl → 1.4.37__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 +20 -15
- fastled/docker_manager.py +12 -6
- fastled/parse_args.py +39 -1
- fastled/select_sketch_directory.py +36 -6
- {fastled-1.4.35.dist-info → fastled-1.4.37.dist-info}/METADATA +2 -1
- {fastled-1.4.35.dist-info → fastled-1.4.37.dist-info}/RECORD +13 -13
- {fastled-1.4.35.dist-info → fastled-1.4.37.dist-info}/WHEEL +0 -0
- {fastled-1.4.35.dist-info → fastled-1.4.37.dist-info}/entry_points.txt +0 -0
- {fastled-1.4.35.dist-info → fastled-1.4.37.dist-info}/licenses/LICENSE +0 -0
- {fastled-1.4.35.dist-info → fastled-1.4.37.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.37"
|
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:
|
@@ -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/parse_args.py
CHANGED
@@ -36,6 +36,7 @@ FastLED WASM Compiler - Useful options:
|
|
36
36
|
--update Update the docker image for the wasm compiler
|
37
37
|
--background-update Update the docker image in the background after compilation
|
38
38
|
--purge Remove all FastLED containers and images
|
39
|
+
--emsdk-headers <path> Export EMSDK headers ZIP to specified path
|
39
40
|
--version Show version information
|
40
41
|
--help Show detailed help
|
41
42
|
Examples:
|
@@ -187,6 +188,12 @@ def parse_args() -> Args:
|
|
187
188
|
action="store_true",
|
188
189
|
help="Run in non-interactive mode (fail instead of prompting for input)",
|
189
190
|
)
|
191
|
+
parser.add_argument(
|
192
|
+
"--emsdk-headers",
|
193
|
+
type=str,
|
194
|
+
default=None,
|
195
|
+
help="Export EMSDK headers ZIP to specified path",
|
196
|
+
)
|
190
197
|
|
191
198
|
build_mode = parser.add_mutually_exclusive_group()
|
192
199
|
build_mode.add_argument("--debug", action="store_true", help="Build in debug mode")
|
@@ -203,12 +210,43 @@ def parse_args() -> Args:
|
|
203
210
|
|
204
211
|
args = parser.parse_args()
|
205
212
|
|
213
|
+
# Handle --emsdk-headers early before other processing
|
214
|
+
if args.emsdk_headers:
|
215
|
+
import httpx
|
216
|
+
|
217
|
+
out_path = args.emsdk_headers
|
218
|
+
base_url = args.web if isinstance(args.web, str) else DEFAULT_URL
|
219
|
+
try:
|
220
|
+
timeout = httpx.Timeout(
|
221
|
+
30.0, read=30.0
|
222
|
+
) # 30 second timeout for read operations
|
223
|
+
with httpx.stream(
|
224
|
+
"GET", f"{base_url}/headers/emsdk", timeout=timeout
|
225
|
+
) as response:
|
226
|
+
if response.status_code == 200:
|
227
|
+
Path(out_path).parent.mkdir(parents=True, exist_ok=True)
|
228
|
+
with open(out_path, "wb") as f:
|
229
|
+
for chunk in response.iter_bytes(chunk_size=512000):
|
230
|
+
f.write(chunk)
|
231
|
+
print(f"SUCCESS: EMSDK headers exported to {out_path}")
|
232
|
+
sys.exit(0)
|
233
|
+
else:
|
234
|
+
print(
|
235
|
+
f"ERROR: Failed to export EMSDK headers: HTTP {response.status_code}"
|
236
|
+
)
|
237
|
+
sys.exit(1)
|
238
|
+
except Exception as e:
|
239
|
+
print(f"ERROR: Exception: {e}")
|
240
|
+
sys.exit(1)
|
241
|
+
|
206
242
|
# Auto-enable app mode if debug is used and Playwright cache exists
|
207
243
|
if args.debug and not args.app:
|
208
244
|
playwright_dir = Path.home() / ".fastled" / "playwright"
|
209
245
|
if playwright_dir.exists() and any(playwright_dir.iterdir()):
|
246
|
+
from fastled.emoji_util import EMO
|
247
|
+
|
210
248
|
print(
|
211
|
-
"
|
249
|
+
f"{EMO('⚠️', 'WARNING:')} Debug mode detected with Playwright installed - automatically enabling app mode"
|
212
250
|
)
|
213
251
|
args.app = True
|
214
252
|
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
|
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.4
|
2
2
|
Name: fastled
|
3
|
-
Version: 1.4.
|
3
|
+
Version: 1.4.37
|
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,15 +1,15 @@
|
|
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=7WAGjT1eoQHogH5kQ2V_LATALda_aTcvqy_fvO8Fu-k,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=
|
12
|
+
fastled/docker_manager.py,sha256=_C-H3_gvT43TTT9yraCXBJmwweBmSe3o_YZOTI_7sfc,41205
|
13
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
|
@@ -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=gn5yEh2RRr5H3CXorW5uB9KQ4zvHowjpE2td562IQy4,15053
|
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
|
@@ -51,9 +51,9 @@ 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
53
|
fastled/test/examples.py,sha256=M0o-5NIhCuwcUHo7CPQw5llLd3OU3FfPgussVScd8Fs,1741
|
54
|
-
fastled-1.4.
|
55
|
-
fastled-1.4.
|
56
|
-
fastled-1.4.
|
57
|
-
fastled-1.4.
|
58
|
-
fastled-1.4.
|
59
|
-
fastled-1.4.
|
54
|
+
fastled-1.4.37.dist-info/licenses/LICENSE,sha256=b6pOoifSXiUaz_lDS84vWlG3fr4yUKwB8fzkrH9R8bQ,1064
|
55
|
+
fastled-1.4.37.dist-info/METADATA,sha256=qkTbeRjT7VSw9eryE-u9D7qg8yJ839XkdVpN9ykJ2-s,31944
|
56
|
+
fastled-1.4.37.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
57
|
+
fastled-1.4.37.dist-info/entry_points.txt,sha256=RCwmzCSOS4-C2i9EziANq7Z2Zb4KFnEMR1FQC0bBwAw,101
|
58
|
+
fastled-1.4.37.dist-info/top_level.txt,sha256=Bbv5kpJpZhWNCvDF4K0VcvtBSDMa8B7PTOrZa9CezHY,8
|
59
|
+
fastled-1.4.37.dist-info/RECORD,,
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|