fastled 1.4.35__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 +20 -15
- fastled/docker_manager.py +12 -6
- fastled/parse_args.py +9 -1
- fastled/select_sketch_directory.py +36 -6
- {fastled-1.4.35.dist-info → fastled-1.4.36.dist-info}/METADATA +2 -1
- {fastled-1.4.35.dist-info → fastled-1.4.36.dist-info}/RECORD +13 -13
- {fastled-1.4.35.dist-info → fastled-1.4.36.dist-info}/WHEEL +0 -0
- {fastled-1.4.35.dist-info → fastled-1.4.36.dist-info}/entry_points.txt +0 -0
- {fastled-1.4.35.dist-info → fastled-1.4.36.dist-info}/licenses/LICENSE +0 -0
- {fastled-1.4.35.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:
|
@@ -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
@@ -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
|
@@ -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,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=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=
|
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=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
|
@@ -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.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
|