fastled 1.4.47__py3-none-any.whl → 1.4.49__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.

Potentially problematic release.


This version of fastled might be problematic. Click here for more details.

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.4.47"
4
+ __version__ = "1.4.49"
5
5
 
6
6
  __version_url_latest__ = "https://raw.githubusercontent.com/zackees/fastled-wasm/refs/heads/main/src/fastled/__version__.py"
fastled/print_filter.py CHANGED
@@ -1,52 +1,52 @@
1
- import re
2
- from abc import ABC, abstractmethod
3
- from enum import Enum
4
-
5
-
6
- class PrintFilter(ABC):
7
- """Abstract base class for filtering text output."""
8
-
9
- def __init__(self, echo: bool = True) -> None:
10
- self.echo = echo
11
-
12
- @abstractmethod
13
- def filter(self, text: str) -> str:
14
- """Filter the text according to implementation-specific rules."""
15
- pass
16
-
17
- def print(self, text: str | bytes) -> str:
18
- """Prints the text to the console after filtering."""
19
- if isinstance(text, bytes):
20
- text = text.decode("utf-8")
21
- text = self.filter(text)
22
- if self.echo:
23
- print(text, end="")
24
- return text
25
-
26
-
27
- def _handle_ino_cpp(line: str) -> str:
28
- if ".ino.cpp" in line[0:30]:
29
- # Extract the filename without path and extension
30
- match = re.search(r"src/([^/]+)\.ino\.cpp", line)
31
- if match:
32
- filename = match.group(1)
33
- # Replace with examples/Filename/Filename.ino format
34
- line = line.replace(
35
- f"src/{filename}.ino.cpp", f"examples/{filename}/{filename}.ino"
36
- )
37
- else:
38
- # Fall back to simple extension replacement if regex doesn't match
39
- line = line.replace(".ino.cpp", ".ino")
40
- return line
41
-
42
-
43
- class PrintFilterDefault(PrintFilter):
44
- """Provides default filtering for FastLED output."""
45
-
46
- def filter(self, text: str) -> str:
47
- return text
48
-
49
-
50
- class CompileOrLink(Enum):
51
- COMPILE = "compile"
52
- LINK = "link"
1
+ import re
2
+ from abc import ABC, abstractmethod
3
+ from enum import Enum
4
+
5
+
6
+ class PrintFilter(ABC):
7
+ """Abstract base class for filtering text output."""
8
+
9
+ def __init__(self, echo: bool = True) -> None:
10
+ self.echo = echo
11
+
12
+ @abstractmethod
13
+ def filter(self, text: str) -> str:
14
+ """Filter the text according to implementation-specific rules."""
15
+ pass
16
+
17
+ def print(self, text: str | bytes) -> str:
18
+ """Prints the text to the console after filtering."""
19
+ if isinstance(text, bytes):
20
+ text = text.decode("utf-8")
21
+ text = self.filter(text)
22
+ if self.echo:
23
+ print(text, end="")
24
+ return text
25
+
26
+
27
+ def _handle_ino_cpp(line: str) -> str:
28
+ if ".ino.cpp" in line[0:30]:
29
+ # Extract the filename without path and extension
30
+ match = re.search(r"src/([^/]+)\.ino\.cpp", line)
31
+ if match:
32
+ filename = match.group(1)
33
+ # Replace with examples/Filename/Filename.ino format
34
+ line = line.replace(
35
+ f"src/{filename}.ino.cpp", f"examples/{filename}/{filename}.ino"
36
+ )
37
+ else:
38
+ # Fall back to simple extension replacement if regex doesn't match
39
+ line = line.replace(".ino.cpp", ".ino")
40
+ return line
41
+
42
+
43
+ class PrintFilterDefault(PrintFilter):
44
+ """Provides default filtering for FastLED output."""
45
+
46
+ def filter(self, text: str) -> str:
47
+ return text
48
+
49
+
50
+ class CompileOrLink(Enum):
51
+ COMPILE = "compile"
52
+ LINK = "link"
@@ -1,6 +1,8 @@
1
1
  from pathlib import Path
2
2
  from typing import Callable, TypeVar, Union
3
3
 
4
+ from fastled.string_diff import string_diff
5
+
4
6
  T = TypeVar("T")
5
7
 
6
8
 
@@ -82,6 +84,44 @@ def _disambiguate_user_choice(
82
84
  0, # Reset default to first match
83
85
  )
84
86
 
