fastled 1.3.30__py3-none-any.whl → 1.4.50__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 +30 -2
- fastled/__main__.py +14 -0
- fastled/__version__.py +1 -1
- fastled/app.py +51 -2
- fastled/args.py +33 -0
- fastled/client_server.py +188 -40
- fastled/compile_server.py +10 -0
- fastled/compile_server_impl.py +34 -1
- fastled/docker_manager.py +56 -14
- fastled/emoji_util.py +27 -0
- fastled/filewatcher.py +6 -3
- fastled/find_good_connection.py +105 -0
- fastled/header_dump.py +63 -0
- fastled/install/__init__.py +1 -0
- fastled/install/examples_manager.py +62 -0
- fastled/install/extension_manager.py +113 -0
- fastled/install/main.py +156 -0
- fastled/install/project_detection.py +167 -0
- fastled/install/test_install.py +373 -0
- fastled/install/vscode_config.py +344 -0
- fastled/interruptible_http.py +148 -0
- fastled/live_client.py +21 -1
- fastled/open_browser.py +84 -16
- fastled/parse_args.py +110 -9
- fastled/playwright/chrome_extension_downloader.py +207 -0
- fastled/playwright/playwright_browser.py +773 -0
- fastled/playwright/resize_tracking.py +127 -0
- fastled/print_filter.py +52 -52
- fastled/project_init.py +20 -13
- fastled/select_sketch_directory.py +142 -19
- fastled/server_flask.py +37 -1
- fastled/settings.py +47 -3
- fastled/sketch.py +121 -4
- fastled/string_diff.py +162 -26
- fastled/test/examples.py +7 -5
- fastled/types.py +4 -0
- fastled/util.py +34 -0
- fastled/version.py +41 -41
- fastled/web_compile.py +379 -236
- fastled/zip_files.py +76 -0
- {fastled-1.3.30.dist-info → fastled-1.4.50.dist-info}/METADATA +533 -508
- fastled-1.4.50.dist-info/RECORD +60 -0
- fastled-1.3.30.dist-info/RECORD +0 -44
- {fastled-1.3.30.dist-info → fastled-1.4.50.dist-info}/WHEEL +0 -0
- {fastled-1.3.30.dist-info → fastled-1.4.50.dist-info}/entry_points.txt +0 -0
- {fastled-1.3.30.dist-info → fastled-1.4.50.dist-info}/licenses/LICENSE +0 -0
- {fastled-1.3.30.dist-info → fastled-1.4.50.dist-info}/top_level.txt +0 -0
fastled/__init__.py
CHANGED
|
@@ -7,6 +7,7 @@ from typing import Generator
|
|
|
7
7
|
|
|
8
8
|
from .__version__ import __version__
|
|
9
9
|
from .compile_server import CompileServer
|
|
10
|
+
from .emoji_util import EMO
|
|
10
11
|
from .live_client import LiveClient
|
|
11
12
|
from .settings import DOCKER_FILE, IMAGE_NAME
|
|
12
13
|
from .site.build import build
|
|
@@ -39,15 +40,31 @@ class Api:
|
|
|
39
40
|
host: str | CompileServer | None = None,
|
|
40
41
|
build_mode: BuildMode = BuildMode.QUICK,
|
|
41
42
|
profile: bool = False, # When true then profile information will be enabled and included in the zip.
|
|
43
|
+
no_platformio: bool = False,
|
|
42
44
|
) -> CompileResult:
|
|
45
|
+
from fastled.sketch import looks_like_fastled_repo
|
|
43
46
|
from fastled.web_compile import web_compile
|
|
44
47
|
|
|
45
48
|
if isinstance(host, CompileServer):
|
|
46
49
|
host = host.url()
|
|
47
50
|
if isinstance(directory, str):
|
|
48
51
|
directory = Path(directory)
|
|
52
|
+
|
|
53
|
+
# Guard: libfastled compilation requires volume source mapping
|
|
54
|
+
# Only allow libcompile if we're in a FastLED repository
|
|
55
|
+
allow_libcompile = looks_like_fastled_repo(Path(".").resolve())
|
|
56
|
+
if not allow_libcompile:
|
|
57
|
+
print(
|
|
58
|
+
f"{EMO('⚠️', 'WARNING:')} libfastled compilation disabled: not running in FastLED repository"
|
|
59
|
+
)
|
|
60
|
+
|
|
49
61
|
out: CompileResult = web_compile(
|
|
50
|
-
directory,
|
|
62
|
+
directory,
|
|
63
|
+
host,
|
|
64
|
+
build_mode=build_mode,
|
|
65
|
+
profile=profile,
|
|
66
|
+
no_platformio=no_platformio,
|
|
67
|
+
allow_libcompile=allow_libcompile,
|
|
51
68
|
)
|
|
52
69
|
return out
|
|
53
70
|
|
|
@@ -64,6 +81,8 @@ class Api:
|
|
|
64
81
|
http_port: (
|
|
65
82
|
int | None
|
|
66
83
|
) = None, # None means auto select a free port. -1 means no server.
|
|
84
|
+
no_platformio: bool = False,
|
|
85
|
+
enable_https: bool = True, # Enable HTTPS for the local server
|
|
67
86
|
) -> LiveClient:
|
|
68
87
|
return LiveClient(
|
|
69
88
|
sketch_directory=sketch_directory,
|
|
@@ -75,6 +94,8 @@ class Api:
|
|
|
75
94
|
build_mode=build_mode,
|
|
76
95
|
profile=profile,
|
|
77
96
|
http_port=http_port,
|
|
97
|
+
no_platformio=no_platformio,
|
|
98
|
+
enable_https=enable_https,
|
|
78
99
|
)
|
|
79
100
|
|
|
80
101
|
@staticmethod
|
|
@@ -85,9 +106,9 @@ class Api:
|
|
|
85
106
|
mapped_dir: Path | None = None, # Sketch directory.
|
|
86
107
|
container_name: str | None = None, # Specific docker container name.
|
|
87
108
|
remove_previous: bool = False,
|
|
109
|
+
no_platformio: bool = False,
|
|
88
110
|
) -> CompileServer:
|
|
89
111
|
"""Uses docker to spawn a compile server from the given name."""
|
|
90
|
-
from fastled.compile_server import CompileServer
|
|
91
112
|
|
|
92
113
|
out = CompileServer(
|
|
93
114
|
container_name=container_name,
|
|
@@ -96,6 +117,7 @@ class Api:
|
|
|
96
117
|
mapped_dir=mapped_dir,
|
|
97
118
|
auto_start=auto_start,
|
|
98
119
|
remove_previous=remove_previous,
|
|
120
|
+
no_platformio=no_platformio,
|
|
99
121
|
)
|
|
100
122
|
return out
|
|
101
123
|
|
|
@@ -108,6 +130,7 @@ class Api:
|
|
|
108
130
|
mapped_dir: Path | None = None, # Sketch directory.
|
|
109
131
|
container_name: str | None = None, # Specific docker container name.
|
|
110
132
|
remove_previous=False,
|
|
133
|
+
no_platformio: bool = False,
|
|
111
134
|
) -> Generator[CompileServer, None, None]:
|
|
112
135
|
server = Api.spawn_server(
|
|
113
136
|
interactive=interactive,
|
|
@@ -116,6 +139,7 @@ class Api:
|
|
|
116
139
|
mapped_dir=mapped_dir,
|
|
117
140
|
container_name=container_name,
|
|
118
141
|
remove_previous=remove_previous,
|
|
142
|
+
no_platformio=no_platformio,
|
|
119
143
|
)
|
|
120
144
|
try:
|
|
121
145
|
yield server
|
|
@@ -196,6 +220,8 @@ class Test:
|
|
|
196
220
|
port: int | None = None,
|
|
197
221
|
compile_server_port: int | None = None,
|
|
198
222
|
open_browser: bool = True,
|
|
223
|
+
app: bool = False,
|
|
224
|
+
enable_https: bool = False, # Default to HTTP for tests (tests use http:// URLs)
|
|
199
225
|
) -> Process:
|
|
200
226
|
from fastled.open_browser import spawn_http_server
|
|
201
227
|
|
|
@@ -207,6 +233,8 @@ class Test:
|
|
|
207
233
|
port=port,
|
|
208
234
|
compile_server_port=compile_server_port,
|
|
209
235
|
open_browser=open_browser,
|
|
236
|
+
app=app,
|
|
237
|
+
enable_https=enable_https,
|
|
210
238
|
)
|
|
211
239
|
return proc
|
|
212
240
|
|
fastled/__main__.py
ADDED
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
"""
|
|
3
|
+
FastLED Package Main Entry Point
|
|
4
|
+
Enables running the package as: python -m fastled
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
import sys
|
|
8
|
+
|
|
9
|
+
from fastled.cli import main
|
|
10
|
+
|
|
11
|
+
if __name__ == "__main__":
|
|
12
|
+
# Pass execution to the main function from cli.py
|
|
13
|
+
# This enables 'python -m fastled' to work the same as 'fastled' command
|
|
14
|
+
sys.exit(main())
|
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
|
+
__version__ = "1.4.50"
|
|
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
|
@@ -9,8 +9,10 @@ from pathlib import Path
|
|
|
9
9
|
|
|
10
10
|
from fastled.client_server import run_client_server
|
|
11
11
|
from fastled.compile_server import CompileServer
|
|
12
|
+
from fastled.emoji_util import EMO
|
|
12
13
|
from fastled.filewatcher import file_watcher_set
|
|
13
14
|
from fastled.parse_args import Args, parse_args
|
|
15
|
+
from fastled.settings import DEFAULT_URL
|
|
14
16
|
from fastled.sketch import find_sketch_directories, looks_like_fastled_repo
|
|
15
17
|
|
|
16
18
|
|
|
@@ -27,6 +29,7 @@ def run_server(args: Args) -> int:
|
|
|
27
29
|
mapped_dir=mapped_dir,
|
|
28
30
|
auto_start=True,
|
|
29
31
|
remove_previous=args.clear,
|
|
32
|
+
no_platformio=args.no_platformio,
|
|
30
33
|
)
|
|
31
34
|
|
|
32
35
|
if not interactive:
|
|
@@ -50,6 +53,41 @@ def main() -> int:
|
|
|
50
53
|
from fastled.select_sketch_directory import select_sketch_directory
|
|
51
54
|
|
|
52
55
|
args = parse_args()
|
|
56
|
+
|
|
57
|
+
if args.emsdk_headers:
|
|
58
|
+
import httpx
|
|
59
|
+
|
|
60
|
+
out_path = args.emsdk_headers
|
|
61
|
+
base_url = args.web if isinstance(args.web, str) else DEFAULT_URL
|
|
62
|
+
try:
|
|
63
|
+
response = httpx.get(f"{base_url}/headers/emsdk")
|
|
64
|
+
if response.status_code == 200:
|
|
65
|
+
Path(out_path).parent.mkdir(parents=True, exist_ok=True)
|
|
66
|
+
with open(out_path, "wb") as f:
|
|
67
|
+
f.write(response.content)
|
|
68
|
+
print(f"{EMO('✅','SUCCESS:')} EMSDK headers exported to {out_path}")
|
|
69
|
+
return 0
|
|
70
|
+
else:
|
|
71
|
+
print(
|
|
72
|
+
f"{EMO('❌','ERROR:')} Failed to export EMSDK headers: HTTP {response.status_code}"
|
|
73
|
+
)
|
|
74
|
+
return 1
|
|
75
|
+
except KeyboardInterrupt:
|
|
76
|
+
print("\nExiting from main...")
|
|
77
|
+
return 1
|
|
78
|
+
except Exception as e:
|
|
79
|
+
print(f"{EMO('❌','ERROR:')} Exception: {e}")
|
|
80
|
+
return 1
|
|
81
|
+
|
|
82
|
+
# Handle --install command early
|
|
83
|
+
if args.install:
|
|
84
|
+
from fastled.install.main import fastled_install
|
|
85
|
+
|
|
86
|
+
result = fastled_install(
|
|
87
|
+
dry_run=args.dry_run, no_interactive=args.no_interactive
|
|
88
|
+
)
|
|
89
|
+
return 0 if result else 1
|
|
90
|
+
|
|
53
91
|
interactive: bool = args.interactive
|
|
54
92
|
has_server = args.server
|
|
55
93
|
update: bool = args.update
|
|
@@ -62,6 +100,14 @@ def main() -> int:
|
|
|
62
100
|
# now it is safe to print out the version
|
|
63
101
|
print(f"FastLED version: {__version__}")
|
|
64
102
|
|
|
103
|
+
# Print current working directory
|
|
104
|
+
print(f"Current working directory: {os.getcwd()}")
|
|
105
|
+
|
|
106
|
+
# Check if Playwright browsers are installed
|
|
107
|
+
playwright_dir = Path.home() / ".fastled" / "playwright"
|
|
108
|
+
if playwright_dir.exists() and any(playwright_dir.iterdir()):
|
|
109
|
+
print(f"{EMO('🎭', '*')} Playwright browsers available at: {playwright_dir}")
|
|
110
|
+
|
|
65
111
|
# Resolve some of the last interactive arguments
|
|
66
112
|
# 1. If interactive is set and the sketch directory is not given,
|
|
67
113
|
# then prompt the user for a sketch directory.
|
|
@@ -75,7 +121,7 @@ def main() -> int:
|
|
|
75
121
|
sketch_list: list[Path] = find_sketch_directories()
|
|
76
122
|
if sketch_list:
|
|
77
123
|
maybe_dir: str | None = select_sketch_directory(
|
|
78
|
-
sketch_list, cwd_looks_like_fastled_repo
|
|
124
|
+
sketch_list, cwd_looks_like_fastled_repo, is_followup=True
|
|
79
125
|
)
|
|
80
126
|
if maybe_dir is not None:
|
|
81
127
|
directory = Path(maybe_dir)
|
|
@@ -87,7 +133,9 @@ def main() -> int:
|
|
|
87
133
|
|
|
88
134
|
if update:
|
|
89
135
|
# Force auto_update to ensure update check happens
|
|
90
|
-
compile_server = CompileServer(
|
|
136
|
+
compile_server = CompileServer(
|
|
137
|
+
interactive=False, auto_updates=True, no_platformio=args.no_platformio
|
|
138
|
+
)
|
|
91
139
|
compile_server.stop()
|
|
92
140
|
print("Finished updating.")
|
|
93
141
|
return 0
|
|
@@ -109,6 +157,7 @@ def main() -> int:
|
|
|
109
157
|
mapped_dir=directory,
|
|
110
158
|
auto_start=False,
|
|
111
159
|
remove_previous=args.clear,
|
|
160
|
+
no_platformio=args.no_platformio,
|
|
112
161
|
)
|
|
113
162
|
|
|
114
163
|
server.start(wait_for_startup=False)
|
fastled/args.py
CHANGED
|
@@ -12,8 +12,11 @@ class Args:
|
|
|
12
12
|
interactive: bool
|
|
13
13
|
profile: bool
|
|
14
14
|
force_compile: bool
|
|
15
|
+
no_platformio: bool
|
|
16
|
+
app: bool # New flag to trigger Playwright browser with browser download if needed
|
|
15
17
|
auto_update: bool | None
|
|
16
18
|
update: bool
|
|
19
|
+
background_update: bool
|
|
17
20
|
localhost: bool
|
|
18
21
|
build: bool
|
|
19
22
|
server: bool
|
|
@@ -23,6 +26,10 @@ class Args:
|
|
|
23
26
|
release: bool
|
|
24
27
|
ram_disk_size: str # suffixed liked "25mb" or "1gb"
|
|
25
28
|
clear = False # Force the last running container to be removed. Useful for benchmarking.
|
|
29
|
+
install: bool = False # Install FastLED development environment
|
|
30
|
+
dry_run: bool = False # Dry run mode for testing
|
|
31
|
+
no_interactive: bool = False # Non-interactive mode
|
|
32
|
+
emsdk_headers: str | None = None # Path to export EMSDK headers ZIP
|
|
26
33
|
|
|
27
34
|
@staticmethod
|
|
28
35
|
def from_namespace(args: argparse.Namespace) -> "Args":
|
|
@@ -47,10 +54,17 @@ class Args:
|
|
|
47
54
|
assert isinstance(
|
|
48
55
|
args.force_compile, bool
|
|
49
56
|
), f"expected bool, got {type(args.force_compile)}"
|
|
57
|
+
assert isinstance(
|
|
58
|
+
args.no_platformio, bool
|
|
59
|
+
), f"expected bool, got {type(args.no_platformio)}"
|
|
60
|
+
assert isinstance(args.app, bool), f"expected bool, got {type(args.app)}"
|
|
50
61
|
assert isinstance(
|
|
51
62
|
args.no_auto_updates, bool | None
|
|
52
63
|
), f"expected bool | None, got {type(args.no_auto_updates)}"
|
|
53
64
|
assert isinstance(args.update, bool), f"expected bool, got {type(args.update)}"
|
|
65
|
+
assert isinstance(
|
|
66
|
+
args.background_update, bool
|
|
67
|
+
), f"expected bool, got {type(args.background_update)}"
|
|
54
68
|
assert isinstance(
|
|
55
69
|
args.localhost, bool
|
|
56
70
|
), f"expected bool, got {type(args.localhost)}"
|
|
@@ -62,6 +76,18 @@ class Args:
|
|
|
62
76
|
assert isinstance(
|
|
63
77
|
args.release, bool
|
|
64
78
|
), f"expected bool, got {type(args.release)}"
|
|
79
|
+
assert isinstance(
|
|
80
|
+
args.install, bool
|
|
81
|
+
), f"expected bool, got {type(args.install)}"
|
|
82
|
+
assert isinstance(
|
|
83
|
+
args.dry_run, bool
|
|
84
|
+
), f"expected bool, got {type(args.dry_run)}"
|
|
85
|
+
assert isinstance(
|
|
86
|
+
args.no_interactive, bool
|
|
87
|
+
), f"expected bool, got {type(args.no_interactive)}"
|
|
88
|
+
assert isinstance(
|
|
89
|
+
args.emsdk_headers, str | None
|
|
90
|
+
), f"expected str | None, got {type(args.emsdk_headers)}"
|
|
65
91
|
|
|
66
92
|
init: bool | str = False
|
|
67
93
|
if args.init is None:
|
|
@@ -78,8 +104,11 @@ class Args:
|
|
|
78
104
|
interactive=args.interactive,
|
|
79
105
|
profile=args.profile,
|
|
80
106
|
force_compile=args.force_compile,
|
|
107
|
+
no_platformio=args.no_platformio,
|
|
108
|
+
app=args.app,
|
|
81
109
|
auto_update=not args.no_auto_updates,
|
|
82
110
|
update=args.update,
|
|
111
|
+
background_update=args.background_update,
|
|
83
112
|
localhost=args.localhost,
|
|
84
113
|
build=args.build,
|
|
85
114
|
server=args.server,
|
|
@@ -88,4 +117,8 @@ class Args:
|
|
|
88
117
|
quick=args.quick,
|
|
89
118
|
release=args.release,
|
|
90
119
|
ram_disk_size=args.ram_disk_size,
|
|
120
|
+
install=args.install,
|
|
121
|
+
dry_run=args.dry_run,
|
|
122
|
+
emsdk_headers=args.emsdk_headers,
|
|
123
|
+
no_interactive=args.no_interactive,
|
|
91
124
|
)
|