fastled 1.4.0__tar.gz → 1.4.2__tar.gz

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.
Files changed (127) hide show
  1. {fastled-1.4.0 → fastled-1.4.2}/PKG-INFO +2 -1
  2. {fastled-1.4.0 → fastled-1.4.2}/README.md +1 -0
  3. {fastled-1.4.0 → fastled-1.4.2}/src/fastled/__init__.py +4 -0
  4. {fastled-1.4.0 → fastled-1.4.2}/src/fastled/__version__.py +1 -1
  5. {fastled-1.4.0 → fastled-1.4.2}/src/fastled/app.py +5 -0
  6. {fastled-1.4.0 → fastled-1.4.2}/src/fastled/args.py +5 -0
  7. {fastled-1.4.0 → fastled-1.4.2}/src/fastled/client_server.py +4 -0
  8. {fastled-1.4.0 → fastled-1.4.2}/src/fastled/live_client.py +3 -0
  9. {fastled-1.4.0 → fastled-1.4.2}/src/fastled/open_browser.py +6 -1
  10. {fastled-1.4.0 → fastled-1.4.2}/src/fastled/parse_args.py +5 -0
  11. {fastled-1.4.0 → fastled-1.4.2}/src/fastled/playwright_browser.py +94 -26
  12. {fastled-1.4.0 → fastled-1.4.2}/src/fastled.egg-info/PKG-INFO +2 -1
  13. {fastled-1.4.0 → fastled-1.4.2}/.aiderignore +0 -0
  14. {fastled-1.4.0 → fastled-1.4.2}/.cursorrules +0 -0
  15. {fastled-1.4.0 → fastled-1.4.2}/.dockerignore +0 -0
  16. {fastled-1.4.0 → fastled-1.4.2}/.github/workflows/build_multi_docker_image.yml +0 -0
  17. {fastled-1.4.0 → fastled-1.4.2}/.github/workflows/build_webpage.yml +0 -0
  18. {fastled-1.4.0 → fastled-1.4.2}/.github/workflows/lint.yml +0 -0
  19. {fastled-1.4.0 → fastled-1.4.2}/.github/workflows/publish_release.yml +0 -0
  20. {fastled-1.4.0 → fastled-1.4.2}/.github/workflows/template_build_docker_image.yml +0 -0
  21. {fastled-1.4.0 → fastled-1.4.2}/.github/workflows/test_build_exe.yml +0 -0
  22. {fastled-1.4.0 → fastled-1.4.2}/.github/workflows/test_macos.yml +0 -0
  23. {fastled-1.4.0 → fastled-1.4.2}/.github/workflows/test_ubuntu.yml +0 -0
  24. {fastled-1.4.0 → fastled-1.4.2}/.github/workflows/test_win.yml +0 -0
  25. {fastled-1.4.0 → fastled-1.4.2}/.gitignore +0 -0
  26. {fastled-1.4.0 → fastled-1.4.2}/.pylintrc +0 -0
  27. {fastled-1.4.0 → fastled-1.4.2}/.vscode/launch.json +0 -0
  28. {fastled-1.4.0 → fastled-1.4.2}/.vscode/settings.json +0 -0
  29. {fastled-1.4.0 → fastled-1.4.2}/.vscode/tasks.json +0 -0
  30. {fastled-1.4.0 → fastled-1.4.2}/DEBUGGER.md +0 -0
  31. {fastled-1.4.0 → fastled-1.4.2}/Dockerfile +0 -0
  32. {fastled-1.4.0 → fastled-1.4.2}/FAQ.md +0 -0
  33. {fastled-1.4.0 → fastled-1.4.2}/LICENSE +0 -0
  34. {fastled-1.4.0 → fastled-1.4.2}/MANIFEST.in +0 -0
  35. {fastled-1.4.0 → fastled-1.4.2}/RELEASE.md +0 -0
  36. {fastled-1.4.0 → fastled-1.4.2}/TODO.md +0 -0
  37. {fastled-1.4.0 → fastled-1.4.2}/build_exe.py +0 -0
  38. {fastled-1.4.0 → fastled-1.4.2}/build_local_docker.py +0 -0
  39. {fastled-1.4.0 → fastled-1.4.2}/build_site.py +0 -0
  40. {fastled-1.4.0 → fastled-1.4.2}/clean +0 -0
  41. {fastled-1.4.0 → fastled-1.4.2}/compiler/debug.sh +0 -0
  42. {fastled-1.4.0 → fastled-1.4.2}/compiler/run.py +0 -0
  43. {fastled-1.4.0 → fastled-1.4.2}/demo/100dots.html +0 -0
  44. {fastled-1.4.0 → fastled-1.4.2}/demo/demo_threejs.html +0 -0
  45. {fastled-1.4.0 → fastled-1.4.2}/demo/micdemo.html +0 -0
  46. {fastled-1.4.0 → fastled-1.4.2}/demo/mp3upload.html +0 -0
  47. {fastled-1.4.0 → fastled-1.4.2}/demo/webgl_postprocessing_unreal_bloom.html +0 -0
  48. {fastled-1.4.0 → fastled-1.4.2}/docker-compose.yml +0 -0
  49. {fastled-1.4.0 → fastled-1.4.2}/entrypoint.sh +0 -0
  50. {fastled-1.4.0 → fastled-1.4.2}/install +0 -0
  51. {fastled-1.4.0 → fastled-1.4.2}/install_linux.sh +0 -0
  52. {fastled-1.4.0 → fastled-1.4.2}/lint +0 -0
  53. {fastled-1.4.0 → fastled-1.4.2}/pyproject.toml +0 -0
  54. {fastled-1.4.0 → fastled-1.4.2}/requirements.docker.txt +0 -0
  55. {fastled-1.4.0 → fastled-1.4.2}/requirements.testing.txt +0 -0
  56. {fastled-1.4.0 → fastled-1.4.2}/setup.cfg +0 -0
  57. {fastled-1.4.0 → fastled-1.4.2}/setup.py +0 -0
  58. {fastled-1.4.0 → fastled-1.4.2}/src/fastled/__main__.py +0 -0
  59. {fastled-1.4.0 → fastled-1.4.2}/src/fastled/assets/example.txt +0 -0
  60. {fastled-1.4.0 → fastled-1.4.2}/src/fastled/assets/localhost-key.pem +0 -0
  61. {fastled-1.4.0 → fastled-1.4.2}/src/fastled/assets/localhost.pem +0 -0
  62. {fastled-1.4.0 → fastled-1.4.2}/src/fastled/cli.py +0 -0
  63. {fastled-1.4.0 → fastled-1.4.2}/src/fastled/cli_test.py +0 -0
  64. {fastled-1.4.0 → fastled-1.4.2}/src/fastled/cli_test_interactive.py +0 -0
  65. {fastled-1.4.0 → fastled-1.4.2}/src/fastled/compile_server.py +0 -0
  66. {fastled-1.4.0 → fastled-1.4.2}/src/fastled/compile_server_impl.py +0 -0
  67. {fastled-1.4.0 → fastled-1.4.2}/src/fastled/docker_manager.py +0 -0
  68. {fastled-1.4.0 → fastled-1.4.2}/src/fastled/filewatcher.py +0 -0
  69. {fastled-1.4.0 → fastled-1.4.2}/src/fastled/keyboard.py +0 -0
  70. {fastled-1.4.0 → fastled-1.4.2}/src/fastled/keyz.py +0 -0
  71. {fastled-1.4.0 → fastled-1.4.2}/src/fastled/paths.py +0 -0
  72. {fastled-1.4.0 → fastled-1.4.2}/src/fastled/print_filter.py +0 -0
  73. {fastled-1.4.0 → fastled-1.4.2}/src/fastled/project_init.py +0 -0
  74. {fastled-1.4.0 → fastled-1.4.2}/src/fastled/select_sketch_directory.py +0 -0
  75. {fastled-1.4.0 → fastled-1.4.2}/src/fastled/server_flask.py +0 -0
  76. {fastled-1.4.0 → fastled-1.4.2}/src/fastled/server_start.py +0 -0
  77. {fastled-1.4.0 → fastled-1.4.2}/src/fastled/settings.py +0 -0
  78. {fastled-1.4.0 → fastled-1.4.2}/src/fastled/site/build.py +0 -0
  79. {fastled-1.4.0 → fastled-1.4.2}/src/fastled/site/examples.py +0 -0
  80. {fastled-1.4.0 → fastled-1.4.2}/src/fastled/sketch.py +0 -0
  81. {fastled-1.4.0 → fastled-1.4.2}/src/fastled/spinner.py +0 -0
  82. {fastled-1.4.0 → fastled-1.4.2}/src/fastled/string_diff.py +0 -0
  83. {fastled-1.4.0 → fastled-1.4.2}/src/fastled/test/can_run_local_docker_tests.py +0 -0
  84. {fastled-1.4.0 → fastled-1.4.2}/src/fastled/test/examples.py +0 -0
  85. {fastled-1.4.0 → fastled-1.4.2}/src/fastled/types.py +0 -0
  86. {fastled-1.4.0 → fastled-1.4.2}/src/fastled/util.py +0 -0
  87. {fastled-1.4.0 → fastled-1.4.2}/src/fastled/version.py +0 -0
  88. {fastled-1.4.0 → fastled-1.4.2}/src/fastled/web_compile.py +0 -0
  89. {fastled-1.4.0 → fastled-1.4.2}/src/fastled.egg-info/SOURCES.txt +0 -0
  90. {fastled-1.4.0 → fastled-1.4.2}/src/fastled.egg-info/dependency_links.txt +0 -0
  91. {fastled-1.4.0 → fastled-1.4.2}/src/fastled.egg-info/entry_points.txt +0 -0
  92. {fastled-1.4.0 → fastled-1.4.2}/src/fastled.egg-info/requires.txt +0 -0
  93. {fastled-1.4.0 → fastled-1.4.2}/src/fastled.egg-info/top_level.txt +0 -0
  94. {fastled-1.4.0 → fastled-1.4.2}/test +0 -0
  95. {fastled-1.4.0 → fastled-1.4.2}/tests/integration/test_build_examples.py +0 -0
  96. {fastled-1.4.0 → fastled-1.4.2}/tests/integration/test_examples.py +0 -0
  97. {fastled-1.4.0 → fastled-1.4.2}/tests/integration/test_playwright_integration.py +0 -0
  98. {fastled-1.4.0 → fastled-1.4.2}/tests/unit/html/index.html +0 -0
  99. {fastled-1.4.0 → fastled-1.4.2}/tests/unit/test_api.py +0 -0
  100. {fastled-1.4.0 → fastled-1.4.2}/tests/unit/test_bad_ino.py +0 -0
  101. {fastled-1.4.0 → fastled-1.4.2}/tests/unit/test_banner_string.py +0 -0
  102. {fastled-1.4.0 → fastled-1.4.2}/tests/unit/test_cli.py +0 -0
  103. {fastled-1.4.0 → fastled-1.4.2}/tests/unit/test_cli_no_platformio.py +0 -0
  104. {fastled-1.4.0 → fastled-1.4.2}/tests/unit/test_compile_server.py +0 -0
  105. {fastled-1.4.0 → fastled-1.4.2}/tests/unit/test_debug_fetch_source_files.py +0 -0
  106. {fastled-1.4.0 → fastled-1.4.2}/tests/unit/test_docker_linux_on_windows.py +0 -0
  107. {fastled-1.4.0 → fastled-1.4.2}/tests/unit/test_embedded_data.py +0 -0
  108. {fastled-1.4.0 → fastled-1.4.2}/tests/unit/test_filechanger.py +0 -0
  109. {fastled-1.4.0 → fastled-1.4.2}/tests/unit/test_flask_headers.py +0 -0
  110. {fastled-1.4.0 → fastled-1.4.2}/tests/unit/test_http_server.py +0 -0
  111. {fastled-1.4.0 → fastled-1.4.2}/tests/unit/test_ino/bad/bad.ino +0 -0
  112. {fastled-1.4.0 → fastled-1.4.2}/tests/unit/test_ino/bad_platformio/bad_platformio.ino +0 -0
  113. {fastled-1.4.0 → fastled-1.4.2}/tests/unit/test_ino/bad_platformio/platformio.ini +0 -0
  114. {fastled-1.4.0 → fastled-1.4.2}/tests/unit/test_ino/embedded/data/bigdata.dat +0 -0
  115. {fastled-1.4.0 → fastled-1.4.2}/tests/unit/test_ino/embedded/wasm.ino +0 -0
  116. {fastled-1.4.0 → fastled-1.4.2}/tests/unit/test_ino/wasm/wasm.ino +0 -0
  117. {fastled-1.4.0 → fastled-1.4.2}/tests/unit/test_manual_api_invocation.py +0 -0
  118. {fastled-1.4.0 → fastled-1.4.2}/tests/unit/test_no_platformio_compile.py +0 -0
  119. {fastled-1.4.0 → fastled-1.4.2}/tests/unit/test_project_init.py +0 -0
  120. {fastled-1.4.0 → fastled-1.4.2}/tests/unit/test_server_and_client_seperatly.py +0 -0
  121. {fastled-1.4.0 → fastled-1.4.2}/tests/unit/test_session_compile.py +0 -0
  122. {fastled-1.4.0 → fastled-1.4.2}/tests/unit/test_string_diff.py +0 -0
  123. {fastled-1.4.0 → fastled-1.4.2}/tests/unit/test_string_diff_comprehensive.py +0 -0
  124. {fastled-1.4.0 → fastled-1.4.2}/tests/unit/test_version.py +0 -0
  125. {fastled-1.4.0 → fastled-1.4.2}/tests/unit/test_webcompile.py +0 -0
  126. {fastled-1.4.0 → fastled-1.4.2}/upload_package.sh +0 -0
  127. {fastled-1.4.0 → fastled-1.4.2}/vscode-plugin/readme +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: fastled
