fastled 1.3.36__py3-none-any.whl → 1.3.38__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/__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.36"
4
+ __version__ = "1.3.38"
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
@@ -1,4 +1,5 @@
1
1
  import shutil
2
+ import sys
2
3
  import tempfile
3
4
  import threading
4
5
  import time
@@ -67,7 +68,20 @@ def TEST_BEFORE_COMPILE(url) -> None:
67
68
  def _chunked_print(stdout: str) -> None:
68
69
  lines = stdout.splitlines()
69
70
  for line in lines:
70
- print(line)
71
+ try:
72
+ print(line)
73
+ except UnicodeEncodeError:
74
+ # On Windows, the console may not support Unicode characters
75
+ # Try to encode the line with the console's encoding and replace problematic characters
76
+ try:
77
+ console_encoding = sys.stdout.encoding or "utf-8"
78
+ encoded_line = line.encode(console_encoding, errors="replace").decode(
79
+ console_encoding
80
+ )
81
+ print(encoded_line)
82
+ except Exception:
83
+ # If all else fails, just print the line without problematic characters
84
+ print(line.encode("ascii", errors="replace").decode("ascii"))
71
85
 
72
86
 
73
87
  def _run_web_compiler(
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
@@ -294,8 +294,16 @@ def web_compile(
294
294
  # Read stdout from out.txt if it exists
295
295
  stdout_file = extract_path / "out.txt"
296
296
  hash_file = extract_path / "hash.txt"
297
- stdout = stdout_file.read_text() if stdout_file.exists() else ""
298
- 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
+ )
299
307
 
300
308
  # now rezip the extracted files since we added the embedded json files
301
309
  out_buffer = io.BytesIO()
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: fastled
3
- Version: 1.3.36
3
+ Version: 1.3.38
4
4
  Summary: FastLED Wasm Compiler
5
5
  Home-page: https://github.com/zackees/fastled-wasm
6
6
  Maintainer: Zachary Vorhies
@@ -1,11 +1,12 @@
1
1
  fastled/__init__.py,sha256=NBk5Ef65nIe0F_rvBrSGeoyouFOKFeQXqHrTCJQheeI,7201
2
- fastled/__version__.py,sha256=hB1zQ1-Sl4c_Khm-2c5WAIFPSBC3V2WrR8ZKi34k3vM,373
2
+ fastled/__main__.py,sha256=OcKv2ER1_iQAsZzLIUb3C8hRC9L2clNOhCrjpshrlf4,336
3
+ fastled/__version__.py,sha256=9FmVYi6n9qXRl6U6l1Xr9-rsxJ3ncEYDzHGxGM-sA_E,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=ATK0GCem9iJXC7zPkFofaR4Df6yWsgAcqf_clwpSZe0,19700
9
+ fastled/client_server.py,sha256=2H3HBstR0kSKfLrz0LFbBIHy2WYBKc5VzhPxavhdS6o,20393
9
10
  fastled/compile_server.py,sha256=yQtwLOSKINO1CKD0NWxf-7YQKSatf9sF9RuqaWGOkCs,3038
10
11
  fastled/compile_server_impl.py,sha256=9vTGaDQ0W_g9Xsfy0gC3nJEc2g_pnXcF4VO2U3GLOVg,11982
11
12
  fastled/docker_manager.py,sha256=rkq39ZKrU6NHIyDa3mzs0Unb6o9oMeAwxhqiuHJU_RY,40291
@@ -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=ef6RwF3xOCbxX568FmRlhS0lMimd1eHVDB1iOpBZsx4,11639
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.36.dist-info/licenses/LICENSE,sha256=b6pOoifSXiUaz_lDS84vWlG3fr4yUKwB8fzkrH9R8bQ,1064
40
- fastled-1.3.36.dist-info/METADATA,sha256=VHWBI1poAVpyHB2paf-eZXSjl0JpKFTK2vP0P1QBeMc,30847
41
- fastled-1.3.36.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
42
- fastled-1.3.36.dist-info/entry_points.txt,sha256=RCwmzCSOS4-C2i9EziANq7Z2Zb4KFnEMR1FQC0bBwAw,101
43
- fastled-1.3.36.dist-info/top_level.txt,sha256=Bbv5kpJpZhWNCvDF4K0VcvtBSDMa8B7PTOrZa9CezHY,8
44
- fastled-1.3.36.dist-info/RECORD,,
40
+ fastled-1.3.38.dist-info/licenses/LICENSE,sha256=b6pOoifSXiUaz_lDS84vWlG3fr4yUKwB8fzkrH9R8bQ,1064
41
+ fastled-1.3.38.dist-info/METADATA,sha256=j0Pj8VUdX6Tvsf6r5lbEfFF9dLO0FCJLHcm3Rw7feuo,30847
42
+ fastled-1.3.38.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
43
+ fastled-1.3.38.dist-info/entry_points.txt,sha256=RCwmzCSOS4-C2i9EziANq7Z2Zb4KFnEMR1FQC0bBwAw,101
44
+ fastled-1.3.38.dist-info/top_level.txt,sha256=Bbv5kpJpZhWNCvDF4K0VcvtBSDMa8B7PTOrZa9CezHY,8
45
+ fastled-1.3.38.dist-info/RECORD,,