fastled 1.3.39__tar.gz → 1.4.0__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.3.39 → fastled-1.4.0}/PKG-INFO +5 -4
  2. {fastled-1.3.39 → fastled-1.4.0}/README.md +4 -3
  3. {fastled-1.3.39 → fastled-1.4.0}/src/fastled/__init__.py +0 -1
  4. {fastled-1.3.39 → fastled-1.4.0}/src/fastled/__version__.py +1 -1
  5. {fastled-1.3.39 → fastled-1.4.0}/src/fastled/args.py +0 -10
  6. {fastled-1.3.39 → fastled-1.4.0}/src/fastled/client_server.py +10 -6
  7. {fastled-1.3.39 → fastled-1.4.0}/src/fastled/open_browser.py +4 -21
  8. {fastled-1.3.39 → fastled-1.4.0}/src/fastled/parse_args.py +3 -18
  9. {fastled-1.3.39 → fastled-1.4.0}/src/fastled/playwright_browser.py +56 -29
  10. {fastled-1.3.39 → fastled-1.4.0}/src/fastled.egg-info/PKG-INFO +5 -4
  11. {fastled-1.3.39 → fastled-1.4.0}/tests/integration/test_playwright_integration.py +0 -58
  12. {fastled-1.3.39 → fastled-1.4.0}/.aiderignore +0 -0
  13. {fastled-1.3.39 → fastled-1.4.0}/.cursorrules +0 -0
  14. {fastled-1.3.39 → fastled-1.4.0}/.dockerignore +0 -0
  15. {fastled-1.3.39 → fastled-1.4.0}/.github/workflows/build_multi_docker_image.yml +0 -0
  16. {fastled-1.3.39 → fastled-1.4.0}/.github/workflows/build_webpage.yml +0 -0
  17. {fastled-1.3.39 → fastled-1.4.0}/.github/workflows/lint.yml +0 -0
  18. {fastled-1.3.39 → fastled-1.4.0}/.github/workflows/publish_release.yml +0 -0
  19. {fastled-1.3.39 → fastled-1.4.0}/.github/workflows/template_build_docker_image.yml +0 -0
  20. {fastled-1.3.39 → fastled-1.4.0}/.github/workflows/test_build_exe.yml +0 -0
  21. {fastled-1.3.39 → fastled-1.4.0}/.github/workflows/test_macos.yml +0 -0
  22. {fastled-1.3.39 → fastled-1.4.0}/.github/workflows/test_ubuntu.yml +0 -0
  23. {fastled-1.3.39 → fastled-1.4.0}/.github/workflows/test_win.yml +0 -0
  24. {fastled-1.3.39 → fastled-1.4.0}/.gitignore +0 -0
  25. {fastled-1.3.39 → fastled-1.4.0}/.pylintrc +0 -0
  26. {fastled-1.3.39 → fastled-1.4.0}/.vscode/launch.json +0 -0
  27. {fastled-1.3.39 → fastled-1.4.0}/.vscode/settings.json +0 -0
  28. {fastled-1.3.39 → fastled-1.4.0}/.vscode/tasks.json +0 -0
  29. {fastled-1.3.39 → fastled-1.4.0}/DEBUGGER.md +0 -0
  30. {fastled-1.3.39 → fastled-1.4.0}/Dockerfile +0 -0
  31. {fastled-1.3.39 → fastled-1.4.0}/FAQ.md +0 -0
  32. {fastled-1.3.39 → fastled-1.4.0}/LICENSE +0 -0
  33. {fastled-1.3.39 → fastled-1.4.0}/MANIFEST.in +0 -0
  34. {fastled-1.3.39 → fastled-1.4.0}/RELEASE.md +0 -0
  35. {fastled-1.3.39 → fastled-1.4.0}/TODO.md +0 -0
  36. {fastled-1.3.39 → fastled-1.4.0}/build_exe.py +0 -0
  37. {fastled-1.3.39 → fastled-1.4.0}/build_local_docker.py +0 -0
  38. {fastled-1.3.39 → fastled-1.4.0}/build_site.py +0 -0
  39. {fastled-1.3.39 → fastled-1.4.0}/clean +0 -0
  40. {fastled-1.3.39 → fastled-1.4.0}/compiler/debug.sh +0 -0
  41. {fastled-1.3.39 → fastled-1.4.0}/compiler/run.py +0 -0
  42. {fastled-1.3.39 → fastled-1.4.0}/demo/100dots.html +0 -0
  43. {fastled-1.3.39 → fastled-1.4.0}/demo/demo_threejs.html +0 -0
  44. {fastled-1.3.39 → fastled-1.4.0}/demo/micdemo.html +0 -0
  45. {fastled-1.3.39 → fastled-1.4.0}/demo/mp3upload.html +0 -0
  46. {fastled-1.3.39 → fastled-1.4.0}/demo/webgl_postprocessing_unreal_bloom.html +0 -0
  47. {fastled-1.3.39 → fastled-1.4.0}/docker-compose.yml +0 -0
  48. {fastled-1.3.39 → fastled-1.4.0}/entrypoint.sh +0 -0
  49. {fastled-1.3.39 → fastled-1.4.0}/install +0 -0
  50. {fastled-1.3.39 → fastled-1.4.0}/install_linux.sh +0 -0
  51. {fastled-1.3.39 → fastled-1.4.0}/lint +0 -0
  52. {fastled-1.3.39 → fastled-1.4.0}/pyproject.toml +0 -0
  53. {fastled-1.3.39 → fastled-1.4.0}/requirements.docker.txt +0 -0
  54. {fastled-1.3.39 → fastled-1.4.0}/requirements.testing.txt +0 -0
  55. {fastled-1.3.39 → fastled-1.4.0}/setup.cfg +0 -0
  56. {fastled-1.3.39 → fastled-1.4.0}/setup.py +0 -0
  57. {fastled-1.3.39 → fastled-1.4.0}/src/fastled/__main__.py +0 -0
  58. {fastled-1.3.39 → fastled-1.4.0}/src/fastled/app.py +0 -0
  59. {fastled-1.3.39 → fastled-1.4.0}/src/fastled/assets/example.txt +0 -0
  60. {fastled-1.3.39 → fastled-1.4.0}/src/fastled/assets/localhost-key.pem +0 -0
  61. {fastled-1.3.39 → fastled-1.4.0}/src/fastled/assets/localhost.pem +0 -0
  62. {fastled-1.3.39 → fastled-1.4.0}/src/fastled/cli.py +0 -0
  63. {fastled-1.3.39 → fastled-1.4.0}/src/fastled/cli_test.py +0 -0
  64. {fastled-1.3.39 → fastled-1.4.0}/src/fastled/cli_test_interactive.py +0 -0
  65. {fastled-1.3.39 → fastled-1.4.0}/src/fastled/compile_server.py +0 -0
  66. {fastled-1.3.39 → fastled-1.4.0}/src/fastled/compile_server_impl.py +0 -0
  67. {fastled-1.3.39 → fastled-1.4.0}/src/fastled/docker_manager.py +0 -0
  68. {fastled-1.3.39 → fastled-1.4.0}/src/fastled/filewatcher.py +0 -0
  69. {fastled-1.3.39 → fastled-1.4.0}/src/fastled/keyboard.py +0 -0
  70. {fastled-1.3.39 → fastled-1.4.0}/src/fastled/keyz.py +0 -0
  71. {fastled-1.3.39 → fastled-1.4.0}/src/fastled/live_client.py +0 -0
  72. {fastled-1.3.39 → fastled-1.4.0}/src/fastled/paths.py +0 -0
  73. {fastled-1.3.39 → fastled-1.4.0}/src/fastled/print_filter.py +0 -0
  74. {fastled-1.3.39 → fastled-1.4.0}/src/fastled/project_init.py +0 -0
  75. {fastled-1.3.39 → fastled-1.4.0}/src/fastled/select_sketch_directory.py +0 -0
  76. {fastled-1.3.39 → fastled-1.4.0}/src/fastled/server_flask.py +0 -0
  77. {fastled-1.3.39 → fastled-1.4.0}/src/fastled/server_start.py +0 -0
  78. {fastled-1.3.39 → fastled-1.4.0}/src/fastled/settings.py +0 -0
  79. {fastled-1.3.39 → fastled-1.4.0}/src/fastled/site/build.py +0 -0
  80. {fastled-1.3.39 → fastled-1.4.0}/src/fastled/site/examples.py +0 -0
  81. {fastled-1.3.39 → fastled-1.4.0}/src/fastled/sketch.py +0 -0
  82. {fastled-1.3.39 → fastled-1.4.0}/src/fastled/spinner.py +0 -0
  83. {fastled-1.3.39 → fastled-1.4.0}/src/fastled/string_diff.py +0 -0
  84. {fastled-1.3.39 → fastled-1.4.0}/src/fastled/test/can_run_local_docker_tests.py +0 -0
  85. {fastled-1.3.39 → fastled-1.4.0}/src/fastled/test/examples.py +0 -0
  86. {fastled-1.3.39 → fastled-1.4.0}/src/fastled/types.py +0 -0
  87. {fastled-1.3.39 → fastled-1.4.0}/src/fastled/util.py +0 -0
  88. {fastled-1.3.39 → fastled-1.4.0}/src/fastled/version.py +0 -0
  89. {fastled-1.3.39 → fastled-1.4.0}/src/fastled/web_compile.py +0 -0
  90. {fastled-1.3.39 → fastled-1.4.0}/src/fastled.egg-info/SOURCES.txt +0 -0
  91. {fastled-1.3.39 → fastled-1.4.0}/src/fastled.egg-info/dependency_links.txt +0 -0
  92. {fastled-1.3.39 → fastled-1.4.0}/src/fastled.egg-info/entry_points.txt +0 -0
  93. {fastled-1.3.39 → fastled-1.4.0}/src/fastled.egg-info/requires.txt +0 -0
  94. {fastled-1.3.39 → fastled-1.4.0}/src/fastled.egg-info/top_level.txt +0 -0
  95. {fastled-1.3.39 → fastled-1.4.0}/test +0 -0
  96. {fastled-1.3.39 → fastled-1.4.0}/tests/integration/test_build_examples.py +0 -0
  97. {fastled-1.3.39 → fastled-1.4.0}/tests/integration/test_examples.py +0 -0
  98. {fastled-1.3.39 → fastled-1.4.0}/tests/unit/html/index.html +0 -0
  99. {fastled-1.3.39 → fastled-1.4.0}/tests/unit/test_api.py +0 -0
  100. {fastled-1.3.39 → fastled-1.4.0}/tests/unit/test_bad_ino.py +0 -0
  101. {fastled-1.3.39 → fastled-1.4.0}/tests/unit/test_banner_string.py +0 -0
  102. {fastled-1.3.39 → fastled-1.4.0}/tests/unit/test_cli.py +0 -0
  103. {fastled-1.3.39 → fastled-1.4.0}/tests/unit/test_cli_no_platformio.py +0 -0
  104. {fastled-1.3.39 → fastled-1.4.0}/tests/unit/test_compile_server.py +0 -0
  105. {fastled-1.3.39 → fastled-1.4.0}/tests/unit/test_debug_fetch_source_files.py +0 -0
  106. {fastled-1.3.39 → fastled-1.4.0}/tests/unit/test_docker_linux_on_windows.py +0 -0
  107. {fastled-1.3.39 → fastled-1.4.0}/tests/unit/test_embedded_data.py +0 -0
  108. {fastled-1.3.39 → fastled-1.4.0}/tests/unit/test_filechanger.py +0 -0
  109. {fastled-1.3.39 → fastled-1.4.0}/tests/unit/test_flask_headers.py +0 -0
  110. {fastled-1.3.39 → fastled-1.4.0}/tests/unit/test_http_server.py +0 -0
  111. {fastled-1.3.39 → fastled-1.4.0}/tests/unit/test_ino/bad/bad.ino +0 -0
  112. {fastled-1.3.39 → fastled-1.4.0}/tests/unit/test_ino/bad_platformio/bad_platformio.ino +0 -0
  113. {fastled-1.3.39 → fastled-1.4.0}/tests/unit/test_ino/bad_platformio/platformio.ini +0 -0
  114. {fastled-1.3.39 → fastled-1.4.0}/tests/unit/test_ino/embedded/data/bigdata.dat +0 -0
  115. {fastled-1.3.39 → fastled-1.4.0}/tests/unit/test_ino/embedded/wasm.ino +0 -0
  116. {fastled-1.3.39 → fastled-1.4.0}/tests/unit/test_ino/wasm/wasm.ino +0 -0
  117. {fastled-1.3.39 → fastled-1.4.0}/tests/unit/test_manual_api_invocation.py +0 -0
  118. {fastled-1.3.39 → fastled-1.4.0}/tests/unit/test_no_platformio_compile.py +0 -0
  119. {fastled-1.3.39 → fastled-1.4.0}/tests/unit/test_project_init.py +0 -0
  120. {fastled-1.3.39 → fastled-1.4.0}/tests/unit/test_server_and_client_seperatly.py +0 -0
  121. {fastled-1.3.39 → fastled-1.4.0}/tests/unit/test_session_compile.py +0 -0
  122. {fastled-1.3.39 → fastled-1.4.0}/tests/unit/test_string_diff.py +0 -0
  123. {fastled-1.3.39 → fastled-1.4.0}/tests/unit/test_string_diff_comprehensive.py +0 -0
  124. {fastled-1.3.39 → fastled-1.4.0}/tests/unit/test_version.py +0 -0
  125. {fastled-1.3.39 → fastled-1.4.0}/tests/unit/test_webcompile.py +0 -0
  126. {fastled-1.3.39 → fastled-1.4.0}/upload_package.sh +0 -0
  127. {fastled-1.3.39 → fastled-1.4.0}/vscode-plugin/readme +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: fastled
3
- Version: 1.3.39
3
+ Version: 1.4.0
4
4
  Summary: FastLED Wasm Compiler
5
5
  Home-page: https://github.com/zackees/fastled-wasm
6
6
  Maintainer: Zachary Vorhies
@@ -81,10 +81,10 @@ For enhanced browser control and automation capabilities, you can install the fu
81
81
  $ pip install fastled[full]
82
82
  ```
83
83
 
84
- This enables the `--playwright` flag which opens your compiled sketch in a Playwright-controlled browser instead of your system's default browser:
84
+ When installed, FastLED will automatically use Playwright to open your compiled sketch in a controlled browser environment instead of your system's default browser:
85
85
 
86
86
  ```bash
87
- $ fastled my_sketch --playwright
87
+ $ fastled my_sketch
88
88
  ```
89
89
 
90
90
  The Playwright browser provides better automation capabilities and is especially useful for:
@@ -94,12 +94,13 @@ The Playwright browser provides better automation capabilities and is especially
94
94
  - Persistent browser sessions that stay open until the FastLED process exits
95
95
 
96
96
  **Key Benefits:**
97
+ - Automatically enabled when `fastled[full]` is installed - no additional flags needed
97
98
  - The Playwright browser remains open throughout your development session
98
99
  - Automatic cleanup when the FastLED process exits
99
100
  - Better control over browser behavior and automation capabilities
100
101
  - Consistent behavior across different platforms
101
102
 
102
- If Playwright is not installed and you use the `--playwright` flag, the system will gracefully fall back to your default browser.
103
+ If Playwright is not installed, the system will gracefully fall back to your default browser.
103
104
 
104
105
  # Install
105
106
 
@@ -51,10 +51,10 @@ For enhanced browser control and automation capabilities, you can install the fu
51
51
  $ pip install fastled[full]
52
52
  ```
53
53
 
54
- This enables the `--playwright` flag which opens your compiled sketch in a Playwright-controlled browser instead of your system's default browser:
54
+ When installed, FastLED will automatically use Playwright to open your compiled sketch in a controlled browser environment instead of your system's default browser:
55
55
 
56
56
  ```bash
57
- $ fastled my_sketch --playwright
57
+ $ fastled my_sketch
58
58
  ```
59
59
 
60
60
  The Playwright browser provides better automation capabilities and is especially useful for:
@@ -64,12 +64,13 @@ The Playwright browser provides better automation capabilities and is especially
64
64
  - Persistent browser sessions that stay open until the FastLED process exits
65
65
 
66
66
  **Key Benefits:**
67
+ - Automatically enabled when `fastled[full]` is installed - no additional flags needed
67
68
  - The Playwright browser remains open throughout your development session
68
69
  - Automatic cleanup when the FastLED process exits
69
70
  - Better control over browser behavior and automation capabilities
70
71
  - Consistent behavior across different platforms
71
72
 
72
- If Playwright is not installed and you use the `--playwright` flag, the system will gracefully fall back to your default browser.
73
+ If Playwright is not installed, the system will gracefully fall back to your default browser.
73
74
 
74
75
  # Install
75
76
 
@@ -95,7 +95,6 @@ class Api:
95
95
  no_platformio: bool = False,
96
96
  ) -> CompileServer:
97
97
  """Uses docker to spawn a compile server from the given name."""
98
- from fastled.compile_server import CompileServer
99
98
 
100
99
  out = CompileServer(
101
100
  container_name=container_name,
@@ -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.3.39"
4
+ __version__ = "1.4.0"
5
5
 
6
6
  __version_url_latest__ = "https://raw.githubusercontent.com/zackees/fastled-wasm/refs/heads/main/src/fastled/__version__.py"
@@ -23,8 +23,6 @@ class Args:
23
23
  quick: bool
24
24
  release: bool
25
25
  ram_disk_size: str # suffixed liked "25mb" or "1gb"
26
- playwright: bool = False # Use Playwright browser instead of system default
27
- no_playwright_auto_resize: bool = False # Disable Playwright auto-resize
28
26
  clear = False # Force the last running container to be removed. Useful for benchmarking.
29
27
 
30
28
  @staticmethod
@@ -68,12 +66,6 @@ class Args:
68
66
  assert isinstance(
69
67
  args.release, bool
70
68
  ), f"expected bool, got {type(args.release)}"
71
- assert isinstance(
72
- args.playwright, bool
73
- ), f"expected bool, got {type(args.playwright)}"
74
- assert isinstance(
75
- args.no_playwright_auto_resize, bool
76
- ), f"expected bool, got {type(args.no_playwright_auto_resize)}"
77
69
 
78
70
  init: bool | str = False
79
71
  if args.init is None:
@@ -101,6 +93,4 @@ class Args:
101
93
  quick=args.quick,
102
94
  release=args.release,
103
95
  ram_disk_size=args.ram_disk_size,
104
- playwright=args.playwright,
105
- no_playwright_auto_resize=args.no_playwright_auto_resize,
106
96
  )
@@ -25,6 +25,16 @@ from fastled.web_compile import (
25
25
  )
26
26
 
27
27
 
28
+ def _always_false() -> bool:
29
+ return False
30
+
31
+
32
+ try:
33
+ from fastled.playwright_browser import is_playwright_available
34
+ except ImportError:
35
+ is_playwright_available = _always_false
36
+
37
+
28
38
  def _create_error_html(error_message: str) -> str:
29
39
  return f"""<!DOCTYPE html>
30
40
  <html>
@@ -258,8 +268,6 @@ def run_client(
258
268
  ) = None, # None means auto select a free port, http_port < 0 means no server.
259
269
  clear: bool = False,
260
270
  no_platformio: bool = False,
261
- use_playwright: bool = False,
262
- playwright_auto_resize: bool = True,
263
271
  ) -> int:
264
272
  has_checked_newer_version_yet = False
265
273
  compile_server: CompileServer | None = None
@@ -340,8 +348,6 @@ def run_client(
340
348
  port=http_port,
341
349
  compile_server_port=port,
342
350
  open_browser=open_web_browser,
343
- use_playwright=use_playwright,
344
- playwright_auto_resize=playwright_auto_resize,
345
351
  )
346
352
  else:
347
353
  print("\nCompilation successful.")
@@ -564,8 +570,6 @@ def run_client_server(args: Args) -> int:
564
570
  profile=profile,
565
571
  clear=args.clear,
566
572
  no_platformio=no_platformio,
567
- use_playwright=args.playwright,
568
- playwright_auto_resize=not args.no_playwright_auto_resize,
569
573
  )
570
574
  except KeyboardInterrupt:
571
575
  return 1
@@ -101,8 +101,6 @@ def spawn_http_server(
101
101
  compile_server_port: int,
102
102
  port: int | None = None,
103
103
  open_browser: bool = True,
104
- use_playwright: bool = False,
105
- playwright_auto_resize: bool = True,
106
104
  ) -> Process:
107
105
 
108
106
  if port is not None and not is_port_free(port):
@@ -131,28 +129,13 @@ def spawn_http_server(
131
129
  wait_for_server(port)
132
130
  if open_browser:
133
131
  url = f"http://localhost:{port}"
134
- if use_playwright and PLAYWRIGHT_AVAILABLE and open_with_playwright is not None:
132
+ if PLAYWRIGHT_AVAILABLE and open_with_playwright is not None:
135
133
  print(f"Opening FastLED sketch in Playwright browser: {url}")
136
- if playwright_auto_resize:
137
- print(
138
- "Auto-resize enabled: Browser window will automatically adjust to content size"
139
- )
140
- global _playwright_browser_proxy
141
- _playwright_browser_proxy = open_with_playwright(
142
- url, auto_resize=playwright_auto_resize
143
- )
144
- elif use_playwright and not PLAYWRIGHT_AVAILABLE:
145
134
  print(
146
- "Playwright requested but not available. Install with: pip install fastled[full]"
147
- )
148
- print(f"Falling back to system browser: {url}")
149
- import webbrowser
150
-
151
- webbrowser.open(
152
- url=url,
153
- new=1,
154
- autoraise=True,
135
+ "Auto-resize enabled: Browser window will automatically adjust to content size"
155
136
  )
137
+ global _playwright_browser_proxy
138
+ _playwright_browser_proxy = open_with_playwright(url)
156
139
  else:
157
140
  print(f"Opening browser to {url}")
158
141
  import webbrowser
@@ -35,15 +35,12 @@ FastLED WASM Compiler - Useful options:
35
35
  --profile Enable profiling the C++ build system
36
36
  --update Update the docker image for the wasm compiler
37
37
  --purge Remove all FastLED containers and images
38
- --playwright Use Playwright browser (requires 'pip install fastled[full]')
39
- --no-playwright-auto-resize Disable automatic window resizing in Playwright
40
38
  --version Show version information
41
39
  --help Show detailed help
42
40
  Examples:
43
41
  fastled (will auto detect the sketch directory and prompt you)
44
42
  fastled my_sketch
45
43
  fastled my_sketch --web (compiles using the web compiler only)
46
- fastled my_sketch --playwright (opens in Playwright browser)
47
44
  fastled --init Blink (initializes a new sketch directory with the Blink example)
48
45
  fastled --server (runs the compiler server in the current directory)
49
46
 
@@ -85,8 +82,8 @@ def parse_args() -> Args:
85
82
  parser.add_argument(
86
83
  "--ram-disk-size",
87
84
  type=str,
88
- default="0",
89
- help="Set the size of the ramdisk for the docker container. Use suffixes like '25mb' or '1gb'.",
85
+ default="1gb",
86
+ help="Size of the RAM disk for compilation (e.g., '1gb', '512mb')",
90
87
  )
91
88
  parser.add_argument(
92
89
  "--web",
@@ -116,7 +113,7 @@ def parse_args() -> Args:
116
113
  parser.add_argument(
117
114
  "--no-auto-updates",
118
115
  action="store_true",
119
- help="Disable automatic updates of the wasm compiler image when using docker.",
116
+ help="Disable automatic updates of the wasm compiler image when using docker. (Default: False)",
120
117
  )
121
118
  parser.add_argument(
122
119
  "--no-platformio",
@@ -161,18 +158,6 @@ def parse_args() -> Args:
161
158
  help="Remove all FastLED containers and images",
162
159
  )
163
160
 
164
- parser.add_argument(
165
- "--playwright",
166
- action="store_true",
167
- help="Use Playwright browser instead of system default (requires 'pip install fastled[full]')",
168
- )
169
-
170
- parser.add_argument(
171
- "--no-playwright-auto-resize",
172
- action="store_true",
173
- help="Disable automatic window resizing in Playwright browser",
174
- )
175
-
176
161
  build_mode = parser.add_mutually_exclusive_group()
177
162
  build_mode.add_argument("--debug", action="store_true", help="Build in debug mode")
178
163
  build_mode.add_argument(
@@ -33,26 +33,23 @@ def is_playwright_available() -> bool:
33
33
  class PlaywrightBrowser:
34
34
  """Playwright browser manager for FastLED sketches."""
35
35
 
36
- def __init__(self, headless: bool = False, auto_resize: bool = True):
36
+ def __init__(self, headless: bool = False):
37
37
  """Initialize the Playwright browser manager.
38
38
 
39
39
  Args:
40
40
  headless: Whether to run the browser in headless mode
41
- auto_resize: Whether to automatically resize the browser window to fit content
42
41
  """
43
42
  if not PLAYWRIGHT_AVAILABLE:
44
43
  raise ImportError(
45
44
  "Playwright is not installed. Install with: pip install fastled[full]"
46
45
  )
47
46
 
48
- # debug
49
- auto_resize = True
50
-
51
47
  self.headless = headless
52
- self.auto_resize = auto_resize
48
+ self.auto_resize = True # Always enable auto-resize
53
49
  self.browser: Any = None
54
50
  self.page: Any = None
55
51
  self.playwright: Any = None
52
+ self._should_exit = asyncio.Event()
56
53
 
57
54
  async def start(self) -> None:
58
55
  """Start the Playwright browser."""
@@ -158,8 +155,9 @@ class PlaywrightBrowser:
158
155
 
159
156
  # Check if page is still alive
160
157
  if self.page is None or self.page.is_closed():
161
- print("[PYTHON] Page closed, stopping browser tracking")
162
- break
158
+ print("[PYTHON] Page closed, signaling exit")
159
+ self._should_exit.set()
160
+ return
163
161
 
164
162
  # Get browser window dimensions
165
163
  window_info = await self._get_window_info()
@@ -258,15 +256,12 @@ class PlaywrightBrowser:
258
256
  self.playwright = None
259
257
 
260
258
 
261
- def run_playwright_browser(
262
- url: str, headless: bool = False, auto_resize: bool = True
263
- ) -> None:
259
+ def run_playwright_browser(url: str, headless: bool = False) -> None:
264
260
  """Run Playwright browser in a separate process.
265
261
 
266
262
  Args:
267
263
  url: The URL to open
268
264
  headless: Whether to run in headless mode
269
- auto_resize: Whether to automatically resize the browser window to fit content
270
265
  """
271
266
  if not PLAYWRIGHT_AVAILABLE:
272
267
  warnings.warn(
@@ -276,7 +271,7 @@ def run_playwright_browser(
276
271
  return
277
272
 
278
273
  async def main():
279
- browser = PlaywrightBrowser(headless=headless, auto_resize=auto_resize)
274
+ browser = PlaywrightBrowser(headless=headless)
280
275
  try:
281
276
  await browser.start()
282
277
  await browser.open_url(url)
@@ -309,14 +304,15 @@ class PlaywrightBrowserProxy:
309
304
  def __init__(self):
310
305
  self.process = None
311
306
  self.browser_manager = None
307
+ self.monitor_thread = None
308
+ self._closing_intentionally = False
312
309
 
313
- def open(self, url: str, headless: bool = False, auto_resize: bool = True) -> None:
310
+ def open(self, url: str, headless: bool = False) -> None:
314
311
  """Open URL with Playwright browser and keep it alive.
315
312
 
316
313
  Args:
317
314
  url: The URL to open
318
315
  headless: Whether to run in headless mode
319
- auto_resize: Whether to automatically resize the browser window to fit content
320
316
  """
321
317
  if not PLAYWRIGHT_AVAILABLE:
322
318
  warnings.warn(
@@ -335,10 +331,13 @@ class PlaywrightBrowserProxy:
335
331
 
336
332
  self.process = multiprocessing.Process(
337
333
  target=run_playwright_browser_persistent,
338
- args=(url, headless, auto_resize),
334
+ args=(url, headless),
339
335
  )
340
336
  self.process.start()
341
337
 
338
+ # Start monitoring thread to exit main process when browser subprocess exits
339
+ self._start_monitor_thread()
340
+
342
341
  # Register cleanup
343
342
  import atexit
344
343
 
@@ -352,10 +351,44 @@ class PlaywrightBrowserProxy:
352
351
 
353
352
  webbrowser.open(url)
354
353
 
354
+ def _start_monitor_thread(self) -> None:
355
+ """Start a thread to monitor the browser process and exit main process when it terminates."""
356
+ if self.monitor_thread is not None:
357
+ return
358
+
359
+ import os
360
+ import threading
361
+
362
+ def monitor_process():
363
+ """Monitor the browser process and exit when it terminates."""
364
+ if self.process is None:
365
+ return
366
+
367
+ try:
368
+ # Wait for the process to terminate
369
+ self.process.join()
370
+
371
+ # Check if the process terminated (and we didn't kill it ourselves)
372
+ if (
373
+ self.process.exitcode is not None
374
+ and not self._closing_intentionally
375
+ ):
376
+ print("[MAIN] Browser closed, exiting main program")
377
+ # Force exit the entire program
378
+ os._exit(0)
379
+
380
+ except Exception as e:
381
+ print(f"[MAIN] Error monitoring browser process: {e}")
382
+
383
+ self.monitor_thread = threading.Thread(target=monitor_process, daemon=True)
384
+ self.monitor_thread.start()
385
+
355
386
  def close(self) -> None:
356
387
  """Close the Playwright browser."""
357
388
  if self.process and self.process.is_alive():
358
389
  print("Closing Playwright browser...")
390
+ # Mark that we're intentionally closing to prevent monitor from triggering exit
391
+ self._closing_intentionally = True
359
392
  self.process.terminate()
360
393
  self.process.join(timeout=5)
361
394
  if self.process.is_alive():
@@ -363,21 +396,18 @@ class PlaywrightBrowserProxy:
363
396
  self.process = None
364
397
 
365
398
 
366
- def run_playwright_browser_persistent(
367
- url: str, headless: bool = False, auto_resize: bool = True
368
- ) -> None:
399
+ def run_playwright_browser_persistent(url: str, headless: bool = False) -> None:
369
400
  """Run Playwright browser in a persistent mode that stays alive until terminated.
370
401
 
371
402
  Args:
372
403
  url: The URL to open
373
404
  headless: Whether to run in headless mode
374
- auto_resize: Whether to automatically resize the browser window to fit content
375
405
  """
376
406
  if not PLAYWRIGHT_AVAILABLE:
377
407
  return
378
408
 
379
409
  async def main():
380
- browser = PlaywrightBrowser(headless=headless, auto_resize=auto_resize)
410
+ browser = PlaywrightBrowser(headless=headless)
381
411
  try:
382
412
  await browser.start()
383
413
  await browser.open_url(url)
@@ -386,9 +416,9 @@ def run_playwright_browser_persistent(
386
416
  "Playwright browser opened. Browser will remain open until the FastLED process exits."
387
417
  )
388
418
 
389
- # Keep the browser alive indefinitely
390
- while True:
391
- await asyncio.sleep(1)
419
+ # Keep the browser alive until exit is signaled
420
+ while not browser._should_exit.is_set():
421
+ await asyncio.sleep(0.1)
392
422
 
393
423
  except KeyboardInterrupt:
394
424
  print("\nClosing Playwright browser...")
@@ -405,9 +435,7 @@ def run_playwright_browser_persistent(
405
435
  print(f"Playwright browser failed: {e}")
406
436
 
407
437
 
408
- def open_with_playwright(
409
- url: str, headless: bool = False, auto_resize: bool = True
410
- ) -> PlaywrightBrowserProxy:
438
+ def open_with_playwright(url: str, headless: bool = False) -> PlaywrightBrowserProxy:
411
439
  """Open URL with Playwright browser and return a proxy object for lifecycle management.
