fastled 1.4.36__tar.gz → 1.4.39__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 (149) hide show
  1. fastled-1.4.39/.claude/settings.local.json +10 -0
  2. {fastled-1.4.36 → fastled-1.4.39}/PKG-INFO +1 -1
  3. fastled-1.4.39/requirements.docker.txt +1 -0
  4. {fastled-1.4.36 → fastled-1.4.39}/src/fastled/__version__.py +1 -1
  5. {fastled-1.4.36 → fastled-1.4.39}/src/fastled/compile_server.py +6 -0
  6. {fastled-1.4.36 → fastled-1.4.39}/src/fastled/compile_server_impl.py +11 -0
  7. fastled-1.4.39/src/fastled/header_dump.py +63 -0
  8. {fastled-1.4.36 → fastled-1.4.39}/src/fastled/live_client.py +12 -0
  9. {fastled-1.4.36 → fastled-1.4.39}/src/fastled/parse_args.py +9 -0
  10. {fastled-1.4.36 → fastled-1.4.39}/src/fastled/util.py +34 -0
  11. {fastled-1.4.36 → fastled-1.4.39}/src/fastled.egg-info/PKG-INFO +1 -1
  12. {fastled-1.4.36 → fastled-1.4.39}/src/fastled.egg-info/SOURCES.txt +3 -0
  13. fastled-1.4.39/tests/unit/test_header_dump.py +120 -0
  14. fastled-1.4.36/requirements.docker.txt +0 -1
  15. {fastled-1.4.36 → fastled-1.4.39}/.aiderignore +0 -0
  16. {fastled-1.4.36 → fastled-1.4.39}/.cursorrules +0 -0
  17. {fastled-1.4.36 → fastled-1.4.39}/.dockerignore +0 -0
  18. {fastled-1.4.36 → fastled-1.4.39}/.github/workflows/build_multi_docker_image.yml +0 -0
  19. {fastled-1.4.36 → fastled-1.4.39}/.github/workflows/build_webpage.yml +0 -0
  20. {fastled-1.4.36 → fastled-1.4.39}/.github/workflows/lint.yml +0 -0
  21. {fastled-1.4.36 → fastled-1.4.39}/.github/workflows/publish_release.yml +0 -0
  22. {fastled-1.4.36 → fastled-1.4.39}/.github/workflows/template_build_docker_image.yml +0 -0
  23. {fastled-1.4.36 → fastled-1.4.39}/.github/workflows/test_build_exe.yml +0 -0
  24. {fastled-1.4.36 → fastled-1.4.39}/.github/workflows/test_macos.yml +0 -0
  25. {fastled-1.4.36 → fastled-1.4.39}/.github/workflows/test_ubuntu.yml +0 -0
  26. {fastled-1.4.36 → fastled-1.4.39}/.github/workflows/test_win.yml +0 -0
  27. {fastled-1.4.36 → fastled-1.4.39}/.gitignore +0 -0
  28. {fastled-1.4.36 → fastled-1.4.39}/.pylintrc +0 -0
  29. {fastled-1.4.36 → fastled-1.4.39}/.vscode/launch.json +0 -0
  30. {fastled-1.4.36 → fastled-1.4.39}/.vscode/settings.json +0 -0
  31. {fastled-1.4.36 → fastled-1.4.39}/.vscode/tasks.json +0 -0
  32. {fastled-1.4.36 → fastled-1.4.39}/DEBUGGER.md +0 -0
  33. {fastled-1.4.36 → fastled-1.4.39}/Dockerfile +0 -0
  34. {fastled-1.4.36 → fastled-1.4.39}/EXTENDED_INO.md +0 -0
  35. {fastled-1.4.36 → fastled-1.4.39}/FAQ.md +0 -0
  36. {fastled-1.4.36 → fastled-1.4.39}/LICENSE +0 -0
  37. {fastled-1.4.36 → fastled-1.4.39}/MANIFEST.in +0 -0
  38. {fastled-1.4.36 → fastled-1.4.39}/README.md +0 -0
  39. {fastled-1.4.36 → fastled-1.4.39}/RELEASE.md +0 -0
  40. {fastled-1.4.36 → fastled-1.4.39}/TODO.md +0 -0
  41. {fastled-1.4.36 → fastled-1.4.39}/build_exe.py +0 -0
  42. {fastled-1.4.36 → fastled-1.4.39}/build_local_docker.py +0 -0
  43. {fastled-1.4.36 → fastled-1.4.39}/build_site.py +0 -0
  44. {fastled-1.4.36 → fastled-1.4.39}/chrome_vscode_bridge_design_task.md +0 -0
  45. {fastled-1.4.36 → fastled-1.4.39}/clean +0 -0
  46. {fastled-1.4.36 → fastled-1.4.39}/compiler/debug.sh +0 -0
  47. {fastled-1.4.36 → fastled-1.4.39}/compiler/run.py +0 -0
  48. {fastled-1.4.36 → fastled-1.4.39}/demo/100dots.html +0 -0
  49. {fastled-1.4.36 → fastled-1.4.39}/demo/demo_threejs.html +0 -0
  50. {fastled-1.4.36 → fastled-1.4.39}/demo/micdemo.html +0 -0
  51. {fastled-1.4.36 → fastled-1.4.39}/demo/mp3upload.html +0 -0
  52. {fastled-1.4.36 → fastled-1.4.39}/demo/webgl_postprocessing_unreal_bloom.html +0 -0
  53. {fastled-1.4.36 → fastled-1.4.39}/docker-compose.yml +0 -0
  54. {fastled-1.4.36 → fastled-1.4.39}/entrypoint.sh +0 -0
  55. {fastled-1.4.36 → fastled-1.4.39}/install +0 -0
  56. {fastled-1.4.36 → fastled-1.4.39}/install_linux.sh +0 -0
  57. {fastled-1.4.36 → fastled-1.4.39}/lint +0 -0
  58. {fastled-1.4.36 → fastled-1.4.39}/pyproject.toml +0 -0
  59. {fastled-1.4.36 → fastled-1.4.39}/requirements.testing.txt +0 -0
  60. {fastled-1.4.36 → fastled-1.4.39}/setup.cfg +0 -0
  61. {fastled-1.4.36 → fastled-1.4.39}/setup.py +0 -0
  62. {fastled-1.4.36 → fastled-1.4.39}/src/fastled/__init__.py +0 -0
  63. {fastled-1.4.36 → fastled-1.4.39}/src/fastled/__main__.py +0 -0
  64. {fastled-1.4.36 → fastled-1.4.39}/src/fastled/app.py +0 -0
  65. {fastled-1.4.36 → fastled-1.4.39}/src/fastled/args.py +0 -0
  66. {fastled-1.4.36 → fastled-1.4.39}/src/fastled/assets/example.txt +0 -0
  67. {fastled-1.4.36 → fastled-1.4.39}/src/fastled/assets/localhost-key.pem +0 -0
  68. {fastled-1.4.36 → fastled-1.4.39}/src/fastled/assets/localhost.pem +0 -0
  69. {fastled-1.4.36 → fastled-1.4.39}/src/fastled/cli.py +0 -0
  70. {fastled-1.4.36 → fastled-1.4.39}/src/fastled/cli_test.py +0 -0
  71. {fastled-1.4.36 → fastled-1.4.39}/src/fastled/cli_test_interactive.py +0 -0
  72. {fastled-1.4.36 → fastled-1.4.39}/src/fastled/client_server.py +0 -0
  73. {fastled-1.4.36 → fastled-1.4.39}/src/fastled/docker_manager.py +0 -0
  74. {fastled-1.4.36 → fastled-1.4.39}/src/fastled/emoji_util.py +0 -0
  75. {fastled-1.4.36 → fastled-1.4.39}/src/fastled/filewatcher.py +0 -0
  76. {fastled-1.4.36 → fastled-1.4.39}/src/fastled/find_good_connection.py +0 -0
  77. {fastled-1.4.36 → fastled-1.4.39}/src/fastled/install/__init__.py +0 -0
  78. {fastled-1.4.36 → fastled-1.4.39}/src/fastled/install/examples_manager.py +0 -0
  79. {fastled-1.4.36 → fastled-1.4.39}/src/fastled/install/extension_manager.py +0 -0
  80. {fastled-1.4.36 → fastled-1.4.39}/src/fastled/install/main.py +0 -0
  81. {fastled-1.4.36 → fastled-1.4.39}/src/fastled/install/project_detection.py +0 -0
  82. {fastled-1.4.36 → fastled-1.4.39}/src/fastled/install/test_install.py +0 -0
  83. {fastled-1.4.36 → fastled-1.4.39}/src/fastled/install/vscode_config.py +0 -0
  84. {fastled-1.4.36 → fastled-1.4.39}/src/fastled/interruptible_http.py +0 -0
  85. {fastled-1.4.36 → fastled-1.4.39}/src/fastled/keyboard.py +0 -0
  86. {fastled-1.4.36 → fastled-1.4.39}/src/fastled/keyz.py +0 -0
  87. {fastled-1.4.36 → fastled-1.4.39}/src/fastled/open_browser.py +0 -0
  88. {fastled-1.4.36 → fastled-1.4.39}/src/fastled/paths.py +0 -0
  89. {fastled-1.4.36 → fastled-1.4.39}/src/fastled/playwright/chrome_extension_downloader.py +0 -0
  90. {fastled-1.4.36 → fastled-1.4.39}/src/fastled/playwright/playwright_browser.py +0 -0
  91. {fastled-1.4.36 → fastled-1.4.39}/src/fastled/playwright/resize_tracking.py +0 -0
  92. {fastled-1.4.36 → fastled-1.4.39}/src/fastled/print_filter.py +0 -0
  93. {fastled-1.4.36 → fastled-1.4.39}/src/fastled/project_init.py +0 -0
  94. {fastled-1.4.36 → fastled-1.4.39}/src/fastled/select_sketch_directory.py +0 -0
  95. {fastled-1.4.36 → fastled-1.4.39}/src/fastled/server_flask.py +0 -0
  96. {fastled-1.4.36 → fastled-1.4.39}/src/fastled/server_start.py +0 -0
  97. {fastled-1.4.36 → fastled-1.4.39}/src/fastled/settings.py +0 -0
  98. {fastled-1.4.36 → fastled-1.4.39}/src/fastled/site/build.py +0 -0
  99. {fastled-1.4.36 → fastled-1.4.39}/src/fastled/site/examples.py +0 -0
  100. {fastled-1.4.36 → fastled-1.4.39}/src/fastled/sketch.py +0 -0
  101. {fastled-1.4.36 → fastled-1.4.39}/src/fastled/spinner.py +0 -0
  102. {fastled-1.4.36 → fastled-1.4.39}/src/fastled/string_diff.py +0 -0
  103. {fastled-1.4.36 → fastled-1.4.39}/src/fastled/test/can_run_local_docker_tests.py +0 -0
  104. {fastled-1.4.36 → fastled-1.4.39}/src/fastled/test/examples.py +0 -0
  105. {fastled-1.4.36 → fastled-1.4.39}/src/fastled/types.py +0 -0
  106. {fastled-1.4.36 → fastled-1.4.39}/src/fastled/version.py +0 -0
  107. {fastled-1.4.36 → fastled-1.4.39}/src/fastled/web_compile.py +0 -0
  108. {fastled-1.4.36 → fastled-1.4.39}/src/fastled/zip_files.py +0 -0
  109. {fastled-1.4.36 → fastled-1.4.39}/src/fastled.egg-info/dependency_links.txt +0 -0
  110. {fastled-1.4.36 → fastled-1.4.39}/src/fastled.egg-info/entry_points.txt +0 -0
  111. {fastled-1.4.36 → fastled-1.4.39}/src/fastled.egg-info/requires.txt +0 -0
  112. {fastled-1.4.36 → fastled-1.4.39}/src/fastled.egg-info/top_level.txt +0 -0
  113. {fastled-1.4.36 → fastled-1.4.39}/task.md +0 -0
  114. {fastled-1.4.36 → fastled-1.4.39}/task2.md +0 -0
  115. {fastled-1.4.36 → fastled-1.4.39}/test +0 -0
  116. {fastled-1.4.36 → fastled-1.4.39}/tests/integration/test_build_examples.py +0 -0
  117. {fastled-1.4.36 → fastled-1.4.39}/tests/integration/test_examples.py +0 -0
  118. {fastled-1.4.36 → fastled-1.4.39}/tests/integration/test_libcompile.py +0 -0
  119. {fastled-1.4.36 → fastled-1.4.39}/tests/integration/test_playwright_integration.py +0 -0
  120. {fastled-1.4.36 → fastled-1.4.39}/tests/unit/html/index.html +0 -0
  121. {fastled-1.4.36 → fastled-1.4.39}/tests/unit/test_api.py +0 -0
  122. {fastled-1.4.36 → fastled-1.4.39}/tests/unit/test_bad_ino.py +0 -0
  123. {fastled-1.4.36 → fastled-1.4.39}/tests/unit/test_banner_string.py +0 -0
  124. {fastled-1.4.36 → fastled-1.4.39}/tests/unit/test_cli.py +0 -0
  125. {fastled-1.4.36 → fastled-1.4.39}/tests/unit/test_cli_no_platformio.py +0 -0
  126. {fastled-1.4.36 → fastled-1.4.39}/tests/unit/test_compile_server.py +0 -0
  127. {fastled-1.4.36 → fastled-1.4.39}/tests/unit/test_debug_fetch_source_files.py +0 -0
  128. {fastled-1.4.36 → fastled-1.4.39}/tests/unit/test_docker_linux_on_windows.py +0 -0
  129. {fastled-1.4.36 → fastled-1.4.39}/tests/unit/test_embedded_data.py +0 -0
  130. {fastled-1.4.36 → fastled-1.4.39}/tests/unit/test_filechanger.py +0 -0
  131. {fastled-1.4.36 → fastled-1.4.39}/tests/unit/test_flask_headers.py +0 -0
  132. {fastled-1.4.36 → fastled-1.4.39}/tests/unit/test_http_server.py +0 -0
  133. {fastled-1.4.36 → fastled-1.4.39}/tests/unit/test_ino/bad/bad.ino +0 -0
  134. {fastled-1.4.36 → fastled-1.4.39}/tests/unit/test_ino/bad_platformio/bad_platformio.ino +0 -0
  135. {fastled-1.4.36 → fastled-1.4.39}/tests/unit/test_ino/bad_platformio/platformio.ini +0 -0
  136. {fastled-1.4.36 → fastled-1.4.39}/tests/unit/test_ino/embedded/data/bigdata.dat +0 -0
  137. {fastled-1.4.36 → fastled-1.4.39}/tests/unit/test_ino/embedded/wasm.ino +0 -0
  138. {fastled-1.4.36 → fastled-1.4.39}/tests/unit/test_ino/wasm/wasm.ino +0 -0
  139. {fastled-1.4.36 → fastled-1.4.39}/tests/unit/test_manual_api_invocation.py +0 -0
  140. {fastled-1.4.36 → fastled-1.4.39}/tests/unit/test_no_platformio_compile.py +0 -0
  141. {fastled-1.4.36 → fastled-1.4.39}/tests/unit/test_project_init.py +0 -0
  142. {fastled-1.4.36 → fastled-1.4.39}/tests/unit/test_server_and_client_seperatly.py +0 -0
  143. {fastled-1.4.36 → fastled-1.4.39}/tests/unit/test_session_compile.py +0 -0
  144. {fastled-1.4.36 → fastled-1.4.39}/tests/unit/test_string_diff.py +0 -0
  145. {fastled-1.4.36 → fastled-1.4.39}/tests/unit/test_string_diff_comprehensive.py +0 -0
  146. {fastled-1.4.36 → fastled-1.4.39}/tests/unit/test_version.py +0 -0
  147. {fastled-1.4.36 → fastled-1.4.39}/tests/unit/test_webcompile.py +0 -0
  148. {fastled-1.4.36 → fastled-1.4.39}/upload_package.sh +0 -0
  149. {fastled-1.4.36 → fastled-1.4.39}/vscode-plugin/readme +0 -0
