fastled 1.1.20__py2.py3-none-any.whl → 1.1.21__py2.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/__init__.py +1 -1
- fastled/app.py +3 -287
- fastled/client_server.py +299 -0
- fastled/env.py +8 -0
- fastled/keyboard.py +25 -5
- fastled/types.py +10 -0
- {fastled-1.1.20.dist-info → fastled-1.1.21.dist-info}/METADATA +2 -1
- {fastled-1.1.20.dist-info → fastled-1.1.21.dist-info}/RECORD +12 -9
- {fastled-1.1.20.dist-info → fastled-1.1.21.dist-info}/LICENSE +0 -0
- {fastled-1.1.20.dist-info → fastled-1.1.21.dist-info}/WHEEL +0 -0
- {fastled-1.1.20.dist-info → fastled-1.1.21.dist-info}/entry_points.txt +0 -0
- {fastled-1.1.20.dist-info → fastled-1.1.21.dist-info}/top_level.txt +0 -0
fastled/__init__.py
CHANGED
fastled/app.py
CHANGED
@@ -4,48 +4,19 @@ Uses the latest wasm compiler image to compile the FastLED sketch.
|
|
4
4
|
|
5
5
|
import argparse
|
6
6
|
import os
|
7
|
-
import platform
|
8
|
-
import shutil
|
9
|
-
import subprocess
|
10
7
|
import sys
|
11
|
-
import tempfile
|
12
8
|
import time
|
13
|
-
from dataclasses import dataclass
|
14
9
|
from pathlib import Path
|
15
10
|
|
16
11
|
from fastled import __version__
|
17
|
-
from fastled.
|
12
|
+
from fastled.client_server import run_client_server
|
18
13
|
from fastled.compile_server import CompileServer
|
19
|
-
from fastled.
|
20
|
-
from fastled.filewatcher import FileWatcherProcess
|
21
|
-
from fastled.keyboard import SpaceBarWatcher
|
22
|
-
from fastled.open_browser import open_browser_thread
|
14
|
+
from fastled.env import DEFAULT_URL
|
23
15
|
from fastled.sketch import (
|
24
16
|
find_sketch_directories,
|
25
17
|
looks_like_fastled_repo,
|
26
18
|
looks_like_sketch_directory,
|
27
19
|
)
|
28
|
-
from fastled.web_compile import (
|
29
|
-
SERVER_PORT,
|
30
|
-
ConnectionResult,
|
31
|
-
find_good_connection,
|
32
|
-
web_compile,
|
33
|
-
)
|
34
|
-
|
35
|
-
machine = platform.machine().lower()
|
36
|
-
IS_ARM: bool = "arm" in machine or "aarch64" in machine
|
37
|
-
PLATFORM_TAG: str = "-arm64" if IS_ARM else ""
|
38
|
-
CONTAINER_NAME = f"fastled-wasm-compiler{PLATFORM_TAG}"
|
39
|
-
DEFAULT_URL = "https://fastled.onrender.com"
|
40
|
-
|
41
|
-
|
42
|
-
@dataclass
|
43
|
-
class CompiledResult:
|
44
|
-
"""Dataclass to hold the result of the compilation."""
|
45
|
-
|
46
|
-
success: bool
|
47
|
-
fastled_js: str
|
48
|
-
hash_value: str | None
|
49
20
|
|
50
21
|
|
51
22
|
def parse_args() -> argparse.Namespace:
|
@@ -182,261 +153,6 @@ def parse_args() -> argparse.Namespace:
|
|
182
153
|
return args
|
183
154
|
|
184
155
|
|
185
|
-
def run_web_compiler(
|
186
|
-
directory: Path,
|
187
|
-
host: str,
|
188
|
-
build_mode: BuildMode,
|
189
|
-
profile: bool,
|
190
|
-
last_hash_value: str | None,
|
191
|
-
) -> CompiledResult:
|
192
|
-
input_dir = Path(directory)
|
193
|
-
output_dir = input_dir / "fastled_js"
|
194
|
-
start = time.time()
|
195
|
-
web_result = web_compile(
|
196
|
-
directory=input_dir, host=host, build_mode=build_mode, profile=profile
|
197
|
-
)
|
198
|
-
diff = time.time() - start
|
199
|
-
if not web_result.success:
|
200
|
-
print("\nWeb compilation failed:")
|
201
|
-
print(f"Time taken: {diff:.2f} seconds")
|
202
|
-
print(web_result.stdout)
|
203
|
-
return CompiledResult(success=False, fastled_js="", hash_value=None)
|
204
|
-
|
205
|
-
def print_results() -> None:
|
206
|
-
hash_value = (
|
207
|
-
web_result.hash_value
|
208
|
-
if web_result.hash_value is not None
|
209
|
-
else "NO HASH VALUE"
|
210
|
-
)
|
211
|
-
print(
|
212
|
-
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"
|
213
|
-
)
|
214
|
-
|
215
|
-
# now check to see if the hash value is the same as the last hash value
|
216
|
-
if last_hash_value is not None and last_hash_value == web_result.hash_value:
|
217
|
-
print("\nSkipping redeploy: No significant changes found.")
|
218
|
-
print_results()
|
219
|
-
return CompiledResult(
|
220
|
-
success=True, fastled_js=str(output_dir), hash_value=web_result.hash_value
|
221
|
-
)
|
222
|
-
|
223
|
-
# Extract zip contents to fastled_js directory
|
224
|
-
output_dir.mkdir(exist_ok=True)
|
225
|
-
with tempfile.TemporaryDirectory() as temp_dir:
|
226
|
-
temp_path = Path(temp_dir)
|
227
|
-
temp_zip = temp_path / "result.zip"
|
228
|
-
temp_zip.write_bytes(web_result.zip_bytes)
|
229
|
-
|
230
|
-
# Clear existing contents
|
231
|
-
shutil.rmtree(output_dir, ignore_errors=True)
|
232
|
-
output_dir.mkdir(exist_ok=True)
|
233
|
-
|
234
|
-
# Extract zip contents
|
235
|
-
shutil.unpack_archive(temp_zip, output_dir, "zip")
|
236
|
-
|
237
|
-
print(web_result.stdout)
|
238
|
-
print_results()
|
239
|
-
return CompiledResult(
|
240
|
-
success=True, fastled_js=str(output_dir), hash_value=web_result.hash_value
|
241
|
-
)
|
242
|
-
|
243
|
-
|
244
|
-
def _try_start_server_or_get_url(args: argparse.Namespace) -> str | CompileServer:
|
245
|
-
auto_update = args.auto_update
|
246
|
-
is_local_host = "localhost" in args.web or "127.0.0.1" in args.web or args.localhost
|
247
|
-
# test to see if there is already a local host server
|
248
|
-
local_host_needs_server = False
|
249
|
-
if is_local_host:
|
250
|
-
addr = "localhost" if args.localhost else args.web
|
251
|
-
urls = [addr]
|
252
|
-
if ":" not in addr:
|
253
|
-
urls.append(f"{addr}:{SERVER_PORT}")
|
254
|
-
|
255
|
-
result: ConnectionResult | None = find_good_connection(urls)
|
256
|
-
if result is not None:
|
257
|
-
print(f"Found local server at {result.host}")
|
258
|
-
return result.host
|
259
|
-
else:
|
260
|
-
local_host_needs_server = True
|
261
|
-
|
262
|
-
if not local_host_needs_server and args.web:
|
263
|
-
if isinstance(args.web, str):
|
264
|
-
return args.web
|
265
|
-
if isinstance(args.web, bool):
|
266
|
-
return DEFAULT_URL
|
267
|
-
return args.web
|
268
|
-
else:
|
269
|
-
try:
|
270
|
-
print("No local server found, starting one...")
|
271
|
-
compile_server = CompileServer(auto_updates=auto_update)
|
272
|
-
print("Waiting for the local compiler to start...")
|
273
|
-
if not compile_server.wait_for_startup():
|
274
|
-
print("Failed to start local compiler.")
|
275
|
-
raise RuntimeError("Failed to start local compiler.")
|
276
|
-
return compile_server
|
277
|
-
except KeyboardInterrupt:
|
278
|
-
raise
|
279
|
-
except RuntimeError:
|
280
|
-
print("Failed to start local compile server, using web compiler instead.")
|
281
|
-
return DEFAULT_URL
|
282
|
-
|
283
|
-
|
284
|
-
def run_client(args: argparse.Namespace) -> int:
|
285
|
-
compile_server: CompileServer | None = None
|
286
|
-
open_web_browser = not args.just_compile and not args.interactive
|
287
|
-
profile = args.profile
|
288
|
-
if not args.force_compile and not looks_like_sketch_directory(Path(args.directory)):
|
289
|
-
print(
|
290
|
-
"Error: Not a valid FastLED sketch directory, if you are sure it is, use --force-compile"
|
291
|
-
)
|
292
|
-
return 1
|
293
|
-
|
294
|
-
# If not explicitly using web compiler, check Docker installation
|
295
|
-
if not args.web and not DockerManager.is_docker_installed():
|
296
|
-
print(
|
297
|
-
"\nDocker is not installed on this system - switching to web compiler instead."
|
298
|
-
)
|
299
|
-
args.web = True
|
300
|
-
|
301
|
-
url: str
|
302
|
-
try:
|
303
|
-
try:
|
304
|
-
url_or_server: str | CompileServer = _try_start_server_or_get_url(args)
|
305
|
-
if isinstance(url_or_server, str):
|
306
|
-
print(f"Found URL: {url_or_server}")
|
307
|
-
url = url_or_server
|
308
|
-
else:
|
309
|
-
compile_server = url_or_server
|
310
|
-
print(f"Server started at {compile_server.url()}")
|
311
|
-
url = compile_server.url()
|
312
|
-
except KeyboardInterrupt:
|
313
|
-
print("\nExiting from first try...")
|
314
|
-
if compile_server:
|
315
|
-
compile_server.stop()
|
316
|
-
return 1
|
317
|
-
except Exception as e:
|
318
|
-
print(f"Error: {e}")
|
319
|
-
return 1
|
320
|
-
build_mode: BuildMode = get_build_mode(args)
|
321
|
-
|
322
|
-
def compile_function(
|
323
|
-
url: str = url,
|
324
|
-
build_mode: BuildMode = build_mode,
|
325
|
-
profile: bool = profile,
|
326
|
-
last_hash_value: str | None = None,
|
327
|
-
) -> CompiledResult:
|
328
|
-
return run_web_compiler(
|
329
|
-
args.directory,
|
330
|
-
host=url,
|
331
|
-
build_mode=build_mode,
|
332
|
-
profile=profile,
|
333
|
-
last_hash_value=last_hash_value,
|
334
|
-
)
|
335
|
-
|
336
|
-
result: CompiledResult = compile_function(last_hash_value=None)
|
337
|
-
last_compiled_result: CompiledResult = result
|
338
|
-
|
339
|
-
if not result.success:
|
340
|
-
print("\nCompilation failed.")
|
341
|
-
|
342
|
-
browser_proc: subprocess.Popen | None = None
|
343
|
-
if open_web_browser:
|
344
|
-
browser_proc = open_browser_thread(Path(args.directory) / "fastled_js")
|
345
|
-
else:
|
346
|
-
print("\nCompilation successful.")
|
347
|
-
if compile_server:
|
348
|
-
print("Shutting down compile server...")
|
349
|
-
compile_server.stop()
|
350
|
-
return 0
|
351
|
-
|
352
|
-
if args.just_compile:
|
353
|
-
if compile_server:
|
354
|
-
compile_server.stop()
|
355
|
-
if browser_proc:
|
356
|
-
browser_proc.kill()
|
357
|
-
return 0 if result.success else 1
|
358
|
-
except KeyboardInterrupt:
|
359
|
-
print("\nExiting from main")
|
360
|
-
if compile_server:
|
361
|
-
compile_server.stop()
|
362
|
-
return 1
|
363
|
-
|
364
|
-
print("\nWatching for changes. Press Ctrl+C to stop...")
|
365
|
-
sketch_filewatcher = FileWatcherProcess(
|
366
|
-
args.directory, excluded_patterns=["fastled_js"]
|
367
|
-
)
|
368
|
-
|
369
|
-
source_code_watcher: FileWatcherProcess | None = None
|
370
|
-
if compile_server and compile_server.using_fastled_src_dir_volume():
|
371
|
-
assert compile_server.fastled_src_dir is not None
|
372
|
-
source_code_watcher = FileWatcherProcess(
|
373
|
-
compile_server.fastled_src_dir, excluded_patterns=[]
|
374
|
-
)
|
375
|
-
|
376
|
-
def trigger_rebuild_if_sketch_changed(
|
377
|
-
last_compiled_result: CompiledResult,
|
378
|
-
) -> CompiledResult:
|
379
|
-
changed_files = sketch_filewatcher.get_all_changes()
|
380
|
-
if changed_files:
|
381
|
-
print(f"\nChanges detected in {changed_files}")
|
382
|
-
last_hash_value = last_compiled_result.hash_value
|
383
|
-
out = compile_function(last_hash_value=last_hash_value)
|
384
|
-
if not out.success:
|
385
|
-
print("\nRecompilation failed.")
|
386
|
-
else:
|
387
|
-
print("\nRecompilation successful.")
|
388
|
-
return out
|
389
|
-
return last_compiled_result
|
390
|
-
|
391
|
-
try:
|
392
|
-
while True:
|
393
|
-
last_compiled_result = trigger_rebuild_if_sketch_changed(
|
394
|
-
last_compiled_result
|
395
|
-
)
|
396
|
-
if compile_server and not compile_server.proceess_running():
|
397
|
-
print("Server process is not running. Exiting...")
|
398
|
-
return 1
|
399
|
-
if source_code_watcher is not None:
|
400
|
-
changed_files = source_code_watcher.get_all_changes()
|
401
|
-
# de-duplicate changes
|
402
|
-
changed_files = sorted(list(set(changed_files)))
|
403
|
-
if changed_files:
|
404
|
-
print(f"\nChanges detected in FastLED source code: {changed_files}")
|
405
|
-
print("Press space bar to trigger compile.")
|
406
|
-
|
407
|
-
space_key_watcher = SpaceBarWatcher()
|
408
|
-
try:
|
409
|
-
while True:
|
410
|
-
if space_key_watcher.space_bar_pressed():
|
411
|
-
print("Space bar pressed, triggering recompile...")
|
412
|
-
last_compiled_result = compile_function(
|
413
|
-
last_hash_value=None
|
414
|
-
)
|
415
|
-
print("Finished recompile.")
|
416
|
-
break
|
417
|
-
elif len(sketch_filewatcher.get_all_changes()) > 0:
|
418
|
-
last_compiled_result = compile_function(
|
419
|
-
last_hash_value=None
|
420
|
-
)
|
421
|
-
break
|
422
|
-
time.sleep(0.1)
|
423
|
-
finally:
|
424
|
-
space_key_watcher.stop()
|
425
|
-
|
426
|
-
except KeyboardInterrupt:
|
427
|
-
print("\nStopping watch mode...")
|
428
|
-
return 0
|
429
|
-
except Exception as e:
|
430
|
-
print(f"Error: {e}")
|
431
|
-
return 1
|
432
|
-
finally:
|
433
|
-
sketch_filewatcher.stop()
|
434
|
-
if compile_server:
|
435
|
-
compile_server.stop()
|
436
|
-
if browser_proc:
|
437
|
-
browser_proc.kill()
|
438
|
-
|
439
|
-
|
440
156
|
def run_server(args: argparse.Namespace) -> int:
|
441
157
|
interactive = args.interactive
|
442
158
|
auto_update = args.auto_update
|
@@ -465,7 +181,7 @@ def main() -> int:
|
|
465
181
|
return run_server(args)
|
466
182
|
else:
|
467
183
|
print("Running in client/server mode.")
|
468
|
-
return
|
184
|
+
return run_client_server(args)
|
469
185
|
|
470
186
|
|
471
187
|
if __name__ == "__main__":
|
fastled/client_server.py
ADDED
@@ -0,0 +1,299 @@
|
|
1
|
+
import argparse
|
2
|
+
import shutil
|
3
|
+
import subprocess
|
4
|
+
import tempfile
|
5
|
+
import time
|
6
|
+
from pathlib import Path
|
7
|
+
|
8
|
+
from fastled.build_mode import BuildMode, get_build_mode
|
9
|
+
from fastled.compile_server import CompileServer
|
10
|
+
from fastled.docker_manager import DockerManager
|
11
|
+
from fastled.env import DEFAULT_URL
|
12
|
+
from fastled.filewatcher import FileWatcherProcess
|
13
|
+
from fastled.keyboard import SpaceBarWatcher
|
14
|
+
from fastled.open_browser import open_browser_thread
|
15
|
+
from fastled.sketch import looks_like_sketch_directory
|
16
|
+
|
17
|
+
# CompiledResult
|
18
|
+
from fastled.types import CompiledResult
|
19
|
+
from fastled.web_compile import (
|
20
|
+
SERVER_PORT,
|
21
|
+
ConnectionResult,
|
22
|
+
find_good_connection,
|
23
|
+
web_compile,
|
24
|
+
)
|
25
|
+
|
26
|
+
|
27
|
+
def _run_web_compiler(
|
28
|
+
directory: Path,
|
29
|
+
host: str,
|
30
|
+
build_mode: BuildMode,
|
31
|
+
profile: bool,
|
32
|
+
last_hash_value: str | None,
|
33
|
+
) -> CompiledResult:
|
34
|
+
input_dir = Path(directory)
|
35
|
+
output_dir = input_dir / "fastled_js"
|
36
|
+
start = time.time()
|
37
|
+
web_result = web_compile(
|
38
|
+
directory=input_dir, host=host, build_mode=build_mode, profile=profile
|
39
|
+
)
|
40
|
+
diff = time.time() - start
|
41
|
+
if not web_result.success:
|
42
|
+
print("\nWeb compilation failed:")
|
43
|
+
print(f"Time taken: {diff:.2f} seconds")
|
44
|
+
print(web_result.stdout)
|
45
|
+
return CompiledResult(success=False, fastled_js="", hash_value=None)
|
46
|
+
|
47
|
+
def print_results() -> None:
|
48
|
+
hash_value = (
|
49
|
+
web_result.hash_value
|
50
|
+
if web_result.hash_value is not None
|
51
|
+
else "NO HASH VALUE"
|
52
|
+
)
|
53
|
+
print(
|
54
|
+
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"
|
55
|
+
)
|
56
|
+
|
57
|
+
# now check to see if the hash value is the same as the last hash value
|
58
|
+
if last_hash_value is not None and last_hash_value == web_result.hash_value:
|
59
|
+
print("\nSkipping redeploy: No significant changes found.")
|
60
|
+
print_results()
|
61
|
+
return CompiledResult(
|
62
|
+
success=True, fastled_js=str(output_dir), hash_value=web_result.hash_value
|
63
|
+
)
|
64
|
+
|
65
|
+
# Extract zip contents to fastled_js directory
|
66
|
+
output_dir.mkdir(exist_ok=True)
|
67
|
+
with tempfile.TemporaryDirectory() as temp_dir:
|
68
|
+
temp_path = Path(temp_dir)
|
69
|
+
temp_zip = temp_path / "result.zip"
|
70
|
+
temp_zip.write_bytes(web_result.zip_bytes)
|
71
|
+
|
72
|
+
# Clear existing contents
|
73
|
+
shutil.rmtree(output_dir, ignore_errors=True)
|
74
|
+
output_dir.mkdir(exist_ok=True)
|
75
|
+
|
76
|
+
# Extract zip contents
|
77
|
+
shutil.unpack_archive(temp_zip, output_dir, "zip")
|
78
|
+
|
79
|
+
print(web_result.stdout)
|
80
|
+
print_results()
|
81
|
+
return CompiledResult(
|
82
|
+
success=True, fastled_js=str(output_dir), hash_value=web_result.hash_value
|
83
|
+
)
|
84
|
+
|
85
|
+
|
86
|
+
def _try_start_server_or_get_url(args: argparse.Namespace) -> str | CompileServer:
|
87
|
+
auto_update = args.auto_update
|
88
|
+
is_local_host = "localhost" in args.web or "127.0.0.1" in args.web or args.localhost
|
89
|
+
# test to see if there is already a local host server
|
90
|
+
local_host_needs_server = False
|
91
|
+
if is_local_host:
|
92
|
+
addr = "localhost" if args.localhost else args.web
|
93
|
+
urls = [addr]
|
94
|
+
if ":" not in addr:
|
95
|
+
urls.append(f"{addr}:{SERVER_PORT}")
|
96
|
+
|
97
|
+
result: ConnectionResult | None = find_good_connection(urls)
|
98
|
+
if result is not None:
|
99
|
+
print(f"Found local server at {result.host}")
|
100
|
+
return result.host
|
101
|
+
else:
|
102
|
+
local_host_needs_server = True
|
103
|
+
|
104
|
+
if not local_host_needs_server and args.web:
|
105
|
+
if isinstance(args.web, str):
|
106
|
+
return args.web
|
107
|
+
if isinstance(args.web, bool):
|
108
|
+
return DEFAULT_URL
|
109
|
+
return args.web
|
110
|
+
else:
|
111
|
+
try:
|
112
|
+
print("No local server found, starting one...")
|
113
|
+
compile_server = CompileServer(auto_updates=auto_update)
|
114
|
+
print("Waiting for the local compiler to start...")
|
115
|
+
if not compile_server.wait_for_startup():
|
116
|
+
print("Failed to start local compiler.")
|
117
|
+
raise RuntimeError("Failed to start local compiler.")
|
118
|
+
return compile_server
|
119
|
+
except KeyboardInterrupt:
|
120
|
+
raise
|
121
|
+
except RuntimeError:
|
122
|
+
print("Failed to start local compile server, using web compiler instead.")
|
123
|
+
return DEFAULT_URL
|
124
|
+
|
125
|
+
|
126
|
+
def run_client_server(args: argparse.Namespace) -> int:
|
127
|
+
compile_server: CompileServer | None = None
|
128
|
+
open_web_browser = not args.just_compile and not args.interactive
|
129
|
+
profile = args.profile
|
130
|
+
if not args.force_compile and not looks_like_sketch_directory(Path(args.directory)):
|
131
|
+
print(
|
132
|
+
"Error: Not a valid FastLED sketch directory, if you are sure it is, use --force-compile"
|
133
|
+
)
|
134
|
+
return 1
|
135
|
+
|
136
|
+
# If not explicitly using web compiler, check Docker installation
|
137
|
+
if not args.web and not DockerManager.is_docker_installed():
|
138
|
+
print(
|
139
|
+
"\nDocker is not installed on this system - switching to web compiler instead."
|
140
|
+
)
|
141
|
+
args.web = True
|
142
|
+
|
143
|
+
url: str
|
144
|
+
try:
|
145
|
+
try:
|
146
|
+
url_or_server: str | CompileServer = _try_start_server_or_get_url(args)
|
147
|
+
if isinstance(url_or_server, str):
|
148
|
+
print(f"Found URL: {url_or_server}")
|
149
|
+
url = url_or_server
|
150
|
+
else:
|
151
|
+
compile_server = url_or_server
|
152
|
+
print(f"Server started at {compile_server.url()}")
|
153
|
+
url = compile_server.url()
|
154
|
+
except KeyboardInterrupt:
|
155
|
+
print("\nExiting from first try...")
|
156
|
+
if compile_server:
|
157
|
+
compile_server.stop()
|
158
|
+
return 1
|
159
|
+
except Exception as e:
|
160
|
+
print(f"Error: {e}")
|
161
|
+
return 1
|
162
|
+
build_mode: BuildMode = get_build_mode(args)
|
163
|
+
|
164
|
+
def compile_function(
|
165
|
+
url: str = url,
|
166
|
+
build_mode: BuildMode = build_mode,
|
167
|
+
profile: bool = profile,
|
168
|
+
last_hash_value: str | None = None,
|
169
|
+
) -> CompiledResult:
|
170
|
+
return _run_web_compiler(
|
171
|
+
args.directory,
|
172
|
+
host=url,
|
173
|
+
build_mode=build_mode,
|
174
|
+
profile=profile,
|
175
|
+
last_hash_value=last_hash_value,
|
176
|
+
)
|
177
|
+
|
178
|
+
result: CompiledResult = compile_function(last_hash_value=None)
|
179
|
+
last_compiled_result: CompiledResult = result
|
180
|
+
|
181
|
+
if not result.success:
|
182
|
+
print("\nCompilation failed.")
|
183
|
+
|
184
|
+
browser_proc: subprocess.Popen | None = None
|
185
|
+
if open_web_browser:
|
186
|
+
browser_proc = open_browser_thread(Path(args.directory) / "fastled_js")
|
187
|
+
else:
|
188
|
+
print("\nCompilation successful.")
|
189
|
+
if compile_server:
|
190
|
+
print("Shutting down compile server...")
|
191
|
+
compile_server.stop()
|
192
|
+
return 0
|
193
|
+
|
194
|
+
if args.just_compile:
|
195
|
+
if compile_server:
|
196
|
+
compile_server.stop()
|
197
|
+
if browser_proc:
|
198
|
+
browser_proc.kill()
|
199
|
+
return 0 if result.success else 1
|
200
|
+
except KeyboardInterrupt:
|
201
|
+
print("\nExiting from main")
|
202
|
+
if compile_server:
|
203
|
+
compile_server.stop()
|
204
|
+
return 1
|
205
|
+
|
206
|
+
sketch_filewatcher = FileWatcherProcess(
|
207
|
+
args.directory, excluded_patterns=["fastled_js"]
|
208
|
+
)
|
209
|
+
|
210
|
+
source_code_watcher: FileWatcherProcess | None = None
|
211
|
+
if compile_server and compile_server.using_fastled_src_dir_volume():
|
212
|
+
assert compile_server.fastled_src_dir is not None
|
213
|
+
source_code_watcher = FileWatcherProcess(
|
214
|
+
compile_server.fastled_src_dir, excluded_patterns=[]
|
215
|
+
)
|
216
|
+
|
217
|
+
def trigger_rebuild_if_sketch_changed(
|
218
|
+
last_compiled_result: CompiledResult,
|
219
|
+
) -> tuple[bool, CompiledResult]:
|
220
|
+
changed_files = sketch_filewatcher.get_all_changes()
|
221
|
+
if changed_files:
|
222
|
+
print(f"\nChanges detected in {changed_files}")
|
223
|
+
last_hash_value = last_compiled_result.hash_value
|
224
|
+
out = compile_function(last_hash_value=last_hash_value)
|
225
|
+
if not out.success:
|
226
|
+
print("\nRecompilation failed.")
|
227
|
+
else:
|
228
|
+
print("\nRecompilation successful.")
|
229
|
+
return True, out
|
230
|
+
return False, last_compiled_result
|
231
|
+
|
232
|
+
def print_status() -> None:
|
233
|
+
print("Will compile on sketch changes or if you hit the space bar.")
|
234
|
+
|
235
|
+
print_status()
|
236
|
+
print("Press Ctrl+C to stop...")
|
237
|
+
|
238
|
+
try:
|
239
|
+
while True:
|
240
|
+
if SpaceBarWatcher.watch_space_bar_pressed(timeout=1.0):
|
241
|
+
print("Compiling...")
|
242
|
+
last_compiled_result = compile_function(last_hash_value=None)
|
243
|
+
if not last_compiled_result.success:
|
244
|
+
print("\nRecompilation failed.")
|
245
|
+
else:
|
246
|
+
print("\nRecompilation successful.")
|
247
|
+
# drain the space bar queue
|
248
|
+
SpaceBarWatcher.watch_space_bar_pressed()
|
249
|
+
print_status()
|
250
|
+
continue
|
251
|
+
changed, last_compiled_result = trigger_rebuild_if_sketch_changed(
|
252
|
+
last_compiled_result
|
253
|
+
)
|
254
|
+
if changed:
|
255
|
+
print_status()
|
256
|
+
continue
|
257
|
+
if compile_server and not compile_server.proceess_running():
|
258
|
+
print("Server process is not running. Exiting...")
|
259
|
+
return 1
|
260
|
+
if source_code_watcher is not None:
|
261
|
+
changed_files = source_code_watcher.get_all_changes()
|
262
|
+
# de-duplicate changes
|
263
|
+
changed_files = sorted(list(set(changed_files)))
|
264
|
+
if changed_files:
|
265
|
+
print(f"\nChanges detected in FastLED source code: {changed_files}")
|
266
|
+
print("Press space bar to trigger compile.")
|
267
|
+
while True:
|
268
|
+
space_bar_pressed = SpaceBarWatcher.watch_space_bar_pressed(
|
269
|
+
timeout=1.0
|
270
|
+
)
|
271
|
+
file_had_changes = (
|
272
|
+
len(source_code_watcher.get_all_changes()) > 0
|
273
|
+
)
|
274
|
+
if space_bar_pressed or file_had_changes:
|
275
|
+
if space_bar_pressed:
|
276
|
+
print("Space bar pressed, triggering recompile...")
|
277
|
+
elif file_had_changes:
|
278
|
+
print("Changes detected, triggering recompile...")
|
279
|
+
last_compiled_result = compile_function(
|
280
|
+
last_hash_value=None
|
281
|
+
)
|
282
|
+
print("Finished recompile.")
|
283
|
+
# Drain the space bar queue
|
284
|
+
SpaceBarWatcher.watch_space_bar_pressed()
|
285
|
+
print_status()
|
286
|
+
continue
|
287
|
+
|
288
|
+
except KeyboardInterrupt:
|
289
|
+
print("\nStopping watch mode...")
|
290
|
+
return 0
|
291
|
+
except Exception as e:
|
292
|
+
print(f"Error: {e}")
|
293
|
+
return 1
|
294
|
+
finally:
|
295
|
+
sketch_filewatcher.stop()
|
296
|
+
if compile_server:
|
297
|
+
compile_server.stop()
|
298
|
+
if browser_proc:
|
299
|
+
browser_proc.kill()
|
fastled/env.py
ADDED
@@ -0,0 +1,8 @@
|
|
1
|
+
import os
|
2
|
+
import platform
|
3
|
+
|
4
|
+
MACHINE = platform.machine().lower()
|
5
|
+
IS_ARM: bool = "arm" in MACHINE or "aarch64" in MACHINE
|
6
|
+
PLATFORM_TAG: str = "-arm64" if IS_ARM else ""
|
7
|
+
CONTAINER_NAME = f"fastled-wasm-compiler{PLATFORM_TAG}"
|
8
|
+
DEFAULT_URL = str(os.environ.get("FASTLED_URL", "https://fastled.onrender.com"))
|
fastled/keyboard.py
CHANGED
@@ -5,8 +5,25 @@ import time
|
|
5
5
|
from multiprocessing import Process, Queue
|
6
6
|
from queue import Empty
|
7
7
|
|
8
|
+
_WHITE_SPACE = [" ", "\r", "\n"]
|
8
9
|
|
10
|
+
|
11
|
+
# Original space bar, but now also enter key.
|
9
12
|
class SpaceBarWatcher:
|
13
|
+
|
14
|
+
@classmethod
|
15
|
+
def watch_space_bar_pressed(cls, timeout: float = 0) -> bool:
|
16
|
+
watcher = cls()
|
17
|
+
try:
|
18
|
+
start_time = time.time()
|
19
|
+
while True:
|
20
|
+
if watcher.space_bar_pressed():
|
21
|
+
return True
|
22
|
+
if time.time() - start_time > timeout:
|
23
|
+
return False
|
24
|
+
finally:
|
25
|
+
watcher.stop()
|
26
|
+
|
10
27
|
def __init__(self) -> None:
|
11
28
|
self.queue: Queue = Queue()
|
12
29
|
self.queue_cancel: Queue = Queue()
|
@@ -31,7 +48,7 @@ class SpaceBarWatcher:
|
|
31
48
|
# Check if there's input ready
|
32
49
|
if msvcrt.kbhit(): # type: ignore
|
33
50
|
char = msvcrt.getch().decode() # type: ignore
|
34
|
-
if char
|
51
|
+
if char in _WHITE_SPACE:
|
35
52
|
self.queue.put(ord(" "))
|
36
53
|
|
37
54
|
else: # Unix-like systems
|
@@ -52,7 +69,7 @@ class SpaceBarWatcher:
|
|
52
69
|
# Check if there's input ready
|
53
70
|
if select.select([sys.stdin], [], [], 0.1)[0]:
|
54
71
|
char = sys.stdin.read(1)
|
55
|
-
if char
|
72
|
+
if char in _WHITE_SPACE:
|
56
73
|
self.queue.put(ord(" "))
|
57
74
|
finally:
|
58
75
|
termios.tcsetattr(fd, termios.TCSADRAIN, old_settings) # type: ignore
|
@@ -60,9 +77,12 @@ class SpaceBarWatcher:
|
|
60
77
|
def space_bar_pressed(self) -> bool:
|
61
78
|
found = False
|
62
79
|
while not self.queue.empty():
|
63
|
-
|
64
|
-
|
65
|
-
|
80
|
+
try:
|
81
|
+
key = self.queue.get(block=False, timeout=0.1)
|
82
|
+
if key == ord(" "):
|
83
|
+
found = True
|
84
|
+
except Empty:
|
85
|
+
break
|
66
86
|
return found
|
67
87
|
|
68
88
|
def stop(self) -> None:
|
fastled/types.py
ADDED
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.1
|
2
2
|
Name: fastled
|
3
|
-
Version: 1.1.
|
3
|
+
Version: 1.1.21
|
4
4
|
Summary: FastLED Wasm Compiler
|
5
5
|
Home-page: https://github.com/zackees/fastled-wasm
|
6
6
|
Maintainer: Zachary Vorhies
|
@@ -161,6 +161,7 @@ A: A big chunk of space is being used by unnecessary javascript `emscripten` is
|
|
161
161
|
|
162
162
|
# Revisions
|
163
163
|
|
164
|
+
* 1.1.21 - Now always watches for space/enter key events to trigger a recompile.
|
164
165
|
* 1.1.20 - Fixed a regression for 1.1.16 involving docker throwing an exception before DockerManager.is_running() could be called so it can be launched.
|
165
166
|
* 1.1.19 - Automatically does a limit searches for sketch directories if you leave it blank.
|
166
167
|
* 1.1.18 - Fixes for when the image has never been downloaded.
|
@@ -1,20 +1,23 @@
|
|
1
|
-
fastled/__init__.py,sha256=
|
2
|
-
fastled/app.py,sha256=
|
1
|
+
fastled/__init__.py,sha256=pOw5nbbJX94KgZRkQws_Mailvb2JN7Uvr39bN4PjGqk,64
|
2
|
+
fastled/app.py,sha256=ymCiVQjBGfqg7B_zFQmBIHFMD2SkDj1m_DzUNTbpOEw,6583
|
3
3
|
fastled/build_mode.py,sha256=joMwsV4K1y_LijT4gEAcjx69RZBoe_KmFmHZdPYbL_4,631
|
4
4
|
fastled/cli.py,sha256=CNR_pQR0sNVPNuv8e_nmm-0PI8sU-eUBUgnWgWkzW9c,237
|
5
|
+
fastled/client_server.py,sha256=TLEmCxafrcBzo9FAz3OlIIgsSbNpVGsSuvZnIXpHXBA,11090
|
5
6
|
fastled/compile_server.py,sha256=aBdpILSRrDsCJ5e9g5uwIqt9bcqE_8FrSddCV2ygtrI,5401
|
6
7
|
fastled/docker_manager.py,sha256=5IXaLt8k4WSSiWmvqMvwMYKngAgZ-t2p2deJ6cmJNwk,20434
|
8
|
+
fastled/env.py,sha256=8wctQwl5qE4CI8NBugHtgMmUfEfHZ869JX5lGdSOJxc,304
|
7
9
|
fastled/filewatcher.py,sha256=5dVmjEG23kMeJa29tRVm5XKSr9sTD4ME2boo-CFDuUM,6910
|
8
|
-
fastled/keyboard.py,sha256=
|
10
|
+
fastled/keyboard.py,sha256=TkFjDxGtGdDbjQF_LRqp54hmdcKaXjf1olTT8l6dEJk,3170
|
9
11
|
fastled/open_browser.py,sha256=RRHcsZ5Vzsw1AuZUEYuSfjKmf_9j3NGMDUR-FndHmqs,1483
|
10
12
|
fastled/paths.py,sha256=VsPmgu0lNSCFOoEC0BsTYzDygXqy15AHUfN-tTuzDZA,99
|
11
13
|
fastled/sketch.py,sha256=5nRjg281lMH8Bo9wKjbcpTQCfEP574ZCG-lukvFmyQ8,2656
|
14
|
+
fastled/types.py,sha256=dDIsGHJkHNJ7B61wNp6X0JSLs_nrHiq7RlNqNWbwFec,194
|
12
15
|
fastled/util.py,sha256=t4M3NFMhnCzfYbLvIyJi0RdFssZqbTN_vVIaej1WV-U,265
|
13
16
|
fastled/web_compile.py,sha256=KuvKGdX6SSUUqC7YgX4T9SMSP5wdcPUhpg9-K9zPoTI,10378
|
14
17
|
fastled/assets/example.txt,sha256=lTBovRjiz0_TgtAtbA1C5hNi2ffbqnNPqkKg6UiKCT8,54
|
15
|
-
fastled-1.1.
|
16
|
-
fastled-1.1.
|
17
|
-
fastled-1.1.
|
18
|
-
fastled-1.1.
|
19
|
-
fastled-1.1.
|
20
|
-
fastled-1.1.
|
18
|
+
fastled-1.1.21.dist-info/LICENSE,sha256=b6pOoifSXiUaz_lDS84vWlG3fr4yUKwB8fzkrH9R8bQ,1064
|
19
|
+
fastled-1.1.21.dist-info/METADATA,sha256=jsn8MyWpGA55L60pDAQ_Z1oHGVVJ51LGku8IzCG6f1g,13898
|
20
|
+
fastled-1.1.21.dist-info/WHEEL,sha256=0VNUDWQJzfRahYI3neAhz2UVbRCtztpN5dPHAGvmGXc,109
|
21
|
+
fastled-1.1.21.dist-info/entry_points.txt,sha256=RCwmzCSOS4-C2i9EziANq7Z2Zb4KFnEMR1FQC0bBwAw,101
|
22
|
+
fastled-1.1.21.dist-info/top_level.txt,sha256=xfG6Z_ol9V5YmBROkZq2QTRwjbS2ouCUxaTJsOwfkOo,14
|
23
|
+
fastled-1.1.21.dist-info/RECORD,,
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|