fastled 1.2.84__py3-none-any.whl → 1.2.87__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.84"
17
+ __version__ = "1.2.87"
18
18
 
19
19
 
20
20
  class Api:
@@ -25,6 +25,10 @@ SERVER_OPTIONS = [
25
25
  "--no-auto-update", # Don't auto live updates from the git repo.
26
26
  ]
27
27
 
28
+ LOCAL_DOCKER_ENV = {
29
+ "ONLY_QUICK_BUILDS": "0" # When running docker always allow release and debug.
30
+ }
31
+
28
32
 
29
33
  def _try_get_fastled_src(path: Path) -> Path | None:
30
34
  fastled_src_dir: Path | None = None
@@ -310,6 +314,7 @@ class CompileServerImpl:
310
314
  ports=ports,
311
315
  volumes=volumes,
312
316
  remove_previous=self.interactive or self.remove_previous or updated,
317
+ environment=LOCAL_DOCKER_ENV,
313
318
  )
314
319
  self.running_container = self.docker.attach_and_run(container)
315
320
  assert self.running_container is not None, "Container should be running"
@@ -330,6 +335,7 @@ class CompileServerImpl:
330
335
  command=cmd_str,
331
336
  ports=ports,
332
337
  volumes=volumes,
338
+ environment=LOCAL_DOCKER_ENV,
333
339
  )
334
340
 
335
341
  print("Exiting interactive mode")
fastled/docker_manager.py CHANGED
@@ -533,6 +533,7 @@ class DockerManager:
533
533
  volumes: list[Volume] | None = None,
534
534
  ports: dict[int, int] | None = None,
535
535
  remove_previous: bool = False,
536
+ environment: dict[str, str] | None = None,
536
537
  ) -> Container:
