fastled 1.4.44__py3-none-any.whl → 1.4.46__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/__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.44"
4
+ __version__ = "1.4.46"
5
5
 
6
6
  __version_url_latest__ = "https://raw.githubusercontent.com/zackees/fastled-wasm/refs/heads/main/src/fastled/__version__.py"
fastled/docker_manager.py CHANGED
@@ -251,7 +251,34 @@ class DockerManager:
251
251
  @property
252
252
  def client(self) -> DockerClient:
253
253
  if self._client is None:
254
- self._client = docker.from_env()
254
+ # Retry logic for WSL startup on Windows
255
+ max_retries = 10
256
+ retry_delay = 2 # seconds
257
+ last_error = None
258
+
259
+ for attempt in range(max_retries):
260
+ try:
261
+ self._client = docker.from_env()
262
+ if attempt > 0:
263
+ print(
264
+ f"Successfully connected to Docker after {attempt + 1} attempts"
265
+ )
266
+ return self._client
267
+ except DockerException as e:
268
+ last_error = e
269
+ if attempt < max_retries - 1:
270
+ if attempt == 0:
271
+ print("Waiting for Docker/WSL to be ready...")
272
+ print(
273
+ f"Attempt {attempt + 1}/{max_retries} failed, retrying in {retry_delay}s..."
274
+ )
275
+ time.sleep(retry_delay)
276
+ else:
277
+ print(
278
+ f"Failed to connect to Docker after {max_retries} attempts"
279
+ )
280
+ raise last_error
281
+ assert self._client is not None
255
282
  return self._client
256
283
 
257
284
  @staticmethod
fastled/parse_args.py CHANGED
@@ -368,7 +368,7 @@ def parse_args() -> Args:
368
368
  print("Searching for sketch directories...")
369
369
  sketch_directories = find_sketch_directories(maybe_sketch_dir)
370
370
  selected_dir = select_sketch_directory(
371
- sketch_directories, cwd_is_fastled
371
+ sketch_directories, cwd_is_fastled, is_followup=True
372
372
  )
373
373
  if selected_dir:
374
374
  print(f"Using sketch directory: {selected_dir}")
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"
@@ -101,21 +101,20 @@ def select_sketch_directory(
101
101
  print(f"\nUsing sketch directory: {sketch_directories[0]}")
102
102
  return str(sketch_directories[0])
103
103
  elif len(sketch_directories) > 1:
104
- if is_followup:
105
- # Only disambiguate on follow-up calls
106
- result = _disambiguate_user_choice(
107
- sketch_directories,
108
- option_to_str=lambda x: str(x),
109
- prompt="Multiple Directories found, choose one:",
110
- default_index=0,
111
- )
112
-
113
- if result is None:
114
- return None
115
-
116
- return str(result)
117
- else:
118
- # On first call, use the first directory automatically
119
- print(f"\nUsing sketch directory: {sketch_directories[0]}")
120
- return str(sketch_directories[0])
104
+ # First scan with >4 directories: return None (too many to auto-select)
105
+ if not is_followup and len(sketch_directories) > 4:
106
+ return None
107
+
108
+ # Prompt user to disambiguate
109
+ result = _disambiguate_user_choice(
110
+ sketch_directories,
111
+ option_to_str=lambda x: str(x),
112
+ prompt="Multiple Directories found, choose one:",
113
+ default_index=0,
114
+ )
115
+
116
+ if result is None:
117
+ return None
118
+
119
+ return str(result)
121
120
  return None
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()