@@ -0,0 +1,10 @@
1
+ {
2
+ "permissions": {
3
+ "allow": [
4
+ "Bash(python:*)",
5
+ "Bash(uv run:*)"
6
+ ],
7
+ "deny": [],
8
+ "ask": []
9
+ }
10
+ }
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: fastled
3
- Version: 1.4.36
3
+ Version: 1.4.39
4
4
  Summary: FastLED Wasm Compiler
5
5
  Home-page: https://github.com/zackees/fastled-wasm
6
6
  Maintainer: Zachary Vorhies
@@ -0,0 +1 @@
1
+ fastled-wasm-server>=1.1.44
@@ -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.36"
4
+ __version__ = "1.4.39"
5
5
 
6
6
  __version_url_latest__ = "https://raw.githubusercontent.com/zackees/fastled-wasm/refs/heads/main/src/fastled/__version__.py"
@@ -101,3 +101,9 @@ class CompileServer:
101
101
 
102
102
  def process_running(self) -> bool:
103
103
  return self.impl.process_running()
104
+
105
+ def get_emsdk_headers(self, filepath: Path) -> None:
106
+ """Get EMSDK headers ZIP data from the server and save to filepath."""
107
+ if not str(filepath).endswith(".zip"):
108
+ raise ValueError("Filepath must end with .zip")
109
+ return self.impl.get_emsdk_headers(filepath)
@@ -338,3 +338,14 @@ class CompileServerImpl:
338
338
  self.docker.suspend_container(self.container_name)
