fastled 1.4.1__py3-none-any.whl → 1.4.3__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,9 +1,9 @@
1
1
  """FastLED Wasm Compiler package."""
2
2
 
3
+ from collections.abc import Generator
3
4
  from contextlib import contextmanager
4
5
  from multiprocessing import Process
5
6
  from pathlib import Path
6
- from typing import Generator
7
7
 
8
8
  from .__version__ import __version__
9
9
  from .compile_server import CompileServer
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.1"
4
+ __version__ = "1.4.3"
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
@@ -63,6 +63,11 @@ def main() -> int:
63
63
  # now it is safe to print out the version
64
64
  print(f"FastLED version: {__version__}")
65
65
 
66
+ # Check if Playwright browsers are installed
67
+ playwright_dir = Path.home() / ".fastled" / "playwright"
68
+ if playwright_dir.exists() and any(playwright_dir.iterdir()):
69
+ print(f"🎭 Playwright browsers available at: {playwright_dir}")
70
+
66
71
  # Resolve some of the last interactive arguments
67
72
  # 1. If interactive is set and the sketch directory is not given,
68
73
  # then prompt the user for a sketch directory.
fastled/filewatcher.py CHANGED
@@ -10,7 +10,6 @@ from contextlib import redirect_stdout
10
10
  from multiprocessing import Process, Queue
11
11
  from pathlib import Path
12
12
  from queue import Empty
13
- from typing import Dict, Set
14
13
 
15
14
  from watchdog.events import FileSystemEvent, FileSystemEventHandler
16
15
  from watchdog.observers import Observer
@@ -35,8 +34,8 @@ class MyEventHandler(FileSystemEventHandler):
35
34
  def __init__(
36
35
  self,
37
36
  change_queue: queue.Queue,
38
- excluded_patterns: Set[str],
39
- file_hashes: Dict[str, str],
37
+ excluded_patterns: set[str],
38
+ file_hashes: dict[str, str],
40
39
  ) -> None:
41
40
  super().__init__()
42
41
  self.change_queue = change_queue
@@ -94,8 +93,8 @@ class FileChangedNotifier(threading.Thread):
94
93
  )
95
94
  self.stopped = False
96
95
  self.change_queue: queue.Queue = queue.Queue()
97
- self.last_notification: Dict[str, float] = {}
98
- self.file_hashes: Dict[str, str] = {}
96
+ self.last_notification: dict[str, float] = {}
97
+ self.file_hashes: dict[str, str] = {}
99
98
  self.debounce_seconds = debounce_seconds
100
99
 
101
100
  def stop(self) -> None:
@@ -1,18 +1,23 @@
1
1
  """
2
2
  Playwright browser integration for FastLED WASM compiler.
3
3
 
4
- This module provides functionality to open the compiled FastLED sketch
4
+ This module provides a Playwright-based browser implementation that can be used
5
5
  in a Playwright browser instead of the default system browser when
6
- the 'full' optional dependency is installed.
6
+ Playwright is available.
7
7
  """
8
8
 
9
9
  import asyncio
10
+ import os
10
11
  import sys
12
+ import threading
11
13
  import warnings
12
- from typing import TYPE_CHECKING, Any
14
+ from pathlib import Path
15
+ from typing import Any
13
16
 
14
- if TYPE_CHECKING:
15
- from playwright.async_api import Browser, Page
17
+ # Set custom Playwright browser installation path
18
+ PLAYWRIGHT_DIR = Path.home() / ".fastled" / "playwright"
19
+ PLAYWRIGHT_DIR.mkdir(parents=True, exist_ok=True)
20
+ os.environ["PLAYWRIGHT_BROWSERS_PATH"] = str(PLAYWRIGHT_DIR)
16
21
 
17
22
  try:
18
23
  from playwright.async_api import Browser, Page, async_playwright
@@ -21,8 +26,8 @@ try:
21
26
  except ImportError:
22
27
  PLAYWRIGHT_AVAILABLE = False
23
28
  async_playwright = None
24
- Browser = Any # type: ignore
25
- Page = Any # type: ignore
29
+ Browser = None
30
+ Page = None
26
31
 
27
32
 
28
33
  def is_playwright_available() -> bool:
