fastled 1.1.17__py2.py3-none-any.whl → 1.1.19__py2.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
@@ -1,3 +1,3 @@
1
1
  """FastLED Wasm Compiler package."""
2
2
 
3
- __version__ = "1.1.17"
3
+ __version__ = "1.1.19"
fastled/app.py CHANGED
@@ -20,7 +20,11 @@ from fastled.docker_manager import DockerManager
20
20
  from fastled.filewatcher import FileWatcherProcess
21
21
  from fastled.keyboard import SpaceBarWatcher
22
22
  from fastled.open_browser import open_browser_thread
23
- from fastled.sketch import looks_like_fastled_repo, looks_like_sketch_directory
23
+ from fastled.sketch import (
24
+ find_sketch_directories,
25
+ looks_like_fastled_repo,
26
+ looks_like_sketch_directory,
27
+ )
24
28
  from fastled.web_compile import (
25
29
  SERVER_PORT,
26
30
  ConnectionResult,
@@ -82,28 +86,6 @@ def parse_args() -> argparse.Namespace:
82
86
  action="store_true",
83
87
  help="Enable profiling for web compilation",
84
88
  )
85
- build_mode = parser.add_mutually_exclusive_group()
86
- build_mode.add_argument("--debug", action="store_true", help="Build in debug mode")
87
- build_mode.add_argument(
88
- "--quick",
89
- action="store_true",
90
- default=True,
91
- help="Build in quick mode (default)",
92
- )
93
- build_mode.add_argument(
94
- "--release", action="store_true", help="Build in release mode"
95
- )
96
- build_mode.add_argument(
97
- "--localhost",
98
- "--local",
99
- action="store_true",
100
- help="Use localhost for web compilation from an instance of fastled --server, creating it if necessary",
101
- )
102
- build_mode.add_argument(
103
- "--server",
104
- action="store_true",
105
- help="Run the server in the current directory, volume mapping fastled if we are in the repo",
106
- )
107
89
  parser.add_argument(
108
90
  "--force-compile",
109
91
  action="store_true",
@@ -119,6 +101,30 @@ def parse_args() -> argparse.Namespace:
119
101
  action="store_true",
120
102
  help="Update the wasm compiler (if necessary) before running",
121
103
  )
104
+ parser.add_argument(
105
+ "--localhost",
106
+ "--local",
107
+ "-l",
108
+ action="store_true",
109
+ help="Use localhost for web compilation from an instance of fastled --server, creating it if necessary",
110
+ )
111
+ parser.add_argument(
112
+ "--server",
113
+ "-s",
114
+ action="store_true",
115
+ help="Run the server in the current directory, volume mapping fastled if we are in the repo",
116
+ )
117
+ build_mode = parser.add_mutually_exclusive_group()
118
+ build_mode.add_argument("--debug", action="store_true", help="Build in debug mode")
119
+ build_mode.add_argument(
120
+ "--quick",
121
+ action="store_true",
122
+ default=True,
123
+ help="Build in quick mode (default)",
124
+ )
125
+ build_mode.add_argument(
126
+ "--release", action="store_true", help="Build in release mode"
127
+ )
122
128
 
123
129
  cwd_is_fastled = looks_like_fastled_repo(Path(os.getcwd()))
124
130
 
@@ -133,7 +139,7 @@ def parse_args() -> argparse.Namespace:
133
139
  if not cwd_is_fastled and not args.localhost and not args.web and not args.server:
134
140
  print(f"Using web compiler at {DEFAULT_URL}")
135
141
  args.web = DEFAULT_URL
136
- if cwd_is_fastled and not args.web:
142
+ if cwd_is_fastled and not args.web and not args.server:
137
143
  print("Forcing --local mode because we are in the FastLED repo")
138
144
  args.localhost = True
139
145
  if args.localhost:
@@ -147,10 +153,31 @@ def parse_args() -> argparse.Namespace:
147
153
  if looks_like_sketch_directory(maybe_sketch_dir):
148
154
  args.directory = str(maybe_sketch_dir)
149
155
  else:
150
- print(
151
- "\nYou either need to specify a sketch directory or run in --server mode."
152
- )
153
- sys.exit(1)
156
+ sketch_directories = find_sketch_directories(maybe_sketch_dir)
157
+ if len(sketch_directories) == 1:
158
+ print(f"\nUsing sketch directory: {sketch_directories[0]}")
159
+ args.directory = str(sketch_directories[0])
160
+ elif len(sketch_directories) > 1:
161
+ print("\nMultiple Directories found, choose one:")
162
+ for i, sketch_dir in enumerate(sketch_directories):
163
+ print(f" [{i+1}]: {sketch_dir}")
164
+ which = input("\nPlease specify a sketch directory: ")
165
+ try:
166
+ index = int(which) - 1
167
+ args.directory = str(sketch_directories[index])
168
+ except (ValueError, IndexError):
169
+ print("Invalid selection.")
170
+ sys.exit(1)
171
+ else:
172
+ print(
173
+ "\nYou either need to specify a sketch directory or run in --server mode."
174
+ )
175
+ sys.exit(1)
176
+ elif args.directory is not None and os.path.isfile(args.directory):
177
+ dir_path = Path(args.directory).parent
178
+ if looks_like_sketch_directory(dir_path):
179
+ print(f"Using sketch directory: {dir_path}")
180
+ args.directory = str(dir_path)
154
181
 
155
182
  return args
156
183
 
fastled/docker_manager.py CHANGED
@@ -176,6 +176,8 @@ class DockerManager:
176
176
  If upgrade is True, will pull the latest version even if image exists locally.