339
339
  self._port = 0
340
340
  print("Compile server stopped")
341
+
342
+ def get_emsdk_headers(self, filepath: Path) -> None:
343
+ """Get EMSDK headers ZIP data from the server and save to filepath."""
344
+ from fastled.util import download_emsdk_headers
345
+
346
+ if not self._port:
347
+ raise RuntimeError("Server has not been started yet")
348
+ if not self.ping():
349
+ raise RuntimeError("Server is not running")
350
+
351
+ download_emsdk_headers(self.url(), filepath)
@@ -0,0 +1,63 @@
1
+ """Header dump functionality for EMSDK headers export."""
2
+
3
+ import sys
4
+ from pathlib import Path
5
+
6
+
7
+ def dump_emsdk_headers(output_path: Path | str, server_url: str | None = None) -> None:
8
+ """
9
+ Dump EMSDK headers to a specified path.
10
+
11
+ Args:
12
+ output_path: Path where to save the headers ZIP file
13
+ server_url: URL of the server. If None, tries to create local server first,
14
+ then falls back to remote server if local fails.
15
+ """
16
+ from fastled import Api
17
+ from fastled.settings import DEFAULT_URL
18
+ from fastled.util import download_emsdk_headers
19
+
20
+ # Convert to Path if string
21
+ if isinstance(output_path, str):
22
+ output_path = Path(output_path)
23
+
24
+ ends_with_zip = output_path.suffix == ".zip"
25
+ if not ends_with_zip:
26
+ raise ValueError(f"{output_path} must end with .zip")
27
+
28
+ try:
29
+ if server_url is not None:
30
+ # Use the provided server URL
31
+ download_emsdk_headers(server_url, output_path)
32
+ print(f"SUCCESS: EMSDK headers exported to {output_path}")
33
+ else:
34
+ # Try to create local server first
35
+ try:
36
+ with Api.server() as server:
37
+ base_url = server.url()
38
+ download_emsdk_headers(base_url, output_path)
39
+ print(
40
+ f"SUCCESS: EMSDK headers exported to {output_path} (using local server)"
41
+ )
42
+ except Exception as local_error:
43
+ print(
44
+ f"WARNING: Local server failed ({local_error}), falling back to remote server"
45
+ )
46
+ # Fall back to remote server
47
+ download_emsdk_headers(DEFAULT_URL, output_path)
48
+ print(
49
+ f"SUCCESS: EMSDK headers exported to {output_path} (using remote server)"
50
+ )
51
+
52
+ except Exception as e:
53
+ print(f"ERROR: Exception during header dump: {e}")
54
+ sys.exit(1)
55
+
56
+
57
+ if __name__ == "__main__":
58
+ if len(sys.argv) != 2:
59
+ print("Usage: python -m fastled.header_dump <output_path>")
60
+ sys.exit(1)
61
+
62
+ output_path = sys.argv[1]
63
+ dump_emsdk_headers(output_path)
@@ -99,3 +99,15 @@ class LiveClient:
99
99
 
100
100
  def __exit__(self, exc_type, exc_value, traceback) -> None:
101
101
  self.finalize()
102
+
103
+ def get_emsdk_headers(self, filepath: Path) -> None:
104
+ """Get EMSDK headers ZIP data from the server and save to filepath."""
105
+ if isinstance(self.host, CompileServer):
106
+ self.host.get_emsdk_headers(filepath)
107
+ else:
108
+ # Handle string host or None case by using web_compile approach
109
+ from fastled.settings import DEFAULT_URL
110
+ from fastled.util import download_emsdk_headers
111
+
112
+ base_url = self.host if isinstance(self.host, str) else DEFAULT_URL
113
+ download_emsdk_headers(base_url, filepath)
@@ -36,6 +36,7 @@ FastLED WASM Compiler - Useful options:
36
36
  --update Update the docker image for the wasm compiler
37
37
  --background-update Update the docker image in the background after compilation
38
38
  --purge Remove all FastLED containers and images
39
+ --emsdk-headers <path> Export EMSDK headers ZIP to specified path
39
40
  --version Show version information
40
41
  --help Show detailed help
41
42
  Examples:
@@ -209,6 +210,14 @@ def parse_args() -> Args:
209
210
 
210
211
  args = parser.parse_args()
211
212
 
213
+ # Handle --emsdk-headers early before other processing
214
+ if args.emsdk_headers:
215
+ from fastled.header_dump import dump_emsdk_headers
216
+
217
+ out_path = args.emsdk_headers
218
+ dump_emsdk_headers(out_path)
219
+ sys.exit(0)
220
+
212
221
  # Auto-enable app mode if debug is used and Playwright cache exists
213
222
  if args.debug and not args.app:
214
223
  playwright_dir = Path.home() / ".fastled" / "playwright"
@@ -52,3 +52,37 @@ def find_free_port(start_port: int, end_port: int) -> int | None:
52
52
  f"No free port found in the range {start_port}-{end_port}. Using {start_port}."
53
53
  )
54
54
  return None
55
+
56
+
57
+ def download_emsdk_headers(base_url: str, filepath: Path) -> None:
58
+ """Download EMSDK headers from the specified URL and save to filepath.
59
+
60
+ Args:
61
+ base_url: Base URL of the server (e.g., 'http://localhost:8080')
62
+ filepath: Path where to save the headers ZIP file (must end with .zip)
63
+
64
+ Raises:
65
+ ValueError: If filepath doesn't end with .zip
66
+ RuntimeError: If download fails or server returns error
67
+ """
68
+ if not str(filepath).endswith(".zip"):
69
+ raise ValueError("Filepath must end with .zip")
70
+
71
+ import httpx
72
+
73
+ try:
74
+ timeout = httpx.Timeout(30.0, read=30.0)
75
+ with httpx.stream(
76
+ "GET", f"{base_url}/headers/emsdk", timeout=timeout
77
+ ) as response:
78
+ if response.status_code == 200:
79
+ filepath.parent.mkdir(parents=True, exist_ok=True)
80
+ with open(filepath, "wb") as f:
81
+ for chunk in response.iter_bytes(chunk_size=512000):
82
+ f.write(chunk)
83
+ else:
84
+ raise RuntimeError(
85
+ f"Failed to get EMSDK headers: HTTP {response.status_code}"
86
+ )
87
+ except Exception as e:
88
+ raise RuntimeError(f"Error downloading EMSDK headers: {e}") from e
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: fastled
3
- Version: 1.4.36
3
+ Version: 1.4.39
4
4
  Summary: FastLED Wasm Compiler
5
5
  Home-page: https://github.com/zackees/fastled-wasm
6
6
  Maintainer: Zachary Vorhies
@@ -30,6 +30,7 @@ task.md
30
30
  task2.md
31
31
  test
32
32
  upload_package.sh
33
+ .claude/settings.local.json
33
34
  .github/workflows/build_multi_docker_image.yml
34
35
  .github/workflows/build_webpage.yml
35
36
  .github/workflows/lint.yml
@@ -64,6 +65,7 @@ src/fastled/docker_manager.py
64
65
  src/fastled/emoji_util.py
65
66
  src/fastled/filewatcher.py
66
67
  src/fastled/find_good_connection.py
68
+ src/fastled/header_dump.py
67
69
  src/fastled/interruptible_http.py
68
70
  src/fastled/keyboard.py
69
71
  src/fastled/keyz.py
@@ -123,6 +125,7 @@ tests/unit/test_docker_linux_on_windows.py
123
125
  tests/unit/test_embedded_data.py
124
126
  tests/unit/test_filechanger.py
125
127
  tests/unit/test_flask_headers.py
128
+ tests/unit/test_header_dump.py
126
129
  tests/unit/test_http_server.py
127
130
  tests/unit/test_manual_api_invocation.py
128
131
  tests/unit/test_no_platformio_compile.py
@@ -0,0 +1,120 @@
1
+ """
2
+ Test header dump functionality for EMSDK headers export.
3
+ """
4
+
5
+ import unittest
6
+ from pathlib import Path
7
+ from tempfile import TemporaryDirectory
8
+
9
+ from fastled import Test
10
+ from fastled.compile_server import CompileServer
11
+ from fastled.header_dump import dump_emsdk_headers
12
+
13
+
14
+ def _enabled() -> bool:
15
+ """Check if this system can run the tests."""
16
+ return Test.can_run_local_docker_tests()
17
+
18
+
19
+ class HeaderDumpTester(unittest.TestCase):
20
+ """Test header dump functionality."""
21
+
22
+ @unittest.skipUnless(_enabled(), "Skipping test on non-Linux system on github")
23
+ def test_compile_server_header_dump(self) -> None:
24
+ """Test that EMSDK headers can be dumped from a live CompileServer."""
25
+
26
+ server = CompileServer(auto_start=True)
27
+ try:
28
+ with TemporaryDirectory() as tmpdir:
29
+ output_path = Path(tmpdir) / "emsdk_headers.zip"
30
+
31
+ # Test the server's get_emsdk_headers method directly
32
+ server.get_emsdk_headers(output_path)
33
+
34
+ # Verify the ZIP file was created
35
+ self.assertTrue(
36
+ output_path.exists(), "EMSDK headers ZIP file was not created"
37
+ )
38
+
39
+ # Verify it's not empty
40
+ self.assertGreater(
41
+ output_path.stat().st_size, 0, "EMSDK headers ZIP file is empty"
42
+ )
43
+
44
+ # Verify it's a valid ZIP file by checking the magic header
45
+ with open(output_path, "rb") as f:
46
+ header = f.read(4)
47
+ self.assertEqual(
48
+ header[:2], b"PK", "File does not appear to be a valid ZIP file"
49
+ )
50
+ finally:
51
+ # Stop the server
52
+ server.stop()
53
+
54
+ # Verify server stopped
55
+ self.assertFalse(server.running, "Server did not stop")
56
+
57
+ @unittest.skipUnless(_enabled(), "Skipping test on non-Linux system on github")
58
+ def test_dump_with_server_url(self) -> None:
59
+ """Test that EMSDK headers can be dumped using a specific server URL."""
60
+
61
+ server = CompileServer(auto_start=True)
62
+ try:
63
+ with TemporaryDirectory() as tmpdir:
64
+ output_path = Path(tmpdir) / "emsdk_headers_url.zip"
65
+
66
+ # Use dump_emsdk_headers with the server's URL
67
+ server_url = server.url()
68
+ dump_emsdk_headers(output_path, server_url=server_url)
69
+
70
+ # Verify the ZIP file was created
71
+ self.assertTrue(
72
+ output_path.exists(), "EMSDK headers ZIP file was not created"
73
+ )
74
+
75
+ # Verify it's not empty
76
+ self.assertGreater(
77
+ output_path.stat().st_size, 0, "EMSDK headers ZIP file is empty"
78
+ )
79
+ finally:
80
+ # Stop the server
81
+ server.stop()
82
+
83
+ # Verify server stopped
84
+ self.assertFalse(server.running, "Server did not stop")
85
+
86
+ def test_filepath_validation(self) -> None:
87
+ """Test that filepath validation works correctly."""
88
+
89
+ with TemporaryDirectory() as tmpdir:
90
+ invalid_path = Path(tmpdir) / "headers.txt" # Wrong extension
91
+
92
+ # Should raise ValueError for non-.zip files
93
+ with self.assertRaises(ValueError) as context:
94
+ dump_emsdk_headers(invalid_path, server_url="http://example.com")
95
+
96
+ self.assertIn("must end with .zip", str(context.exception))
97
+
98
+ @unittest.skipUnless(_enabled(), "Skipping test on non-Linux system on github")
99
+ def test_dump_with_auto_fallback(self) -> None:
100
+ """Test dump_emsdk_headers with None server_url (auto local server creation)."""
101
+
102
+ with TemporaryDirectory() as tmpdir:
103
+ output_path = Path(tmpdir) / "emsdk_headers_auto.zip"
104
+
105
+ # Test with None server_url - should create local server automatically
106
+ dump_emsdk_headers(output_path, server_url=None)
107
+
108
+ # Verify the ZIP file was created
109
+ self.assertTrue(
110
+ output_path.exists(), "EMSDK headers ZIP file was not created"
111
+ )
112
+
113
+ # Verify it's not empty
114
+ self.assertGreater(
115
+ output_path.stat().st_size, 0, "EMSDK headers ZIP file is empty"
116
+ )
117
+
118
+
119
+ if __name__ == "__main__":
120
+ unittest.main()
@@ -1 +0,0 @@
1
- fastled-wasm-server>=1.1.42
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