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.
- {fastled-1.4.0 → fastled-1.4.2}/PKG-INFO +2 -1
- {fastled-1.4.0 → fastled-1.4.2}/README.md +1 -0
- {fastled-1.4.0 → fastled-1.4.2}/src/fastled/__init__.py +4 -0
- {fastled-1.4.0 → fastled-1.4.2}/src/fastled/__version__.py +1 -1
- {fastled-1.4.0 → fastled-1.4.2}/src/fastled/app.py +5 -0
- {fastled-1.4.0 → fastled-1.4.2}/src/fastled/args.py +5 -0
- {fastled-1.4.0 → fastled-1.4.2}/src/fastled/client_server.py +4 -0
- {fastled-1.4.0 → fastled-1.4.2}/src/fastled/live_client.py +3 -0
- {fastled-1.4.0 → fastled-1.4.2}/src/fastled/open_browser.py +6 -1
- {fastled-1.4.0 → fastled-1.4.2}/src/fastled/parse_args.py +5 -0
- {fastled-1.4.0 → fastled-1.4.2}/src/fastled/playwright_browser.py +94 -26
- {fastled-1.4.0 → fastled-1.4.2}/src/fastled.egg-info/PKG-INFO +2 -1
- {fastled-1.4.0 → fastled-1.4.2}/.aiderignore +0 -0
- {fastled-1.4.0 → fastled-1.4.2}/.cursorrules +0 -0
- {fastled-1.4.0 → fastled-1.4.2}/.dockerignore +0 -0
- {fastled-1.4.0 → fastled-1.4.2}/.github/workflows/build_multi_docker_image.yml +0 -0
- {fastled-1.4.0 → fastled-1.4.2}/.github/workflows/build_webpage.yml +0 -0
- {fastled-1.4.0 → fastled-1.4.2}/.github/workflows/lint.yml +0 -0
- {fastled-1.4.0 → fastled-1.4.2}/.github/workflows/publish_release.yml +0 -0
- {fastled-1.4.0 → fastled-1.4.2}/.github/workflows/template_build_docker_image.yml +0 -0
- {fastled-1.4.0 → fastled-1.4.2}/.github/workflows/test_build_exe.yml +0 -0
- {fastled-1.4.0 → fastled-1.4.2}/.github/workflows/test_macos.yml +0 -0
- {fastled-1.4.0 → fastled-1.4.2}/.github/workflows/test_ubuntu.yml +0 -0
- {fastled-1.4.0 → fastled-1.4.2}/.github/workflows/test_win.yml +0 -0
- {fastled-1.4.0 → fastled-1.4.2}/.gitignore +0 -0
- {fastled-1.4.0 → fastled-1.4.2}/.pylintrc +0 -0
- {fastled-1.4.0 → fastled-1.4.2}/.vscode/launch.json +0 -0
- {fastled-1.4.0 → fastled-1.4.2}/.vscode/settings.json +0 -0
- {fastled-1.4.0 → fastled-1.4.2}/.vscode/tasks.json +0 -0
- {fastled-1.4.0 → fastled-1.4.2}/DEBUGGER.md +0 -0
- {fastled-1.4.0 → fastled-1.4.2}/Dockerfile +0 -0
- {fastled-1.4.0 → fastled-1.4.2}/FAQ.md +0 -0
- {fastled-1.4.0 → fastled-1.4.2}/LICENSE +0 -0
- {fastled-1.4.0 → fastled-1.4.2}/MANIFEST.in +0 -0
- {fastled-1.4.0 → fastled-1.4.2}/RELEASE.md +0 -0
- {fastled-1.4.0 → fastled-1.4.2}/TODO.md +0 -0
- {fastled-1.4.0 → fastled-1.4.2}/build_exe.py +0 -0
- {fastled-1.4.0 → fastled-1.4.2}/build_local_docker.py +0 -0
- {fastled-1.4.0 → fastled-1.4.2}/build_site.py +0 -0
- {fastled-1.4.0 → fastled-1.4.2}/clean +0 -0
- {fastled-1.4.0 → fastled-1.4.2}/compiler/debug.sh +0 -0
- {fastled-1.4.0 → fastled-1.4.2}/compiler/run.py +0 -0
- {fastled-1.4.0 → fastled-1.4.2}/demo/100dots.html +0 -0
- {fastled-1.4.0 → fastled-1.4.2}/demo/demo_threejs.html +0 -0
- {fastled-1.4.0 → fastled-1.4.2}/demo/micdemo.html +0 -0
- {fastled-1.4.0 → fastled-1.4.2}/demo/mp3upload.html +0 -0
- {fastled-1.4.0 → fastled-1.4.2}/demo/webgl_postprocessing_unreal_bloom.html +0 -0
- {fastled-1.4.0 → fastled-1.4.2}/docker-compose.yml +0 -0
- {fastled-1.4.0 → fastled-1.4.2}/entrypoint.sh +0 -0
- {fastled-1.4.0 → fastled-1.4.2}/install +0 -0
- {fastled-1.4.0 → fastled-1.4.2}/install_linux.sh +0 -0
- {fastled-1.4.0 → fastled-1.4.2}/lint +0 -0
- {fastled-1.4.0 → fastled-1.4.2}/pyproject.toml +0 -0
- {fastled-1.4.0 → fastled-1.4.2}/requirements.docker.txt +0 -0
- {fastled-1.4.0 → fastled-1.4.2}/requirements.testing.txt +0 -0
- {fastled-1.4.0 → fastled-1.4.2}/setup.cfg +0 -0
- {fastled-1.4.0 → fastled-1.4.2}/setup.py +0 -0
- {fastled-1.4.0 → fastled-1.4.2}/src/fastled/__main__.py +0 -0
- {fastled-1.4.0 → fastled-1.4.2}/src/fastled/assets/example.txt +0 -0
- {fastled-1.4.0 → fastled-1.4.2}/src/fastled/assets/localhost-key.pem +0 -0
- {fastled-1.4.0 → fastled-1.4.2}/src/fastled/assets/localhost.pem +0 -0
- {fastled-1.4.0 → fastled-1.4.2}/src/fastled/cli.py +0 -0
- {fastled-1.4.0 → fastled-1.4.2}/src/fastled/cli_test.py +0 -0
- {fastled-1.4.0 → fastled-1.4.2}/src/fastled/cli_test_interactive.py +0 -0
- {fastled-1.4.0 → fastled-1.4.2}/src/fastled/compile_server.py +0 -0
- {fastled-1.4.0 → fastled-1.4.2}/src/fastled/compile_server_impl.py +0 -0
- {fastled-1.4.0 → fastled-1.4.2}/src/fastled/docker_manager.py +0 -0
- {fastled-1.4.0 → fastled-1.4.2}/src/fastled/filewatcher.py +0 -0
- {fastled-1.4.0 → fastled-1.4.2}/src/fastled/keyboard.py +0 -0
- {fastled-1.4.0 → fastled-1.4.2}/src/fastled/keyz.py +0 -0
- {fastled-1.4.0 → fastled-1.4.2}/src/fastled/paths.py +0 -0
- {fastled-1.4.0 → fastled-1.4.2}/src/fastled/print_filter.py +0 -0
- {fastled-1.4.0 → fastled-1.4.2}/src/fastled/project_init.py +0 -0
- {fastled-1.4.0 → fastled-1.4.2}/src/fastled/select_sketch_directory.py +0 -0
- {fastled-1.4.0 → fastled-1.4.2}/src/fastled/server_flask.py +0 -0
- {fastled-1.4.0 → fastled-1.4.2}/src/fastled/server_start.py +0 -0
- {fastled-1.4.0 → fastled-1.4.2}/src/fastled/settings.py +0 -0
- {fastled-1.4.0 → fastled-1.4.2}/src/fastled/site/build.py +0 -0
- {fastled-1.4.0 → fastled-1.4.2}/src/fastled/site/examples.py +0 -0
- {fastled-1.4.0 → fastled-1.4.2}/src/fastled/sketch.py +0 -0
- {fastled-1.4.0 → fastled-1.4.2}/src/fastled/spinner.py +0 -0
- {fastled-1.4.0 → fastled-1.4.2}/src/fastled/string_diff.py +0 -0
- {fastled-1.4.0 → fastled-1.4.2}/src/fastled/test/can_run_local_docker_tests.py +0 -0
- {fastled-1.4.0 → fastled-1.4.2}/src/fastled/test/examples.py +0 -0
- {fastled-1.4.0 → fastled-1.4.2}/src/fastled/types.py +0 -0
- {fastled-1.4.0 → fastled-1.4.2}/src/fastled/util.py +0 -0
- {fastled-1.4.0 → fastled-1.4.2}/src/fastled/version.py +0 -0
- {fastled-1.4.0 → fastled-1.4.2}/src/fastled/web_compile.py +0 -0
- {fastled-1.4.0 → fastled-1.4.2}/src/fastled.egg-info/SOURCES.txt +0 -0
- {fastled-1.4.0 → fastled-1.4.2}/src/fastled.egg-info/dependency_links.txt +0 -0
- {fastled-1.4.0 → fastled-1.4.2}/src/fastled.egg-info/entry_points.txt +0 -0
- {fastled-1.4.0 → fastled-1.4.2}/src/fastled.egg-info/requires.txt +0 -0
- {fastled-1.4.0 → fastled-1.4.2}/src/fastled.egg-info/top_level.txt +0 -0
- {fastled-1.4.0 → fastled-1.4.2}/test +0 -0
- {fastled-1.4.0 → fastled-1.4.2}/tests/integration/test_build_examples.py +0 -0
- {fastled-1.4.0 → fastled-1.4.2}/tests/integration/test_examples.py +0 -0
- {fastled-1.4.0 → fastled-1.4.2}/tests/integration/test_playwright_integration.py +0 -0
- {fastled-1.4.0 → fastled-1.4.2}/tests/unit/html/index.html +0 -0
- {fastled-1.4.0 → fastled-1.4.2}/tests/unit/test_api.py +0 -0
- {fastled-1.4.0 → fastled-1.4.2}/tests/unit/test_bad_ino.py +0 -0
- {fastled-1.4.0 → fastled-1.4.2}/tests/unit/test_banner_string.py +0 -0
- {fastled-1.4.0 → fastled-1.4.2}/tests/unit/test_cli.py +0 -0
- {fastled-1.4.0 → fastled-1.4.2}/tests/unit/test_cli_no_platformio.py +0 -0
- {fastled-1.4.0 → fastled-1.4.2}/tests/unit/test_compile_server.py +0 -0
- {fastled-1.4.0 → fastled-1.4.2}/tests/unit/test_debug_fetch_source_files.py +0 -0
- {fastled-1.4.0 → fastled-1.4.2}/tests/unit/test_docker_linux_on_windows.py +0 -0
- {fastled-1.4.0 → fastled-1.4.2}/tests/unit/test_embedded_data.py +0 -0
- {fastled-1.4.0 → fastled-1.4.2}/tests/unit/test_filechanger.py +0 -0
- {fastled-1.4.0 → fastled-1.4.2}/tests/unit/test_flask_headers.py +0 -0
- {fastled-1.4.0 → fastled-1.4.2}/tests/unit/test_http_server.py +0 -0
- {fastled-1.4.0 → fastled-1.4.2}/tests/unit/test_ino/bad/bad.ino +0 -0
- {fastled-1.4.0 → fastled-1.4.2}/tests/unit/test_ino/bad_platformio/bad_platformio.ino +0 -0
- {fastled-1.4.0 → fastled-1.4.2}/tests/unit/test_ino/bad_platformio/platformio.ini +0 -0
- {fastled-1.4.0 → fastled-1.4.2}/tests/unit/test_ino/embedded/data/bigdata.dat +0 -0
- {fastled-1.4.0 → fastled-1.4.2}/tests/unit/test_ino/embedded/wasm.ino +0 -0
- {fastled-1.4.0 → fastled-1.4.2}/tests/unit/test_ino/wasm/wasm.ino +0 -0
- {fastled-1.4.0 → fastled-1.4.2}/tests/unit/test_manual_api_invocation.py +0 -0
- {fastled-1.4.0 → fastled-1.4.2}/tests/unit/test_no_platformio_compile.py +0 -0
- {fastled-1.4.0 → fastled-1.4.2}/tests/unit/test_project_init.py +0 -0
- {fastled-1.4.0 → fastled-1.4.2}/tests/unit/test_server_and_client_seperatly.py +0 -0
- {fastled-1.4.0 → fastled-1.4.2}/tests/unit/test_session_compile.py +0 -0
- {fastled-1.4.0 → fastled-1.4.2}/tests/unit/test_string_diff.py +0 -0
- {fastled-1.4.0 → fastled-1.4.2}/tests/unit/test_string_diff_comprehensive.py +0 -0
- {fastled-1.4.0 → fastled-1.4.2}/tests/unit/test_version.py +0 -0
- {fastled-1.4.0 → fastled-1.4.2}/tests/unit/test_webcompile.py +0 -0
- {fastled-1.4.0 → fastled-1.4.2}/upload_package.sh +0 -0
- {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.
|
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.
|
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
|
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
|
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
|
-
|
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
|
14
|
+
from pathlib import Path
|
15
|
+
from typing import Any
|
13
16
|
|
14
|
-
|
15
|
-
|
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 =
|
25
|
-
Page =
|
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 =
|
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
|
-
|
280
|
-
|
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
|
-
|
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
|
-
|
297
|
-
|
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 =
|
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
|
-
|
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.
|
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
|
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
|
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
|