fastled 1.2.95__py3-none-any.whl → 1.2.97__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 +1 -1
- fastled/client_server.py +513 -513
- fastled/compile_server_impl.py +355 -355
- fastled/docker_manager.py +987 -987
- fastled/open_browser.py +137 -137
- fastled/print_filter.py +190 -190
- fastled/project_init.py +129 -129
- fastled/server_flask.py +3 -9
- fastled/site/build.py +449 -449
- fastled/string_diff.py +82 -82
- {fastled-1.2.95.dist-info → fastled-1.2.97.dist-info}/METADATA +471 -471
- {fastled-1.2.95.dist-info → fastled-1.2.97.dist-info}/RECORD +16 -16
- {fastled-1.2.95.dist-info → fastled-1.2.97.dist-info}/WHEEL +0 -0
- {fastled-1.2.95.dist-info → fastled-1.2.97.dist-info}/entry_points.txt +0 -0
- {fastled-1.2.95.dist-info → fastled-1.2.97.dist-info}/licenses/LICENSE +0 -0
- {fastled-1.2.95.dist-info → fastled-1.2.97.dist-info}/top_level.txt +0 -0
fastled/project_init.py
CHANGED
@@ -1,129 +1,129 @@
|
|
1
|
-
import _thread
|
2
|
-
import threading
|
3
|
-
import time
|
4
|
-
import zipfile
|
5
|
-
from pathlib import Path
|
6
|
-
|
7
|
-
import httpx
|
8
|
-
|
9
|
-
from fastled.settings import DEFAULT_URL
|
10
|
-
from fastled.spinner import Spinner
|
11
|
-
|
12
|
-
DEFAULT_EXAMPLE = "wasm"
|
13
|
-
|
14
|
-
|
15
|
-
def get_examples(host: str | None = None) -> list[str]:
|
16
|
-
host = host or DEFAULT_URL
|
17
|
-
url_info = f"{host}/info"
|
18
|
-
response = httpx.get(url_info, timeout=4)
|
19
|
-
response.raise_for_status()
|
20
|
-
examples: list[str] = response.json()["examples"]
|
21
|
-
return sorted(examples)
|
22
|
-
|
23
|
-
|
24
|
-
def _prompt_for_example() -> str:
|
25
|
-
examples = get_examples()
|
26
|
-
while True:
|
27
|
-
print("Available examples:")
|
28
|
-
for i, example in enumerate(examples):
|
29
|
-
print(f" [{i+1}]: {example}")
|
30
|
-
answer = input("Enter the example number or name: ").strip()
|
31
|
-
if answer.isdigit():
|
32
|
-
example_num = int(answer) - 1
|
33
|
-
if example_num < 0 or example_num >= len(examples):
|
34
|
-
print("Invalid example number")
|
35
|
-
continue
|
36
|
-
return examples[example_num]
|
37
|
-
elif answer in examples:
|
38
|
-
return answer
|
39
|
-
|
40
|
-
|
41
|
-
class DownloadThread(threading.Thread):
|
42
|
-
def __init__(self, url: str, json: str):
|
43
|
-
super().__init__(daemon=True)
|
44
|
-
self.url = url
|
45
|
-
self.json = json
|
46
|
-
self.bytes_downloaded = 0
|
47
|
-
self.content: bytes | None = None
|
48
|
-
self.error: Exception | None = None
|
49
|
-
self.success = False
|
50
|
-
|
51
|
-
def run(self) -> None:
|
52
|
-
timeout = httpx.Timeout(5.0, connect=5.0, read=120.0, write=30.0)
|
53
|
-
try:
|
54
|
-
with httpx.Client(timeout=timeout) as client:
|
55
|
-
with client.stream("POST", self.url, json=self.json) as response:
|
56
|
-
response.raise_for_status()
|
57
|
-
content = b""
|
58
|
-
for chunk in response.iter_bytes():
|
59
|
-
content += chunk
|
60
|
-
self.bytes_downloaded += len(chunk)
|
61
|
-
self.content = content
|
62
|
-
self.success = True
|
63
|
-
except KeyboardInterrupt:
|
64
|
-
self.error = RuntimeError("Download cancelled")
|
65
|
-
_thread.interrupt_main()
|
66
|
-
except Exception as e:
|
67
|
-
self.error = e
|
68
|
-
|
69
|
-
|
70
|
-
def project_init(
|
71
|
-
example: str | None = "PROMPT", # prompt for example
|
72
|
-
outputdir: Path | None = None,
|
73
|
-
host: str | None = None,
|
74
|
-
) -> Path:
|
75
|
-
"""
|
76
|
-
Initialize a new FastLED project.
|
77
|
-
"""
|
78
|
-
host = host or DEFAULT_URL
|
79
|
-
outputdir = Path(outputdir) if outputdir is not None else Path("fastled")
|
80
|
-
outputdir.mkdir(exist_ok=True, parents=True)
|
81
|
-
if example == "PROMPT" or example is None:
|
82
|
-
try:
|
83
|
-
example = _prompt_for_example()
|
84
|
-
except httpx.HTTPStatusError:
|
85
|
-
print(
|
86
|
-
f"Failed to fetch examples, using default example '{DEFAULT_EXAMPLE}'"
|
87
|
-
)
|
88
|
-
example = DEFAULT_EXAMPLE
|
89
|
-
assert example is not None
|
90
|
-
endpoint_url = f"{host}/project/init"
|
91
|
-
json = example
|
92
|
-
print(f"Initializing project with example '{example}', url={endpoint_url}")
|
93
|
-
|
94
|
-
# Start download thread
|
95
|
-
download_thread = DownloadThread(endpoint_url, json)
|
96
|
-
# spinner = Spinner("Downloading project...")
|
97
|
-
with Spinner(f"Downloading project {example}..."):
|
98
|
-
download_thread.start()
|
99
|
-
while download_thread.is_alive():
|
100
|
-
time.sleep(0.1)
|
101
|
-
|
102
|
-
print() # New line after progress
|
103
|
-
download_thread.join()
|
104
|
-
|
105
|
-
# Check for errors
|
106
|
-
if not download_thread.success:
|
107
|
-
assert download_thread.error is not None
|
108
|
-
raise download_thread.error
|
109
|
-
|
110
|
-
content = download_thread.content
|
111
|
-
assert content is not None
|
112
|
-
tmpzip = outputdir / "fastled.zip"
|
113
|
-
outputdir.mkdir(exist_ok=True)
|
114
|
-
tmpzip.write_bytes(content)
|
115
|
-
with zipfile.ZipFile(tmpzip, "r") as zip_ref:
|
116
|
-
zip_ref.extractall(outputdir)
|
117
|
-
tmpzip.unlink()
|
118
|
-
out = outputdir / example
|
119
|
-
print(f"Project initialized at {out}")
|
120
|
-
assert out.exists()
|
121
|
-
return out
|
122
|
-
|
123
|
-
|
124
|
-
def unit_test() -> None:
|
125
|
-
project_init()
|
126
|
-
|
127
|
-
|
128
|
-
if __name__ == "__main__":
|
129
|
-
unit_test()
|
1
|
+
import _thread
|
2
|
+
import threading
|
3
|
+
import time
|
4
|
+
import zipfile
|
5
|
+
from pathlib import Path
|
6
|
+
|
7
|
+
import httpx
|
8
|
+
|
9
|
+
from fastled.settings import DEFAULT_URL
|
10
|
+
from fastled.spinner import Spinner
|
11
|
+
|
12
|
+
DEFAULT_EXAMPLE = "wasm"
|
13
|
+
|
14
|
+
|
15
|
+
def get_examples(host: str | None = None) -> list[str]:
|
16
|
+
host = host or DEFAULT_URL
|
17
|
+
url_info = f"{host}/info"
|
18
|
+
response = httpx.get(url_info, timeout=4)
|
19
|
+
response.raise_for_status()
|
20
|
+
examples: list[str] = response.json()["examples"]
|
21
|
+
return sorted(examples)
|
22
|
+
|
23
|
+
|
24
|
+
def _prompt_for_example() -> str:
|
25
|
+
examples = get_examples()
|
26
|
+
while True:
|
27
|
+
print("Available examples:")
|
28
|
+
for i, example in enumerate(examples):
|
29
|
+
print(f" [{i+1}]: {example}")
|
30
|
+
answer = input("Enter the example number or name: ").strip()
|
31
|
+
if answer.isdigit():
|
32
|
+
example_num = int(answer) - 1
|
33
|
+
if example_num < 0 or example_num >= len(examples):
|
34
|
+
print("Invalid example number")
|
35
|
+
continue
|
36
|
+
return examples[example_num]
|
37
|
+
elif answer in examples:
|
38
|
+
return answer
|
39
|
+
|
40
|
+
|
41
|
+
class DownloadThread(threading.Thread):
|
42
|
+
def __init__(self, url: str, json: str):
|
43
|
+
super().__init__(daemon=True)
|
44
|
+
self.url = url
|
45
|
+
self.json = json
|
46
|
+
self.bytes_downloaded = 0
|
47
|
+
self.content: bytes | None = None
|
48
|
+
self.error: Exception | None = None
|
49
|
+
self.success = False
|
50
|
+
|
51
|
+
def run(self) -> None:
|
52
|
+
timeout = httpx.Timeout(5.0, connect=5.0, read=120.0, write=30.0)
|
53
|
+
try:
|
54
|
+
with httpx.Client(timeout=timeout) as client:
|
55
|
+
with client.stream("POST", self.url, json=self.json) as response:
|
56
|
+
response.raise_for_status()
|
57
|
+
content = b""
|
58
|
+
for chunk in response.iter_bytes():
|
59
|
+
content += chunk
|
60
|
+
self.bytes_downloaded += len(chunk)
|
61
|
+
self.content = content
|
62
|
+
self.success = True
|
63
|
+
except KeyboardInterrupt:
|
64
|
+
self.error = RuntimeError("Download cancelled")
|
65
|
+
_thread.interrupt_main()
|
66
|
+
except Exception as e:
|
67
|
+
self.error = e
|
68
|
+
|
69
|
+
|
70
|
+
def project_init(
|
71
|
+
example: str | None = "PROMPT", # prompt for example
|
72
|
+
outputdir: Path | None = None,
|
73
|
+
host: str | None = None,
|
74
|
+
) -> Path:
|
75
|
+
"""
|
76
|
+
Initialize a new FastLED project.
|
77
|
+
"""
|
78
|
+
host = host or DEFAULT_URL
|
79
|
+
outputdir = Path(outputdir) if outputdir is not None else Path("fastled")
|
80
|
+
outputdir.mkdir(exist_ok=True, parents=True)
|
81
|
+
if example == "PROMPT" or example is None:
|
82
|
+
try:
|
83
|
+
example = _prompt_for_example()
|
84
|
+
except httpx.HTTPStatusError:
|
85
|
+
print(
|
86
|
+
f"Failed to fetch examples, using default example '{DEFAULT_EXAMPLE}'"
|
87
|
+
)
|
88
|
+
example = DEFAULT_EXAMPLE
|
89
|
+
assert example is not None
|
90
|
+
endpoint_url = f"{host}/project/init"
|
91
|
+
json = example
|
92
|
+
print(f"Initializing project with example '{example}', url={endpoint_url}")
|
93
|
+
|
94
|
+
# Start download thread
|
95
|
+
download_thread = DownloadThread(endpoint_url, json)
|
96
|
+
# spinner = Spinner("Downloading project...")
|
97
|
+
with Spinner(f"Downloading project {example}..."):
|
98
|
+
download_thread.start()
|
99
|
+
while download_thread.is_alive():
|
100
|
+
time.sleep(0.1)
|
101
|
+
|
102
|
+
print() # New line after progress
|
103
|
+
download_thread.join()
|
104
|
+
|
105
|
+
# Check for errors
|
106
|
+
if not download_thread.success:
|
107
|
+
assert download_thread.error is not None
|
108
|
+
raise download_thread.error
|
109
|
+
|
110
|
+
content = download_thread.content
|
111
|
+
assert content is not None
|
112
|
+
tmpzip = outputdir / "fastled.zip"
|
113
|
+
outputdir.mkdir(exist_ok=True)
|
114
|
+
tmpzip.write_bytes(content)
|
115
|
+
with zipfile.ZipFile(tmpzip, "r") as zip_ref:
|
116
|
+
zip_ref.extractall(outputdir)
|
117
|
+
tmpzip.unlink()
|
118
|
+
out = outputdir / example
|
119
|
+
print(f"Project initialized at {out}")
|
120
|
+
assert out.exists()
|
121
|
+
return out
|
122
|
+
|
123
|
+
|
124
|
+
def unit_test() -> None:
|
125
|
+
project_init()
|
126
|
+
|
127
|
+
|
128
|
+
if __name__ == "__main__":
|
129
|
+
unit_test()
|
fastled/server_flask.py
CHANGED
@@ -8,7 +8,7 @@ import httpx
|
|
8
8
|
from livereload import Server
|
9
9
|
|
10
10
|
# Logging configuration
|
11
|
-
_ENABLE_LOGGING =
|
11
|
+
_ENABLE_LOGGING = True # Set to False to disable logging
|
12
12
|
|
13
13
|
if _ENABLE_LOGGING:
|
14
14
|
logging.basicConfig(
|
@@ -153,14 +153,8 @@ def _run_flask_server(
|
|
153
153
|
logger.error(error_msg)
|
154
154
|
return Response(error_msg, status=400)
|
155
155
|
|
156
|
-
resolved: str | None = _resolve_fastled_src(path)
|
157
|
-
if resolved is None:
|
158
|
-
# If the path does not match the expected patterns, return a 404
|
159
|
-
logger.error(f"Path does not match expected patterns: {path}")
|
160
|
-
return Response("Not Found", status=404)
|
161
|
-
|
162
156
|
# Forward the request to the compile server
|
163
|
-
target_url = f"http://localhost:{compile_server_port}/
|
157
|
+
target_url = f"http://localhost:{compile_server_port}/{path}"
|
164
158
|
logger.info(f"Requesting: {target_url}")
|
165
159
|
logger.info(f"Processing dwarfsource request for {path}")
|
166
160
|
|
@@ -219,7 +213,7 @@ def _run_flask_server(
|
|
219
213
|
logger.info(f"Processing sourcefile request for {path}")
|
220
214
|
|
221
215
|
# Forward the request to the compile server
|
222
|
-
target_url = f"http://localhost:{compile_server_port}/
|
216
|
+
target_url = f"http://localhost:{compile_server_port}/{path}"
|
223
217
|
logger.info(f"Forwarding to: {target_url}")
|
224
218
|
|
225
219
|
# Log request headers
|