fastled 1.0.15__py2.py3-none-any.whl → 1.1.0__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 +0 -3
- fastled/app.py +82 -160
- fastled/check_cpp_syntax.py +34 -0
- fastled/compile_server.py +207 -221
- fastled/docker_manager.py +7 -11
- fastled/filewatcher.py +146 -196
- fastled/open_browser.py +1 -5
- fastled/web_compile.py +173 -291
- fastled-1.1.0.dist-info/METADATA +113 -0
- fastled-1.1.0.dist-info/RECORD +18 -0
- fastled/keyboard.py +0 -91
- fastled/sketch.py +0 -55
- fastled/util.py +0 -10
- fastled-1.0.15.dist-info/METADATA +0 -196
- fastled-1.0.15.dist-info/RECORD +0 -20
- {fastled-1.0.15.dist-info → fastled-1.1.0.dist-info}/LICENSE +0 -0
- {fastled-1.0.15.dist-info → fastled-1.1.0.dist-info}/WHEEL +0 -0
- {fastled-1.0.15.dist-info → fastled-1.1.0.dist-info}/entry_points.txt +0 -0
- {fastled-1.0.15.dist-info → fastled-1.1.0.dist-info}/top_level.txt +0 -0
fastled/__init__.py
CHANGED
fastled/app.py
CHANGED
@@ -1,5 +1,7 @@
|
|
1
1
|
"""
|
2
2
|
Uses the latest wasm compiler image to compile the FastLED sketch.
|
3
|
+
|
4
|
+
|
3
5
|
"""
|
4
6
|
|
5
7
|
import argparse
|
@@ -13,15 +15,12 @@ import time
|
|
13
15
|
from dataclasses import dataclass
|
14
16
|
from pathlib import Path
|
15
17
|
|
16
|
-
from fastled import __version__
|
17
18
|
from fastled.build_mode import BuildMode, get_build_mode
|
18
19
|
from fastled.compile_server import CompileServer
|
19
20
|
from fastled.docker_manager import DockerManager
|
20
|
-
from fastled.filewatcher import
|
21
|
-
from fastled.keyboard import SpaceBarWatcher
|
21
|
+
from fastled.filewatcher import FileChangedNotifier
|
22
22
|
from fastled.open_browser import open_browser_thread
|
23
|
-
from fastled.
|
24
|
-
from fastled.web_compile import ConnectionResult, find_good_connection, web_compile
|
23
|
+
from fastled.web_compile import web_compile
|
25
24
|
|
26
25
|
machine = platform.machine().lower()
|
27
26
|
IS_ARM: bool = "arm" in machine or "aarch64" in machine
|
@@ -44,15 +43,12 @@ DOCKER = DockerManager(container_name=CONTAINER_NAME)
|
|
44
43
|
|
45
44
|
def parse_args() -> argparse.Namespace:
|
46
45
|
"""Parse command-line arguments."""
|
47
|
-
parser = argparse.ArgumentParser(description=
|
48
|
-
parser.add_argument(
|
49
|
-
"--version", action="version", version=f"%(prog)s {__version__}"
|
50
|
-
)
|
46
|
+
parser = argparse.ArgumentParser(description="FastLED WASM Compiler")
|
51
47
|
parser.add_argument(
|
52
48
|
"directory",
|
53
49
|
type=str,
|
54
50
|
nargs="?",
|
55
|
-
default=
|
51
|
+
default=os.getcwd(),
|
56
52
|
help="Directory containing the FastLED sketch to compile",
|
57
53
|
)
|
58
54
|
parser.add_argument(
|
@@ -60,6 +56,11 @@ def parse_args() -> argparse.Namespace:
|
|
60
56
|
action="store_true",
|
61
57
|
help="Just compile, skip opening the browser and watching for changes.",
|
62
58
|
)
|
59
|
+
parser.add_argument(
|
60
|
+
"--no-auto-clean",
|
61
|
+
action="store_true",
|
62
|
+
help="Big performance gains for compilation, but it's flaky at this time",
|
63
|
+
)
|
63
64
|
parser.add_argument(
|
64
65
|
"--web",
|
65
66
|
"-w",
|
@@ -70,10 +71,15 @@ def parse_args() -> argparse.Namespace:
|
|
70
71
|
help="Use web compiler. Optional URL can be provided (default: https://fastled.onrender.com)",
|
71
72
|
)
|
72
73
|
parser.add_argument(
|
73
|
-
"
|
74
|
-
"--interactive",
|
74
|
+
"--reuse",
|
75
75
|
action="store_true",
|
76
|
-
help="
|
76
|
+
help="Reuse the existing container if it exists. (Not available with --web)",
|
77
|
+
)
|
78
|
+
parser.add_argument(
|
79
|
+
"--exclude",
|
80
|
+
type=str,
|
81
|
+
nargs="+",
|
82
|
+
help="Additional patterns to exclude from file watching (Not available with --web)",
|
77
83
|
)
|
78
84
|
parser.add_argument(
|
79
85
|
"--profile",
|
@@ -91,17 +97,6 @@ def parse_args() -> argparse.Namespace:
|
|
91
97
|
build_mode.add_argument(
|
92
98
|
"--release", action="store_true", help="Build in release mode"
|
93
99
|
)
|
94
|
-
build_mode.add_argument(
|
95
|
-
"--localhost",
|
96
|
-
"--local",
|
97
|
-
action="store_true",
|
98
|
-
help="Use localhost for web compilation from an instance of fastled --server, creating it if necessary",
|
99
|
-
)
|
100
|
-
build_mode.add_argument(
|
101
|
-
"--server",
|
102
|
-
action="store_true",
|
103
|
-
help="Run the server in the current directory, volume mapping fastled if we are in the repo",
|
104
|
-
)
|
105
100
|
|
106
101
|
build_mode.add_argument(
|
107
102
|
"--force-compile",
|
@@ -109,30 +104,14 @@ def parse_args() -> argparse.Namespace:
|
|
109
104
|
help="Skips the test to see if the current directory is a valid FastLED sketch directory",
|
110
105
|
)
|
111
106
|
|
112
|
-
cwd_is_fastled = looks_like_fastled_repo(Path(os.getcwd()))
|
113
|
-
|
114
107
|
args = parser.parse_args()
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
args.
|
121
|
-
|
122
|
-
args.web = "localhost"
|
123
|
-
if args.interactive and not args.server:
|
124
|
-
print("--interactive forces --server mode")
|
125
|
-
args.server = True
|
126
|
-
if args.directory is None and not args.server:
|
127
|
-
# does current directory look like a sketch?
|
128
|
-
maybe_sketch_dir = Path(os.getcwd())
|
129
|
-
if looks_like_sketch_directory(maybe_sketch_dir):
|
130
|
-
args.directory = str(maybe_sketch_dir)
|
131
|
-
else:
|
132
|
-
print(
|
133
|
-
"\nYou either need to specify a sketch directory or run in --server mode."
|
134
|
-
)
|
135
|
-
sys.exit(1)
|
108
|
+
|
109
|
+
# Handle --web implications
|
110
|
+
if args.web:
|
111
|
+
if args.reuse:
|
112
|
+
parser.error("--reuse cannot be used with --web")
|
113
|
+
if args.exclude:
|
114
|
+
parser.error("--exclude cannot be used with --web")
|
136
115
|
|
137
116
|
return args
|
138
117
|
|
@@ -169,7 +148,9 @@ def run_web_compiler(
|
|
169
148
|
|
170
149
|
# now check to see if the hash value is the same as the last hash value
|
171
150
|
if last_hash_value is not None and last_hash_value == web_result.hash_value:
|
172
|
-
print(
|
151
|
+
print(
|
152
|
+
"\nNo significant source code changes detected and data was the same, skipping recompilation."
|
153
|
+
)
|
173
154
|
print_results()
|
174
155
|
return CompiledResult(
|
175
156
|
success=True, fastled_js=str(output_dir), hash_value=web_result.hash_value
|
@@ -197,29 +178,16 @@ def run_web_compiler(
|
|
197
178
|
|
198
179
|
|
199
180
|
def _try_start_server_or_get_url(args: argparse.Namespace) -> str | CompileServer:
|
200
|
-
|
201
|
-
|
202
|
-
# test to see if there is already a local host server
|
203
|
-
local_host_needs_server = False
|
204
|
-
if is_local_host:
|
205
|
-
addr = "localhost" if args.localhost else args.web
|
206
|
-
result: ConnectionResult | None = find_good_connection([addr])
|
207
|
-
if result is not None:
|
208
|
-
print(f"Found local server at {result.host}")
|
209
|
-
return result.host
|
210
|
-
else:
|
211
|
-
local_host_needs_server = True
|
212
|
-
|
213
|
-
if not local_host_needs_server and args.web:
|
181
|
+
if args.web:
|
214
182
|
if isinstance(args.web, str):
|
215
183
|
return args.web
|
216
184
|
if isinstance(args.web, bool):
|
217
185
|
return DEFAULT_URL
|
218
186
|
return args.web
|
219
187
|
else:
|
188
|
+
disable_auto_clean = args.no_auto_clean
|
220
189
|
try:
|
221
|
-
|
222
|
-
compile_server = CompileServer()
|
190
|
+
compile_server = CompileServer(disable_auto_clean=disable_auto_clean)
|
223
191
|
print("Waiting for the local compiler to start...")
|
224
192
|
if not compile_server.wait_for_startup():
|
225
193
|
print("Failed to start local compiler.")
|
@@ -232,11 +200,31 @@ def _try_start_server_or_get_url(args: argparse.Namespace) -> str | CompileServe
|
|
232
200
|
return DEFAULT_URL
|
233
201
|
|
234
202
|
|
235
|
-
def
|
236
|
-
|
237
|
-
|
203
|
+
def _looks_like_sketch_directory(directory: Path) -> bool:
|
204
|
+
# walk the path and if there are over 30 files, return False
|
205
|
+
# at the root of the directory there should either be an ino file or a src directory
|
206
|
+
# or some cpp files
|
207
|
+
# if there is a platformio.ini file, return True
|
208
|
+
ino_file_at_root = list(directory.glob("*.ino"))
|
209
|
+
if ino_file_at_root:
|
210
|
+
return True
|
211
|
+
cpp_file_at_root = list(directory.glob("*.cpp"))
|
212
|
+
if cpp_file_at_root:
|
213
|
+
return True
|
214
|
+
platformini_file = list(directory.glob("platformio.ini"))
|
215
|
+
if platformini_file:
|
216
|
+
return True
|
217
|
+
return False
|
218
|
+
|
219
|
+
|
220
|
+
def main() -> int:
|
221
|
+
args = parse_args()
|
222
|
+
open_web_browser = not args.just_compile
|
238
223
|
profile = args.profile
|
239
|
-
|
224
|
+
|
225
|
+
if not args.force_compile and not _looks_like_sketch_directory(
|
226
|
+
Path(args.directory)
|
227
|
+
):
|
240
228
|
print(
|
241
229
|
"Error: Not a valid FastLED sketch directory, if you are sure it is, use --force-compile"
|
242
230
|
)
|
@@ -249,16 +237,16 @@ def run_client(args: argparse.Namespace) -> int:
|
|
249
237
|
)
|
250
238
|
args.web = True
|
251
239
|
|
240
|
+
compile_server: CompileServer | None = None
|
252
241
|
url: str
|
242
|
+
|
253
243
|
try:
|
254
244
|
try:
|
255
245
|
url_or_server: str | CompileServer = _try_start_server_or_get_url(args)
|
256
246
|
if isinstance(url_or_server, str):
|
257
|
-
print(f"Found URL: {url_or_server}")
|
258
247
|
url = url_or_server
|
259
248
|
else:
|
260
249
|
compile_server = url_or_server
|
261
|
-
print(f"Server started at {compile_server.url()}")
|
262
250
|
url = compile_server.url()
|
263
251
|
except KeyboardInterrupt:
|
264
252
|
print("\nExiting from first try...")
|
@@ -315,115 +303,49 @@ def run_client(args: argparse.Namespace) -> int:
|
|
315
303
|
compile_server.stop()
|
316
304
|
return 1
|
317
305
|
|
306
|
+
# Watch mode
|
318
307
|
print("\nWatching for changes. Press Ctrl+C to stop...")
|
319
|
-
|
320
|
-
|
321
|
-
)
|
322
|
-
|
323
|
-
source_code_watcher: FileWatcherProcess | None = None
|
324
|
-
if compile_server and compile_server.using_fastled_src_dir_volume():
|
325
|
-
assert compile_server.fastled_src_dir is not None
|
326
|
-
source_code_watcher = FileWatcherProcess(
|
327
|
-
compile_server.fastled_src_dir, excluded_patterns=[]
|
328
|
-
)
|
329
|
-
|
330
|
-
def trigger_rebuild_if_sketch_changed(
|
331
|
-
last_compiled_result: CompiledResult,
|
332
|
-
) -> CompiledResult:
|
333
|
-
changed_files = sketch_filewatcher.get_all_changes()
|
334
|
-
if changed_files:
|
335
|
-
print(f"\nChanges detected in {changed_files}")
|
336
|
-
last_hash_value = last_compiled_result.hash_value
|
337
|
-
out = compile_function(last_hash_value=last_hash_value)
|
338
|
-
if not out.success:
|
339
|
-
print("\nRecompilation failed.")
|
340
|
-
else:
|
341
|
-
print("\nRecompilation successful.")
|
342
|
-
return out
|
343
|
-
return last_compiled_result
|
308
|
+
watcher = FileChangedNotifier(args.directory, excluded_patterns=["fastled_js"])
|
309
|
+
watcher.start()
|
344
310
|
|
345
311
|
try:
|
346
312
|
while True:
|
347
|
-
|
348
|
-
|
349
|
-
|
350
|
-
|
351
|
-
|
352
|
-
|
353
|
-
|
354
|
-
changed_files =
|
355
|
-
|
356
|
-
|
357
|
-
|
358
|
-
|
359
|
-
|
360
|
-
|
361
|
-
|
362
|
-
|
363
|
-
|
364
|
-
last_compiled_result = compile_function(
|
365
|
-
last_hash_value=None
|
366
|
-
)
|
367
|
-
print("Finished recompile.")
|
368
|
-
break
|
369
|
-
elif len(sketch_filewatcher.get_all_changes()) > 0:
|
370
|
-
last_compiled_result = compile_function(
|
371
|
-
last_hash_value=None
|
372
|
-
)
|
373
|
-
break
|
374
|
-
time.sleep(0.1)
|
375
|
-
finally:
|
376
|
-
space_key_watcher.stop()
|
377
|
-
|
313
|
+
try:
|
314
|
+
changed_files = watcher.get_all_changes()
|
315
|
+
except KeyboardInterrupt:
|
316
|
+
print("\nExiting from watcher...")
|
317
|
+
raise
|
318
|
+
except Exception as e:
|
319
|
+
print(f"Error getting changes: {e}")
|
320
|
+
changed_files = []
|
321
|
+
if changed_files:
|
322
|
+
print(f"\nChanges detected in {changed_files}")
|
323
|
+
last_hash_value = last_compiled_result.hash_value
|
324
|
+
result = compile_function(last_hash_value=last_hash_value)
|
325
|
+
if not result.success:
|
326
|
+
print("\nRecompilation failed.")
|
327
|
+
else:
|
328
|
+
print("\nRecompilation successful.")
|
329
|
+
time.sleep(0.3)
|
378
330
|
except KeyboardInterrupt:
|
331
|
+
watcher.stop()
|
379
332
|
print("\nStopping watch mode...")
|
380
333
|
return 0
|
381
334
|
except Exception as e:
|
335
|
+
watcher.stop()
|
382
336
|
print(f"Error: {e}")
|
383
337
|
return 1
|
384
338
|
finally:
|
385
|
-
|
339
|
+
watcher.stop()
|
386
340
|
if compile_server:
|
387
341
|
compile_server.stop()
|
388
342
|
if browser_proc:
|
389
343
|
browser_proc.kill()
|
390
344
|
|
391
345
|
|
392
|
-
def run_server(args: argparse.Namespace) -> int:
|
393
|
-
interactive = args.interactive
|
394
|
-
compile_server = CompileServer(interactive=interactive)
|
395
|
-
if not interactive:
|
396
|
-
print(f"Server started at {compile_server.url()}")
|
397
|
-
compile_server.wait_for_startup()
|
398
|
-
try:
|
399
|
-
while True:
|
400
|
-
if not compile_server.proceess_running():
|
401
|
-
print("Server process is not running. Exiting...")
|
402
|
-
return 1
|
403
|
-
time.sleep(1)
|
404
|
-
except KeyboardInterrupt:
|
405
|
-
print("\nExiting from server...")
|
406
|
-
return 1
|
407
|
-
finally:
|
408
|
-
compile_server.stop()
|
409
|
-
return 0
|
410
|
-
|
411
|
-
|
412
|
-
def main() -> int:
|
413
|
-
args = parse_args()
|
414
|
-
if args.server:
|
415
|
-
print("Running in server only mode.")
|
416
|
-
return run_server(args)
|
417
|
-
else:
|
418
|
-
print("Running in client/server mode.")
|
419
|
-
return run_client(args)
|
420
|
-
|
421
|
-
|
422
346
|
if __name__ == "__main__":
|
423
347
|
try:
|
424
|
-
|
425
|
-
sys.argv.append("examples/SdCard")
|
426
|
-
sys.argv.append("--localhost")
|
348
|
+
sys.argv.append("examples/wasm")
|
427
349
|
sys.exit(main())
|
428
350
|
except KeyboardInterrupt:
|
429
351
|
print("\nExiting from main...")
|
@@ -0,0 +1,34 @@
|
|
1
|
+
from pygments import lex
|
2
|
+
from pygments.lexers import CppLexer
|
3
|
+
from pygments.token import Token
|
4
|
+
|
5
|
+
|
6
|
+
def check_cpp_syntax(code):
|
7
|
+
try:
|
8
|
+
# Tokenize the code to check for basic syntax issues
|
9
|
+
for token_type, token_value in lex(code, CppLexer()):
|
10
|
+
if token_type == Token.Error:
|
11
|
+
print(f"Syntax error detected: {token_value}")
|
12
|
+
return False
|
13
|
+
print("No syntax errors detected.")
|
14
|
+
return True
|
15
|
+
except Exception as e:
|
16
|
+
print(f"Error during syntax check: {e}")
|
17
|
+
return False
|
18
|
+
|
19
|
+
|
20
|
+
def main():
|
21
|
+
file_path = input("Enter the path to your C++ file: ")
|
22
|
+
try:
|
23
|
+
with open(file_path, "r") as file:
|
24
|
+
code = file.read()
|
25
|
+
if check_cpp_syntax(code):
|
26
|
+
print("The file can now be sent to the server.")
|
27
|
+
else:
|
28
|
+
print("Please fix the syntax errors before sending.")
|
29
|
+
except FileNotFoundError:
|
30
|
+
print("File not found. Please check the path and try again.")
|
31
|
+
|
32
|
+
|
33
|
+
if __name__ == "__main__":
|
34
|
+
main()
|