3
- Version: 1.4.0
3
+ Version: 1.4.2
4
4
  Summary: FastLED Wasm Compiler
5
5
  Home-page: https://github.com/zackees/fastled-wasm
6
6
  Maintainer: Zachary Vorhies
@@ -371,6 +371,7 @@ A: A big chunk of space is being used by unnecessary javascript `emscripten` bun
371
371
 
372
372
 
373
373
  # Revisions
374
+ * 1.4.00 - Browser now uses playwright when `pip install fastled[full]` is used. Much better app like experience.
374
375
  * 1.2.31 - Bunch of fixes and ease of use while compiling code in the repo.
375
376
  * 1.2.22 - Prefer to use `live-server` from npm. If npm exists on the system then do a background install of `live-server` for next run.
376
377
  * 1.2.20 - Fixed up path issue for web browser launch for hot reload.
@@ -341,6 +341,7 @@ A: A big chunk of space is being used by unnecessary javascript `emscripten` bun
341
341
 
342
342
 
343
343
  # Revisions
344
+ * 1.4.00 - Browser now uses playwright when `pip install fastled[full]` is used. Much better app like experience.
344
345
  * 1.2.31 - Bunch of fixes and ease of use while compiling code in the repo.
345
346
  * 1.2.22 - Prefer to use `live-server` from npm. If npm exists on the system then do a background install of `live-server` for next run.