@@ -268,34 +273,57 @@ def run_playwright_browser(url: str, headless: bool = False) -> None:
268
273
  "Playwright is not installed. Install with: pip install fastled[full]. "
269
274
  "Falling back to default browser."
270
275
  )
276
+ import webbrowser
277
+
278
+ webbrowser.open(url)
271
279
  return
272
280
 
273
281
  async def main():
274
- browser = PlaywrightBrowser(headless=headless)
282
+ browser = None
275
283
  try:
284
+ browser = PlaywrightBrowser(headless=headless)
276
285
  await browser.start()
277
286
  await browser.open_url(url)
278
287
 
279
- if not headless:
280
- print("Playwright browser opened. Press Ctrl+C to close.")
281
- await browser.wait_for_close()
282
- else:
283
- # In headless mode, just wait a bit for the page to load
284
- await asyncio.sleep(2)
288
+ print("Playwright browser opened. Press Ctrl+C to close.")
289
+ await browser.wait_for_close()
285
290
 
291
+ except Exception as e:
292
+ # If we get an error that suggests browsers aren't installed, try to install them
293
+ if "executable doesn't exist" in str(e) or "Browser not found" in str(e):
294
+ print("🎭 Playwright browsers not found. Installing...")
295
+ if install_playwright_browsers():
296
+ print("🎭 Retrying browser startup...")
297
+ # Try again with fresh browser instance
298
+ browser = PlaywrightBrowser(headless=headless)
299
+ await browser.start()
300
+ await browser.open_url(url)
301
+
302
+ print("Playwright browser opened. Press Ctrl+C to close.")
303
+ await browser.wait_for_close()
304
+ else:
305
+ print("❌ Failed to install Playwright browsers")
306
+ raise e
307
+ else:
308
+ raise e
286
309
  except KeyboardInterrupt:
287
310
  print("\nClosing Playwright browser...")
288
311
  finally:
289
- await browser.close()
312
+ if browser is not None:
313
+ try:
314
+ await browser.close()
315
+ except Exception as e:
316
+ print(f"Warning: Failed to close Playwright browser: {e}")
290
317
 
291
318
  try:
292
319
  asyncio.run(main())
293
320
  except KeyboardInterrupt:
294
321
  print("\nPlaywright browser closed.")
295
322
  except Exception as e:
296
- warnings.warn(
297
- f"Playwright browser failed: {e}. Falling back to default browser."
298
- )
323
+ print(f"Playwright browser failed: {e}. Falling back to default browser.")
324
+ import webbrowser
325
+
326
+ webbrowser.open(url)
299
327
 
300
328
 
301
329
  class PlaywrightBrowserProxy:
@@ -357,7 +385,6 @@ class PlaywrightBrowserProxy:
357
385
  return
358
386
 
359
387
  import os
360
- import threading
361
388
 
362
389
  def monitor_process():
363
390
  """Monitor the browser process and exit when it terminates."""
@@ -407,8 +434,9 @@ def run_playwright_browser_persistent(url: str, headless: bool = False) -> None:
407
434
  return
408
435
 
409
436
  async def main():
410
- browser = PlaywrightBrowser(headless=headless)
437
+ browser = None
411
438
  try:
439
+ browser = PlaywrightBrowser(headless=headless)
412
440
  await browser.start()
413
441
  await browser.open_url(url)
414
442
 
@@ -420,12 +448,37 @@ def run_playwright_browser_persistent(url: str, headless: bool = False) -> None:
420
448
  while not browser._should_exit.is_set():
421
449
  await asyncio.sleep(0.1)
422
450
 
451
+ except Exception as e:
452
+ # If we get an error that suggests browsers aren't installed, try to install them
453
+ if "executable doesn't exist" in str(e) or "Browser not found" in str(e):
454
+ print("🎭 Playwright browsers not found. Installing...")
455
+ if install_playwright_browsers():
456
+ print("🎭 Retrying browser startup...")
457
+ # Try again with fresh browser instance
458
+ browser = PlaywrightBrowser(headless=headless)
459
+ await browser.start()
460
+ await browser.open_url(url)
461
+
462
+ print(
463
+ "Playwright browser opened. Browser will remain open until the FastLED process exits."
464
+ )
465
+
466
+ # Keep the browser alive until exit is signaled
467
+ while not browser._should_exit.is_set():
468
+ await asyncio.sleep(0.1)
469
+ else:
470
+ print("❌ Failed to install Playwright browsers")
471
+ raise e
472
+ else:
473
+ raise e
423
474
  except KeyboardInterrupt:
424
475
  print("\nClosing Playwright browser...")
425
- except Exception as e:
426
- print(f"Playwright browser error: {e}")
427
476
  finally:
428
- await browser.close()
477
+ if browser is not None:
478
+ try:
479
+ await browser.close()
480
+ except Exception as e:
481
+ print(f"Warning: Failed to close Playwright browser: {e}")
429
482
 
430
483
  try:
431
484
  asyncio.run(main())
@@ -455,6 +508,8 @@ def open_with_playwright(url: str, headless: bool = False) -> PlaywrightBrowserP
455
508
  def install_playwright_browsers() -> bool:
456
509
  """Install Playwright browsers if not already installed.
457
510
 
511
+ Installs browsers to ~/.fastled/playwright directory.
512
+
458
513
  Returns:
459
514
  True if installation was successful or browsers were already installed
460
515
  """
@@ -462,6 +517,16 @@ def install_playwright_browsers() -> bool:
462
517
  return False
463
518
 
464
519
  try:
520
+ import os
521
+ from pathlib import Path
522
+
523
+ # Set custom browser installation path
524
+ playwright_dir = Path.home() / ".fastled" / "playwright"
525
+ playwright_dir.mkdir(parents=True, exist_ok=True)
526
+
527
+ # Set environment variable for Playwright browser path
528
+ os.environ["PLAYWRIGHT_BROWSERS_PATH"] = str(playwright_dir)
529
+
465
530
  from playwright.sync_api import sync_playwright
466
531
 
467
532
  with sync_playwright() as p:
@@ -475,21 +540,24 @@ def install_playwright_browsers() -> bool:
475
540
 
476
541
  # If we get here, browsers need to be installed
477
542
  print("Installing Playwright browsers...")
543
+ print(f"Installing to: {playwright_dir}")
478
544
  import subprocess
479
545
 
480
546
  result = subprocess.run(
481
547
  [sys.executable, "-m", "playwright", "install", "chromium"],
482
548
  capture_output=True,
483
549
  text=True,
550
+ env=dict(os.environ, PLAYWRIGHT_BROWSERS_PATH=str(playwright_dir)),
484
551
  )
485
552
 
486
553
  if result.returncode == 0:
487
- print("Playwright browsers installed successfully.")
554
+ print("Playwright browsers installed successfully!")
555
+ print(f" Location: {playwright_dir}")
488
556
  return True
489
557
  else:
490
- print(f"Failed to install Playwright browsers: {result.stderr}")
558
+ print(f"Failed to install Playwright browsers: {result.stderr}")
491
559
  return False
492
560
 
493
561
  except Exception as e:
494
- print(f"Error installing Playwright browsers: {e}")
562
+ print(f"Error installing Playwright browsers: {e}")
495
563
  return False
fastled/site/build.py CHANGED
@@ -265,7 +265,6 @@ INDEX_TEMPLATE = """<!DOCTYPE html>
265
265
  checkmark.style.color = '#E0E0E0';
266
266
  link.appendChild(checkmark);
267
267
  }});
268
-
269
268
  // Now load first example and show its checkmark
270
269
  if (links.length > 0) {{
271
270
  // Try to find SdCard example first
@@ -274,7 +273,6 @@ INDEX_TEMPLATE = """<!DOCTYPE html>
274
273
  startLink.classList.add('active');
275
274
  startLink.querySelector('.fa-check').style.display = 'inline-block';
276
275
  }}
277
-
278
276
  // Add click handlers
