atomicshop 2.5.16__py3-none-any.whl → 2.6.0__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 atomicshop might be problematic. Click here for more details.
- atomicshop/__init__.py +1 -1
- atomicshop/basics/multiprocesses.py +312 -0
- atomicshop/basics/numbers.py +13 -0
- atomicshop/system_resources.py +26 -0
- atomicshop/wrappers/loggingw/loggingw.py +18 -0
- {atomicshop-2.5.16.dist-info → atomicshop-2.6.0.dist-info}/METADATA +1 -1
- {atomicshop-2.5.16.dist-info → atomicshop-2.6.0.dist-info}/RECORD +10 -9
- {atomicshop-2.5.16.dist-info → atomicshop-2.6.0.dist-info}/WHEEL +1 -1
- {atomicshop-2.5.16.dist-info → atomicshop-2.6.0.dist-info}/LICENSE.txt +0 -0
- {atomicshop-2.5.16.dist-info → atomicshop-2.6.0.dist-info}/top_level.txt +0 -0
atomicshop/__init__.py
CHANGED
|
@@ -1,5 +1,8 @@
|
|
|
1
1
|
import multiprocessing
|
|
2
2
|
import queue
|
|
3
|
+
from concurrent.futures import ProcessPoolExecutor, as_completed
|
|
4
|
+
|
|
5
|
+
from ..import system_resources
|
|
3
6
|
|
|
4
7
|
|
|
5
8
|
def process_wrap_queue(function_reference, *args, **kwargs):
|
|
@@ -28,3 +31,312 @@ def process_wrap_queue(function_reference, *args, **kwargs):
|
|
|
28
31
|
process_object.join()
|
|
29
32
|
|
|
30
33
|
return queue_object.get()
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
class MultiProcessorRecursive:
|
|
37
|
+
def __init__(
|
|
38
|
+
self,
|
|
39
|
+
process_function,
|
|
40
|
+
input_list: list,
|
|
41
|
+
max_workers: int = None,
|
|
42
|
+
cpu_percent_max: int = 80,
|
|
43
|
+
memory_percent_max: int = 80,
|
|
44
|
+
wait_time: float = 5
|
|
45
|
+
):
|
|
46
|
+
"""
|
|
47
|
+
MultiProcessor class. Used to execute functions in parallel. The result of each execution is feeded back
|
|
48
|
+
to the provided function. Making it sort of recursive execution.
|
|
49
|
+
:param process_function: function, function to execute on the input list.
|
|
50
|
+
:param input_list: list, list of inputs to process.
|
|
51
|
+
:param max_workers: integer, number of workers to execute functions in parallel. Default is None, which
|
|
52
|
+
is the number of CPUs.
|
|
53
|
+
:param cpu_percent_max: integer, maximum CPU percentage. Above that usage, we will wait before starting new
|
|
54
|
+
execution.
|
|
55
|
+
:param memory_percent_max: integer, maximum memory percentage. Above that usage, we will wait, before starting
|
|
56
|
+
new execution.
|
|
57
|
+
:param wait_time: float, time to wait if the CPU or memory usage is above the maximum percentage.
|
|
58
|
+
|
|
59
|
+
Usage:
|
|
60
|
+
def unpack_file(file_path):
|
|
61
|
+
# Process the file at file_path and unpack it.
|
|
62
|
+
# Return a list of new file paths that were extracted from the provided path.
|
|
63
|
+
return [new_file_path1, new_file_path2] # Example return value
|
|
64
|
+
|
|
65
|
+
# List of file paths to process
|
|
66
|
+
file_paths = ["path1", "path2", "path3"]
|
|
67
|
+
|
|
68
|
+
# Create an instance of MultiProcessor
|
|
69
|
+
# Note: unpacking.unpack_file is passed without parentheses
|
|
70
|
+
processor = MultiProcessor(
|
|
71
|
+
process_function=unpack_file,
|
|
72
|
+
input_list=file_paths,
|
|
73
|
+
max_workers=4, # Number of parallel workers
|
|
74
|
+
cpu_percent_max=80, # Max CPU usage percentage
|
|
75
|
+
memory_percent_max=80, # Max memory usage percentage
|
|
76
|
+
wait_time=5 # Time to wait if resources are overused
|
|
77
|
+
)
|
|
78
|
+
|
|
79
|
+
# Run the processing
|
|
80
|
+
processor.run_process()
|
|
81
|
+
"""
|
|
82
|
+
|
|
83
|
+
self.process_function = process_function
|
|
84
|
+
self.input_list: list = input_list
|
|
85
|
+
self.max_workers: int = max_workers
|
|
86
|
+
self.cpu_percent_max: int = cpu_percent_max
|
|
87
|
+
self.memory_percent_max: int = memory_percent_max
|
|
88
|
+
self.wait_time: float = wait_time
|
|
89
|
+
|
|
90
|
+
def run_process(self):
|
|
91
|
+
with multiprocessing.Pool(processes=self.max_workers) as pool:
|
|
92
|
+
while self.input_list:
|
|
93
|
+
system_resources.wait_for_resource_availability(
|
|
94
|
+
cpu_percent_max=self.cpu_percent_max,
|
|
95
|
+
memory_percent_max=self.memory_percent_max,
|
|
96
|
+
wait_time=self.wait_time)
|
|
97
|
+
|
|
98
|
+
# Apply the provided function to the items in the input list
|
|
99
|
+
results = pool.map(self.process_function, self.input_list)
|
|
100
|
+
|
|
101
|
+
# Flatten list of lists and update the queue
|
|
102
|
+
self.input_list = [item for sublist in results for item in sublist]
|
|
103
|
+
|
|
104
|
+
|
|
105
|
+
class _MultiProcessorTest:
|
|
106
|
+
def __init__(self, worker_count: int = 8, initialize_at_start: bool = True):
|
|
107
|
+
"""
|
|
108
|
+
MultiProcessor class. Used to execute functions in parallel.
|
|
109
|
+
:param worker_count: integer, number of workers to execute functions in parallel.
|
|
110
|
+
:param initialize_at_start: boolean, if True, the workers will be initialized at the start of the class.
|
|
111
|
+
|
|
112
|
+
Usage:
|
|
113
|
+
# Example functions
|
|
114
|
+
def my_function1(x):
|
|
115
|
+
return x * x
|
|
116
|
+
|
|
117
|
+
def my_callback(result):
|
|
118
|
+
print(f"Result received: {result}")
|
|
119
|
+
|
|
120
|
+
# Usage example
|
|
121
|
+
if __name__ == "__main__":
|
|
122
|
+
processor = MultiProcessor()
|
|
123
|
+
|
|
124
|
+
# Adding tasks with callback (asynchronous)
|
|
125
|
+
for i in range(5):
|
|
126
|
+
processor.add_task(my_function1, i, callback=my_callback)
|
|
127
|
+
|
|
128
|
+
# Adding a task and waiting for the result (synchronous)
|
|
129
|
+
result = processor.add_task(my_function1, 10, wait=True)
|
|
130
|
+
print(f"Synchronous result: {result}")
|
|
131
|
+
|
|
132
|
+
# Shutdown and wait for all tasks to complete
|
|
133
|
+
processor.shutdown()
|
|
134
|
+
"""
|
|
135
|
+
|
|
136
|
+
self.worker_count: int = worker_count
|
|
137
|
+
self.task_queue = multiprocessing.Queue()
|
|
138
|
+
self.result_queue = multiprocessing.Queue()
|
|
139
|
+
self.workers: list = list()
|
|
140
|
+
|
|
141
|
+
if initialize_at_start:
|
|
142
|
+
self._init_workers()
|
|
143
|
+
|
|
144
|
+
def _worker(self):
|
|
145
|
+
while True:
|
|
146
|
+
task = self.task_queue.get()
|
|
147
|
+
if task is None: # Termination signal
|
|
148
|
+
break
|
|
149
|
+
func, args, kwargs, callback, return_result = task
|
|
150
|
+
try:
|
|
151
|
+
result = func(*args, **kwargs)
|
|
152
|
+
if callback:
|
|
153
|
+
callback(result)
|
|
154
|
+
if return_result:
|
|
155
|
+
self.result_queue.put(result)
|
|
156
|
+
except Exception as e:
|
|
157
|
+
if callback:
|
|
158
|
+
callback(e)
|
|
159
|
+
if return_result:
|
|
160
|
+
self.result_queue.put(e)
|
|
161
|
+
|
|
162
|
+
def _init_workers(self):
|
|
163
|
+
for _ in range(self.worker_count):
|
|
164
|
+
p = multiprocessing.Process(target=self._worker)
|
|
165
|
+
p.start()
|
|
166
|
+
self.workers.append(p)
|
|
167
|
+
|
|
168
|
+
def add_task(self, func, *args, callback=None, wait=False, **kwargs):
|
|
169
|
+
"""
|
|
170
|
+
Add a task to the queue.
|
|
171
|
+
:param func: reference, function to execute.
|
|
172
|
+
:param args: arguments for the function.
|
|
173
|
+
:param callback: reference, function to execute after the task is completed. The result of the task will be
|
|
174
|
+
passed to the callback function.
|
|
175
|
+
:param wait: boolean, if True, the function will wait for the task to complete and return the result.
|
|
176
|
+
:param kwargs: keyword arguments for the function.
|
|
177
|
+
:return:
|
|
178
|
+
"""
|
|
179
|
+
if wait:
|
|
180
|
+
self.task_queue.put((func, args, kwargs, None, True))
|
|
181
|
+
return self.result_queue.get()
|
|
182
|
+
else:
|
|
183
|
+
self.task_queue.put((func, args, kwargs, callback, False))
|
|
184
|
+
return None
|
|
185
|
+
|
|
186
|
+
def shutdown(self):
|
|
187
|
+
# Signal workers to exit
|
|
188
|
+
for _ in self.workers:
|
|
189
|
+
self.task_queue.put(None)
|
|
190
|
+
|
|
191
|
+
# Wait for all workers to finish
|
|
192
|
+
for p in self.workers:
|
|
193
|
+
p.join()
|
|
194
|
+
|
|
195
|
+
|
|
196
|
+
class _MultiConcuratorTest:
|
|
197
|
+
def __init__(self, max_workers: int = 2, initialize_at_start: bool = False):
|
|
198
|
+
"""
|
|
199
|
+
MultiConcurator class. Used to execute functions in parallel with the ProcessPoolExecutor.
|
|
200
|
+
|
|
201
|
+
:param max_workers: integer, number of workers to execute functions in parallel.
|
|
202
|
+
:param initialize_at_start: boolean, if True, the workers will be initialized at the start of the class.
|
|
203
|
+
|
|
204
|
+
Usage 1:
|
|
205
|
+
if __name__ == "__main__":
|
|
206
|
+
concurator = MultiConcurator(max_workers=4, initialize_at_start=True)
|
|
207
|
+
|
|
208
|
+
# ... add tasks to concurator ...
|
|
209
|
+
|
|
210
|
+
concurator.wait_for_completion()
|
|
211
|
+
|
|
212
|
+
# Continuously get and process results
|
|
213
|
+
for result in concurator.get_results():
|
|
214
|
+
print(result)
|
|
215
|
+
|
|
216
|
+
concurator.shutdown()
|
|
217
|
+
|
|
218
|
+
Usage 2:
|
|
219
|
+
# Basic Usage - Executing Functions in Parallel
|
|
220
|
+
This example shows how to execute a simple function in parallel.
|
|
221
|
+
|
|
222
|
+
def square(number):
|
|
223
|
+
return number * number
|
|
224
|
+
|
|
225
|
+
if __name__ == "__main__":
|
|
226
|
+
concurator = MultiConcurator(max_workers=4, initialize_at_start=True)
|
|
227
|
+
|
|
228
|
+
# Submit tasks
|
|
229
|
+
for num in range(10):
|
|
230
|
+
concurator.add_to_queue(square, num)
|
|
231
|
+
|
|
232
|
+
# Wait for completion and handle results
|
|
233
|
+
concurator.wait_for_completion()
|
|
234
|
+
|
|
235
|
+
# Retrieve results
|
|
236
|
+
while not concurator.queue.empty():
|
|
237
|
+
result = concurator.queue.get()
|
|
238
|
+
print(result)
|
|
239
|
+
|
|
240
|
+
concurator.shutdown()
|
|
241
|
+
|
|
242
|
+
Usage 3:
|
|
243
|
+
# Handling Results with a Callback Function
|
|
244
|
+
# This example demonstrates handling the results of each task using a callback function.
|
|
245
|
+
|
|
246
|
+
def multiply(x, y):
|
|
247
|
+
return x * y
|
|
248
|
+
|
|
249
|
+
def handle_result(result):
|
|
250
|
+
print(f"Result: {result}")
|
|
251
|
+
|
|
252
|
+
if __name__ == "__main__":
|
|
253
|
+
concurator = MultiConcurator(max_workers=4, initialize_at_start=True)
|
|
254
|
+
|
|
255
|
+
for i in range(5):
|
|
256
|
+
concurator.add_to_queue(multiply, i, i+1)
|
|
257
|
+
|
|
258
|
+
concurator.wait_for_completion(handle_result)
|
|
259
|
+
concurator.shutdown()
|
|
260
|
+
|
|
261
|
+
Usage 4:
|
|
262
|
+
# Dynamically Initializing the Executor
|
|
263
|
+
# This example shows how to initialize the executor dynamically and process tasks.
|
|
264
|
+
|
|
265
|
+
def compute_power(base, exponent):
|
|
266
|
+
return base ** exponent
|
|
267
|
+
|
|
268
|
+
if __name__ == "__main__":
|
|
269
|
+
concurator = MultiConcurator(max_workers=3)
|
|
270
|
+
|
|
271
|
+
# Initialize executor when needed
|
|
272
|
+
concurator.init_executor()
|
|
273
|
+
|
|
274
|
+
for i in range(1, 5):
|
|
275
|
+
concurator.add_to_queue(compute_power, i, 2)
|
|
276
|
+
|
|
277
|
+
concurator.wait_for_completion()
|
|
278
|
+
while not concurator.queue.empty():
|
|
279
|
+
print(concurator.queue.get())
|
|
280
|
+
|
|
281
|
+
concurator.shutdown()
|
|
282
|
+
|
|
283
|
+
Usage 5:
|
|
284
|
+
# Handling Exceptions in Tasks
|
|
285
|
+
# This example demonstrates how you can handle exceptions that might occur in the tasks.
|
|
286
|
+
|
|
287
|
+
def risky_division(x, y):
|
|
288
|
+
if y == 0:
|
|
289
|
+
raise ValueError("Cannot divide by zero")
|
|
290
|
+
return x / y
|
|
291
|
+
|
|
292
|
+
def handle_result(result):
|
|
293
|
+
if isinstance(result, Exception):
|
|
294
|
+
print(f"Error occurred: {result}")
|
|
295
|
+
else:
|
|
296
|
+
print(f"Result: {result}")
|
|
297
|
+
|
|
298
|
+
if __name__ == "__main__":
|
|
299
|
+
concurator = MultiConcurator(max_workers=4, initialize_at_start=True)
|
|
300
|
+
|
|
301
|
+
concurator.add_to_queue(risky_division, 10, 2)
|
|
302
|
+
concurator.add_to_queue(risky_division, 10, 0) # This will raise an exception
|
|
303
|
+
|
|
304
|
+
concurator.wait_for_completion(handle_result)
|
|
305
|
+
concurator.shutdown()
|
|
306
|
+
"""
|
|
307
|
+
|
|
308
|
+
self.executor = None
|
|
309
|
+
self.max_workers: int = max_workers
|
|
310
|
+
self.futures: list = list()
|
|
311
|
+
self.queue = multiprocessing.Queue()
|
|
312
|
+
|
|
313
|
+
if initialize_at_start:
|
|
314
|
+
self.init_executor()
|
|
315
|
+
|
|
316
|
+
def init_executor(self):
|
|
317
|
+
if self.executor is None:
|
|
318
|
+
self.executor = ProcessPoolExecutor(max_workers=self.max_workers)
|
|
319
|
+
|
|
320
|
+
def add_to_queue(self, func, *args, **kwargs):
|
|
321
|
+
if self.executor is None:
|
|
322
|
+
raise RuntimeError("Executor has not been initialized. Call init_executor() first.")
|
|
323
|
+
future = self.executor.submit(func, *args, **kwargs)
|
|
324
|
+
self.futures.append(future)
|
|
325
|
+
return future
|
|
326
|
+
|
|
327
|
+
def wait_for_completion(self, handle_result=None):
|
|
328
|
+
for future in as_completed(self.futures):
|
|
329
|
+
result = future.result()
|
|
330
|
+
if handle_result:
|
|
331
|
+
handle_result(result)
|
|
332
|
+
else:
|
|
333
|
+
self.queue.put(result)
|
|
334
|
+
|
|
335
|
+
def get_results(self):
|
|
336
|
+
while not self.queue.empty():
|
|
337
|
+
yield self.queue.get()
|
|
338
|
+
|
|
339
|
+
def shutdown(self):
|
|
340
|
+
if self.executor is not None:
|
|
341
|
+
self.executor.shutdown()
|
|
342
|
+
self.executor = None
|
atomicshop/basics/numbers.py
CHANGED
|
@@ -5,3 +5,16 @@ def is_divisible(n, k):
|
|
|
5
5
|
return True
|
|
6
6
|
else:
|
|
7
7
|
return False
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
def find_highest_number(numbers: list[float, int, str]):
|
|
11
|
+
"""
|
|
12
|
+
Takes a list of numbers (float or integers) and returns the highest one.
|
|
13
|
+
|
|
14
|
+
:param numbers: List of floats or integers.
|
|
15
|
+
:return: The highest number in the list.
|
|
16
|
+
"""
|
|
17
|
+
if not numbers:
|
|
18
|
+
raise ValueError('The list of numbers is empty.')
|
|
19
|
+
|
|
20
|
+
return max(numbers)
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import psutil
|
|
2
|
+
import time
|
|
3
|
+
|
|
4
|
+
from .print_api import print_api
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
def check_system_resources():
|
|
8
|
+
cpu_usage = psutil.cpu_percent(interval=0.1)
|
|
9
|
+
memory_usage = psutil.virtual_memory().percent
|
|
10
|
+
return cpu_usage, memory_usage
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
def wait_for_resource_availability(cpu_percent_max: int = 80, memory_percent_max: int = 80, wait_time: float = 5):
|
|
14
|
+
"""
|
|
15
|
+
Wait for system resources to be available.
|
|
16
|
+
:param cpu_percent_max: int, maximum CPU percentage. Above that usage, we will wait.
|
|
17
|
+
:param memory_percent_max: int, maximum memory percentage. Above that usage, we will wait.
|
|
18
|
+
:param wait_time: float, time to wait between checks.
|
|
19
|
+
:return: None
|
|
20
|
+
"""
|
|
21
|
+
while True:
|
|
22
|
+
cpu, memory = check_system_resources()
|
|
23
|
+
if cpu < cpu_percent_max or memory < memory_percent_max:
|
|
24
|
+
break
|
|
25
|
+
print_api(f"Waiting for resources to be available... CPU: {cpu}%, Memory: {memory}%", color='yellow')
|
|
26
|
+
time.sleep(wait_time) # Wait for 'wait_time' seconds before checking again
|
|
@@ -231,3 +231,21 @@ def start_queue_listener_for_file_handler_and_get_queue_handler(file_handler):
|
|
|
231
231
|
handlers.start_queue_listener_for_file_handler(file_handler, queue_object)
|
|
232
232
|
|
|
233
233
|
return handlers.get_queue_handler(queue_object)
|
|
234
|
+
|
|
235
|
+
|
|
236
|
+
def disable_default_logger():
|
|
237
|
+
"""
|
|
238
|
+
Function to disable default logger.
|
|
239
|
+
"""
|
|
240
|
+
|
|
241
|
+
# # Get the default logger.
|
|
242
|
+
# logger = logging.getLogger()
|
|
243
|
+
# # Remove all handlers from the logger.
|
|
244
|
+
# logger.handlers.clear()
|
|
245
|
+
# # Set the logger level to 'NOTSET'.
|
|
246
|
+
# logger.setLevel(logging.NOTSET)
|
|
247
|
+
# # Disable propagation from the 'root' logger, so we will not see the messages twice.
|
|
248
|
+
# loggers.set_propagation(logger)
|
|
249
|
+
|
|
250
|
+
# Disabling the default logger in Python
|
|
251
|
+
logging.disable(logging.CRITICAL)
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
atomicshop/__init__.py,sha256=
|
|
1
|
+
atomicshop/__init__.py,sha256=NXDiuw7KfoCVJPfpRXHeFAgfmcvLx-4zWrrJZldKjJ0,122
|
|
2
2
|
atomicshop/_basics_temp.py,sha256=6cu2dd6r2dLrd1BRNcVDKTHlsHs_26Gpw8QS6v32lQ0,3699
|
|
3
3
|
atomicshop/appointment_management.py,sha256=N3wVGJgrqJfsj_lqiRfaL3FxMEe57by5Stzanh189mk,7263
|
|
4
4
|
atomicshop/archiver.py,sha256=QuDKx6bJEM29u-7r2tsizXEEGJmPuv0Xm91JQOpg__8,7152
|
|
@@ -34,6 +34,7 @@ atomicshop/sound.py,sha256=KSzWRF8dkpEVXmFidIv-Eftc3kET-hQzQOxZRE7rMto,24297
|
|
|
34
34
|
atomicshop/speech_recognize.py,sha256=55-dIjgkpF93mvJnJuxSFuft5H5eRvGNlUj9BeIOZxk,5903
|
|
35
35
|
atomicshop/ssh_remote.py,sha256=Sas3nrQv8ardxR51t59xZZsYm8nvUcA7tMSqEDViRLk,17155
|
|
36
36
|
atomicshop/sys_functions.py,sha256=MTBxRve5bh58SPvhX3gMiGqHlSBuI_rdNN1NnnBBWqI,906
|
|
37
|
+
atomicshop/system_resources.py,sha256=rYRNsl9BaJgFSSgygXNtUsVFxUb9WGxZ1Ek7bKLomVo,1033
|
|
37
38
|
atomicshop/tempfiles.py,sha256=uq1ve2WlWehZ3NOTXJnpBBMt6HyCdBufqedF0HyzA6k,2517
|
|
38
39
|
atomicshop/timer.py,sha256=KxBBgVM8po6pUJDW8TgY1UXj0iiDmRmL5XDCq0VHAfU,1670
|
|
39
40
|
atomicshop/urls.py,sha256=CQl1j1kjEVDlAuYJqYD9XxPF1SUSgrmG8PjlcXNEKsQ,597
|
|
@@ -72,8 +73,8 @@ atomicshop/basics/hexs.py,sha256=i8CTG-J0TGGa25yFSbWEvpVyHFnof_qSWUrmXY-ylKM,105
|
|
|
72
73
|
atomicshop/basics/isinstancing.py,sha256=fQ35xfqbguQz2BUn-3a4KVGskhTcIn8JjRtxV2rFcRQ,876
|
|
73
74
|
atomicshop/basics/list_of_dicts.py,sha256=fu0H6dUD9uUo2kl7FYIrWzOQMwCmg7qRxGnFM5S319E,5716
|
|
74
75
|
atomicshop/basics/lists.py,sha256=ZyTjHyvkta-4_xCG1P-LFMENELmgAYlDdPq4hMRAOR8,2545
|
|
75
|
-
atomicshop/basics/multiprocesses.py,sha256=
|
|
76
|
-
atomicshop/basics/numbers.py,sha256=
|
|
76
|
+
atomicshop/basics/multiprocesses.py,sha256=On2PbXDpVBkhdocISNDTGFcElpSOONfYjkIPKIRCIHI,12887
|
|
77
|
+
atomicshop/basics/numbers.py,sha256=II-jP8MG0IYvmjT9_BLEai65xzDJ0LTHK2eFVSrgVqo,527
|
|
77
78
|
atomicshop/basics/randoms.py,sha256=DmYLtnIhDK29tAQrGP1Nt-A-v8WC7WIEB8Edi-nk3N4,282
|
|
78
79
|
atomicshop/basics/strings.py,sha256=uhl-5cqZ3qLK7M38lOEDSGCAkG3xmeLoEU3V0oCgMxU,14358
|
|
79
80
|
atomicshop/basics/threads.py,sha256=xvgdDJdmgN0wmmARoZ-H7Kvl1GOcEbvgaeGL4M3Hcx8,2819
|
|
@@ -162,7 +163,7 @@ atomicshop/wrappers/loggingw/checks.py,sha256=AGFsTsLxHQd1yAraa5popqLaGO9VM0KpcP
|
|
|
162
163
|
atomicshop/wrappers/loggingw/formatters.py,sha256=mUtcJJfmhLNrwUVYShXTmdu40dBaJu4TS8FiuTXI7ys,7189
|
|
163
164
|
atomicshop/wrappers/loggingw/handlers.py,sha256=qm5Fbu8eDmlstMduUe5nKUlJU5IazFkSnQizz8Qt2os,5479
|
|
164
165
|
atomicshop/wrappers/loggingw/loggers.py,sha256=DHOOTAtqkwn1xgvLHSkOiBm6yFGNuQy1kvbhG-TDog8,2374
|
|
165
|
-
atomicshop/wrappers/loggingw/loggingw.py,sha256=
|
|
166
|
+
atomicshop/wrappers/loggingw/loggingw.py,sha256=v9WAseZXB50LluT9rIUcRvvevg2nLVKPgz3dbGejfV0,12151
|
|
166
167
|
atomicshop/wrappers/loggingw/reading.py,sha256=cHco0EG8bEB6fJ7JxkFdV_d8J-voYRBCUzS-qVqv4aU,3697
|
|
167
168
|
atomicshop/wrappers/playwrightw/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
168
169
|
atomicshop/wrappers/playwrightw/_tryouts.py,sha256=l1BLkFsiIMNlgv7nfZd1XGEvXQkIQkIcg48__9OaC00,4920
|
|
@@ -192,8 +193,8 @@ atomicshop/wrappers/socketw/socket_server_tester.py,sha256=VfNthyBvgI5tL9v3Qprh4
|
|
|
192
193
|
atomicshop/wrappers/socketw/socket_wrapper.py,sha256=aXBwlEIJhFT0-c4i8iNlFx2It9VpCEpsv--5Oqcpxao,11624
|
|
193
194
|
atomicshop/wrappers/socketw/ssl_base.py,sha256=k4V3gwkbq10MvOH4btU4onLX2GNOsSfUAdcHmL1rpVE,2274
|
|
194
195
|
atomicshop/wrappers/socketw/statistics_csv.py,sha256=t3dtDEfN47CfYVi0CW6Kc2QHTEeZVyYhc57IYYh5nmA,826
|
|
195
|
-
atomicshop-2.
|
|
196
|
-
atomicshop-2.
|
|
197
|
-
atomicshop-2.
|
|
198
|
-
atomicshop-2.
|
|
199
|
-
atomicshop-2.
|
|
196
|
+
atomicshop-2.6.0.dist-info/LICENSE.txt,sha256=lLU7EYycfYcK2NR_1gfnhnRC8b8ccOTElACYplgZN88,1094
|
|
197
|
+
atomicshop-2.6.0.dist-info/METADATA,sha256=hIocyrjd0H35Wh9NFhQ_OldHC9DtqBZfV2LVpZ7IQdo,10267
|
|
198
|
+
atomicshop-2.6.0.dist-info/WHEEL,sha256=oiQVh_5PnQM0E3gPdiz09WCNmwiHDMaGer_elqB3coM,92
|
|
199
|
+
atomicshop-2.6.0.dist-info/top_level.txt,sha256=EgKJB-7xcrAPeqTRF2laD_Np2gNGYkJkd4OyXqpJphA,11
|
|
200
|
+
atomicshop-2.6.0.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|