fastled 1.3.35__py3-none-any.whl → 1.3.37__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
@@ -39,6 +39,7 @@ class Api:
39
39
  host: str | CompileServer | None = None,
40
40
  build_mode: BuildMode = BuildMode.QUICK,
41
41
  profile: bool = False, # When true then profile information will be enabled and included in the zip.
42
+ no_platformio: bool = False,
42
43
  ) -> CompileResult:
43
44
  from fastled.web_compile import web_compile
44
45
 
@@ -47,7 +48,11 @@ class Api:
47
48
  if isinstance(directory, str):
48
49
  directory = Path(directory)
49
50
  out: CompileResult = web_compile(
50
- directory, host, build_mode=build_mode, profile=profile
51
+ directory,
52
+ host,
53
+ build_mode=build_mode,
54
+ profile=profile,
55
+ no_platformio=no_platformio,
51
56
  )
52
57
  return out
53
58
 
fastled/__main__.py ADDED
@@ -0,0 +1,14 @@
1
+ #!/usr/bin/env python3
2
+ """
3
+ FastLED Package Main Entry Point
4
+ Enables running the package as: python -m fastled
5
+ """
6
+
7
+ import sys
8
+
9
+ from fastled.cli import main
10
+
11
+ if __name__ == "__main__":
12
+ # Pass execution to the main function from cli.py
13
+ # This enables 'python -m fastled' to work the same as 'fastled' command
14
+ sys.exit(main())
fastled/__version__.py CHANGED
@@ -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.35"
4
+ __version__ = "1.3.37"
5
5
 
6
6
  __version_url_latest__ = "https://raw.githubusercontent.com/zackees/fastled-wasm/refs/heads/main/src/fastled/__version__.py"
fastled/client_server.py CHANGED
@@ -76,12 +76,17 @@ def _run_web_compiler(
76
76
  build_mode: BuildMode,
77
77
  profile: bool,
78
78
  last_hash_value: str | None,
79
+ no_platformio: bool = False,
79
80
  ) -> CompileResult:
80
81
  input_dir = Path(directory)
81
82
  output_dir = input_dir / "fastled_js"
82
83
  start = time.time()
83
84
  web_result = web_compile(
84
- directory=input_dir, host=host, build_mode=build_mode, profile=profile
85
+ directory=input_dir,
86
+ host=host,
87
+ build_mode=build_mode,
88
+ profile=profile,
89
+ no_platformio=no_platformio,
85
90
  )
86
91
  diff = time.time() - start
87
92
  if not web_result.success:
@@ -287,6 +292,7 @@ def run_client(
287
292
  build_mode: BuildMode = build_mode,
288
293
  profile: bool = profile,
289
294
  last_hash_value: str | None = None,
295
+ no_platformio: bool = no_platformio,
290
296
  ) -> CompileResult:
291
297
  TEST_BEFORE_COMPILE(url)
