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 CHANGED
@@ -1,3 +0,0 @@
1
- """FastLED Wasm Compiler package."""
2
-
3
- __version__ = "1.0.15"
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 FileWatcherProcess
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.sketch import looks_like_fastled_repo, looks_like_sketch_directory
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=f"FastLED WASM Compiler {__version__}")
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=None,
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
- "-i",
74
- "--interactive",
74
+ "--reuse",
75
75
  action="store_true",
76
- help="Run in interactive mode (Not available with --web)",
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
- if not cwd_is_fastled and not args.localhost and not args.web and not args.server:
116
- print(f"Using web compiler at {DEFAULT_URL}")
117
- args.web = DEFAULT_URL
118
- if cwd_is_fastled and not args.web:
119
- print("Forcing --local mode because we are in the FastLED repo")
120
- args.localhost = True
121
- if args.localhost:
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("\nSkipping redeploy: No significant changes found.")
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
- is_local_host = "localhost" in args.web or "127.0.0.1" in args.web or args.localhost
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
- print("No local server found, starting one...")
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 run_client(args: argparse.Namespace) -> int:
236
- compile_server: CompileServer | None = None
237
- open_web_browser = not args.just_compile and not args.interactive
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
- if not args.force_compile and not looks_like_sketch_directory(Path(args.directory)):
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
- sketch_filewatcher = FileWatcherProcess(
320
- args.directory, excluded_patterns=["fastled_js"]
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
- last_compiled_result = trigger_rebuild_if_sketch_changed(
348
- last_compiled_result
349
- )
350
- if compile_server and not compile_server.proceess_running():
351
- print("Server process is not running. Exiting...")
352
- return 1
353
- if source_code_watcher is not None:
354
- changed_files = source_code_watcher.get_all_changes()
355
- if changed_files:
356
- print(f"\nChanges detected in FastLED source code: {changed_files}")
357
- print("Press space bar to trigger compile.")
358
-
359
- space_key_watcher = SpaceBarWatcher()
360
- try:
361
- while True:
362
- if space_key_watcher.space_bar_pressed():
363
- print("Space bar pressed, triggering recompile...")
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
- sketch_filewatcher.stop()
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
- # os.chdir("../fastled")
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()