fastled 1.1.6__py2.py3-none-any.whl → 1.1.15__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 +3 -0
- fastled/app.py +133 -105
- fastled/compile_server.py +221 -264
- fastled/docker_manager.py +3 -1
- fastled/filewatcher.py +196 -146
- fastled/keyboard.py +91 -0
- fastled/open_browser.py +5 -1
- fastled/sketch.py +37 -0
- fastled/util.py +10 -0
- fastled/web_compile.py +299 -227
- fastled-1.1.15.dist-info/METADATA +195 -0
- fastled-1.1.15.dist-info/RECORD +20 -0
- fastled/check_cpp_syntax.py +0 -34
- fastled-1.1.6.dist-info/METADATA +0 -118
- fastled-1.1.6.dist-info/RECORD +0 -19
- {fastled-1.1.6.dist-info → fastled-1.1.15.dist-info}/LICENSE +0 -0
- {fastled-1.1.6.dist-info → fastled-1.1.15.dist-info}/WHEEL +0 -0
- {fastled-1.1.6.dist-info → fastled-1.1.15.dist-info}/entry_points.txt +0 -0
- {fastled-1.1.6.dist-info → fastled-1.1.15.dist-info}/top_level.txt +0 -0
fastled/__init__.py
CHANGED
fastled/app.py
CHANGED
@@ -1,7 +1,5 @@
|
|
1
1
|
"""
|
2
2
|
Uses the latest wasm compiler image to compile the FastLED sketch.
|
3
|
-
|
4
|
-
|
5
3
|
"""
|
6
4
|
|
7
5
|
import argparse
|
@@ -15,13 +13,20 @@ import time
|
|
15
13
|
from dataclasses import dataclass
|
16
14
|
from pathlib import Path
|
17
15
|
|
16
|
+
from fastled import __version__
|
18
17
|
from fastled.build_mode import BuildMode, get_build_mode
|
19
|
-
from fastled.compile_server import CompileServer
|
18
|
+
from fastled.compile_server import CompileServer
|
20
19
|
from fastled.docker_manager import DockerManager
|
21
|
-
from fastled.filewatcher import
|
20
|
+
from fastled.filewatcher import FileWatcherProcess
|
21
|
+
from fastled.keyboard import SpaceBarWatcher
|
22
22
|
from fastled.open_browser import open_browser_thread
|
23
|
-
from fastled.sketch import
|
24
|
-
from fastled.web_compile import
|
23
|
+
from fastled.sketch import looks_like_fastled_repo, looks_like_sketch_directory
|
24
|
+
from fastled.web_compile import (
|
25
|
+
SERVER_PORT,
|
26
|
+
ConnectionResult,
|
27
|
+
find_good_connection,
|
28
|
+
web_compile,
|
29
|
+
)
|
25
30
|
|
26
31
|
machine = platform.machine().lower()
|
27
32
|
IS_ARM: bool = "arm" in machine or "aarch64" in machine
|
@@ -44,12 +49,15 @@ DOCKER = DockerManager(container_name=CONTAINER_NAME)
|
|
44
49
|
|
45
50
|
def parse_args() -> argparse.Namespace:
|
46
51
|
"""Parse command-line arguments."""
|
47
|
-
parser = argparse.ArgumentParser(description="FastLED WASM Compiler")
|
52
|
+
parser = argparse.ArgumentParser(description=f"FastLED WASM Compiler {__version__}")
|
53
|
+
parser.add_argument(
|
54
|
+
"--version", action="version", version=f"%(prog)s {__version__}"
|
55
|
+
)
|
48
56
|
parser.add_argument(
|
49
57
|
"directory",
|
50
58
|
type=str,
|
51
59
|
nargs="?",
|
52
|
-
default=
|
60
|
+
default=None,
|
53
61
|
help="Directory containing the FastLED sketch to compile",
|
54
62
|
)
|
55
63
|
parser.add_argument(
|
@@ -57,11 +65,6 @@ def parse_args() -> argparse.Namespace:
|
|
57
65
|
action="store_true",
|
58
66
|
help="Just compile, skip opening the browser and watching for changes.",
|
59
67
|
)
|
60
|
-
parser.add_argument(
|
61
|
-
"--no-auto-clean",
|
62
|
-
action="store_true",
|
63
|
-
help="Big performance gains for compilation, but it's flaky at this time",
|
64
|
-
)
|
65
68
|
parser.add_argument(
|
66
69
|
"--web",
|
67
70
|
"-w",
|
@@ -71,17 +74,6 @@ def parse_args() -> argparse.Namespace:
|
|
71
74
|
const=DEFAULT_URL, # Default value when --web is specified without value
|
72
75
|
help="Use web compiler. Optional URL can be provided (default: https://fastled.onrender.com)",
|
73
76
|
)
|
74
|
-
parser.add_argument(
|
75
|
-
"--reuse",
|
76
|
-
action="store_true",
|
77
|
-
help="Reuse the existing container if it exists. (Not available with --web)",
|
78
|
-
)
|
79
|
-
parser.add_argument(
|
80
|
-
"--exclude",
|
81
|
-
type=str,
|
82
|
-
nargs="+",
|
83
|
-
help="Additional patterns to exclude from file watching (Not available with --web)",
|
84
|
-
)
|
85
77
|
parser.add_argument(
|
86
78
|
"-i",
|
87
79
|
"--interactive",
|
@@ -104,6 +96,12 @@ def parse_args() -> argparse.Namespace:
|
|
104
96
|
build_mode.add_argument(
|
105
97
|
"--release", action="store_true", help="Build in release mode"
|
106
98
|
)
|
99
|
+
build_mode.add_argument(
|
100
|
+
"--localhost",
|
101
|
+
"--local",
|
102
|
+
action="store_true",
|
103
|
+
help="Use localhost for web compilation from an instance of fastled --server, creating it if necessary",
|
104
|
+
)
|
107
105
|
build_mode.add_argument(
|
108
106
|
"--server",
|
109
107
|
action="store_true",
|
@@ -116,14 +114,30 @@ def parse_args() -> argparse.Namespace:
|
|
116
114
|
help="Skips the test to see if the current directory is a valid FastLED sketch directory",
|
117
115
|
)
|
118
116
|
|
119
|
-
|
117
|
+
cwd_is_fastled = looks_like_fastled_repo(Path(os.getcwd()))
|
120
118
|
|
121
|
-
|
122
|
-
if args.web:
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
119
|
+
args = parser.parse_args()
|
120
|
+
if not cwd_is_fastled and not args.localhost and not args.web and not args.server:
|
121
|
+
print(f"Using web compiler at {DEFAULT_URL}")
|
122
|
+
args.web = DEFAULT_URL
|
123
|
+
if cwd_is_fastled and not args.web:
|
124
|
+
print("Forcing --local mode because we are in the FastLED repo")
|
125
|
+
args.localhost = True
|
126
|
+
if args.localhost:
|
127
|
+
args.web = "localhost"
|
128
|
+
if args.interactive and not args.server:
|
129
|
+
print("--interactive forces --server mode")
|
130
|
+
args.server = True
|
131
|
+
if args.directory is None and not args.server:
|
132
|
+
# does current directory look like a sketch?
|
133
|
+
maybe_sketch_dir = Path(os.getcwd())
|
134
|
+
if looks_like_sketch_directory(maybe_sketch_dir):
|
135
|
+
args.directory = str(maybe_sketch_dir)
|
136
|
+
else:
|
137
|
+
print(
|
138
|
+
"\nYou either need to specify a sketch directory or run in --server mode."
|
139
|
+
)
|
140
|
+
sys.exit(1)
|
127
141
|
|
128
142
|
return args
|
129
143
|
|
@@ -188,16 +202,33 @@ def run_web_compiler(
|
|
188
202
|
|
189
203
|
|
190
204
|
def _try_start_server_or_get_url(args: argparse.Namespace) -> str | CompileServer:
|
191
|
-
|
205
|
+
is_local_host = "localhost" in args.web or "127.0.0.1" in args.web or args.localhost
|
206
|
+
|
207
|
+
# test to see if there is already a local host server
|
208
|
+
local_host_needs_server = False
|
209
|
+
if is_local_host:
|
210
|
+
addr = "localhost" if args.localhost else args.web
|
211
|
+
urls = [addr]
|
212
|
+
if ":" not in addr:
|
213
|
+
urls.append(f"{addr}:{SERVER_PORT}")
|
214
|
+
|
215
|
+
result: ConnectionResult | None = find_good_connection(urls)
|
216
|
+
if result is not None:
|
217
|
+
print(f"Found local server at {result.host}")
|
218
|
+
return result.host
|
219
|
+
else:
|
220
|
+
local_host_needs_server = True
|
221
|
+
|
222
|
+
if not local_host_needs_server and args.web:
|
192
223
|
if isinstance(args.web, str):
|
193
224
|
return args.web
|
194
225
|
if isinstance(args.web, bool):
|
195
226
|
return DEFAULT_URL
|
196
227
|
return args.web
|
197
228
|
else:
|
198
|
-
disable_auto_clean = args.no_auto_clean
|
199
229
|
try:
|
200
|
-
|
230
|
+
print("No local server found, starting one...")
|
231
|
+
compile_server = CompileServer()
|
201
232
|
print("Waiting for the local compiler to start...")
|
202
233
|
if not compile_server.wait_for_startup():
|
203
234
|
print("Failed to start local compiler.")
|
@@ -210,42 +241,11 @@ def _try_start_server_or_get_url(args: argparse.Namespace) -> str | CompileServe
|
|
210
241
|
return DEFAULT_URL
|
211
242
|
|
212
243
|
|
213
|
-
def _lots_and_lots_of_files(directory: Path) -> bool:
|
214
|
-
return len(get_sketch_files(directory)) > 100
|
215
|
-
|
216
|
-
|
217
|
-
def _looks_like_sketch_directory(directory: Path) -> bool:
|
218
|
-
if looks_like_fastled_repo(directory):
|
219
|
-
print("Directory looks like the FastLED repo")
|
220
|
-
return False
|
221
|
-
|
222
|
-
if _lots_and_lots_of_files(directory):
|
223
|
-
print("Too many files in the directory, bailing out")
|
224
|
-
return False
|
225
|
-
|
226
|
-
# walk the path and if there are over 30 files, return False
|
227
|
-
# at the root of the directory there should either be an ino file or a src directory
|
228
|
-
# or some cpp files
|
229
|
-
# if there is a platformio.ini file, return True
|
230
|
-
ino_file_at_root = list(directory.glob("*.ino"))
|
231
|
-
if ino_file_at_root:
|
232
|
-
return True
|
233
|
-
cpp_file_at_root = list(directory.glob("*.cpp"))
|
234
|
-
if cpp_file_at_root:
|
235
|
-
return True
|
236
|
-
platformini_file = list(directory.glob("platformio.ini"))
|
237
|
-
if platformini_file:
|
238
|
-
return True
|
239
|
-
return False
|
240
|
-
|
241
|
-
|
242
244
|
def run_client(args: argparse.Namespace) -> int:
|
243
245
|
compile_server: CompileServer | None = None
|
244
|
-
open_web_browser = not args.just_compile
|
246
|
+
open_web_browser = not args.just_compile and not args.interactive
|
245
247
|
profile = args.profile
|
246
|
-
if not args.force_compile and not
|
247
|
-
Path(args.directory)
|
248
|
-
):
|
248
|
+
if not args.force_compile and not looks_like_sketch_directory(Path(args.directory)):
|
249
249
|
print(
|
250
250
|
"Error: Not a valid FastLED sketch directory, if you are sure it is, use --force-compile"
|
251
251
|
)
|
@@ -324,40 +324,76 @@ def run_client(args: argparse.Namespace) -> int:
|
|
324
324
|
compile_server.stop()
|
325
325
|
return 1
|
326
326
|
|
327
|
-
# Watch mode
|
328
327
|
print("\nWatching for changes. Press Ctrl+C to stop...")
|
329
|
-
|
330
|
-
|
328
|
+
sketch_filewatcher = FileWatcherProcess(
|
329
|
+
args.directory, excluded_patterns=["fastled_js"]
|
330
|
+
)
|
331
|
+
|
332
|
+
source_code_watcher: FileWatcherProcess | None = None
|
333
|
+
if compile_server and compile_server.using_fastled_src_dir_volume():
|
334
|
+
assert compile_server.fastled_src_dir is not None
|
335
|
+
source_code_watcher = FileWatcherProcess(
|
336
|
+
compile_server.fastled_src_dir, excluded_patterns=[]
|
337
|
+
)
|
338
|
+
|
339
|
+
def trigger_rebuild_if_sketch_changed(
|
340
|
+
last_compiled_result: CompiledResult,
|
341
|
+
) -> CompiledResult:
|
342
|
+
changed_files = sketch_filewatcher.get_all_changes()
|
343
|
+
if changed_files:
|
344
|
+
print(f"\nChanges detected in {changed_files}")
|
345
|
+
last_hash_value = last_compiled_result.hash_value
|
346
|
+
out = compile_function(last_hash_value=last_hash_value)
|
347
|
+
if not out.success:
|
348
|
+
print("\nRecompilation failed.")
|
349
|
+
else:
|
350
|
+
print("\nRecompilation successful.")
|
351
|
+
return out
|
352
|
+
return last_compiled_result
|
331
353
|
|
332
354
|
try:
|
333
355
|
while True:
|
334
|
-
|
335
|
-
|
336
|
-
|
337
|
-
|
338
|
-
|
339
|
-
|
340
|
-
|
341
|
-
changed_files =
|
342
|
-
|
343
|
-
|
344
|
-
|
345
|
-
|
346
|
-
|
347
|
-
|
348
|
-
|
349
|
-
|
350
|
-
|
356
|
+
last_compiled_result = trigger_rebuild_if_sketch_changed(
|
357
|
+
last_compiled_result
|
358
|
+
)
|
359
|
+
if compile_server and not compile_server.proceess_running():
|
360
|
+
print("Server process is not running. Exiting...")
|
361
|
+
return 1
|
362
|
+
if source_code_watcher is not None:
|
363
|
+
changed_files = source_code_watcher.get_all_changes()
|
364
|
+
# de-duplicate changes
|
365
|
+
changed_files = sorted(list(set(changed_files)))
|
366
|
+
if changed_files:
|
367
|
+
print(f"\nChanges detected in FastLED source code: {changed_files}")
|
368
|
+
print("Press space bar to trigger compile.")
|
369
|
+
|
370
|
+
space_key_watcher = SpaceBarWatcher()
|
371
|
+
try:
|
372
|
+
while True:
|
373
|
+
if space_key_watcher.space_bar_pressed():
|
374
|
+
print("Space bar pressed, triggering recompile...")
|
375
|
+
last_compiled_result = compile_function(
|
376
|
+
last_hash_value=None
|
377
|
+
)
|
378
|
+
print("Finished recompile.")
|
379
|
+
break
|
380
|
+
elif len(sketch_filewatcher.get_all_changes()) > 0:
|
381
|
+
last_compiled_result = compile_function(
|
382
|
+
last_hash_value=None
|
383
|
+
)
|
384
|
+
break
|
385
|
+
time.sleep(0.1)
|
386
|
+
finally:
|
387
|
+
space_key_watcher.stop()
|
388
|
+
|
351
389
|
except KeyboardInterrupt:
|
352
|
-
watcher.stop()
|
353
390
|
print("\nStopping watch mode...")
|
354
391
|
return 0
|
355
392
|
except Exception as e:
|
356
|
-
watcher.stop()
|
357
393
|
print(f"Error: {e}")
|
358
394
|
return 1
|
359
395
|
finally:
|
360
|
-
|
396
|
+
sketch_filewatcher.stop()
|
361
397
|
if compile_server:
|
362
398
|
compile_server.stop()
|
363
399
|
if browser_proc:
|
@@ -366,11 +402,9 @@ def run_client(args: argparse.Namespace) -> int:
|
|
366
402
|
|
367
403
|
def run_server(args: argparse.Namespace) -> int:
|
368
404
|
interactive = args.interactive
|
369
|
-
compile_server = CompileServer(
|
370
|
-
|
371
|
-
|
372
|
-
print(f"Server started at {compile_server.url()}")
|
373
|
-
compile_server.start()
|
405
|
+
compile_server = CompileServer(interactive=interactive)
|
406
|
+
if not interactive:
|
407
|
+
print(f"Server started at {compile_server.url()}")
|
374
408
|
compile_server.wait_for_startup()
|
375
409
|
try:
|
376
410
|
while True:
|
@@ -388,13 +422,7 @@ def run_server(args: argparse.Namespace) -> int:
|
|
388
422
|
|
389
423
|
def main() -> int:
|
390
424
|
args = parse_args()
|
391
|
-
|
392
|
-
cwd_is_target_dir = target_dir == Path(os.getcwd())
|
393
|
-
force_server = cwd_is_target_dir and looks_like_fastled_repo(target_dir)
|
394
|
-
auto_server = (args.server or args.interactive or cwd_is_target_dir) and (
|
395
|
-
not args.web and not args.just_compile
|
396
|
-
)
|
397
|
-
if auto_server or force_server:
|
425
|
+
if args.server:
|
398
426
|
print("Running in server only mode.")
|
399
427
|
return run_server(args)
|
400
428
|
else:
|
@@ -404,9 +432,9 @@ def main() -> int:
|
|
404
432
|
|
405
433
|
if __name__ == "__main__":
|
406
434
|
try:
|
407
|
-
|
408
|
-
sys.argv.append("
|
409
|
-
sys.argv.append("localhost")
|
435
|
+
# os.chdir("../fastled")
|
436
|
+
sys.argv.append("examples/SdCard")
|
437
|
+
sys.argv.append("--localhost")
|
410
438
|
sys.exit(main())
|
411
439
|
except KeyboardInterrupt:
|
412
440
|
print("\nExiting from main...")
|