87
+ # Try fuzzy matching as fallback
88
+ # For better fuzzy matching on paths, extract just the last component (basename)
89
+ # to avoid the "examples/" prefix interfering with matching
90
+ from pathlib import Path as PathLib
91
+
92
+ option_basenames = []
93
+ for option in options:
94
+ option_str = option_to_str(option)
95
+ # Extract basename for fuzzy matching
96
+ basename = (
97
+ PathLib(option_str).name
98
+ if "/" in option_str or "\\" in option_str
99
+ else option_str
100
+ )
101
+ option_basenames.append(basename)
102
+
103
+ fuzzy_results = string_diff(user_input, option_basenames)
104
+
105
+ if fuzzy_results:
106
+ # Map fuzzy results back to original options
107
+ fuzzy_matches = []
108
+ for _, matched_basename in fuzzy_results:
109
+ for i, basename in enumerate(option_basenames):
110
+ if basename == matched_basename:
111
+ fuzzy_matches.append(options[i])
112
+ break
113
+
114
+ if len(fuzzy_matches) == 1:
115
+ return fuzzy_matches[0]
116
+ elif len(fuzzy_matches) > 1:
117
+ # Recursive disambiguation with fuzzy matches
118
+ return _disambiguate_user_choice(
119
+ fuzzy_matches,
120
+ option_to_str,
121
+ f"Multiple fuzzy matches for '{user_input}':",
122
+ 0,
123
+ )
124
+
85
125
  # No match found
86
126
  print(f"No match found for '{user_input}'. Please try again.")
87
127
  return _disambiguate_user_choice(options, option_to_str, prompt, default_index)
fastled/sketch.py CHANGED
@@ -25,10 +25,27 @@ def find_sketch_directories(directory: Path | None = None) -> list[Path]:
25
25
  if looks_like_sketch_directory(path, quick=True):
26
26
  sketch_directories.append(path)
27
27
  if dir_name.lower() == "examples":
28
- for example in path.iterdir():
29
- if example.is_dir():
30
- if looks_like_sketch_directory(example, quick=True):
31
- sketch_directories.append(example)
28
+ # Recursively search examples directory for sketch directories
29
+ def search_examples_recursive(
30
+ examples_path: Path, depth: int = 0, max_depth: int = 3
31
+ ):
32
+ nonlocal file_count
33
+ if depth >= max_depth:
34
+ return
35
+ for example in examples_path.iterdir():
36
+ if example.is_dir():
37
+ if str(example.name).startswith("."):
38
+ continue
39
+ file_count += 1
40
+ if file_count > _MAX_FILES_SEARCH_LIMIT:
41
+ return
42
+ if looks_like_sketch_directory(example, quick=True):
43
+ sketch_directories.append(example)
44
+ else:
45
+ # Keep searching deeper if this isn't a sketch directory
46
+ search_examples_recursive(example, depth + 1, max_depth)
47
+
48
+ search_examples_recursive(path)
32
49
  # make relative to cwd
33
50
  sketch_directories = [p.relative_to(directory) for p in sketch_directories]
34
51
  return sketch_directories
fastled/version.py CHANGED
@@ -1,41 +1,41 @@
1
- from concurrent.futures import Future, ThreadPoolExecutor
2
-
3
- import httpx
4
-
5
- from fastled.__version__ import __version_url_latest__
6
-
7
-
8
- def _fetch_version() -> str | Exception:
9
- """
10
- Helper function to fetch the latest version from the GitHub repository.
11
- """
12
- try:
13
- response = httpx.get(__version_url_latest__)
14
- response.raise_for_status()
15
- # Extract the version string from the response text
16
- version_line = response.text.split("__version__ = ")[1].split('"')[1]
17
- return version_line
18
- except Exception as e:
19
- return e
20
-
21
-
22
- def get_latest_version() -> Future[str | Exception]:
23
- """
24
- Fetch the latest version from the GitHub repository.
25
- Returns a future that will resolve with the version string or an exception.
26
- """
27
- executor = ThreadPoolExecutor()
28
- return executor.submit(_fetch_version)
29
-
30
-
31
- def unit_test() -> None:
32
- future = get_latest_version()
33
- latest_version = future.result() # Wait for the future to complete
34
- if isinstance(latest_version, Exception):
35
- print(f"Error fetching latest version: {latest_version}")
36
- else:
37
- print(f"Latest version: {latest_version}")
38
-
39
-
40
- if __name__ == "__main__":
41
- unit_test()
1
+ from concurrent.futures import Future, ThreadPoolExecutor
2
+
3
+ import httpx
4
+
5
+ from fastled.__version__ import __version_url_latest__
6
+
7
+
8
+ def _fetch_version() -> str | Exception:
9
+ """
10
+ Helper function to fetch the latest version from the GitHub repository.
11
+ """
12
+ try:
13
+ response = httpx.get(__version_url_latest__)
14
+ response.raise_for_status()
15
+ # Extract the version string from the response text
16
+ version_line = response.text.split("__version__ = ")[1].split('"')[1]
17
+ return version_line
18
+ except Exception as e:
19
+ return e
20
+
21
+
22
+ def get_latest_version() -> Future[str | Exception]:
23
+ """
24
+ Fetch the latest version from the GitHub repository.
25
+ Returns a future that will resolve with the version string or an exception.
26
+ """
27
+ executor = ThreadPoolExecutor()
28
+ return executor.submit(_fetch_version)
29
+
30
+
31
+ def unit_test() -> None:
32
+ future = get_latest_version()
33
+ latest_version = future.result() # Wait for the future to complete
34
+ if isinstance(latest_version, Exception):
35
+ print(f"Error fetching latest version: {latest_version}")
36
+ else:
37
+ print(f"Latest version: {latest_version}")
38
+
39
+
40
+ if __name__ == "__main__":
41
+ unit_test()