346
347
  * 1.2.20 - Fixed up path issue for web browser launch for hot reload.
@@ -70,6 +70,7 @@ class Api:
70
70
  int | None
71
71
  ) = None, # None means auto select a free port. -1 means no server.
72
72
  no_platformio: bool = False,
73
+ no_playwright: bool = False,
73
74
  ) -> LiveClient:
74
75
  return LiveClient(
75
76
  sketch_directory=sketch_directory,
@@ -82,6 +83,7 @@ class Api:
82
83
  profile=profile,
83
84
  http_port=http_port,
84
85
  no_platformio=no_platformio,
86
+ no_playwright=no_playwright,
85
87
  )
86
88
 
87
89
  @staticmethod
@@ -206,6 +208,7 @@ class Test:
206
208
  port: int | None = None,
207
209
  compile_server_port: int | None = None,
208
210
  open_browser: bool = True,
211
+ no_playwright: bool = False,
209
212
  ) -> Process:
210
213
  from fastled.open_browser import spawn_http_server
211
214
 
@@ -217,6 +220,7 @@ class Test:
217
220
  port=port,
218
221
  compile_server_port=compile_server_port,
219
222
  open_browser=open_browser,
223
+ no_playwright=no_playwright,
220
224
  )
221
225
  return proc
222
226
 