177
177
  """
178
178
  print(f"Validating image {image_name}:{tag}...")
179
+ remote_image_hash_from_local_image: str | None = None
180
+ remote_image_hash: str | None = None
179
181
 
180
182
  with get_lock(f"{image_name}-{tag}"):
181
183
  try:
@@ -187,7 +189,7 @@ class DockerManager:
187
189
  f"{image_name}:{tag}"
188
190
  )
189
191
  remote_image_hash = remote_image.id
190
- remote_image_hash_from_local_image: str | None = None
192
+
191
193
  try:
192
194
  remote_image_hash_from_local_image = DISK_CACHE.get(
193
195
  local_image.id
@@ -196,9 +198,6 @@ class DockerManager:
196
198
  raise
197
199
  except Exception:
198
200
  remote_image_hash_from_local_image = None
199
- import traceback
200
- import warnings
201
-
202
201
  stack = traceback.format_exc()
203
202
  warnings.warn(
204
203
  f"Error getting remote image hash from local image: {stack}"
@@ -213,7 +212,8 @@ class DockerManager:
213
212
  _ = self.client.images.pull(image_name, tag=tag)
214
213
  print(f"Updated to newer version of {image_name}:{tag}")
215
214
  local_image_hash = self.client.images.get(f"{image_name}:{tag}").id
216
- DISK_CACHE.put(local_image_hash, remote_image_hash)
215
+ if remote_image_hash is not None:
216
+ DISK_CACHE.put(local_image_hash, remote_image_hash)
217
217
 
218
218
  except docker.errors.ImageNotFound:
219
219
  print(f"Image {image_name}:{tag} not found. Downloading...")
@@ -221,11 +221,8 @@ class DockerManager:
221
221
  try:
222
222
  local_image = self.client.images.get(f"{image_name}:{tag}")
223
223
  local_image_hash = local_image.id
224
- DISK_CACHE.put(local_image_hash, remote_image_hash)
225
224
  print(f"Image {image_name}:{tag} downloaded successfully.")
226
225
  except docker.errors.ImageNotFound:
227
- import warnings
228
-
229
226
  warnings.warn(f"Image {image_name}:{tag} not found after download.")
230
227
 
231
228
  def tag_image(self, image_name: str, old_tag: str, new_tag: str) -> None:
fastled/filewatcher.py CHANGED
@@ -1,196 +1,202 @@
1
- """File system watcher implementation using watchdog
2
- """
3
-
4
- import hashlib
5
- import os
6
- import queue
7
- import threading
8
- import time
9
- from contextlib import redirect_stdout
10
- from multiprocessing import Process, Queue
11
- from pathlib import Path
12
- from queue import Empty
13
- from typing import Dict, Set
14
-
15
- from watchdog.events import FileSystemEvent, FileSystemEventHandler
16
- from watchdog.observers import Observer
17
- from watchdog.observers.api import BaseObserver
18
-
19
-
20
- class MyEventHandler(FileSystemEventHandler):
21
- def __init__(
22
- self,
23
- change_queue: queue.Queue,
24
- excluded_patterns: Set[str],
25
- file_hashes: Dict[str, str],
26
- ) -> None:
27
- super().__init__()
28
- self.change_queue = change_queue
29
- self.excluded_patterns = excluded_patterns
30
- self.file_hashes = file_hashes
31
-
32
- def _get_file_hash(self, filepath: str) -> str:
33
- try:
34
- with open(filepath, "rb") as f:
35
- return hashlib.md5(f.read()).hexdigest()
36
- except Exception: # pylint: disable=broad-except
37
- return ""
38
-
39
- def on_modified(self, event: FileSystemEvent) -> None:
40
- if not event.is_directory:
41
- path = Path(event.src_path)
42
- # Check if any part of the path matches excluded patterns
43
- if not any(part in self.excluded_patterns for part in path.parts):
44
- new_hash = self._get_file_hash(event.src_path)
45
- if new_hash and new_hash != self.file_hashes.get(event.src_path):
46
- self.file_hashes[event.src_path] = new_hash
47
- self.change_queue.put(event.src_path)
48
-
49
-
50
- class FileChangedNotifier(threading.Thread):
51
- """Watches a directory for file changes and queues notifications"""
52
-
53
- def __init__(
54
- self,
55
- path: str,
56
- debounce_seconds: float = 1.0,
57
- excluded_patterns: list[str] | None = None,
58
- ) -> None:
59
- """Initialize the notifier with a path to watch
60
-
61
- Args:
62
- path: Directory path to watch for changes
63
- debounce_seconds: Minimum time between notifications for the same file
64
- excluded_patterns: List of directory/file patterns to exclude from watching
65
- """
66
- super().__init__(daemon=True)
67
- self.path = path
68
- self.observer: BaseObserver | None = None
69
- self.event_handler: MyEventHandler | None = None
70
-
71
- # Combine default and user-provided patterns
72
- self.excluded_patterns = (
73
- set(excluded_patterns) if excluded_patterns is not None else set()
74
- )
75
- self.stopped = False
76
- self.change_queue: queue.Queue = queue.Queue()
77
- self.last_notification: Dict[str, float] = {}
78
- self.file_hashes: Dict[str, str] = {}
79
- self.debounce_seconds = debounce_seconds
80
-
81
- def stop(self) -> None:
82
- """Stop watching for changes"""
83
- print("watcher stop")
84
- self.stopped = True
85
- if self.observer:
86
- self.observer.stop()
87
- self.observer.join()
88
- self.observer = None
89
- self.event_handler = None
90
-
91
- def run(self) -> None:
92
- """Thread main loop - starts watching for changes"""
93
- self.event_handler = MyEventHandler(
94
- self.change_queue, self.excluded_patterns, self.file_hashes
95
- )
96
- self.observer = Observer()
97
- self.observer.schedule(self.event_handler, self.path, recursive=True)
98
- self.observer.start()
99
-
100
- try:
101
- while not self.stopped:
102
- time.sleep(0.1)
103
- except KeyboardInterrupt:
104
- print("File watcher stopped by user.")
105
- finally:
106
- self.stop()
107
-
108
- def get_next_change(self, timeout: float = 0.001) -> str | None:
109
- """Get the next file change event from the queue
110
-
111
- Args:
112
- timeout: How long to wait for next change in seconds
113
-
114
- Returns:
115
- Changed filepath or None if no change within timeout
116
- """
117
- try:
118
- filepath = self.change_queue.get(timeout=timeout)
119
- current_time = time.time()
120
-
121
- # Check if we've seen this file recently
122
- last_time = self.last_notification.get(filepath, 0)
123
- if current_time - last_time < self.debounce_seconds:
124
- return None
125
-
126
- self.last_notification[filepath] = current_time
127
- return filepath
128
- except KeyboardInterrupt:
129
- raise
130
- except queue.Empty:
131
- return None
132
-
133
- def get_all_changes(self, timeout: float = 0.001) -> list[str]:
134
- """Get all file change events from the queue
135
-
136
- Args:
137
- timeout: How long to wait for next change in seconds
138
-
139
- Returns:
140
- List of changed filepaths
141
- """
142
- changed_files = []
143
- while True:
144
- changed_file = self.get_next_change(timeout=timeout)
145
- if changed_file is None:
146
- break
147
- changed_files.append(changed_file)
148
- # clear all the changes from the queue
149
- self.change_queue.queue.clear()
150
- return changed_files
151
-
152
-
153
- def _process_wrapper(root: Path, excluded_patterns: list[str], queue: Queue):
154
- with open(os.devnull, "w") as fnull: # Redirect to /dev/null
155
- with redirect_stdout(fnull):
156
- watcher = FileChangedNotifier(
157
- str(root), excluded_patterns=excluded_patterns
158
- )
159
- watcher.start()
160
- while True:
161
- try:
162
- changed_files = watcher.get_all_changes()
163
- for file in changed_files:
164
- queue.put(file)
165
- except KeyboardInterrupt:
166
- break
167
- watcher.stop()
168
-
169
-
170
- class FileWatcherProcess:
171
- def __init__(self, root: Path, excluded_patterns: list[str]) -> None:
172
- self.queue: Queue = Queue()
173
- self.process = Process(
174
- target=_process_wrapper,
175
- args=(root, excluded_patterns, self.queue),
176
- daemon=True,
177
- )
178
- self.process.start()
179
-
180
- def stop(self):
181
- self.process.terminate()
182
- self.process.join()
183
- self.queue.close()
184
- self.queue.join_thread()
185
-
186
- def get_all_changes(self, timeout: float | None = None) -> list[str]:
187
- changed_files = []
188
- block = timeout is not None
189
-
190
- while True:
191
- try:
192
- changed_file = self.queue.get(block=block, timeout=timeout)
193
- changed_files.append(changed_file)
194
- except Empty:
195
- break
196
- return changed_files
1
+ """File system watcher implementation using watchdog
2
+ """
3
+
4
+ import hashlib
5
+ import os
6
+ import queue
7
+ import threading
8
+ import time
9
+ from contextlib import redirect_stdout
10
+ from multiprocessing import Process, Queue
11
+ from pathlib import Path
12
+ from queue import Empty
13
+ from typing import Dict, Set
14
+
15
+ from watchdog.events import FileSystemEvent, FileSystemEventHandler
16
+ from watchdog.observers import Observer
17
+ from watchdog.observers.api import BaseObserver
18
+
19
+
20
+ class MyEventHandler(FileSystemEventHandler):
21
+ def __init__(
22
+ self,
23
+ change_queue: queue.Queue,
24
+ excluded_patterns: Set[str],
25
+ file_hashes: Dict[str, str],
26
+ ) -> None:
27
+ super().__init__()
28
+ self.change_queue = change_queue
29
+ self.excluded_patterns = excluded_patterns
30
+ self.file_hashes = file_hashes
31
+
32
+ def _get_file_hash(self, filepath: str) -> str:
33
+ try:
34
+ with open(filepath, "rb") as f:
35
+ return hashlib.md5(f.read()).hexdigest()
36
+ except Exception: # pylint: disable=broad-except
37
+ return ""
38
+
39
+ def on_modified(self, event: FileSystemEvent) -> None:
40
+ if not event.is_directory:
41
+ # Convert src_path to str if it's bytes
42
+ src_path = (
43
+ event.src_path.decode()
44
+ if isinstance(event.src_path, bytes)
45
+ else event.src_path
46
+ )
47
+ path = Path(src_path)
48
+ # Check if any part of the path matches excluded patterns
49
+ if not any(part in self.excluded_patterns for part in path.parts):
50
+ new_hash = self._get_file_hash(src_path)
51
+ if new_hash and new_hash != self.file_hashes.get(src_path):
52
+ self.file_hashes[src_path] = new_hash
53
+ self.change_queue.put(src_path)
54
+
55
+
56
+ class FileChangedNotifier(threading.Thread):
57
+ """Watches a directory for file changes and queues notifications"""
58
+
59
+ def __init__(
60
+ self,
61
+ path: str,
62
+ debounce_seconds: float = 1.0,
63
+ excluded_patterns: list[str] | None = None,
64
+ ) -> None:
65
+ """Initialize the notifier with a path to watch
66
+
67
+ Args:
68
+ path: Directory path to watch for changes
69
+ debounce_seconds: Minimum time between notifications for the same file
70
+ excluded_patterns: List of directory/file patterns to exclude from watching
71
+ """
72
+ super().__init__(daemon=True)
73
+ self.path = path
74
+ self.observer: BaseObserver | None = None
75
+ self.event_handler: MyEventHandler | None = None
76
+
77
+ # Combine default and user-provided patterns
78
+ self.excluded_patterns = (
79
+ set(excluded_patterns) if excluded_patterns is not None else set()
80
+ )
81
+ self.stopped = False
82
+ self.change_queue: queue.Queue = queue.Queue()
83
+ self.last_notification: Dict[str, float] = {}
84
+ self.file_hashes: Dict[str, str] = {}
85
+ self.debounce_seconds = debounce_seconds
86
+
87
+ def stop(self) -> None:
88
+ """Stop watching for changes"""
89
+ print("watcher stop")
90
+ self.stopped = True
91
+ if self.observer:
92
+ self.observer.stop()
93
+ self.observer.join()
94
+ self.observer = None
95
+ self.event_handler = None
96
+
97
+ def run(self) -> None:
98
+ """Thread main loop - starts watching for changes"""
99
+ self.event_handler = MyEventHandler(
100
+ self.change_queue, self.excluded_patterns, self.file_hashes
101
+ )
102
+ self.observer = Observer()
103
+ self.observer.schedule(self.event_handler, self.path, recursive=True)
104
+ self.observer.start()
105
+
106
+ try:
107
+ while not self.stopped:
108
+ time.sleep(0.1)
109
+ except KeyboardInterrupt:
110
+ print("File watcher stopped by user.")
111
+ finally:
112
+ self.stop()
113
+
114
+ def get_next_change(self, timeout: float = 0.001) -> str | None:
115
+ """Get the next file change event from the queue
116
+
117
+ Args:
118
+ timeout: How long to wait for next change in seconds
119
+
120
+ Returns:
121
+ Changed filepath or None if no change within timeout
122
+ """
123
+ try:
124
+ filepath = self.change_queue.get(timeout=timeout)
125
+ current_time = time.time()
126
+
127
+ # Check if we've seen this file recently
128
+ last_time = self.last_notification.get(filepath, 0)
129
+ if current_time - last_time < self.debounce_seconds:
130
+ return None
131
+
132
+ self.last_notification[filepath] = current_time
133
+ return filepath
134
+ except KeyboardInterrupt:
135
+ raise
136
+ except queue.Empty:
137
+ return None
138
+
139
+ def get_all_changes(self, timeout: float = 0.001) -> list[str]:
140
+ """Get all file change events from the queue
141
+
142
+ Args:
143
+ timeout: How long to wait for next change in seconds
144
+
145
+ Returns:
146
+ List of changed filepaths
147
+ """
148
+ changed_files = []
149
+ while True:
150
+ changed_file = self.get_next_change(timeout=timeout)
151
+ if changed_file is None:
152
+ break
153
+ changed_files.append(changed_file)
154
+ # clear all the changes from the queue
155
+ self.change_queue.queue.clear()
156
+ return changed_files
157
+
158
+
159
+ def _process_wrapper(root: Path, excluded_patterns: list[str], queue: Queue):
160
+ with open(os.devnull, "w") as fnull: # Redirect to /dev/null
161
+ with redirect_stdout(fnull):
162
+ watcher = FileChangedNotifier(
163
+ str(root), excluded_patterns=excluded_patterns
164
+ )
165
+ watcher.start()
166
+ while True:
167
+ try:
168
+ changed_files = watcher.get_all_changes()
169
+ for file in changed_files:
170
+ queue.put(file)
171
+ except KeyboardInterrupt:
172
+ break
173
+ watcher.stop()
174
+
175
+
176
+ class FileWatcherProcess:
177
+ def __init__(self, root: Path, excluded_patterns: list[str]) -> None:
178
+ self.queue: Queue = Queue()
179
+ self.process = Process(
180
+ target=_process_wrapper,
181
+ args=(root, excluded_patterns, self.queue),
182
+ daemon=True,
183
+ )
184
+ self.process.start()
185
+
186
+ def stop(self):
187
+ self.process.terminate()
188
+ self.process.join()
189
+ self.queue.close()
190
+ self.queue.join_thread()
191
+
192
+ def get_all_changes(self, timeout: float | None = None) -> list[str]:
193
+ changed_files = []
194
+ block = timeout is not None
195
+
196
+ while True:
197
+ try:
198
+ changed_file = self.queue.get(block=block, timeout=timeout)
199
+ changed_files.append(changed_file)
200
+ except Empty:
201
+ break
202
+ return changed_files
fastled/sketch.py CHANGED
@@ -2,6 +2,27 @@ import os
2
2
  from pathlib import Path
3
3
 
4
4
 
5
+ def find_sketch_directories(directory: Path) -> list[Path]:
6
+ sketch_directories: list[Path] = []
7
+ # search all the paths one level deep
8
+ for path in directory.iterdir():
9
+ if path.is_dir():
10
+ dir_name = path.name
11
+ if str(dir_name).startswith("."):
12
+ continue
13
+
14
+ if looks_like_sketch_directory(path, quick=True):
15
+ sketch_directories.append(path)
16
+ if dir_name.lower() == "examples":
17
+ for example in path.iterdir():
18
+ if example.is_dir():
19
+ if looks_like_sketch_directory(example, quick=True):
20
+ sketch_directories.append(example)
21
+ # make relative to cwd
22
+ sketch_directories = [p.relative_to(directory) for p in sketch_directories]
23
+ return sketch_directories
24
+
25
+
5
26
  def get_sketch_files(directory: Path) -> list[Path]:
6
27
  files: list[Path] = []
7
28
  for root, dirs, filenames in os.walk(directory):
@@ -30,14 +51,14 @@ def _lots_and_lots_of_files(directory: Path) -> bool:
30
51
  return len(get_sketch_files(directory)) > 100
31
52
 
32
53
 
33
- def looks_like_sketch_directory(directory: Path) -> bool:
54
+ def looks_like_sketch_directory(directory: Path, quick=False) -> bool:
34
55
  if looks_like_fastled_repo(directory):
35
56
  print("Directory looks like the FastLED repo")
36
57
  return False
37
58
 
38
- if _lots_and_lots_of_files(directory):
39
- print("Too many files in the directory, bailing out")
40
- return False
59
+ if not quick:
60
+ if _lots_and_lots_of_files(directory):
61
+ return False
41
62
 
42
63
  # walk the path and if there are over 30 files, return False
43
64
  # at the root of the directory there should either be an ino file or a src directory
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: fastled
3
- Version: 1.1.17
3
+ Version: 1.1.19
4
4
  Summary: FastLED Wasm Compiler
5
5
  Home-page: https://github.com/zackees/fastled-wasm
6
6
  Maintainer: Zachary Vorhies
@@ -161,6 +161,8 @@ A: A big chunk of space is being used by unnecessary javascript `emscripten` is
161
161
 
162
162
  # Revisions
163
163
 
164
+ * 1.1.19 - Automatically does a limit searches for sketch directories if you leave it blank.
165
+ * 1.1.18 - Fixes for when the image has never been downloaded.
164
166
  * 1.1.17 - Added `--update` and `--no-auto-update` to control whether the compiler in docker mode will try to update.
165
167
  * 1.1.16 - Rewrote docker logic to use container suspension and resumption. Much much faster.
166
168
  * 1.1.15 - Fixed logic for considering ipv6 addresses. Auto selection of ipv6 is now restored.
@@ -1,20 +1,20 @@
1
- fastled/__init__.py,sha256=eYxLUpPhHXARLnRFwdJgoCDIx4kVkzNiZ_--PzqMApE,64
2
- fastled/app.py,sha256=xgMl-9s3dy2TurnSusVdIAr3ZbSi5oyEAofHsa7hZho,15695
1
+ fastled/__init__.py,sha256=S0nyYWk7HxAJsrOn1JMsxyV2GhDT9lICQ3IDATqujh8,64
2
+ fastled/app.py,sha256=GuYL67fzR7iifJ6zwd023KeXRHwOSv8Uliz9ZNmFy9A,16903
3
3
  fastled/build_mode.py,sha256=joMwsV4K1y_LijT4gEAcjx69RZBoe_KmFmHZdPYbL_4,631
4
4
  fastled/cli.py,sha256=CNR_pQR0sNVPNuv8e_nmm-0PI8sU-eUBUgnWgWkzW9c,237
5
5
  fastled/compile_server.py,sha256=aBdpILSRrDsCJ5e9g5uwIqt9bcqE_8FrSddCV2ygtrI,5401
6
- fastled/docker_manager.py,sha256=dj6s1mT-ecURqYJH-JpZZWuFHr-dGkQIOuFm845Nz40,20042
7
- fastled/filewatcher.py,sha256=fJNMQRDCpihSL4nQeYPqbD4m1Jzjcz_-YRAo-wlPW6k,6518
6
+ fastled/docker_manager.py,sha256=AzQBXqWB1Uq_Qb1mp1NS4hIbkC8aYp-pzpYhFRpI5ww,19940
7
+ fastled/filewatcher.py,sha256=5dVmjEG23kMeJa29tRVm5XKSr9sTD4ME2boo-CFDuUM,6910
8
8
  fastled/keyboard.py,sha256=rqndglWYzRy6oiqHgsmx1peLd0Yrpci01zGENlCzh_s,2576
9
9
  fastled/open_browser.py,sha256=RRHcsZ5Vzsw1AuZUEYuSfjKmf_9j3NGMDUR-FndHmqs,1483
10
10
  fastled/paths.py,sha256=VsPmgu0lNSCFOoEC0BsTYzDygXqy15AHUfN-tTuzDZA,99
11
- fastled/sketch.py,sha256=KhhPFqlFVlBk8YrzFy7-ioe7zEzecgrVLhyFbLpBp7k,1845
11
+ fastled/sketch.py,sha256=5nRjg281lMH8Bo9wKjbcpTQCfEP574ZCG-lukvFmyQ8,2656
12
12
  fastled/util.py,sha256=t4M3NFMhnCzfYbLvIyJi0RdFssZqbTN_vVIaej1WV-U,265
13
13
  fastled/web_compile.py,sha256=KuvKGdX6SSUUqC7YgX4T9SMSP5wdcPUhpg9-K9zPoTI,10378
14
14
  fastled/assets/example.txt,sha256=lTBovRjiz0_TgtAtbA1C5hNi2ffbqnNPqkKg6UiKCT8,54
15
- fastled-1.1.17.dist-info/LICENSE,sha256=b6pOoifSXiUaz_lDS84vWlG3fr4yUKwB8fzkrH9R8bQ,1064
16
- fastled-1.1.17.dist-info/METADATA,sha256=IX_gRsLWHvl9Fk7sbMWTmVoLqRGuDcAW_88tbfLAKuA,13496
17
- fastled-1.1.17.dist-info/WHEEL,sha256=0VNUDWQJzfRahYI3neAhz2UVbRCtztpN5dPHAGvmGXc,109
18
- fastled-1.1.17.dist-info/entry_points.txt,sha256=RCwmzCSOS4-C2i9EziANq7Z2Zb4KFnEMR1FQC0bBwAw,101
19
- fastled-1.1.17.dist-info/top_level.txt,sha256=xfG6Z_ol9V5YmBROkZq2QTRwjbS2ouCUxaTJsOwfkOo,14
20
- fastled-1.1.17.dist-info/RECORD,,
15
+ fastled-1.1.19.dist-info/LICENSE,sha256=b6pOoifSXiUaz_lDS84vWlG3fr4yUKwB8fzkrH9R8bQ,1064
16
+ fastled-1.1.19.dist-info/METADATA,sha256=zW3vY83mwHyd8N76_rzBcu1YwEU-HEgdYBRoliVonoY,13658
17
+ fastled-1.1.19.dist-info/WHEEL,sha256=0VNUDWQJzfRahYI3neAhz2UVbRCtztpN5dPHAGvmGXc,109
18
+ fastled-1.1.19.dist-info/entry_points.txt,sha256=RCwmzCSOS4-C2i9EziANq7Z2Zb4KFnEMR1FQC0bBwAw,101
19
+ fastled-1.1.19.dist-info/top_level.txt,sha256=xfG6Z_ol9V5YmBROkZq2QTRwjbS2ouCUxaTJsOwfkOo,14
20
+ fastled-1.1.19.dist-info/RECORD,,