292
298
  return _run_web_compiler(
@@ -295,6 +301,7 @@ def run_client(
295
301
  build_mode=build_mode,
296
302
  profile=profile,
297
303
  last_hash_value=last_hash_value,
304
+ no_platformio=no_platformio,
298
305
  )
299
306
 
300
307
  result: CompileResult = compile_function(last_hash_value=None)
@@ -107,7 +107,11 @@ class CompileServerImpl:
107
107
  if not self.ping():
108
108
  raise RuntimeError("Server is not running")
109
109
  out: CompileResult = web_compile(
110
- directory, host=self.url(), build_mode=build_mode, profile=profile
110
+ directory,
111
+ host=self.url(),
112
+ build_mode=build_mode,
113
+ profile=profile,
114
+ no_platformio=self.no_platformio,
111
115
  )
112
116
  return out
113
117
 
fastled/string_diff.py CHANGED
@@ -10,11 +10,14 @@ def _filter_out_obvious_bad_choices(
10
10
  Filter out strings that are too different from the input string.
11
11
  This is a heuristic and may not be perfect.
12
12
  """
13
- input_chars = set(input_str)
13
+ if not input_str.strip(): # Handle empty input
14
+ return string_list
15
+
16
+ input_chars = set(input_str.lower())
14
17
  filtered_list = []
15
18
  for s in string_list:
16
19
  # Check if at least half of the input characters are in the string
17
- s_chars = set(s)
20
+ s_chars = set(s.lower())
18
21
  common_chars = input_chars.intersection(s_chars)
19
22
  if len(common_chars) >= len(input_chars) / 2:
20
23
  filtered_list.append(s)
@@ -29,8 +32,8 @@ def is_in_order_match(input_str: str, other: str) -> bool:
29
32
  """
30
33
 
31
34
  # Remove spaces from input string for matching
32
- input_chars = [c for c in input_str if c != " "]
33
- other_chars = list(other)
35
+ input_chars = [c.lower() for c in input_str if c != " "]
36
+ other_chars = [c.lower() for c in other]
34
37
  input_index = 0
35
38
  other_index = 0
36
39
  while input_index < len(input_chars) and other_index < len(other_chars):
@@ -53,6 +56,14 @@ def string_diff(
53
56
  def normalize(s: str) -> str:
54
57
  return s.lower() if ignore_case else s
55
58
 
59
+ # Handle empty input or empty list
60
+ if not input_string.strip():
61
+ # Return all strings with equal distance for empty input
62
+ return [(i, s) for i, s in enumerate(string_list)]
63
+
64
+ if not string_list:
65
+ return []
66
+
56
67
  map_string: dict[str, str] = {}
57
68
 
58
69
  if ignore_case:
@@ -60,38 +71,71 @@ def string_diff(
60
71
  else:
61
72
  map_string = {s: s for s in string_list}
62
73
 
74
+ original_string_list = string_list.copy()
63
75
  if ignore_case:
64
76
  string_list = [s.lower() for s in string_list]
65
77
  input_string = input_string.lower()
66
78
 
79
+ # Check for exact matches, but also check if there are other substring matches
80
+ exact_matches = [s for s in string_list if s == input_string]
81
+ substring_matches = [s for s in string_list if input_string in s]
82
+
83
+ # If there's an exact match AND other substring matches, return all substring matches
84
+ # This provides better user experience for partial matching
85
+ if exact_matches and len(substring_matches) > 1:
86
+ out: list[tuple[float, str]] = []
87
+ for i, s in enumerate(substring_matches):
88
+ s_mapped = map_string.get(s, s)
89
+ out.append((i, s_mapped))
90
+ return out
91
+
92
+ # If there's only an exact match and no other substring matches, return just the exact match
93
+ if exact_matches and len(substring_matches) == 1:
94
+ out: list[tuple[float, str]] = []
95
+ for i, s in enumerate(exact_matches):
96
+ s_mapped = map_string.get(s, s)
97
+ out.append((i, s_mapped))
98
+ return out
99
+
67
100
  # Apply set membership filtering for queries with 3+ characters
68
- if len(input_string) >= 3:
69
- string_list = _filter_out_obvious_bad_choices(input_string, string_list)
101
+ if len(input_string.strip()) >= 3:
102
+ filtered = _filter_out_obvious_bad_choices(input_string, string_list)
103
+ if filtered: # Only apply filter if it doesn't eliminate everything
104
+ string_list = filtered
70
105
 
71
106
  # Second filter: exact substring filtering if applicable
72
- is_substring = False
73
- for s in string_list:
74
- if input_string in s:
75
- is_substring = True
76
- break
77
-
78
- if is_substring:
79
- string_list = [s for s in string_list if input_string in s]
107
+ if substring_matches:
108
+ string_list = substring_matches
109
+ # Return all substring matches
110
+ out: list[tuple[float, str]] = []
111
+ for i, s in enumerate(string_list):
112
+ s_mapped = map_string.get(s, s)
113
+ out.append((i, s_mapped))
114
+ return out
80
115
 
81
116
  # Third filter: in order exact match filtering if applicable.
82
- is_in_order = False
83
- for s in string_list:
84
- if is_in_order_match(input_string, s):
85
- is_in_order = True
86
- break
87
-
88
- if is_in_order:
89
- string_list = [s for s in string_list if is_in_order_match(input_string, s)]
117
+ in_order_matches = [s for s in string_list if is_in_order_match(input_string, s)]
118
+ if in_order_matches:
119
+ string_list = in_order_matches
90
120
 
121
+ # Calculate distances
91
122
  distances: list[float] = []
92
123
  for s in string_list:
93
124
  dist = fuzz.token_sort_ratio(normalize(input_string), normalize(s))
94
125
  distances.append(1.0 / (dist + 1.0))
126
+
127
+ # Handle case where no strings remain after filtering
128
+ if not distances:
129
+ # Fall back to original list and calculate distances
130
+ string_list = original_string_list.copy()
131
+ if ignore_case:
132
+ string_list = [s.lower() for s in string_list]
133
+
134
+ distances = []
135
+ for s in string_list:
136
+ dist = fuzz.token_sort_ratio(normalize(input_string), normalize(s))
137
+ distances.append(1.0 / (dist + 1.0))
138
+
95
139
  min_distance = min(distances)
96
140
  out: list[tuple[float, str]] = []
97
141
  for i, d in enumerate(distances):
@@ -106,10 +150,16 @@ def string_diff(
106
150
  def string_diff_paths(
107
151
  input_string: str | Path, path_list: list[Path], ignore_case=True
108
152
  ) -> list[tuple[float, Path]]:
109
- string_list = [str(p) for p in path_list]
110
- tmp = string_diff(str(input_string), string_list, ignore_case)
153
+ # Normalize path separators to forward slashes for consistent comparison
154
+ string_list = [str(p).replace("\\", "/") for p in path_list]
155
+ input_str = str(input_string).replace("\\", "/")
156
+
157
+ tmp = string_diff(input_str, string_list, ignore_case)
111
158
  out: list[tuple[float, Path]] = []
112
159
  for i, j in tmp:
113
- p = Path(j)
114
- out.append((i, p))
160
+ # Find the original path that matches the normalized result
161
+ for idx, orig_path in enumerate(path_list):
162
+ if str(orig_path).replace("\\", "/") == j:
163
+ out.append((i, orig_path))
164
+ break
115
165
  return out
fastled/web_compile.py CHANGED
@@ -195,6 +195,7 @@ def web_compile(
195
195
  auth_token: str | None = None,
196
196
  build_mode: BuildMode | None = None,
197
197
  profile: bool = False,
198
+ no_platformio: bool = False,
198
199
  ) -> CompileResult:
199
200
  start_time = time.time()
200
201
  if isinstance(directory, str):
@@ -249,6 +250,7 @@ def web_compile(
249
250
  else BuildMode.QUICK.value.lower()
250
251
  ),
251
252
  "profile": "true" if profile else "false",
253
+ "no-platformio": "true" if no_platformio else "false",
252
254
  }
253
255
 
254
256
  url = f"{connection_result.host}/{ENDPOINT_COMPILED_WASM}"
@@ -292,8 +294,16 @@ def web_compile(
292
294
  # Read stdout from out.txt if it exists
293
295
  stdout_file = extract_path / "out.txt"
294
296
  hash_file = extract_path / "hash.txt"
295
- stdout = stdout_file.read_text() if stdout_file.exists() else ""
296
- hash_value = hash_file.read_text() if hash_file.exists() else None
297
+ stdout = (
298
+ stdout_file.read_text(encoding="utf-8", errors="replace")
299
+ if stdout_file.exists()
300
+ else ""
301
+ )
302
+ hash_value = (
303
+ hash_file.read_text(encoding="utf-8", errors="replace")
304
+ if hash_file.exists()
305
+ else None
306
+ )
297
307
 
298
308
  # now rezip the extracted files since we added the embedded json files
299
309
  out_buffer = io.BytesIO()
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: fastled
3
- Version: 1.3.35
3
+ Version: 1.3.37
4
4
  Summary: FastLED Wasm Compiler
5
5
  Home-page: https://github.com/zackees/fastled-wasm
6
6
  Maintainer: Zachary Vorhies
@@ -1,13 +1,14 @@
1
- fastled/__init__.py,sha256=QbQGFxPGTjlf4poTh-NiGuyyzSiO7qqz0KKfJn4M-Vw,7086
2
- fastled/__version__.py,sha256=-15zyEprr1jMh8Ah0BOI61VommdW3bUa79iSN98eN9Q,373
1
+ fastled/__init__.py,sha256=NBk5Ef65nIe0F_rvBrSGeoyouFOKFeQXqHrTCJQheeI,7201
2
+ fastled/__main__.py,sha256=OcKv2ER1_iQAsZzLIUb3C8hRC9L2clNOhCrjpshrlf4,336
3
+ fastled/__version__.py,sha256=6DzB8Pydf4Zp3pw17QZL6CMeti7MBDNhX04qQV2_ssU,373
3
4
  fastled/app.py,sha256=TFVn4qIRdt7dYbpDWudEHrhvD9pwyj9sIGXs4F26nhk,5880
4
5
  fastled/args.py,sha256=kucRGYpff_YKfmMpwWsJh6WIrvW_UPcNlZNFdw15z-Y,3475
5
6
  fastled/cli.py,sha256=drgR2AOxVrj3QEz58iiKscYAumbbin2vIV-k91VCOAA,561
6
7
  fastled/cli_test.py,sha256=W-1nODZrip_JU6BEbYhxOa4ckxduOsiX8zIoRkTyxv4,550
7
8
  fastled/cli_test_interactive.py,sha256=BjNhveZOk5aCffHbcrxPQQjWmAuj4ClVKKcKX5eY6yM,542
8
- fastled/client_server.py,sha256=YID7O7e8dAhpFRGwRburfSuMOw5h7MJpsjzgbDY9xKg,19511
9
+ fastled/client_server.py,sha256=ATK0GCem9iJXC7zPkFofaR4Df6yWsgAcqf_clwpSZe0,19700
9
10
  fastled/compile_server.py,sha256=yQtwLOSKINO1CKD0NWxf-7YQKSatf9sF9RuqaWGOkCs,3038
10
- fastled/compile_server_impl.py,sha256=EzNWAy501beDiiysuUXW5bgySnpqzqoTeLzMUVy3ZzE,11899
11
+ fastled/compile_server_impl.py,sha256=9vTGaDQ0W_g9Xsfy0gC3nJEc2g_pnXcF4VO2U3GLOVg,11982
11
12
  fastled/docker_manager.py,sha256=rkq39ZKrU6NHIyDa3mzs0Unb6o9oMeAwxhqiuHJU_RY,40291
12
13
  fastled/filewatcher.py,sha256=gEcJJHTDJ1X3gKJzltmEBhixWGbZj2eJD7a4vwSvITQ,10036
13
14
  fastled/keyboard.py,sha256=UTAsqCn1UMYnB8YDzENiLTj4GeL45tYfEcO7_5fLFEg,3556
@@ -24,11 +25,11 @@ fastled/server_start.py,sha256=W9yKStkRlRNuXeV6j_6O7HjjFPyVLBHMcF9Uy2QjDWQ,479
24
25
  fastled/settings.py,sha256=dUVyJ8Mtprg0RwaS6oMWP8jBhr4C3R8fu4Hdx_Z1lCM,577
25
26
  fastled/sketch.py,sha256=Ftbh55Nt-p4hmPuPpj8Q9HrMzvnUazhoG_q9FHcxkns,3473
26
27
  fastled/spinner.py,sha256=VHxmvB92P0Z_zYxRajb5HiNmkHHvZ5dG7hKtZltzpcs,867
27
- fastled/string_diff.py,sha256=dlhJCFHSiqW9GMByS2DFnguZ28387VNcFwR6zGVlKeU,3729
28
+ fastled/string_diff.py,sha256=oTncu0qYdLlLUtYLLDB4bzdQ2OfzegAR6XNAzwE9fIs,6002
28
29
  fastled/types.py,sha256=ZDf1TbTT4XgA_pKIwr4JbkDB38_29ogSdDORjoT-zuY,1803
29
30
  fastled/util.py,sha256=TjhXbUNh4p2BGhNAldSeL68B7BBOjsWAXji5gy-vDEQ,1440
30
31
  fastled/version.py,sha256=TpBMiEVdO3_sUZEu6wmwN8Q4AgX2BiCxStCsnPKh6E0,1209
31
- fastled/web_compile.py,sha256=JYxhZBhbv2Rq2SvN2_pl_p9ewgskfKghQ8UJllC-T4I,11535
32
+ fastled/web_compile.py,sha256=BPrlrW7RMAtnbYUFF3LDn0ORx7aiMOuQkSlYF_gA1o0,11867
32
33
  fastled/assets/example.txt,sha256=lTBovRjiz0_TgtAtbA1C5hNi2ffbqnNPqkKg6UiKCT8,54
33
34
  fastled/assets/localhost-key.pem,sha256=Q-CNO_UoOd8fFNN4ljcnqwUeCMhzTplRjLO2x0pYRlU,1704
34
35
  fastled/assets/localhost.pem,sha256=QTwUtTwjYWbm9m3pHW2IlK2nFZJ8b0pppxPjhgVZqQo,1619
@@ -36,9 +37,9 @@ fastled/site/build.py,sha256=2YKU_UWKlJdGnjdbAbaL0co6kceFMSTVYwH1KCmgPZA,13987
36
37
  fastled/site/examples.py,sha256=s6vj2zJc6BfKlnbwXr1QWY1mzuDBMt6j5MEBOWjO_U8,155
37
38
  fastled/test/can_run_local_docker_tests.py,sha256=LEuUbHctRhNNFWcvnz2kEGmjDJeXO4c3kNpizm3yVJs,400
38
39
  fastled/test/examples.py,sha256=GfaHeY1E8izBl6ZqDVjz--RHLyVR4NRnQ5pBesCFJFY,1673
39
- fastled-1.3.35.dist-info/licenses/LICENSE,sha256=b6pOoifSXiUaz_lDS84vWlG3fr4yUKwB8fzkrH9R8bQ,1064
40
- fastled-1.3.35.dist-info/METADATA,sha256=p78fly8dbXf0skn_cwXTmwpwAF9NUvf7wtCxTPFx1jM,30847
41
- fastled-1.3.35.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
42
- fastled-1.3.35.dist-info/entry_points.txt,sha256=RCwmzCSOS4-C2i9EziANq7Z2Zb4KFnEMR1FQC0bBwAw,101
43
- fastled-1.3.35.dist-info/top_level.txt,sha256=Bbv5kpJpZhWNCvDF4K0VcvtBSDMa8B7PTOrZa9CezHY,8
44
- fastled-1.3.35.dist-info/RECORD,,
40
+ fastled-1.3.37.dist-info/licenses/LICENSE,sha256=b6pOoifSXiUaz_lDS84vWlG3fr4yUKwB8fzkrH9R8bQ,1064
41
+ fastled-1.3.37.dist-info/METADATA,sha256=PNqojURrkwG5ZvAO8Qnfr5d8ELBLcU5q7X9zmNze2dM,30847
42
+ fastled-1.3.37.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
43
+ fastled-1.3.37.dist-info/entry_points.txt,sha256=RCwmzCSOS4-C2i9EziANq7Z2Zb4KFnEMR1FQC0bBwAw,101
44
+ fastled-1.3.37.dist-info/top_level.txt,sha256=Bbv5kpJpZhWNCvDF4K0VcvtBSDMa8B7PTOrZa9CezHY,8
45
+ fastled-1.3.37.dist-info/RECORD,,