@@ -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.0"
4
+ __version__ = "1.4.2"
5
5
 
6
6
  __version_url_latest__ = "https://raw.githubusercontent.com/zackees/fastled-wasm/refs/heads/main/src/fastled/__version__.py"
@@ -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.
@@ -13,6 +13,7 @@ class Args:
13
13
  profile: bool
14
14
  force_compile: bool
15
15
  no_platformio: bool
16
+ no_playwright: bool
16
17
  auto_update: bool | None
17
18
  update: bool
18
19
  localhost: bool
@@ -51,6 +52,9 @@ class Args:
51
52
  assert isinstance(
52
53
  args.no_platformio, bool
53
54
  ), f"expected bool, got {type(args.no_platformio)}"
55
+ assert isinstance(
56
+ args.no_playwright, bool
57
+ ), f"expected bool, got {type(args.no_playwright)}"
54
58
  assert isinstance(
55
59
  args.no_auto_updates, bool | None
56
60
  ), f"expected bool | None, got {type(args.no_auto_updates)}"
@@ -83,6 +87,7 @@ class Args:
83
87
  profile=args.profile,
84
88
  force_compile=args.force_compile,
85
89
  no_platformio=args.no_platformio,
90
+ no_playwright=args.no_playwright,
86
91
  auto_update=not args.no_auto_updates,
87
92
  update=args.update,
88
93
  localhost=args.localhost,
@@ -268,6 +268,7 @@ def run_client(
268
268
  ) = None, # None means auto select a free port, http_port < 0 means no server.
269
269
  clear: bool = False,
