fastled 1.1.17__py2.py3-none-any.whl → 1.1.18__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 +1 -1
- fastled/app.py +24 -22
- fastled/docker_manager.py +5 -8
- fastled/filewatcher.py +202 -196
- {fastled-1.1.17.dist-info → fastled-1.1.18.dist-info}/METADATA +2 -1
- {fastled-1.1.17.dist-info → fastled-1.1.18.dist-info}/RECORD +10 -10
- {fastled-1.1.17.dist-info → fastled-1.1.18.dist-info}/LICENSE +0 -0
- {fastled-1.1.17.dist-info → fastled-1.1.18.dist-info}/WHEEL +0 -0
- {fastled-1.1.17.dist-info → fastled-1.1.18.dist-info}/entry_points.txt +0 -0
- {fastled-1.1.17.dist-info → fastled-1.1.18.dist-info}/top_level.txt +0 -0
fastled/__init__.py
CHANGED
fastled/app.py
CHANGED
@@ -82,28 +82,6 @@ def parse_args() -> argparse.Namespace:
|
|
82
82
|
action="store_true",
|
83
83
|
help="Enable profiling for web compilation",
|
84
84
|
)
|
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
85
|
parser.add_argument(
|
108
86
|
"--force-compile",
|
109
87
|
action="store_true",
|
@@ -119,6 +97,30 @@ def parse_args() -> argparse.Namespace:
|
|
119
97
|
action="store_true",
|
120
98
|
help="Update the wasm compiler (if necessary) before running",
|
121
99
|
)
|
100
|
+
parser.add_argument(
|
101
|
+
"--localhost",
|
102
|
+
"--local",
|
103
|
+
"-l",
|
104
|
+
action="store_true",
|
105
|
+
help="Use localhost for web compilation from an instance of fastled --server, creating it if necessary",
|
106
|
+
)
|
107
|
+
parser.add_argument(
|
108
|
+
"--server",
|
109
|
+
"-s",
|
110
|
+
action="store_true",
|
111
|
+
help="Run the server in the current directory, volume mapping fastled if we are in the repo",
|
112
|
+
)
|
113
|
+
build_mode = parser.add_mutually_exclusive_group()
|
114
|
+
build_mode.add_argument("--debug", action="store_true", help="Build in debug mode")
|
115
|
+
build_mode.add_argument(
|
116
|
+
"--quick",
|
117
|
+
action="store_true",
|
118
|
+
default=True,
|
119
|
+
help="Build in quick mode (default)",
|
120
|
+
)
|
121
|
+
build_mode.add_argument(
|
122
|
+
"--release", action="store_true", help="Build in release mode"
|
123
|
+
)
|
122
124
|
|
123
125
|
cwd_is_fastled = looks_like_fastled_repo(Path(os.getcwd()))
|
124
126
|
|
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
|
-
|
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
|
-
|
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
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
"""
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
self.
|
76
|
-
|
77
|
-
|
78
|
-
self.
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
self.
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
self.
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
|
150
|
-
|
151
|
-
|
152
|
-
|
153
|
-
|
154
|
-
|
155
|
-
|
156
|
-
|
157
|
-
|
158
|
-
|
159
|
-
|
160
|
-
|
161
|
-
|
162
|
-
|
163
|
-
|
164
|
-
|
165
|
-
|
166
|
-
|
167
|
-
|
168
|
-
|
169
|
-
|
170
|
-
|
171
|
-
|
172
|
-
|
173
|
-
|
174
|
-
|
175
|
-
|
176
|
-
|
177
|
-
|
178
|
-
self.
|
179
|
-
|
180
|
-
|
181
|
-
|
182
|
-
|
183
|
-
|
184
|
-
self.
|
185
|
-
|
186
|
-
def
|
187
|
-
|
188
|
-
|
189
|
-
|
190
|
-
|
191
|
-
|
192
|
-
|
193
|
-
|
194
|
-
|
195
|
-
|
196
|
-
|
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
|
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.1
|
2
2
|
Name: fastled
|
3
|
-
Version: 1.1.
|
3
|
+
Version: 1.1.18
|
4
4
|
Summary: FastLED Wasm Compiler
|
5
5
|
Home-page: https://github.com/zackees/fastled-wasm
|
6
6
|
Maintainer: Zachary Vorhies
|
@@ -161,6 +161,7 @@ A: A big chunk of space is being used by unnecessary javascript `emscripten` is
|
|
161
161
|
|
162
162
|
# Revisions
|
163
163
|
|
164
|
+
* 1.1.18 - Fixes for when the image has never been downloaded.
|
164
165
|
* 1.1.17 - Added `--update` and `--no-auto-update` to control whether the compiler in docker mode will try to update.
|
165
166
|
* 1.1.16 - Rewrote docker logic to use container suspension and resumption. Much much faster.
|
166
167
|
* 1.1.15 - Fixed logic for considering ipv6 addresses. Auto selection of ipv6 is now restored.
|
@@ -1,10 +1,10 @@
|
|
1
|
-
fastled/__init__.py,sha256=
|
2
|
-
fastled/app.py,sha256=
|
1
|
+
fastled/__init__.py,sha256=IHbpe-aq0aVLbSOXEoXCoEu9sNWQTsV5OEghbd4DLsE,64
|
2
|
+
fastled/app.py,sha256=dUCHM-1yQGrpTtfUCn1NYlG7hIJm_Tg445zhyxsMBhY,15715
|
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=
|
7
|
-
fastled/filewatcher.py,sha256=
|
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
|
@@ -12,9 +12,9 @@ fastled/sketch.py,sha256=KhhPFqlFVlBk8YrzFy7-ioe7zEzecgrVLhyFbLpBp7k,1845
|
|
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.
|
16
|
-
fastled-1.1.
|
17
|
-
fastled-1.1.
|
18
|
-
fastled-1.1.
|
19
|
-
fastled-1.1.
|
20
|
-
fastled-1.1.
|
15
|
+
fastled-1.1.18.dist-info/LICENSE,sha256=b6pOoifSXiUaz_lDS84vWlG3fr4yUKwB8fzkrH9R8bQ,1064
|
16
|
+
fastled-1.1.18.dist-info/METADATA,sha256=5crAxI6_10i2pfPFIX8KxFCmX_3yyvGWZKjBR6JIRMU,13562
|
17
|
+
fastled-1.1.18.dist-info/WHEEL,sha256=0VNUDWQJzfRahYI3neAhz2UVbRCtztpN5dPHAGvmGXc,109
|
18
|
+
fastled-1.1.18.dist-info/entry_points.txt,sha256=RCwmzCSOS4-C2i9EziANq7Z2Zb4KFnEMR1FQC0bBwAw,101
|
19
|
+
fastled-1.1.18.dist-info/top_level.txt,sha256=xfG6Z_ol9V5YmBROkZq2QTRwjbS2ouCUxaTJsOwfkOo,14
|
20
|
+
fastled-1.1.18.dist-info/RECORD,,
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|