fastled 1.3.29__tar.gz → 1.3.30__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.3.29 → fastled-1.3.30}/PKG-INFO +5 -1
- {fastled-1.3.29 → fastled-1.3.30}/README.md +3 -0
- {fastled-1.3.29 → fastled-1.3.30}/pyproject.toml +1 -0
- fastled-1.3.30/requirements.docker.txt +1 -0
- {fastled-1.3.29 → fastled-1.3.30}/src/fastled/__version__.py +1 -1
- {fastled-1.3.29 → fastled-1.3.30}/src/fastled/server_flask.py +17 -0
- {fastled-1.3.29 → fastled-1.3.30}/src/fastled.egg-info/PKG-INFO +5 -1
- {fastled-1.3.29 → fastled-1.3.30}/src/fastled.egg-info/SOURCES.txt +1 -0
- {fastled-1.3.29 → fastled-1.3.30}/src/fastled.egg-info/requires.txt +1 -0
- fastled-1.3.30/tests/unit/test_manual_api_invocation.py +368 -0
- {fastled-1.3.29 → fastled-1.3.30}/tests/unit/test_string_diff.py +1 -1
- fastled-1.3.29/requirements.docker.txt +0 -1
- {fastled-1.3.29 → fastled-1.3.30}/.aiderignore +0 -0
- {fastled-1.3.29 → fastled-1.3.30}/.dockerignore +0 -0
- {fastled-1.3.29 → fastled-1.3.30}/.github/workflows/build_multi_docker_image.yml +0 -0
- {fastled-1.3.29 → fastled-1.3.30}/.github/workflows/build_webpage.yml +0 -0
- {fastled-1.3.29 → fastled-1.3.30}/.github/workflows/lint.yml +0 -0
- {fastled-1.3.29 → fastled-1.3.30}/.github/workflows/publish_release.yml +0 -0
- {fastled-1.3.29 → fastled-1.3.30}/.github/workflows/template_build_docker_image.yml +0 -0
- {fastled-1.3.29 → fastled-1.3.30}/.github/workflows/test_build_exe.yml +0 -0
- {fastled-1.3.29 → fastled-1.3.30}/.github/workflows/test_macos.yml +0 -0
- {fastled-1.3.29 → fastled-1.3.30}/.github/workflows/test_ubuntu.yml +0 -0
- {fastled-1.3.29 → fastled-1.3.30}/.github/workflows/test_win.yml +0 -0
- {fastled-1.3.29 → fastled-1.3.30}/.gitignore +0 -0
- {fastled-1.3.29 → fastled-1.3.30}/.pylintrc +0 -0
- {fastled-1.3.29 → fastled-1.3.30}/.vscode/launch.json +0 -0
- {fastled-1.3.29 → fastled-1.3.30}/.vscode/settings.json +0 -0
- {fastled-1.3.29 → fastled-1.3.30}/.vscode/tasks.json +0 -0
- {fastled-1.3.29 → fastled-1.3.30}/DEBUGGER.md +0 -0
- {fastled-1.3.29 → fastled-1.3.30}/Dockerfile +0 -0
- {fastled-1.3.29 → fastled-1.3.30}/FAQ.md +0 -0
- {fastled-1.3.29 → fastled-1.3.30}/LICENSE +0 -0
- {fastled-1.3.29 → fastled-1.3.30}/MANIFEST.in +0 -0
- {fastled-1.3.29 → fastled-1.3.30}/RELEASE.md +0 -0
- {fastled-1.3.29 → fastled-1.3.30}/TODO.md +0 -0
- {fastled-1.3.29 → fastled-1.3.30}/build_exe.py +0 -0
- {fastled-1.3.29 → fastled-1.3.30}/build_local_docker.py +0 -0
- {fastled-1.3.29 → fastled-1.3.30}/build_site.py +0 -0
- {fastled-1.3.29 → fastled-1.3.30}/clean +0 -0
- {fastled-1.3.29 → fastled-1.3.30}/compiler/debug.sh +0 -0
- {fastled-1.3.29 → fastled-1.3.30}/compiler/run.py +0 -0
- {fastled-1.3.29 → fastled-1.3.30}/demo/100dots.html +0 -0
- {fastled-1.3.29 → fastled-1.3.30}/demo/demo_threejs.html +0 -0
- {fastled-1.3.29 → fastled-1.3.30}/demo/micdemo.html +0 -0
- {fastled-1.3.29 → fastled-1.3.30}/demo/mp3upload.html +0 -0
- {fastled-1.3.29 → fastled-1.3.30}/demo/webgl_postprocessing_unreal_bloom.html +0 -0
- {fastled-1.3.29 → fastled-1.3.30}/docker-compose.yml +0 -0
- {fastled-1.3.29 → fastled-1.3.30}/entrypoint.sh +0 -0
- {fastled-1.3.29 → fastled-1.3.30}/install +0 -0
- {fastled-1.3.29 → fastled-1.3.30}/install_linux.sh +0 -0
- {fastled-1.3.29 → fastled-1.3.30}/lint +0 -0
- {fastled-1.3.29 → fastled-1.3.30}/requirements.testing.txt +0 -0
- {fastled-1.3.29 → fastled-1.3.30}/setup.cfg +0 -0
- {fastled-1.3.29 → fastled-1.3.30}/setup.py +0 -0
- {fastled-1.3.29 → fastled-1.3.30}/src/fastled/__init__.py +0 -0
- {fastled-1.3.29 → fastled-1.3.30}/src/fastled/app.py +0 -0
- {fastled-1.3.29 → fastled-1.3.30}/src/fastled/args.py +0 -0
- {fastled-1.3.29 → fastled-1.3.30}/src/fastled/assets/example.txt +0 -0
- {fastled-1.3.29 → fastled-1.3.30}/src/fastled/assets/localhost-key.pem +0 -0
- {fastled-1.3.29 → fastled-1.3.30}/src/fastled/assets/localhost.pem +0 -0
- {fastled-1.3.29 → fastled-1.3.30}/src/fastled/cli.py +0 -0
- {fastled-1.3.29 → fastled-1.3.30}/src/fastled/cli_test.py +0 -0
- {fastled-1.3.29 → fastled-1.3.30}/src/fastled/cli_test_interactive.py +0 -0
- {fastled-1.3.29 → fastled-1.3.30}/src/fastled/client_server.py +0 -0
- {fastled-1.3.29 → fastled-1.3.30}/src/fastled/compile_server.py +0 -0
- {fastled-1.3.29 → fastled-1.3.30}/src/fastled/compile_server_impl.py +0 -0
- {fastled-1.3.29 → fastled-1.3.30}/src/fastled/docker_manager.py +0 -0
- {fastled-1.3.29 → fastled-1.3.30}/src/fastled/filewatcher.py +0 -0
- {fastled-1.3.29 → fastled-1.3.30}/src/fastled/keyboard.py +0 -0
- {fastled-1.3.29 → fastled-1.3.30}/src/fastled/keyz.py +0 -0
- {fastled-1.3.29 → fastled-1.3.30}/src/fastled/live_client.py +0 -0
- {fastled-1.3.29 → fastled-1.3.30}/src/fastled/open_browser.py +0 -0
- {fastled-1.3.29 → fastled-1.3.30}/src/fastled/parse_args.py +0 -0
- {fastled-1.3.29 → fastled-1.3.30}/src/fastled/paths.py +0 -0
- {fastled-1.3.29 → fastled-1.3.30}/src/fastled/print_filter.py +0 -0
- {fastled-1.3.29 → fastled-1.3.30}/src/fastled/project_init.py +0 -0
- {fastled-1.3.29 → fastled-1.3.30}/src/fastled/select_sketch_directory.py +0 -0
- {fastled-1.3.29 → fastled-1.3.30}/src/fastled/server_start.py +0 -0
- {fastled-1.3.29 → fastled-1.3.30}/src/fastled/settings.py +0 -0
- {fastled-1.3.29 → fastled-1.3.30}/src/fastled/site/build.py +0 -0
- {fastled-1.3.29 → fastled-1.3.30}/src/fastled/site/examples.py +0 -0
- {fastled-1.3.29 → fastled-1.3.30}/src/fastled/sketch.py +0 -0
- {fastled-1.3.29 → fastled-1.3.30}/src/fastled/spinner.py +0 -0
- {fastled-1.3.29 → fastled-1.3.30}/src/fastled/string_diff.py +0 -0
- {fastled-1.3.29 → fastled-1.3.30}/src/fastled/test/can_run_local_docker_tests.py +0 -0
- {fastled-1.3.29 → fastled-1.3.30}/src/fastled/test/examples.py +0 -0
- {fastled-1.3.29 → fastled-1.3.30}/src/fastled/types.py +0 -0
- {fastled-1.3.29 → fastled-1.3.30}/src/fastled/util.py +0 -0
- {fastled-1.3.29 → fastled-1.3.30}/src/fastled/version.py +0 -0
- {fastled-1.3.29 → fastled-1.3.30}/src/fastled/web_compile.py +0 -0
- {fastled-1.3.29 → fastled-1.3.30}/src/fastled.egg-info/dependency_links.txt +0 -0
- {fastled-1.3.29 → fastled-1.3.30}/src/fastled.egg-info/entry_points.txt +0 -0
- {fastled-1.3.29 → fastled-1.3.30}/src/fastled.egg-info/top_level.txt +0 -0
- {fastled-1.3.29 → fastled-1.3.30}/test +0 -0
- {fastled-1.3.29 → fastled-1.3.30}/tests/integration/test_build_examples.py +0 -0
- {fastled-1.3.29 → fastled-1.3.30}/tests/integration/test_examples.py +0 -0
- {fastled-1.3.29 → fastled-1.3.30}/tests/unit/html/index.html +0 -0
- {fastled-1.3.29 → fastled-1.3.30}/tests/unit/test_api.py +0 -0
- {fastled-1.3.29 → fastled-1.3.30}/tests/unit/test_bad_ino.py +0 -0
- {fastled-1.3.29 → fastled-1.3.30}/tests/unit/test_banner_string.py +0 -0
- {fastled-1.3.29 → fastled-1.3.30}/tests/unit/test_cli.py +0 -0
- {fastled-1.3.29 → fastled-1.3.30}/tests/unit/test_compile_server.py +0 -0
- {fastled-1.3.29 → fastled-1.3.30}/tests/unit/test_debug_fetch_source_files.py +0 -0
- {fastled-1.3.29 → fastled-1.3.30}/tests/unit/test_docker_linux_on_windows.py +0 -0
- {fastled-1.3.29 → fastled-1.3.30}/tests/unit/test_embedded_data.py +0 -0
- {fastled-1.3.29 → fastled-1.3.30}/tests/unit/test_filechanger.py +0 -0
- {fastled-1.3.29 → fastled-1.3.30}/tests/unit/test_http_server.py +0 -0
- {fastled-1.3.29 → fastled-1.3.30}/tests/unit/test_ino/bad/bad.ino +0 -0
- {fastled-1.3.29 → fastled-1.3.30}/tests/unit/test_ino/bad_platformio/bad_platformio.ino +0 -0
- {fastled-1.3.29 → fastled-1.3.30}/tests/unit/test_ino/bad_platformio/platformio.ini +0 -0
- {fastled-1.3.29 → fastled-1.3.30}/tests/unit/test_ino/embedded/data/bigdata.dat +0 -0
- {fastled-1.3.29 → fastled-1.3.30}/tests/unit/test_ino/embedded/wasm.ino +0 -0
- {fastled-1.3.29 → fastled-1.3.30}/tests/unit/test_ino/wasm/wasm.ino +0 -0
- {fastled-1.3.29 → fastled-1.3.30}/tests/unit/test_project_init.py +0 -0
- {fastled-1.3.29 → fastled-1.3.30}/tests/unit/test_server_and_client_seperatly.py +0 -0
- {fastled-1.3.29 → fastled-1.3.30}/tests/unit/test_version.py +0 -0
- {fastled-1.3.29 → fastled-1.3.30}/tests/unit/test_webcompile.py +0 -0
- {fastled-1.3.29 → fastled-1.3.30}/upload_package.sh +0 -0
- {fastled-1.3.29 → fastled-1.3.30}/vscode-plugin/readme +0 -0
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.4
|
2
2
|
Name: fastled
|
3
|
-
Version: 1.3.
|
3
|
+
Version: 1.3.30
|
4
4
|
Summary: FastLED Wasm Compiler
|
5
5
|
Home-page: https://github.com/zackees/fastled-wasm
|
6
6
|
Maintainer: Zachary Vorhies
|
@@ -19,6 +19,7 @@ Requires-Dist: rapidfuzz>=3.10.1
|
|
19
19
|
Requires-Dist: progress>=1.6
|
20
20
|
Requires-Dist: watchfiles>=1.0.5
|
21
21
|
Requires-Dist: Flask>=3.0.0
|
22
|
+
Requires-Dist: flask-cors>=4.0.0
|
22
23
|
Requires-Dist: livereload
|
23
24
|
Requires-Dist: disklru>=2.0.4
|
24
25
|
Dynamic: home-page
|
@@ -55,8 +56,10 @@ Compile times are extremely fast, thanks to aggressive object caching for C++ an
|
|
55
56
|
|
56
57
|
If you have docker installed, the compiler will download the docker image and run a private local server on your machine. If you don't have Docker installed then the app will fall back to using the public web compiler.
|
57
58
|
|
59
|
+
|
58
60
|
In every conceivable way, the local compiler will be much faster than the web version.
|
59
61
|
|
62
|
+
|
60
63
|
# Run
|
61
64
|
|
62
65
|
Once `fastled` is installed you'll just navigate to your sketch directory and run it.
|
@@ -69,6 +72,7 @@ $ fastled
|
|
69
72
|
```
|
70
73
|
|
71
74
|
|
75
|
+
|
72
76
|
# Install
|
73
77
|
|
74
78
|
This is a python app, so any python package manager will work. We also provide python compiled binaries for Windows, MacOS, and Linux.
|
@@ -28,8 +28,10 @@ Compile times are extremely fast, thanks to aggressive object caching for C++ an
|
|
28
28
|
|
29
29
|
If you have docker installed, the compiler will download the docker image and run a private local server on your machine. If you don't have Docker installed then the app will fall back to using the public web compiler.
|
30
30
|
|
31
|
+
|
31
32
|
In every conceivable way, the local compiler will be much faster than the web version.
|
32
33
|
|
34
|
+
|
33
35
|
# Run
|
34
36
|
|
35
37
|
Once `fastled` is installed you'll just navigate to your sketch directory and run it.
|
@@ -42,6 +44,7 @@ $ fastled
|
|
42
44
|
```
|
43
45
|
|
44
46
|
|
47
|
+
|
45
48
|
# Install
|
46
49
|
|
47
50
|
This is a python app, so any python package manager will work. We also provide python compiled binaries for Windows, MacOS, and Linux.
|
@@ -0,0 +1 @@
|
|
1
|
+
fastled-wasm-server>=1.0.91
|
@@ -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.
|
4
|
+
__version__ = "1.3.30"
|
5
5
|
|
6
6
|
__version_url_latest__ = "https://raw.githubusercontent.com/zackees/fastled-wasm/refs/heads/main/src/fastled/__version__.py"
|
@@ -60,9 +60,26 @@ def _run_flask_server(
|
|
60
60
|
"""
|
61
61
|
try:
|
62
62
|
from flask import Flask, Response, request, send_from_directory
|
63
|
+
from flask_cors import CORS
|
63
64
|
|
64
65
|
app = Flask(__name__)
|
65
66
|
|
67
|
+
# Enable CORS for all domains on all routes
|
68
|
+
CORS(
|
69
|
+
app,
|
70
|
+
resources={
|
71
|
+
r"/*": {
|
72
|
+
"origins": "*",
|
73
|
+
"methods": ["GET", "POST", "PUT", "DELETE", "OPTIONS"],
|
74
|
+
"allow_headers": [
|
75
|
+
"Content-Type",
|
76
|
+
"Authorization",
|
77
|
+
"X-Requested-With",
|
78
|
+
],
|
79
|
+
}
|
80
|
+
},
|
81
|
+
)
|
82
|
+
|
66
83
|
# Must be a full path or flask will fail to find the file.
|
67
84
|
fastled_js = fastled_js.resolve()
|
68
85
|
|
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.4
|
2
2
|
Name: fastled
|
3
|
-
Version: 1.3.
|
3
|
+
Version: 1.3.30
|
4
4
|
Summary: FastLED Wasm Compiler
|
5
5
|
Home-page: https://github.com/zackees/fastled-wasm
|
6
6
|
Maintainer: Zachary Vorhies
|
@@ -19,6 +19,7 @@ Requires-Dist: rapidfuzz>=3.10.1
|
|
19
19
|
Requires-Dist: progress>=1.6
|
20
20
|
Requires-Dist: watchfiles>=1.0.5
|
21
21
|
Requires-Dist: Flask>=3.0.0
|
22
|
+
Requires-Dist: flask-cors>=4.0.0
|
22
23
|
Requires-Dist: livereload
|
23
24
|
Requires-Dist: disklru>=2.0.4
|
24
25
|
Dynamic: home-page
|
@@ -55,8 +56,10 @@ Compile times are extremely fast, thanks to aggressive object caching for C++ an
|
|
55
56
|
|
56
57
|
If you have docker installed, the compiler will download the docker image and run a private local server on your machine. If you don't have Docker installed then the app will fall back to using the public web compiler.
|
57
58
|
|
59
|
+
|
58
60
|
In every conceivable way, the local compiler will be much faster than the web version.
|
59
61
|
|
62
|
+
|
60
63
|
# Run
|
61
64
|
|
62
65
|
Once `fastled` is installed you'll just navigate to your sketch directory and run it.
|
@@ -69,6 +72,7 @@ $ fastled
|
|
69
72
|
```
|
70
73
|
|
71
74
|
|
75
|
+
|
72
76
|
# Install
|
73
77
|
|
74
78
|
This is a python app, so any python package manager will work. We also provide python compiled binaries for Windows, MacOS, and Linux.
|
@@ -100,6 +100,7 @@ tests/unit/test_docker_linux_on_windows.py
|
|
100
100
|
tests/unit/test_embedded_data.py
|
101
101
|
tests/unit/test_filechanger.py
|
102
102
|
tests/unit/test_http_server.py
|
103
|
+
tests/unit/test_manual_api_invocation.py
|
103
104
|
tests/unit/test_project_init.py
|
104
105
|
tests/unit/test_server_and_client_seperatly.py
|
105
106
|
tests/unit/test_string_diff.py
|
@@ -0,0 +1,368 @@
|
|
1
|
+
"""
|
2
|
+
Unit test file demonstrating manual API invocation of fastled-wasm-server.
|
3
|
+
|
4
|
+
This test file shows how to manually invoke the fastled-wasm-server API endpoints
|
5
|
+
using raw HTTP requests, bypassing the high-level Python API wrapper.
|
6
|
+
"""
|
7
|
+
|
8
|
+
import io
|
9
|
+
import tempfile
|
10
|
+
import time
|
11
|
+
import unittest
|
12
|
+
import zipfile
|
13
|
+
from pathlib import Path
|
14
|
+
|
15
|
+
import httpx
|
16
|
+
|
17
|
+
from fastled import Api
|
18
|
+
from fastled.settings import DEFAULT_URL
|
19
|
+
from fastled.types import BuildMode
|
20
|
+
|
21
|
+
|
22
|
+
class TestManualApiInvocation(unittest.TestCase):
|
23
|
+
"""Test manual invocation of fastled-wasm-server API endpoints."""
|
24
|
+
|
25
|
+
# Class-level variables for shared server instance
|
26
|
+
server = None
|
27
|
+
base_url = None
|
28
|
+
|
29
|
+
@classmethod
|
30
|
+
def setUpClass(cls):
|
31
|
+
"""Set up test environment once for all tests."""
|
32
|
+
cls.test_dir = Path(__file__).parent / "unit" / "test_ino" / "wasm"
|
33
|
+
cls.timeout = 30
|
34
|
+
|
35
|
+
# Check if we can run local docker tests
|
36
|
+
if cls._enabled():
|
37
|
+
print("\n🚀 Starting local FastLED WASM server for manual API tests...")
|
38
|
+
cls.server = Api.spawn_server()
|
39
|
+
cls.base_url = cls.server.url()
|
40
|
+
print(f"✅ Server started at: {cls.base_url}")
|
41
|
+
else:
|
42
|
+
print("\n🌐 Using web server for manual API tests...")
|
43
|
+
cls.server = None
|
44
|
+
cls.base_url = DEFAULT_URL
|
45
|
+
print(f"✅ Using web server: {cls.base_url}")
|
46
|
+
|
47
|
+
@classmethod
|
48
|
+
def tearDownClass(cls):
|
49
|
+
"""Clean up server after all tests."""
|
50
|
+
if cls.server is not None:
|
51
|
+
print("\n🛑 Stopping local FastLED WASM server...")
|
52
|
+
cls.server.stop()
|
53
|
+
print("✅ Server stopped")
|
54
|
+
|
55
|
+
@classmethod
|
56
|
+
def _enabled(cls) -> bool:
|
57
|
+
"""Check if this system can run the tests."""
|
58
|
+
from fastled import Test
|
59
|
+
|
60
|
+
return Test.can_run_local_docker_tests()
|
61
|
+
|
62
|
+
def _create_test_sketch_zip(self) -> bytes:
|
63
|
+
"""Create a test sketch zip file for upload."""
|
64
|
+
# Create in-memory zip file with test sketch
|
65
|
+
zip_buffer = io.BytesIO()
|
66
|
+
with zipfile.ZipFile(zip_buffer, "w", zipfile.ZIP_DEFLATED) as zip_file:
|
67
|
+
# Add the main sketch file
|
68
|
+
sketch_content = """#include <FastLED.h>
|
69
|
+
|
70
|
+
#define LED_PIN 3
|
71
|
+
#define NUM_LEDS 100
|
72
|
+
|
73
|
+
CRGB leds[NUM_LEDS];
|
74
|
+
|
75
|
+
void setup() {
|
76
|
+
FastLED.addLeds<WS2812, LED_PIN>(leds, NUM_LEDS);
|
77
|
+
}
|
78
|
+
|
79
|
+
void loop() {
|
80
|
+
fill_rainbow(leds, NUM_LEDS, 0, 7);
|
81
|
+
FastLED.show();
|
82
|
+
delay(30);
|
83
|
+
}"""
|
84
|
+
zip_file.writestr("wasm/wasm.ino", sketch_content)
|
85
|
+
# Add build mode identifier
|
86
|
+
zip_file.writestr("wasm/build_mode.txt", BuildMode.QUICK.value)
|
87
|
+
|
88
|
+
return zip_buffer.getvalue()
|
89
|
+
|
90
|
+
@unittest.skipUnless(True, "Test manual API invocation")
|
91
|
+
def test_info_endpoint_manual(self) -> None:
|
92
|
+
"""Test the /info endpoint to get available examples using manual HTTP requests."""
|
93
|
+
# Test /info endpoint manually
|
94
|
+
info_url = f"{self.base_url}/info"
|
95
|
+
print(f"\nTesting INFO endpoint manually: {info_url}")
|
96
|
+
|
97
|
+
response = httpx.get(info_url, timeout=self.timeout)
|
98
|
+
|
99
|
+
self.assertEqual(response.status_code, 200)
|
100
|
+
data = response.json()
|
101
|
+
self.assertIn("examples", data)
|
102
|
+
self.assertIsInstance(data["examples"], list)
|
103
|
+
self.assertGreater(len(data["examples"]), 0)
|
104
|
+
|
105
|
+
print(f"✅ Found {len(data['examples'])} examples: {data['examples']}")
|
106
|
+
|
107
|
+
@unittest.skipUnless(True, "Test manual API invocation")
|
108
|
+
def test_healthz_endpoint_manual(self) -> None:
|
109
|
+
"""Test the /healthz endpoint for health check using manual HTTP requests."""
|
110
|
+
# Test /healthz endpoint manually
|
111
|
+
healthz_url = f"{self.base_url}/healthz"
|
112
|
+
print(f"\nTesting HEALTHZ endpoint manually: {healthz_url}")
|
113
|
+
|
114
|
+
response = httpx.get(healthz_url, timeout=self.timeout)
|
115
|
+
|
116
|
+
self.assertEqual(response.status_code, 200)
|
117
|
+
print(f"✅ Health check successful: {response.text}")
|
118
|
+
|
119
|
+
@unittest.skipUnless(True, "Test manual API invocation")
|
120
|
+
def test_compile_wasm_endpoint_manual(self) -> None:
|
121
|
+
"""Test manual invocation of /compile/wasm endpoint using raw HTTP requests.
|
122
|
+
|
123
|
+
This test demonstrates how to manually call the FastLED WASM compilation API
|
124
|
+
without using the high-level Python wrapper functions.
|
125
|
+
"""
|
126
|
+
# Create test sketch zip
|
127
|
+
zip_bytes = self._create_test_sketch_zip()
|
128
|
+
|
129
|
+
# Test /compile/wasm endpoint manually
|
130
|
+
compile_url = f"{self.base_url}/compile/wasm"
|
131
|
+
print(f"\nTesting COMPILE/WASM endpoint manually: {compile_url}")
|
132
|
+
print(f"📦 Upload size: {len(zip_bytes)} bytes")
|
133
|
+
|
134
|
+
# Prepare headers (exactly as the internal API does)
|
135
|
+
headers = {
|
136
|
+
"accept": "application/json",
|
137
|
+
"authorization": "oBOT5jbsO4ztgrpNsQwlmFLIKB", # Default auth token
|
138
|
+
"build": BuildMode.QUICK.value.lower(),
|
139
|
+
"profile": "false",
|
140
|
+
}
|
141
|
+
|
142
|
+
# Prepare files for upload
|
143
|
+
files = {"file": ("wasm.zip", zip_bytes, "application/x-zip-compressed")}
|
144
|
+
|
145
|
+
# Make the request manually
|
146
|
+
start_time = time.time()
|
147
|
+
|
148
|
+
with httpx.Client(timeout=60 * 2) as client: # 2 minute timeout
|
149
|
+
response = client.post(
|
150
|
+
compile_url, files=files, headers=headers, follow_redirects=True
|
151
|
+
)
|
152
|
+
|
153
|
+
compile_time = time.time() - start_time
|
154
|
+
print(f"⏱️ Compilation took: {compile_time:.2f} seconds")
|
155
|
+
|
156
|
+
# Verify response
|
157
|
+
print(f"📋 Response status: {response.status_code}")
|
158
|
+
if response.status_code != 200:
|
159
|
+
print(f"❌ Response content: {response.text}")
|
160
|
+
|
161
|
+
self.assertEqual(response.status_code, 200)
|
162
|
+
|
163
|
+
# Verify we got a zip file back
|
164
|
+
self.assertGreater(len(response.content), 0)
|
165
|
+
print(f"📥 Response zip size: {len(response.content)} bytes")
|
166
|
+
|
167
|
+
# Try to extract and verify the response contains expected files
|
168
|
+
with tempfile.TemporaryDirectory() as temp_dir:
|
169
|
+
temp_path = Path(temp_dir)
|
170
|
+
zip_path = temp_path / "response.zip"
|
171
|
+
zip_path.write_bytes(response.content)
|
172
|
+
|
173
|
+
# Extract and check contents
|
174
|
+
import shutil
|
175
|
+
|
176
|
+
shutil.unpack_archive(zip_path, temp_path, "zip")
|
177
|
+
|
178
|
+
# Look for expected output files
|
179
|
+
js_files = list(temp_path.glob("**/*.js"))
|
180
|
+
wasm_files = list(temp_path.glob("**/*.wasm"))
|
181
|
+
|
182
|
+
print(f"🔍 Found JS files: {[f.name for f in js_files]}")
|
183
|
+
print(f"🔍 Found WASM files: {[f.name for f in wasm_files]}")
|
184
|
+
|
185
|
+
self.assertGreater(len(js_files), 0, "Expected to find .js files")
|
186
|
+
self.assertGreater(len(wasm_files), 0, "Expected to find .wasm files")
|
187
|
+
|
188
|
+
# Verify file sizes are reasonable
|
189
|
+
for js_file in js_files:
|
190
|
+
size = js_file.stat().st_size
|
191
|
+
self.assertGreater(
|
192
|
+
size, 1000, f"JS file {js_file.name} too small: {size} bytes"
|
193
|
+
)
|
194
|
+
print(f"📄 {js_file.name}: {size:,} bytes")
|
195
|
+
|
196
|
+
for wasm_file in wasm_files:
|
197
|
+
size = wasm_file.stat().st_size
|
198
|
+
self.assertGreater(
|
199
|
+
size, 1000, f"WASM file {wasm_file.name} too small: {size} bytes"
|
200
|
+
)
|
201
|
+
print(f"⚙️ {wasm_file.name}: {size:,} bytes")
|
202
|
+
|
203
|
+
@unittest.skipUnless(True, "Test manual API invocation")
|
204
|
+
def test_compile_libfastled_endpoint_manual(self) -> None:
|
205
|
+
"""Test manual invocation of /compile/libfastled endpoint using raw HTTP requests.
|
206
|
+
|
207
|
+
This test demonstrates how to manually call the FastLED library compilation API
|
208
|
+
which compiles just the FastLED library without a sketch.
|
209
|
+
"""
|
210
|
+
# Test /compile/libfastled endpoint manually
|
211
|
+
compile_url = f"{self.base_url}/compile/libfastled"
|
212
|
+
print(f"\nTesting COMPILE/LIBFASTLED endpoint manually: {compile_url}")
|
213
|
+
|
214
|
+
# Prepare headers for libfastled compilation
|
215
|
+
headers = {
|
216
|
+
"accept": "application/json",
|
217
|
+
"authorization": "oBOT5jbsO4ztgrpNsQwlmFLIKB", # Default auth token
|
218
|
+
"build": BuildMode.QUICK.value.lower(),
|
219
|
+
}
|
220
|
+
|
221
|
+
print(f"🔧 Build mode: {headers['build']}")
|
222
|
+
|
223
|
+
# Make the request manually (no file upload needed for library compilation)
|
224
|
+
start_time = time.time()
|
225
|
+
|
226
|
+
with httpx.Client(
|
227
|
+
timeout=60 * 3
|
228
|
+
) as client: # 3 minute timeout for library compilation
|
229
|
+
response = client.post(compile_url, headers=headers, follow_redirects=True)
|
230
|
+
|
231
|
+
compile_time = time.time() - start_time
|
232
|
+
print(f"⏱️ Library compilation took: {compile_time:.2f} seconds")
|
233
|
+
|
234
|
+
# Verify response
|
235
|
+
print(f"📋 Response status: {response.status_code}")
|
236
|
+
if response.status_code != 200:
|
237
|
+
print(f"❌ Response content: {response.text}")
|
238
|
+
|
239
|
+
self.assertEqual(response.status_code, 200)
|
240
|
+
|
241
|
+
# Verify we got some content back (streaming response)
|
242
|
+
self.assertGreater(len(response.content), 0)
|
243
|
+
print(f"📥 Response size: {len(response.content)} bytes")
|
244
|
+
|
245
|
+
# Check if it's a zip file or other binary content
|
246
|
+
if response.content.startswith(b"PK"): # ZIP file magic bytes
|
247
|
+
print("📦 Response appears to be a ZIP file")
|
248
|
+
# Try to extract and verify the response contains expected library files
|
249
|
+
with tempfile.TemporaryDirectory() as temp_dir:
|
250
|
+
temp_path = Path(temp_dir)
|
251
|
+
zip_path = temp_path / "libfastled.zip"
|
252
|
+
zip_path.write_bytes(response.content)
|
253
|
+
|
254
|
+
# Extract and check contents
|
255
|
+
import shutil
|
256
|
+
|
257
|
+
shutil.unpack_archive(zip_path, temp_path, "zip")
|
258
|
+
|
259
|
+
# Look for expected library files
|
260
|
+
lib_files = list(temp_path.glob("**/*.a")) + list(
|
261
|
+
temp_path.glob("**/*.so")
|
262
|
+
)
|
263
|
+
header_files = list(temp_path.glob("**/*.h")) + list(
|
264
|
+
temp_path.glob("**/*.hpp")
|
265
|
+
)
|
266
|
+
|
267
|
+
print(f"🔍 Found library files: {[f.name for f in lib_files]}")
|
268
|
+
print(f"🔍 Found header files: {[f.name for f in header_files]}")
|
269
|
+
|
270
|
+
# We expect at least some library or header files
|
271
|
+
self.assertGreater(
|
272
|
+
len(lib_files) + len(header_files),
|
273
|
+
0,
|
274
|
+
"Expected to find library or header files",
|
275
|
+
)
|
276
|
+
else:
|
277
|
+
print("📄 Response appears to be text/binary data")
|
278
|
+
# Could be a streaming response with compilation logs
|
279
|
+
try:
|
280
|
+
text_content = response.content.decode("utf-8")
|
281
|
+
print(f"📝 Response preview: {text_content[:200]}...")
|
282
|
+
except UnicodeDecodeError:
|
283
|
+
print("🔧 Response contains binary data")
|
284
|
+
|
285
|
+
@unittest.skipUnless(True, "Test manual API invocation")
|
286
|
+
def test_project_init_endpoint_manual(self) -> None:
|
287
|
+
"""Test the /project/init endpoint to initialize a project using manual HTTP requests."""
|
288
|
+
# Test /project/init endpoint manually
|
289
|
+
init_url = f"{self.base_url}/project/init"
|
290
|
+
print(f"\nTesting PROJECT/INIT endpoint manually: {init_url}")
|
291
|
+
|
292
|
+
# Request a basic example project
|
293
|
+
example_name = "wasm" # This should be a basic available example
|
294
|
+
|
295
|
+
response = httpx.post(
|
296
|
+
init_url,
|
297
|
+
json=example_name,
|
298
|
+
headers={"accept": "application/json"},
|
299
|
+
timeout=self.timeout,
|
300
|
+
)
|
301
|
+
|
302
|
+
self.assertEqual(response.status_code, 200)
|
303
|
+
|
304
|
+
# Verify we got a zip file back
|
305
|
+
self.assertGreater(len(response.content), 0)
|
306
|
+
print(f"📦 Project init zip size: {len(response.content)} bytes")
|
307
|
+
|
308
|
+
# Verify the zip contains expected files
|
309
|
+
with tempfile.TemporaryDirectory() as temp_dir:
|
310
|
+
temp_path = Path(temp_dir)
|
311
|
+
zip_path = temp_path / "project.zip"
|
312
|
+
zip_path.write_bytes(response.content)
|
313
|
+
|
314
|
+
# Extract and check contents
|
315
|
+
import shutil
|
316
|
+
|
317
|
+
shutil.unpack_archive(zip_path, temp_path, "zip")
|
318
|
+
|
319
|
+
# Look for .ino files
|
320
|
+
ino_files = list(temp_path.glob("**/*.ino"))
|
321
|
+
print(f"📄 Found .ino files: {[f.name for f in ino_files]}")
|
322
|
+
|
323
|
+
self.assertGreater(len(ino_files), 0, "Expected to find .ino files")
|
324
|
+
|
325
|
+
@unittest.skipUnless(True, "Test manual API invocation")
|
326
|
+
def test_docs_endpoint_manual(self) -> None:
|
327
|
+
"""Test that the /docs endpoint exists (FastAPI documentation) using manual HTTP requests."""
|
328
|
+
if not self._enabled():
|
329
|
+
self.skipTest("Local server not available for /docs test")
|
330
|
+
|
331
|
+
# Test /docs endpoint manually
|
332
|
+
docs_url = f"{self.base_url}/docs"
|
333
|
+
print(f"\nTesting DOCS endpoint manually: {docs_url}")
|
334
|
+
|
335
|
+
response = httpx.get(docs_url, timeout=self.timeout)
|
336
|
+
|
337
|
+
# Should return HTML documentation
|
338
|
+
self.assertEqual(response.status_code, 200)
|
339
|
+
self.assertIn("text/html", response.headers.get("content-type", "").lower())
|
340
|
+
print("✅ FastAPI docs endpoint accessible")
|
341
|
+
|
342
|
+
def test_api_endpoints_summary(self) -> None:
|
343
|
+
"""Test that demonstrates all available API endpoints and their usage.
|
344
|
+
|
345
|
+
This is a comprehensive test showing what endpoints exist and how to use them manually.
|
346
|
+
"""
|
347
|
+
print("\n" + "=" * 70)
|
348
|
+
print("📋 FASTLED WASM SERVER API ENDPOINTS SUMMARY")
|
349
|
+
print("=" * 70)
|
350
|
+
print("Available endpoints:")
|
351
|
+
print(" • /compile/wasm - Main compilation endpoint (POST)")
|
352
|
+
print(" • /compile/libfastled - FastLED library compilation (POST)")
|
353
|
+
print(" • /info - Get available examples (GET)")
|
354
|
+
print(" • /project/init - Initialize project from example (POST)")
|
355
|
+
print(" • /healthz - Health check (GET)")
|
356
|
+
print(" • /docs - FastAPI documentation (GET)")
|
357
|
+
print(" • /dwarfsource - Debug source files (POST)")
|
358
|
+
print(" • /sourcefiles/* - Source file serving (GET)")
|
359
|
+
print("\n✅ NEW: /compile/libfastled endpoint found!")
|
360
|
+
print(" Compiles the FastLED library without requiring a sketch")
|
361
|
+
print("=" * 70)
|
362
|
+
|
363
|
+
# This test always passes - it's just for documentation
|
364
|
+
self.assertTrue(True, "API endpoints summary displayed")
|
365
|
+
|
366
|
+
|
367
|
+
if __name__ == "__main__":
|
368
|
+
unittest.main()
|
@@ -4,6 +4,7 @@ from fastled.string_diff import is_in_order_match, string_diff
|
|
4
4
|
|
5
5
|
_HAYSTACK: list[str] = [
|
6
6
|
"examples\\AnalogOutput",
|
7
|
+
"examples\\Animartrix",
|
7
8
|
"examples\\Apa102",
|
8
9
|
"examples\\Apa102HD",
|
9
10
|
"examples\\Apa102HDOverride",
|
@@ -24,7 +25,6 @@ _HAYSTACK: list[str] = [
|
|
24
25
|
"examples\\FireCylinder",
|
25
26
|
"examples\\FireMatrix",
|
26
27
|
"examples\\FirstLight",
|
27
|
-
"examples\\FxAnimartrix",
|
28
28
|
"examples\\FxCylon",
|
29
29
|
"examples\\FxDemoReel100",
|
30
30
|
"examples\\FxEngine",
|
@@ -1 +0,0 @@
|
|
1
|
-
fastled-wasm-server>=1.0.80
|
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
|