270
270
  no_platformio: bool = False,
271
+ no_playwright: bool = False,
271
272
  ) -> int:
272
273
  has_checked_newer_version_yet = False
273
274
  compile_server: CompileServer | None = None
@@ -348,6 +349,7 @@ def run_client(
348
349
  port=http_port,
349
350
  compile_server_port=port,
350
351
  open_browser=open_web_browser,
352
+ no_playwright=no_playwright,
351
353
  )
352
354
  else:
353
355
  print("\nCompilation successful.")
@@ -508,6 +510,7 @@ def run_client_server(args: Args) -> int:
508
510
  open_web_browser = not just_compile and not interactive
509
511
  build_mode: BuildMode = BuildMode.from_args(args)
510
512
  no_platformio = bool(args.no_platformio)
513
+ no_playwright = bool(args.no_playwright)
511
514
 
512
515
  if not force_compile and not looks_like_sketch_directory(directory):
513
516
  # if there is only one directory in the sketch directory, use that
@@ -570,6 +573,7 @@ def run_client_server(args: Args) -> int:
570
573
  profile=profile,
571
574
  clear=args.clear,
572
575
  no_platformio=no_platformio,
576
+ no_playwright=no_playwright,
573
577
  )
574
578
  except KeyboardInterrupt:
575
579
  return 1
@@ -23,6 +23,7 @@ class LiveClient:
23
23
  build_mode: BuildMode = BuildMode.QUICK,
24
24
  profile: bool = False,
25
25
  no_platformio: bool = False,
26
+ no_playwright: bool = False,
26
27
  ) -> None:
27
28
  self.sketch_directory = sketch_directory
28
29
  self.host = host
@@ -36,6 +37,7 @@ class LiveClient:
36
37
  self.thread: threading.Thread | None = None
37
38
  self.auto_updates = auto_updates
38
39
  self.no_platformio = no_platformio
40
+ self.no_playwright = no_playwright
39
41
  if auto_start:
40
42
  self.start()
41
43
  if self.auto_updates is False:
@@ -55,6 +57,7 @@ class LiveClient:
55
57
  shutdown=self.shutdown,
56
58
  http_port=self.http_port,
57
59
  no_platformio=self.no_platformio,
60
+ no_playwright=self.no_playwright,
58
61
  )
59
62
  return rtn
60
63
 
@@ -101,6 +101,7 @@ def spawn_http_server(
101
101
  compile_server_port: int,
102
102
  port: int | None = None,
103
103
  open_browser: bool = True,
104
+ no_playwright: bool = False,
104
105
  ) -> Process:
105
106
 
106
107
  if port is not None and not is_port_free(port):
@@ -129,7 +130,11 @@ def spawn_http_server(
129
130
  wait_for_server(port)
130
131
  if open_browser:
131
132
  url = f"http://localhost:{port}"
132
- if PLAYWRIGHT_AVAILABLE and open_with_playwright is not None:
133
+ if (
134
+ PLAYWRIGHT_AVAILABLE
135
+ and open_with_playwright is not None
136
+ and not no_playwright
137
+ ):
133
138
  print(f"Opening FastLED sketch in Playwright browser: {url}")
134
139
  print(
135
140
  "Auto-resize enabled: Browser window will automatically adjust to content size"
@@ -120,6 +120,11 @@ def parse_args() -> Args:
120
120
  action="store_true",
121
121
  help="Bypass PlatformIO constraints by using local Docker compilation with custom build environment",
122
122
  )
123
+ parser.add_argument(
124
+ "--no-playwright",
125
+ action="store_true",
126
+ help="Disable Playwright browser and use default system browser instead",
127
+ )
123
128
  parser.add_argument(
124
129
  "-u",
125
130
  "--update",
@@ -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
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: fastled
3
- Version: 1.4.0
3
+ Version: 1.4.2
4
4
  Summary: FastLED Wasm Compiler
5
5
  Home-page: https://github.com/zackees/fastled-wasm
6
6
  Maintainer: Zachary Vorhies
@@ -371,6 +371,7 @@ A: A big chunk of space is being used by unnecessary javascript `emscripten` bun
371
371
 
372
372
 
373
373
  # Revisions
374
+ * 1.4.00 - Browser now uses playwright when `pip install fastled[full]` is used. Much better app like experience.
374
375
  * 1.2.31 - Bunch of fixes and ease of use while compiling code in the repo.
375
376
  * 1.2.22 - Prefer to use `live-server` from npm. If npm exists on the system then do a background install of `live-server` for next run.
376
377
  * 1.2.20 - Fixed up path issue for web browser launch for hot reload.
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes