fastled 1.2.92__py3-none-any.whl → 1.2.94__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 CHANGED
@@ -14,7 +14,7 @@ from .types import BuildMode, CompileResult, CompileServerError, FileResponse
14
14
  # IMPORTANT! There's a bug in github which will REJECT any version update
15
15
  # that has any other change in the repo. Please bump the version as the
16
16
  # ONLY change in a commit, or else the pypi update and the release will fail.
17
- __version__ = "1.2.92"
17
+ __version__ = "1.2.94"
18
18
 
19
19
 
20
20
  class Api:
fastled/client_server.py CHANGED
@@ -12,7 +12,7 @@ from fastled.filewatcher import DebouncedFileWatcherProcess, FileWatcherProcess
12
12
  from fastled.keyboard import SpaceBarWatcher
13
13
  from fastled.open_browser import spawn_http_server
14
14
  from fastled.parse_args import Args
15
- from fastled.settings import DEFAULT_URL
15
+ from fastled.settings import DEFAULT_URL, IMAGE_NAME
16
16
  from fastled.sketch import looks_like_sketch_directory
17
17
  from fastled.types import BuildMode, CompileResult, CompileServerError
18
18
  from fastled.web_compile import (
@@ -223,6 +223,7 @@ def run_client(
223
223
  int | None
224
224
  ) = None, # None means auto select a free port, http_port < 0 means no server.
225
225
  ) -> int:
226
+ has_checked_newer_version_yet = False
226
227
  compile_server: CompileServer | None = None
227
228
 
228
229
  if host is None:
@@ -244,6 +245,7 @@ def run_client(
244
245
  return DEFAULT_URL
245
246
 
246
247
  url = get_url()
248
+ is_local_host = _is_local_host(url)
247
249
  # parse out the port from the url
248
250
  # use a standard host address parser to grab it
249
251
  import urllib.parse
@@ -252,7 +254,7 @@ def run_client(
252
254
  if parsed_url.port is not None:
253
255
  port = parsed_url.port
254
256
  else:
255
- if _is_local_host(url):
257
+ if is_local_host:
256
258
  raise ValueError(
257
259
  "Cannot use local host without a port. Please specify a port."
258
260
  )
@@ -350,6 +352,29 @@ def run_client(
350
352
  if shutdown.is_set():
351
353
  print("\nStopping watch mode...")
352
354
  return 0
355
+
356
+ # Check for newer Docker image version after first successful compilation
357
+ if (
358
+ not has_checked_newer_version_yet
359
+ and last_compiled_result.success
360
+ and is_local_host
361
+ ):
362
+ has_checked_newer_version_yet = True
363
+ try:
364
+
365
+ docker_manager = DockerManager()
366
+ has_update, message = docker_manager.has_newer_version(
367
+ image_name=IMAGE_NAME, tag="latest"
368
+ )
369
+ if has_update:
370
+ print(f"\n🔄 {message}")
371
+ print(
372
+ "Run with --auto-update to automatically update to the latest version."
373
+ )
374
+ except Exception as e:
375
+ # Don't let Docker check failures interrupt the main flow
376
+ warnings.warn(f"Failed to check for Docker image updates: {e}")
377
+
353
378
  if SpaceBarWatcher.watch_space_bar_pressed(timeout=1.0):
354
379
  print("Compiling...")
355
380
  last_compiled_result = compile_function(last_hash_value=None)
fastled/docker_manager.py CHANGED
@@ -353,6 +353,48 @@ class DockerManager:
353
353
  print(f"Error starting Docker: {str(e)}")
354
354
  return False
355
355
 
356
+ def has_newer_version(
357
+ self, image_name: str, tag: str = "latest"
358
+ ) -> tuple[bool, str]:
359
+ """
360
+ Check if a newer version of the image is available in the registry.
361
+
362
+ Args:
363
+ image_name: The name of the image to check
364
+ tag: The tag of the image to check
365
+
366
+ Returns:
367
+ A tuple of (has_newer_version, message)
368
+ has_newer_version: True if a newer version is available, False otherwise
369
+ message: A message describing the result
370
+ """
371
+ try:
372
+ # Get the local image
373
+ local_image = self.client.images.get(f"{image_name}:{tag}")
374
+ local_image_id = local_image.id
375
+ assert local_image_id is not None
376
+
377
+ # Get the remote image data
378
+ remote_image = self.client.images.get_registry_data(f"{image_name}:{tag}")
379
+ remote_image_hash = remote_image.id
380
+
381
+ # Check if we have a cached remote hash for this local image
382
+ try:
383
+ remote_image_hash_from_local_image = DISK_CACHE.get(local_image_id)
384
+ except Exception:
385
+ remote_image_hash_from_local_image = None
386
+
387
+ # Compare the hashes
388
+ if remote_image_hash_from_local_image == remote_image_hash:
389
+ return False, f"Local image {image_name}:{tag} is up to date."
390
+ else:
391
+ return True, f"Newer version of {image_name}:{tag} is available."
392
+
393
+ except ImageNotFound:
394
+ return True, f"Image {image_name}:{tag} not found locally."
395
+ except DockerException as e:
396
+ return False, f"Error checking for newer version: {e}"
397
+
356
398
  def validate_or_download_image(
357
399
  self, image_name: str, tag: str = "latest", upgrade: bool = False
358
400
  ) -> bool:
fastled/server_flask.py CHANGED
@@ -23,9 +23,22 @@ else:
23
23
  logger = logging.getLogger("flask_server")
24
24
  logger.disabled = True
25
25
 
26
- _DRAWF_SOURCE_FASTLED = "drawfsource/js/fastled/src/"
26
+ _DRAWF_SOURCE_FASTLED = "drawfsource/src/drawfsource/git/fastled/src"
27
27
  _DRAWF_SOURCE_EMSDK = "drawfsource/js/drawfsource/emsdk/"
28
28
 
29
+ # Mirrors what's on the server.
30
+ _PATTERNS_FASTLED_SRC = [
31
+ "drawfsource/js/src/drawfsource/git/fastled/src/",
32
+ "drawfsource/js/drawfsource/headers/",
33
+ ]
34
+
35
+
36
+ def _resolve_fastled_src(drawfsource: str) -> str | None:
37
+ for pattern in _PATTERNS_FASTLED_SRC:
38
+ if drawfsource.startswith(pattern):
39
+ return drawfsource[len(pattern) :]
40
+ return None
41
+
29
42
 
30
43
  def _run_flask_server(
31
44
  fastled_js: Path,
@@ -140,21 +153,14 @@ def _run_flask_server(
140
153
  logger.error(error_msg)
141
154
  return Response(error_msg, status=400)
142
155
 
143
- if not path.startswith(_DRAWF_SOURCE_FASTLED) and not path.startswith(
144
- _DRAWF_SOURCE_EMSDK
145
- ):
146
- # unexpected
147
- error_msg = f"Unexpected path: {path}"
148
- logger.error(error_msg)
149
- # Logging disabled
150
- return Response("Malformed path", status=400)
151
-
152
- # Weird magic being played with these paths, it's beyond me.
153
- if path.startswith(_DRAWF_SOURCE_FASTLED):
154
- path = path[len("/drawfsource") :]
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)
155
161
 
156
162
  # Forward the request to the compile server
157
- target_url = f"http://localhost:{compile_server_port}/drawfsource/{path}"
163
+ target_url = f"http://localhost:{compile_server_port}/sourcefiles/{path}"
158
164
  logger.info(f"Requesting: {target_url}")
159
165
  logger.info(f"Processing dwarfsource request for {path}")
160
166
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: fastled
3
- Version: 1.2.92
3
+ Version: 1.2.94
4
4
  Summary: FastLED Wasm Compiler
5
5
  Home-page: https://github.com/zackees/fastled-wasm
6
6
  Maintainer: Zachary Vorhies
@@ -20,7 +20,7 @@ Requires-Dist: progress>=1.6
20
20
  Requires-Dist: watchfiles>=1.0.5
21
21
  Requires-Dist: Flask>=3.0.0
22
22
  Requires-Dist: livereload
23
- Requires-Dist: fastled-wasm-server>=1.0.6
23
+ Requires-Dist: fastled-wasm-server>=1.0.13
24
24
  Dynamic: home-page
25
25
  Dynamic: license-file
26
26
  Dynamic: maintainer
@@ -1,12 +1,12 @@
1
- fastled/__init__.py,sha256=dJxxPCiEssX9zu8rrYMhDrCXm9PLMbYFEZiXJauu6Hg,7044
1
+ fastled/__init__.py,sha256=3olm9Ojfjl2kG3HObvjNcZASUUzAQSRIbXPUzARL7eo,7044
2
2
  fastled/app.py,sha256=LyQXHmIjK8aqel9sDRmzSHjnOiaITbsnGPoz6IDXQFc,6032
3
3
  fastled/cli.py,sha256=FjVr31ht0UPlAcmX-84NwfAGMQHTkrCe4o744jCAxiw,375
4
4
  fastled/cli_test.py,sha256=qJB9yLRFR3OwOwdIWSQ0fQsWLnA37v5pDccufiP_hTs,512
5
5
  fastled/cli_test_interactive.py,sha256=BjNhveZOk5aCffHbcrxPQQjWmAuj4ClVKKcKX5eY6yM,542
6
- fastled/client_server.py,sha256=4oRDccFMifTZPPtOYIfo4xJBJ8oE7gylVF75Rhytwig,17319
6
+ fastled/client_server.py,sha256=falqUhGSHQpNfEXNCcQFPDAZymfncEVhIDcURBIJTFk,18390
7
7
  fastled/compile_server.py,sha256=sRiXYzw7lv9vcWJWGPUkzOGZPmvZGV_TGwbHYoRc15s,3155
8
8
  fastled/compile_server_impl.py,sha256=FxTuQTojpA7j59v7zSGh1LEeG4Yu0MFgW9SKfHpspQg,13243
9
- fastled/docker_manager.py,sha256=_qoDW34jEHTn3Yvxkv8iRUCr2csJnW6okT-FkXhJxzE,35468
9
+ fastled/docker_manager.py,sha256=6zg1JcrBFj0fbFc1adPoT6_8GE0YFAPHG80Cf7ytYGE,37139
10
10
  fastled/filewatcher.py,sha256=3qS3L7zMQhFuVrkeGn1djsB_cB6x_E2YGJmmQWVAU_w,10033
11
11
  fastled/keyboard.py,sha256=UTAsqCn1UMYnB8YDzENiLTj4GeL45tYfEcO7_5fLFEg,3556
12
12
  fastled/keyz.py,sha256=LO-8m_7CpNDiZLM-FXhQ30f9gN1bUYz5lOsUPTIbI-c,4020
@@ -17,7 +17,7 @@ fastled/paths.py,sha256=VsPmgu0lNSCFOoEC0BsTYzDygXqy15AHUfN-tTuzDZA,99
17
17
  fastled/print_filter.py,sha256=B0v493WAFN8DgG7aqM8iXMqI_V1EdMMvOnNQ26JNUxU,5499
18
18
  fastled/project_init.py,sha256=bBt4DwmW5hZkm9ICt9Qk-0Nr_0JQM7icCgH5Iv-bCQs,3984
19
19
  fastled/select_sketch_directory.py,sha256=-eudwCns3AKj4HuHtSkZAFwbnf005SNL07pOzs9VxnE,1383
20
- fastled/server_flask.py,sha256=fbLuF993pbBqoyMbjHT1GPwjlxBib3cUUW719PNfN1w,18108
20
+ fastled/server_flask.py,sha256=He2CZ65YvDWbjF7Lc3ryONfo2D5SWQ4FxsztQlxaE8s,18269
21
21
  fastled/server_start.py,sha256=W9yKStkRlRNuXeV6j_6O7HjjFPyVLBHMcF9Uy2QjDWQ,479
22
22
  fastled/settings.py,sha256=dUVyJ8Mtprg0RwaS6oMWP8jBhr4C3R8fu4Hdx_Z1lCM,577
23
23
  fastled/sketch.py,sha256=Ftbh55Nt-p4hmPuPpj8Q9HrMzvnUazhoG_q9FHcxkns,3473
@@ -33,9 +33,9 @@ fastled/site/build.py,sha256=2YKU_UWKlJdGnjdbAbaL0co6kceFMSTVYwH1KCmgPZA,13987
33
33
  fastled/site/examples.py,sha256=s6vj2zJc6BfKlnbwXr1QWY1mzuDBMt6j5MEBOWjO_U8,155
34
34
  fastled/test/can_run_local_docker_tests.py,sha256=LEuUbHctRhNNFWcvnz2kEGmjDJeXO4c3kNpizm3yVJs,400
35
35
  fastled/test/examples.py,sha256=GfaHeY1E8izBl6ZqDVjz--RHLyVR4NRnQ5pBesCFJFY,1673
36
- fastled-1.2.92.dist-info/licenses/LICENSE,sha256=b6pOoifSXiUaz_lDS84vWlG3fr4yUKwB8fzkrH9R8bQ,1064
37
- fastled-1.2.92.dist-info/METADATA,sha256=8gAhxvb-Iih12m6DZAcdavkZqFoCvTlNhNXqbS4rT_o,30049
38
- fastled-1.2.92.dist-info/WHEEL,sha256=DnLRTWE75wApRYVsjgc6wsVswC54sMSJhAEd4xhDpBk,91
39
- fastled-1.2.92.dist-info/entry_points.txt,sha256=RCwmzCSOS4-C2i9EziANq7Z2Zb4KFnEMR1FQC0bBwAw,101
40
- fastled-1.2.92.dist-info/top_level.txt,sha256=Bbv5kpJpZhWNCvDF4K0VcvtBSDMa8B7PTOrZa9CezHY,8
41
- fastled-1.2.92.dist-info/RECORD,,
36
+ fastled-1.2.94.dist-info/licenses/LICENSE,sha256=b6pOoifSXiUaz_lDS84vWlG3fr4yUKwB8fzkrH9R8bQ,1064
37
+ fastled-1.2.94.dist-info/METADATA,sha256=Tub7m_KbSuL4uHwkj1IvgN7my0omZhONapIFnlTxsFU,30050
38
+ fastled-1.2.94.dist-info/WHEEL,sha256=DnLRTWE75wApRYVsjgc6wsVswC54sMSJhAEd4xhDpBk,91
39
+ fastled-1.2.94.dist-info/entry_points.txt,sha256=RCwmzCSOS4-C2i9EziANq7Z2Zb4KFnEMR1FQC0bBwAw,101
40
+ fastled-1.2.94.dist-info/top_level.txt,sha256=Bbv5kpJpZhWNCvDF4K0VcvtBSDMa8B7PTOrZa9CezHY,8
41
+ fastled-1.2.94.dist-info/RECORD,,