279
277
  links.forEach(link => {{
280
278
  link.addEventListener('click', function(e) {{
@@ -313,11 +311,10 @@ INDEX_TEMPLATE = """<!DOCTYPE html>
313
311
  showNav();
314
312
  }}
315
313
  }});
316
-
317
314
  // Close menu when clicking anywhere in the document
318
315
  document.addEventListener('click', (e) => {{
319
- if (navPane.classList.contains('visible') &&
320
- !navPane.contains(e.target) &&
316
+ if (navPane.classList.contains('visible') &&
317
+ !navPane.contains(e.target) &&
321
318
  !navTrigger.contains(e.target)) {{
322
319
  hideNav();
323
320
  }}
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: fastled
3
- Version: 1.4.1
3
+ Version: 1.4.3
4
4
  Summary: FastLED Wasm Compiler
5
5
  Home-page: https://github.com/zackees/fastled-wasm
6
6
  Maintainer: Zachary Vorhies
@@ -10,7 +10,7 @@ Classifier: Programming Language :: Python :: 3
10
10
  Requires-Python: >=3.10
11
11
  Description-Content-Type: text/markdown
12
12
  License-File: LICENSE
13
- Requires-Dist: httpx>=0.28.1
13
+ Requires-Dist: fastled-wasm-server>=1.1.0
14
14
  Requires-Dist: watchdog>=6.0.0
15
15
  Requires-Dist: docker>=7.1.0
16
16
  Requires-Dist: filelock>=3.16.1
@@ -1,7 +1,7 @@
1
- fastled/__init__.py,sha256=oQFhIrBU0TbMDfQA1ZmubpZPwDzHmruXFa52H5UFSDE,7300
1
+ fastled/__init__.py,sha256=Jdl62kknNs1cGo1ZA6jTS13kWiB0F-mDopDnWBLVDV8,7309
2
2
  fastled/__main__.py,sha256=OcKv2ER1_iQAsZzLIUb3C8hRC9L2clNOhCrjpshrlf4,336
3
- fastled/__version__.py,sha256=jnZS2psG0LYCGykwvL4Zs7g490ZXEjv9AFYQMLaxmlk,372
4
- fastled/app.py,sha256=TFVn4qIRdt7dYbpDWudEHrhvD9pwyj9sIGXs4F26nhk,5880
3
+ fastled/__version__.py,sha256=Hul0Ut4Dc0Q7V2YVvCcsPCYEo4t5gnBErMyN3wRBxPg,372
4
+ fastled/app.py,sha256=6XOuObi72AUnZXASDOVbcSflr4He0xnIDk5P8nVmVus,6131
5
5
  fastled/args.py,sha256=uCMyRIYM8gFE52O12YKUfA-rwJL8Zxwk_hsH3cusSac,3669
6
6
  fastled/cli.py,sha256=drgR2AOxVrj3QEz58iiKscYAumbbin2vIV-k91VCOAA,561
7
7
  fastled/cli_test.py,sha256=W-1nODZrip_JU6BEbYhxOa4ckxduOsiX8zIoRkTyxv4,550
@@ -10,14 +10,14 @@ fastled/client_server.py,sha256=n3N-i7EgWtoyb3eR8TaCc3a3Mth9cUcYsyMNICtlJZc,2074
10
10
  fastled/compile_server.py,sha256=yQtwLOSKINO1CKD0NWxf-7YQKSatf9sF9RuqaWGOkCs,3038
11
11
  fastled/compile_server_impl.py,sha256=9vTGaDQ0W_g9Xsfy0gC3nJEc2g_pnXcF4VO2U3GLOVg,11982
12
12
  fastled/docker_manager.py,sha256=rkq39ZKrU6NHIyDa3mzs0Unb6o9oMeAwxhqiuHJU_RY,40291
13
- fastled/filewatcher.py,sha256=gEcJJHTDJ1X3gKJzltmEBhixWGbZj2eJD7a4vwSvITQ,10036
13
+ fastled/filewatcher.py,sha256=L5kLl9y04e6QeXiOv8xuZ-i73G1FzHrWGvQavwGTuko,10007
14
14
  fastled/keyboard.py,sha256=UTAsqCn1UMYnB8YDzENiLTj4GeL45tYfEcO7_5fLFEg,3556
15
15
  fastled/keyz.py,sha256=LO-8m_7CpNDiZLM-FXhQ30f9gN1bUYz5lOsUPTIbI-c,4020
16
16
  fastled/live_client.py,sha256=aDZqSWDMpqNaEsT3u1nrBcdeIOItv-L0Gk2A10difLA,3209
17
17
  fastled/open_browser.py,sha256=mwjm65p2ydwmsaar7ooH4mhT5_qH_LZvXUpkRPPJ9eA,4881
18
18
  fastled/parse_args.py,sha256=htjap9tWZDJXnJ5upDwcy8EhecJD1uLZwacHR_T5ySs,11518
19
19
  fastled/paths.py,sha256=VsPmgu0lNSCFOoEC0BsTYzDygXqy15AHUfN-tTuzDZA,99
20
- fastled/playwright_browser.py,sha256=SoUZUVfpcGRt6dXoQUASHNgMXIQzFYqN6bBvqsVZDsU,17033
20
+ fastled/playwright_browser.py,sha256=jNSIuWYz19t25-p4yj79oQog4l2njwehif9PiTIlLqk,20041
21
21
  fastled/print_filter.py,sha256=nc_rqYYdCUPinFycaK7fiQF5PG1up51pmJptR__QyAs,1499
22
22
  fastled/project_init.py,sha256=bBt4DwmW5hZkm9ICt9Qk-0Nr_0JQM7icCgH5Iv-bCQs,3984
23
23
  fastled/select_sketch_directory.py,sha256=-eudwCns3AKj4HuHtSkZAFwbnf005SNL07pOzs9VxnE,1383
@@ -34,13 +34,13 @@ fastled/web_compile.py,sha256=BPrlrW7RMAtnbYUFF3LDn0ORx7aiMOuQkSlYF_gA1o0,11867
34
34
  fastled/assets/example.txt,sha256=lTBovRjiz0_TgtAtbA1C5hNi2ffbqnNPqkKg6UiKCT8,54
35
35
  fastled/assets/localhost-key.pem,sha256=Q-CNO_UoOd8fFNN4ljcnqwUeCMhzTplRjLO2x0pYRlU,1704
36
36
  fastled/assets/localhost.pem,sha256=QTwUtTwjYWbm9m3pHW2IlK2nFZJ8b0pppxPjhgVZqQo,1619
37
- fastled/site/build.py,sha256=2YKU_UWKlJdGnjdbAbaL0co6kceFMSTVYwH1KCmgPZA,13987
37
+ fastled/site/build.py,sha256=GZtknx3UqJZAP2x7IqoR5G1MJj_9boOWepkKrWAMThE,13946
38
38
  fastled/site/examples.py,sha256=s6vj2zJc6BfKlnbwXr1QWY1mzuDBMt6j5MEBOWjO_U8,155
39
39
  fastled/test/can_run_local_docker_tests.py,sha256=LEuUbHctRhNNFWcvnz2kEGmjDJeXO4c3kNpizm3yVJs,400
40
40
  fastled/test/examples.py,sha256=GfaHeY1E8izBl6ZqDVjz--RHLyVR4NRnQ5pBesCFJFY,1673
41
- fastled-1.4.1.dist-info/licenses/LICENSE,sha256=b6pOoifSXiUaz_lDS84vWlG3fr4yUKwB8fzkrH9R8bQ,1064
42
- fastled-1.4.1.dist-info/METADATA,sha256=RKYlufX0O87bXsTGUh1XlXzZN5H8TAFGzagLQBXN20Y,32369
43
- fastled-1.4.1.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
44
- fastled-1.4.1.dist-info/entry_points.txt,sha256=RCwmzCSOS4-C2i9EziANq7Z2Zb4KFnEMR1FQC0bBwAw,101
45
- fastled-1.4.1.dist-info/top_level.txt,sha256=Bbv5kpJpZhWNCvDF4K0VcvtBSDMa8B7PTOrZa9CezHY,8
46
- fastled-1.4.1.dist-info/RECORD,,
41
+ fastled-1.4.3.dist-info/licenses/LICENSE,sha256=b6pOoifSXiUaz_lDS84vWlG3fr4yUKwB8fzkrH9R8bQ,1064
42
+ fastled-1.4.3.dist-info/METADATA,sha256=iRUvEJ_aI8qbOYRoD2kiCncSwGu6r1BiWmpleBemiC4,32382
43
+ fastled-1.4.3.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
44
+ fastled-1.4.3.dist-info/entry_points.txt,sha256=RCwmzCSOS4-C2i9EziANq7Z2Zb4KFnEMR1FQC0bBwAw,101
45
+ fastled-1.4.3.dist-info/top_level.txt,sha256=Bbv5kpJpZhWNCvDF4K0VcvtBSDMa8B7PTOrZa9CezHY,8
46
+ fastled-1.4.3.dist-info/RECORD,,