537
538
  """
538
539
  Run a container from an image. If it already exists with matching config, start it.
@@ -617,6 +618,7 @@ class DockerManager:
617
618
  tty=True,
618
619
  volumes=volumes_dict,
619
620
  ports=ports, # type: ignore
621
+ environment=environment,
620
622
  remove=True,
621
623
  )
622
624
  return container
@@ -629,6 +631,7 @@ class DockerManager:
629
631
  command: str | None = None,
630
632
  volumes: list[Volume] | None = None,
631
633
  ports: dict[int, int] | None = None,
634
+ environment: dict[str, str] | None = None,
632
635
  ) -> None:
633
636
  # Convert volumes to the format expected by Docker API
634
637
  volumes = _hack_to_fix_mac(volumes)
@@ -663,6 +666,9 @@ class DockerManager:
663
666
  if ports:
664
667
  for host_port, container_port in ports.items():
665
668
  docker_command.extend(["-p", f"{host_port}:{container_port}"])
669
+ if environment:
670
+ for env_name, env_value in environment.items():
671
+ docker_command.extend(["-e", f"{env_name}={env_value}"])
666
672
  docker_command.append(f"{image_name}:{tag}")
667
673
  if command:
668
674
  docker_command.append(command)
fastled/print_filter.py CHANGED
@@ -1,5 +1,8 @@
1
1
  import re
2
+ import zlib
2
3
  from abc import ABC, abstractmethod
4
+ from dataclasses import dataclass
5
+ from enum import Enum
3
6
 
4
7
 
5
8
  class PrintFilter(ABC):
@@ -56,6 +59,8 @@ class PrintFilterFastled(PrintFilter):
56
59
  def __init__(self, echo: bool = True) -> None:
57
60
  super().__init__(echo)
58
61
  self.build_started = False
62
+ # self.compile_link_active = False
63
+ # self.compile_link_filter:
59
64
 
60
65
  def filter(self, text: str) -> str:
61
66
  lines = text.splitlines()
@@ -73,3 +78,113 @@ class PrintFilterFastled(PrintFilter):
73
78
  out.append(line)
74
79
  text = "\n".join(out)
75
80
  return text
81
+
82
+
83
+ class CompileOrLink(Enum):
84
+ COMPILE = "compile"
85
+ LINK = "link"
86
+
87
+
88
+ @dataclass
89
+ class BuildArtifact:
90
+ timestamp: float
91
+ input_artifact: str | None
92
+ output_artifact: str | None
93
+ build_flags: str
94
+ compile_or_link: CompileOrLink
95
+ hash: int
96
+
97
+ def __str__(self) -> str:
98
+ return f"{self.timestamp} {self.output_artifact} {self.build_flags} {self.compile_or_link} {self.hash}"
99
+
100
+ @staticmethod
101
+ def parse(input_str: str) -> "BuildArtifact | None":
102
+ """
103
+ Parse a single build-log line of the form:
104
+ "<timestamp> ... <some .cpp or .h file> ... <flags>"
105
+
106
+ Returns a BuildArtifact, or None if parsing failed.
107
+ """
108
+ return _parse(input_str)
109
+
110
+
111
+ class TokenFilter(ABC):
112
+ @abstractmethod
113
+ def extract(self, tokens: list[str]) -> str | None:
114
+ """
115
+ Scan `tokens`, remove any tokens this filter is responsible for,
116
+ and return the extracted string (or None if not found/invalid).
117
+ """
118
+ ...
119
+
120
+
121
+ class TimestampFilter(TokenFilter):
122
+ def extract(self, tokens: list[str]) -> str | None:
123
+ if not tokens:
124
+ return None
125
+ candidate = tokens[0]
126
+ try:
127
+ _ = float(candidate)
128
+ return tokens.pop(0)
129
+ except ValueError:
130
+ return None
131
+
132
+
133
+ class InputArtifactFilter(TokenFilter):
134
+ def extract(self, tokens: list[str]) -> str | None:
135
+ for i, tok in enumerate(tokens):
136
+ if tok.endswith(".cpp") or tok.endswith(".h"):
137
+ return tokens.pop(i)
138
+ return None
139
+
140
+
141
+ class OutputArtifactFilter(TokenFilter):
142
+ def extract(self, tokens: list[str]) -> str | None:
143
+ for i, tok in enumerate(tokens):
144
+ if tok == "-o" and i + 1 < len(tokens):
145
+ tokens.pop(i) # drop '-o'
146
+ return tokens.pop(i) # drop & return artifact
147
+ return None
148
+
149
+
150
+ class ActionFilter(TokenFilter):
151
+ def extract(self, tokens: list[str]) -> str | None:
152
+ if "-c" in tokens:
153
+ return CompileOrLink.COMPILE.value
154
+ return CompileOrLink.LINK.value
155
+
156
+
157
+ def _parse(line: str) -> BuildArtifact | None:
158
+ tokens = line.strip().split()
159
+ if not tokens:
160
+ return None
161
+
162
+ # instantiate in the order we need them
163
+ filters: list[TokenFilter] = [
164
+ TimestampFilter(),
165
+ InputArtifactFilter(),
166
+ OutputArtifactFilter(),
167
+ ActionFilter(),
168
+ ]
169
+
170
+ # apply each filter
171
+ raw_ts = filters[0].extract(tokens)
172
+ raw_in = filters[1].extract(tokens)
173
+ raw_out = filters[2].extract(tokens)
174
+ raw_act = filters[3].extract(tokens)
175
+
176
+ if raw_ts is None or raw_in is None or raw_act is None:
177
+ return None
178
+
179
+ # the rest of `tokens` are the flags
180
+ flags_str = " ".join(tokens)
181
+ h = zlib.adler32(flags_str.encode("utf-8"))
182
+
183
+ return BuildArtifact(
184
+ timestamp=float(raw_ts),
185
+ input_artifact=raw_in,
186
+ output_artifact=raw_out,
187
+ build_flags=flags_str,
188
+ compile_or_link=CompileOrLink(raw_act),
189
+ hash=h,
190
+ )
fastled/server_flask.py CHANGED
@@ -23,7 +23,8 @@ else:
23
23
  logger = logging.getLogger("flask_server")
24
24
  logger.disabled = True
25
25
 
26
- _DRAWF_SOURCE_PREFIX = "drawfsource/js/fastled/src/"
26
+ _DRAWF_SOURCE_FASTLED = "drawfsource/js/fastled/src/"
27
+ _DRAWF_SOURCE_EMSDK = "drawfsource/js/drawfsource/emsdk/"
27
28
 
28
29
 
29
30
  def _run_flask_server(
@@ -126,24 +127,34 @@ def _run_flask_server(
126
127
  return Response(f"Error: {str(e)}", status=500)
127
128
 
128
129
  def handle_dwarfsource(path: str) -> Response:
129
- """Handle requests to /drawfsource/js/fastled/src/"""
130
+ """Handle requests to /drawfsource/js/fastled/src/
131
+ or /drawfsource/js/drawfsource/emsdk/*"""
130
132
  from flask import request
131
133
 
132
134
  start_time = time.time()
133
135
  logger.info(f"Processing request: {request.method} {request.url}")
134
136
 
135
- if not path.startswith(_DRAWF_SOURCE_PREFIX):
137
+ if "../" in path:
138
+ # Prevent directory traversal attacks
139
+ error_msg = "Directory traversal attack detected"
140
+ logger.error(error_msg)
141
+ return Response(error_msg, status=400)
142
+
143
+ if not path.startswith(_DRAWF_SOURCE_FASTLED) and not path.startswith(
144
+ _DRAWF_SOURCE_EMSDK
145
+ ):
136
146
  # unexpected
137
147
  error_msg = f"Unexpected path: {path}"
138
148
  logger.error(error_msg)
139
149
  # Logging disabled
140
150
  return Response("Malformed path", status=400)
141
151
 
142
- path = path.replace("drawfsource/js/fastled/src/", "")
143
- logger.info(f"Transformed path: {path}")
152
+ # Weird magic being played with these paths, it's beyond me.
153
+ if path.startswith(_DRAWF_SOURCE_FASTLED):
154
+ path = path[len("/drawfsource") :]
144
155
 
145
156
  # Forward the request to the compile server
146
- target_url = f"http://localhost:{compile_server_port}/sourcefiles/{path}"
157
+ target_url = f"http://localhost:{compile_server_port}/drawfsource/{path}"
147
158
  logger.info(f"Requesting: {target_url}")
148
159
  logger.info(f"Processing dwarfsource request for {path}")
149
160
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: fastled
3
- Version: 1.2.84
3
+ Version: 1.2.87
4
4
  Summary: FastLED Wasm Compiler
5
5
  Home-page: https://github.com/zackees/fastled-wasm
6
6
  Maintainer: Zachary Vorhies
@@ -1,12 +1,12 @@
1
- fastled/__init__.py,sha256=hVVZOZS8MY35SzgumbD6jMLfUY0Kg34cBiADzA5cV3Q,7044
1
+ fastled/__init__.py,sha256=pXj8FDhKR-hgY-Su4vkm_F5lh4GrG-pJ8tYX73QaSxE,7044
2
2
  fastled/app.py,sha256=0W8Mbplo5UCRzj7nMVgkmCBddQGufsUQjkUUT4pMp74,4611
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
6
  fastled/client_server.py,sha256=4oRDccFMifTZPPtOYIfo4xJBJ8oE7gylVF75Rhytwig,17319
7
7
  fastled/compile_server.py,sha256=sRiXYzw7lv9vcWJWGPUkzOGZPmvZGV_TGwbHYoRc15s,3155
8
- fastled/compile_server_impl.py,sha256=t7y19DDB0auH1MmYLCi4yjc_ZyDUJ-WHy14QWTJ-pq8,13043
9
- fastled/docker_manager.py,sha256=SC_qV6grNTGh0QD1ubKrULQblrN-2PORocISlaZg9NQ,35156
8
+ fastled/compile_server_impl.py,sha256=FxTuQTojpA7j59v7zSGh1LEeG4Yu0MFgW9SKfHpspQg,13243
9
+ fastled/docker_manager.py,sha256=_qoDW34jEHTn3Yvxkv8iRUCr2csJnW6okT-FkXhJxzE,35468
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
@@ -14,10 +14,10 @@ fastled/live_client.py,sha256=yoAul8tVgbbPf1oEC79SUZSHkLECxlrXxgWR9XaBIp4,2957
14
14
  fastled/open_browser.py,sha256=DFyMrc1qic4Go7eLNPqMaLuMvTaE73NixdfSKV0yyp8,3709
15
15
  fastled/parse_args.py,sha256=waNeATOEz8D50Py5-9p6HcVSa21piTOAWOXS3ag8PYo,9428
16
16
  fastled/paths.py,sha256=VsPmgu0lNSCFOoEC0BsTYzDygXqy15AHUfN-tTuzDZA,99
17
- fastled/print_filter.py,sha256=ZpebuqfWEraSBD3Dm0PVZhQVBnU_NSILniwBHwjC1qM,2342
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=a8IOX7cgXB9agwF9hlMuAk5fNMAoclSprl0iECcH4qo,17617
20
+ fastled/server_flask.py,sha256=fbLuF993pbBqoyMbjHT1GPwjlxBib3cUUW719PNfN1w,18108
21
21
  fastled/server_start.py,sha256=W9yKStkRlRNuXeV6j_6O7HjjFPyVLBHMcF9Uy2QjDWQ,479
22
22
  fastled/settings.py,sha256=oezRvRUJWwauO-kpC4LDbKg6Q-ij4d09UtR2vkjSAPU,575
23
23
  fastled/sketch.py,sha256=tHckjDj8P6BI_LWzUFM071a9qcqPs-r-qFWIe50P5Xw,3391
@@ -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.84.dist-info/licenses/LICENSE,sha256=b6pOoifSXiUaz_lDS84vWlG3fr4yUKwB8fzkrH9R8bQ,1064
37
- fastled-1.2.84.dist-info/METADATA,sha256=C02EyZg2HxA80WF2AV5tcPt7kxys7h9caPt_gYiEQCM,21940
38
- fastled-1.2.84.dist-info/WHEEL,sha256=DnLRTWE75wApRYVsjgc6wsVswC54sMSJhAEd4xhDpBk,91
39
- fastled-1.2.84.dist-info/entry_points.txt,sha256=RCwmzCSOS4-C2i9EziANq7Z2Zb4KFnEMR1FQC0bBwAw,101
40
- fastled-1.2.84.dist-info/top_level.txt,sha256=Bbv5kpJpZhWNCvDF4K0VcvtBSDMa8B7PTOrZa9CezHY,8
41
- fastled-1.2.84.dist-info/RECORD,,
36
+ fastled-1.2.87.dist-info/licenses/LICENSE,sha256=b6pOoifSXiUaz_lDS84vWlG3fr4yUKwB8fzkrH9R8bQ,1064
37
+ fastled-1.2.87.dist-info/METADATA,sha256=WLh9Pi4s5hfiXZRVV2jW7sK0oyxDq_yU3eb7ZeKdZAc,21940
38
+ fastled-1.2.87.dist-info/WHEEL,sha256=DnLRTWE75wApRYVsjgc6wsVswC54sMSJhAEd4xhDpBk,91
39
+ fastled-1.2.87.dist-info/entry_points.txt,sha256=RCwmzCSOS4-C2i9EziANq7Z2Zb4KFnEMR1FQC0bBwAw,101
40
+ fastled-1.2.87.dist-info/top_level.txt,sha256=Bbv5kpJpZhWNCvDF4K0VcvtBSDMa8B7PTOrZa9CezHY,8
41
+ fastled-1.2.87.dist-info/RECORD,,