412
440
 
413
441
  This function can be used as a drop-in replacement for webbrowser.open().
@@ -415,13 +443,12 @@ def open_with_playwright(
415
443
  Args:
416
444
  url: The URL to open
417
445
  headless: Whether to run in headless mode
418
- auto_resize: Whether to automatically resize the browser window to fit content
419
446
 
420
447
  Returns:
421
448
  PlaywrightBrowserProxy object for managing the browser lifecycle
422
449
  """
423
450
  proxy = PlaywrightBrowserProxy()
424
- proxy.open(url, headless, auto_resize)
451
+ proxy.open(url, headless)
425
452
  return proxy
426
453
 
427
454
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: fastled
3
- Version: 1.3.39
3
+ Version: 1.4.0
4
4
  Summary: FastLED Wasm Compiler
5
5
  Home-page: https://github.com/zackees/fastled-wasm
6
6
  Maintainer: Zachary Vorhies
@@ -81,10 +81,10 @@ For enhanced browser control and automation capabilities, you can install the fu
81
81
  $ pip install fastled[full]
82
82
  ```
83
83
 
84
- This enables the `--playwright` flag which opens your compiled sketch in a Playwright-controlled browser instead of your system's default browser:
84
+ When installed, FastLED will automatically use Playwright to open your compiled sketch in a controlled browser environment instead of your system's default browser:
85
85
 
86
86
  ```bash
87
- $ fastled my_sketch --playwright
87
+ $ fastled my_sketch
88
88
  ```
89
89
 
90
90
  The Playwright browser provides better automation capabilities and is especially useful for:
@@ -94,12 +94,13 @@ The Playwright browser provides better automation capabilities and is especially
94
94
  - Persistent browser sessions that stay open until the FastLED process exits
95
95
 
96
96
  **Key Benefits:**
97
+ - Automatically enabled when `fastled[full]` is installed - no additional flags needed
97
98
  - The Playwright browser remains open throughout your development session
98
99
  - Automatic cleanup when the FastLED process exits
99
100
  - Better control over browser behavior and automation capabilities
100
101
  - Consistent behavior across different platforms
101
102
 
102
- If Playwright is not installed and you use the `--playwright` flag, the system will gracefully fall back to your default browser.
103
+ If Playwright is not installed, the system will gracefully fall back to your default browser.
103
104
 
104
105
  # Install
105
106
 
@@ -56,64 +56,6 @@ class PlaywrightIntegrationTester(unittest.TestCase):
56
56
  # Test cleanup
57
57
  proxy.close() # Should not raise an exception
58
58
 
59
- def test_args_integration(self):
60
- """Test that the playwright argument is properly integrated into the Args class."""
61
- import argparse
62
-
63
- from fastled.args import Args
64
-
65
- # Create a mock namespace with the playwright argument
66
- namespace = argparse.Namespace()
67
- namespace.directory = None
68
- namespace.init = None
69
- namespace.just_compile = False
70
- namespace.web = None
71
- namespace.interactive = False
72
- namespace.profile = False
73
- namespace.force_compile = False
74
- namespace.no_platformio = False
75
- namespace.no_auto_updates = False
76
- namespace.update = False
77
- namespace.localhost = False
78
- namespace.build = False
79
- namespace.server = False
80
- namespace.purge = False
81
- namespace.debug = False
82
- namespace.quick = False
83
- namespace.release = False
84
- namespace.ram_disk_size = "0"
85
- namespace.playwright = True
86
-
87
- # Create Args from namespace
88
- args = Args.from_namespace(namespace)
89
-
90
- # Verify the playwright flag is set
91
- self.assertTrue(args.playwright)
92
-
93
- def test_parse_args_playwright_flag(self):
94
- """Test that the --playwright flag is properly parsed."""
95
- import sys
96
-
97
- from fastled.parse_args import parse_args
98
-
99
- # Save original argv
100
- original_argv = sys.argv
101
-
102
- try:
103
- # Test with --playwright flag
104
- sys.argv = ["fastled", "test_dir", "--playwright"]
105
- args = parse_args()
106
- self.assertTrue(args.playwright)
107
-
108
- # Test without --playwright flag
109
- sys.argv = ["fastled", "test_dir"]
110
- args = parse_args()
111
- self.assertFalse(args.playwright)
112
-
113
- finally:
114
- # Restore original argv
115
- sys.argv = original_argv
116
-
117
59
 
118
60
  if __name__ == "__main__":
119
61
  unittest.main()
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