atomicshop 2.5.16__py3-none-any.whl → 2.6.1__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 CHANGED
@@ -1,4 +1,4 @@
1
1
  """Atomic Basic functions and classes to make developer life easier"""
2
2
 
3
3
  __author__ = "Den Kras"
4
- __version__ = '2.5.16'
4
+ __version__ = '2.6.1'
@@ -32,10 +32,10 @@ def __comparison_usage_example(
32
32
  main folder.
33
33
 
34
34
  Usage:
35
- from atomicshop.filesystem import get_file_paths_and_relative_directories, ComparisonOperator
35
+ from atomicshop.filesystem import get_file_paths_from_directory, ComparisonOperator
36
36
 
37
37
  # Get full paths of all the 'engine_config.ini' files.
38
- engine_config_path_list = get_file_paths_and_relative_directories(
38
+ engine_config_path_list = get_file_paths_from_directory(
39
39
  directory_fullpath=some_directory_path,
40
40
  file_name_check_tuple=(config_file_name, ComparisonOperator.EQ))
41
41
  """
@@ -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,333 @@ 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
+ # Keep track of the async results
93
+ async_results = []
94
+
95
+ while self.input_list:
96
+ new_input_list = []
97
+ for item in self.input_list:
98
+ # Check system resources before processing each item
99
+ system_resources.wait_for_resource_availability(
100
+ cpu_percent_max=self.cpu_percent_max,
101
+ memory_percent_max=self.memory_percent_max,
102
+ wait_time=self.wait_time)
103
+
104
+ # Process the item
105
+ async_result = pool.apply_async(self.process_function, (item,))
106
+ async_results.append(async_result)
107
+
108
+ # Reset input_list for next round of processing
109
+ self.input_list = []
110
+
111
+ # Collect results as they complete
112
+ for async_result in async_results:
113
+ try:
114
+ result = async_result.get()
115
+ # Assuming process_function returns a list, extend new_input_list
116
+ new_input_list.extend(result)
117
+ except Exception as e:
118
+ print(f"An error occurred: {e}")
119
+
120
+ # Update the input_list for the next iteration
121
+ self.input_list = new_input_list
122
+ # Clear the async_results for the next iteration
123
+ async_results.clear()
124
+
125
+
126
+ class _MultiProcessorTest:
127
+ def __init__(self, worker_count: int = 8, initialize_at_start: bool = True):
128
+ """
129
+ MultiProcessor class. Used to execute functions in parallel.
130
+ :param worker_count: integer, number of workers to execute functions in parallel.
131
+ :param initialize_at_start: boolean, if True, the workers will be initialized at the start of the class.
132
+
133
+ Usage:
134
+ # Example functions
135
+ def my_function1(x):
136
+ return x * x
137
+
138
+ def my_callback(result):
139
+ print(f"Result received: {result}")
140
+
141
+ # Usage example
142
+ if __name__ == "__main__":
143
+ processor = MultiProcessor()
144
+
145
+ # Adding tasks with callback (asynchronous)
146
+ for i in range(5):
147
+ processor.add_task(my_function1, i, callback=my_callback)
148
+
149
+ # Adding a task and waiting for the result (synchronous)
150
+ result = processor.add_task(my_function1, 10, wait=True)
151
+ print(f"Synchronous result: {result}")
152
+
153
+ # Shutdown and wait for all tasks to complete
154
+ processor.shutdown()
155
+ """
156
+
157
+ self.worker_count: int = worker_count
158
+ self.task_queue = multiprocessing.Queue()
159
+ self.result_queue = multiprocessing.Queue()
160
+ self.workers: list = list()
161
+
162
+ if initialize_at_start:
163
+ self._init_workers()
164
+
165
+ def _worker(self):
166
+ while True:
167
+ task = self.task_queue.get()
168
+ if task is None: # Termination signal
169
+ break
170
+ func, args, kwargs, callback, return_result = task
171
+ try:
172
+ result = func(*args, **kwargs)
173
+ if callback:
174
+ callback(result)
175
+ if return_result:
176
+ self.result_queue.put(result)
177
+ except Exception as e:
178
+ if callback:
179
+ callback(e)
180
+ if return_result:
181
+ self.result_queue.put(e)
182
+
183
+ def _init_workers(self):
184
+ for _ in range(self.worker_count):
185
+ p = multiprocessing.Process(target=self._worker)
186
+ p.start()
187
+ self.workers.append(p)
188
+
189
+ def add_task(self, func, *args, callback=None, wait=False, **kwargs):
190
+ """
191
+ Add a task to the queue.
192
+ :param func: reference, function to execute.
193
+ :param args: arguments for the function.
194
+ :param callback: reference, function to execute after the task is completed. The result of the task will be
195
+ passed to the callback function.
196
+ :param wait: boolean, if True, the function will wait for the task to complete and return the result.
197
+ :param kwargs: keyword arguments for the function.
198
+ :return:
199
+ """
200
+ if wait:
201
+ self.task_queue.put((func, args, kwargs, None, True))
202
+ return self.result_queue.get()
203
+ else:
204
+ self.task_queue.put((func, args, kwargs, callback, False))
205
+ return None
206
+
207
+ def shutdown(self):
208
+ # Signal workers to exit
209
+ for _ in self.workers:
210
+ self.task_queue.put(None)
211
+
212
+ # Wait for all workers to finish
213
+ for p in self.workers:
214
+ p.join()
215
+
216
+
217
+ class _MultiConcuratorTest:
218
+ def __init__(self, max_workers: int = 2, initialize_at_start: bool = False):
219
+ """
220
+ MultiConcurator class. Used to execute functions in parallel with the ProcessPoolExecutor.
221
+
222
+ :param max_workers: integer, number of workers to execute functions in parallel.
223
+ :param initialize_at_start: boolean, if True, the workers will be initialized at the start of the class.
224
+
225
+ Usage 1:
226
+ if __name__ == "__main__":
227
+ concurator = MultiConcurator(max_workers=4, initialize_at_start=True)
228
+
229
+ # ... add tasks to concurator ...
230
+
231
+ concurator.wait_for_completion()
232
+
233
+ # Continuously get and process results
234
+ for result in concurator.get_results():
235
+ print(result)
236
+
237
+ concurator.shutdown()
238
+
239
+ Usage 2:
240
+ # Basic Usage - Executing Functions in Parallel
241
+ This example shows how to execute a simple function in parallel.
242
+
243
+ def square(number):
244
+ return number * number
245
+
246
+ if __name__ == "__main__":
247
+ concurator = MultiConcurator(max_workers=4, initialize_at_start=True)
248
+
249
+ # Submit tasks
250
+ for num in range(10):
251
+ concurator.add_to_queue(square, num)
252
+
253
+ # Wait for completion and handle results
254
+ concurator.wait_for_completion()
255
+
256
+ # Retrieve results
257
+ while not concurator.queue.empty():
258
+ result = concurator.queue.get()
259
+ print(result)
260
+
261
+ concurator.shutdown()
262
+
263
+ Usage 3:
264
+ # Handling Results with a Callback Function
265
+ # This example demonstrates handling the results of each task using a callback function.
266
+
267
+ def multiply(x, y):
268
+ return x * y
269
+
270
+ def handle_result(result):
271
+ print(f"Result: {result}")
272
+
273
+ if __name__ == "__main__":
274
+ concurator = MultiConcurator(max_workers=4, initialize_at_start=True)
275
+
276
+ for i in range(5):
277
+ concurator.add_to_queue(multiply, i, i+1)
278
+
279
+ concurator.wait_for_completion(handle_result)
280
+ concurator.shutdown()
281
+
282
+ Usage 4:
283
+ # Dynamically Initializing the Executor
284
+ # This example shows how to initialize the executor dynamically and process tasks.
285
+
286
+ def compute_power(base, exponent):
287
+ return base ** exponent
288
+
289
+ if __name__ == "__main__":
290
+ concurator = MultiConcurator(max_workers=3)
291
+
292
+ # Initialize executor when needed
293
+ concurator.init_executor()
294
+
295
+ for i in range(1, 5):
296
+ concurator.add_to_queue(compute_power, i, 2)
297
+
298
+ concurator.wait_for_completion()
299
+ while not concurator.queue.empty():
300
+ print(concurator.queue.get())
301
+
302
+ concurator.shutdown()
303
+
304
+ Usage 5:
305
+ # Handling Exceptions in Tasks
306
+ # This example demonstrates how you can handle exceptions that might occur in the tasks.
307
+
308
+ def risky_division(x, y):
309
+ if y == 0:
310
+ raise ValueError("Cannot divide by zero")
311
+ return x / y
312
+
313
+ def handle_result(result):
314
+ if isinstance(result, Exception):
315
+ print(f"Error occurred: {result}")
316
+ else:
317
+ print(f"Result: {result}")
318
+
319
+ if __name__ == "__main__":
320
+ concurator = MultiConcurator(max_workers=4, initialize_at_start=True)
321
+
322
+ concurator.add_to_queue(risky_division, 10, 2)
323
+ concurator.add_to_queue(risky_division, 10, 0) # This will raise an exception
324
+
325
+ concurator.wait_for_completion(handle_result)
326
+ concurator.shutdown()
327
+ """
328
+
329
+ self.executor = None
330
+ self.max_workers: int = max_workers
331
+ self.futures: list = list()
332
+ self.queue = multiprocessing.Queue()
333
+
334
+ if initialize_at_start:
335
+ self.init_executor()
336
+
337
+ def init_executor(self):
338
+ if self.executor is None:
339
+ self.executor = ProcessPoolExecutor(max_workers=self.max_workers)
340
+
341
+ def add_to_queue(self, func, *args, **kwargs):
342
+ if self.executor is None:
343
+ raise RuntimeError("Executor has not been initialized. Call init_executor() first.")
344
+ future = self.executor.submit(func, *args, **kwargs)
345
+ self.futures.append(future)
346
+ return future
347
+
348
+ def wait_for_completion(self, handle_result=None):
349
+ for future in as_completed(self.futures):
350
+ result = future.result()
351
+ if handle_result:
352
+ handle_result(result)
353
+ else:
354
+ self.queue.put(result)
355
+
356
+ def get_results(self):
357
+ while not self.queue.empty():
358
+ yield self.queue.get()
359
+
360
+ def shutdown(self):
361
+ if self.executor is not None:
362
+ self.executor.shutdown()
363
+ self.executor = None
@@ -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)
@@ -2,7 +2,6 @@ from docx import Document
2
2
  from docx.opc.exceptions import PackageNotFoundError
3
3
 
4
4
  from .. import filesystem, config_init
5
- from . import file_io
6
5
  from ..print_api import print_api
7
6
 
8
7
 
@@ -67,12 +66,13 @@ def search_for_hyperlink_in_files(directory_path: str, hyperlink: str, relative_
67
66
  raise NotADirectoryError(f"Directory doesn't exist: {directory_path}")
68
67
 
69
68
  # Get all the docx files in the specified directory.
70
- files = filesystem.get_file_paths_and_relative_directories(
71
- directory_path, file_name_check_pattern="*.docx", relative_file_name_as_directory=True)
69
+ files = filesystem.get_file_paths_from_directory(
70
+ directory_path, file_name_check_pattern="*.docx",
71
+ add_relative_directory=True, relative_file_name_as_directory=True)
72
72
 
73
73
  found_in_files: list = list()
74
74
  for file_path in files:
75
- hyperlinks = get_hyperlinks(file_path['path'])
75
+ hyperlinks = get_hyperlinks(file_path['file_path'])
76
76
  if hyperlink in hyperlinks:
77
77
  found_in_files.append(file_path)
78
78
 
atomicshop/filesystem.py CHANGED
@@ -381,7 +381,7 @@ def move_files_from_folder_to_folder(source_directory: str, target_directory: st
381
381
  # Move each item to the destination directory
382
382
  shutil.move(source_item, destination_item)
383
383
  # # Get all file names without full paths in source folder.
384
- # file_list_in_source: list = get_file_paths_and_relative_directories(source_directory)
384
+ # file_list_in_source: list = get_file_paths_from_directory(source_directory)
385
385
  #
386
386
  # # Iterate through all the files.
387
387
  # for file_path in file_list_in_source:
@@ -438,10 +438,11 @@ def get_file_names_from_directory(directory_path: str) -> list:
438
438
  return file_list
439
439
 
440
440
 
441
- def get_file_paths_and_relative_directories(
442
- directory_fullpath: str,
441
+ def get_file_paths_from_directory(
442
+ directory_path: str,
443
443
  recursive: bool = True,
444
444
  file_name_check_pattern: str = '*',
445
+ add_relative_directory: bool = False,
445
446
  relative_file_name_as_directory: bool = False,
446
447
  add_last_modified_time: bool = False,
447
448
  sort_by_last_modified_time: bool = False
@@ -453,13 +454,18 @@ def get_file_paths_and_relative_directories(
453
454
  If 'file_name_check_tuple' specified, the function will return only list of files that answer to the input
454
455
  of that tuple.
455
456
 
456
- :param directory_fullpath: string to full path to directory on the filesystem to scan.
457
+ :param directory_path: string to full path to directory on the filesystem to scan.
457
458
  :param recursive: boolean.
458
459
  'True', then the function will scan recursively in subdirectories.
459
460
  'False', then the function will scan only in the directory that was passed.
460
461
  :param file_name_check_pattern: string, if specified, the function will return only files that match the pattern.
461
462
  The string can contain part of file name to check or full file name with extension.
462
463
  Can contain wildcards.
464
+ :param add_relative_directory: boolean, if
465
+ 'True', then the function will add relative directory to the output list.
466
+ In this case the output list will contain dictionaries with keys 'path' and 'relative_dir'.
467
+ 'False', then the function will not add relative directory to the output list.
468
+ And the output list will contain only full file paths.
463
469
  :param relative_file_name_as_directory: boolean that will set if 'relative_directory_list' should contain
464
470
  file name with extension for each entry.
465
471
  :param add_last_modified_time: boolean, if 'True', then the function will add last modified time of the file
@@ -477,33 +483,43 @@ def get_file_paths_and_relative_directories(
477
483
  file, against the main path to directory that was passed to the parent function.
478
484
  """
479
485
 
480
- file_result: dict = dict()
481
-
482
- # Get full file path of the file.
483
- file_result['path'] = os.path.join(dirpath, file)
486
+ file_path: str = os.path.join(dirpath, file)
484
487
 
485
- # if 'relative_file_name_as_directory' was passed.
486
- if relative_file_name_as_directory:
487
- # Output the path with filename.
488
- file_result['relative_dir'] = _get_relative_output_path_from_input_path(directory_fullpath, dirpath, file)
489
- # if 'relative_file_name_as_directory' wasn't passed.
488
+ if not add_relative_directory and not add_last_modified_time:
489
+ file_result: str = file_path
490
490
  else:
491
- # Output the path without filename.
492
- file_result['relative_dir'] = _get_relative_output_path_from_input_path(directory_fullpath, dirpath)
493
-
494
- # Remove separator from the beginning if exists.
495
- file_result['relative_dir'] = file_result['relative_dir'].removeprefix(os.sep)
496
-
497
- # If 'add_last_modified_time' was passed.
498
- if add_last_modified_time:
499
- # Get last modified time of the file.
500
- file_result['last_modified'] = get_file_modified_time(file_result['path'])
491
+ file_result: dict = dict()
492
+
493
+ # Get full file path of the file.
494
+ file_result['file_path'] = file_path
495
+
496
+ if add_relative_directory:
497
+ # if 'relative_file_name_as_directory' was passed.
498
+ if relative_file_name_as_directory:
499
+ # Output the path with filename.
500
+ file_result['relative_dir'] = _get_relative_output_path_from_input_path(
501
+ directory_path, dirpath, file)
502
+ # if 'relative_file_name_as_directory' wasn't passed.
503
+ else:
504
+ # Output the path without filename.
505
+ file_result['relative_dir'] = _get_relative_output_path_from_input_path(directory_path, dirpath)
506
+
507
+ # Remove separator from the beginning if exists.
508
+ file_result['relative_dir'] = file_result['relative_dir'].removeprefix(os.sep)
509
+
510
+ # If 'add_last_modified_time' was passed.
511
+ if add_last_modified_time:
512
+ # Get last modified time of the file.
513
+ file_result['last_modified'] = get_file_modified_time(file_result['path'])
501
514
 
502
515
  object_list.append(file_result)
503
516
 
504
517
  if sort_by_last_modified_time and not add_last_modified_time:
505
518
  raise ValueError('Parameter "sort_by_last_modified_time" cannot be "True" if parameter '
506
519
  '"add_last_modified_time" is not "True".')
520
+ if relative_file_name_as_directory and not add_relative_directory:
521
+ raise ValueError('Parameter "relative_file_name_as_directory" cannot be "True" if parameter '
522
+ '"add_relative_directory" is not "True".')
507
523
 
508
524
  # === Function main ================
509
525
  # Define locals.
@@ -511,7 +527,7 @@ def get_file_paths_and_relative_directories(
511
527
 
512
528
  # "Walk" over all the directories and subdirectories - make list of full file paths inside the directory
513
529
  # recursively.
514
- for dirpath, subdirs, files in os.walk(directory_fullpath):
530
+ for dirpath, subdirs, files in os.walk(directory_path):
515
531
  # Iterate through all the file names that were found in the folder.
516
532
  for file in files:
517
533
  # If 'file_name_check_pattern' was passed.
@@ -674,7 +690,7 @@ def get_file_hashes_from_directory(directory_path: str, recursive: bool = False,
674
690
  """
675
691
 
676
692
  # Get all the files.
677
- file_paths_list = get_file_paths_and_relative_directories(directory_path, recursive=recursive)
693
+ file_paths_list = get_file_paths_from_directory(directory_path, recursive=recursive)
678
694
 
679
695
  # Create a list of dictionaries, each dictionary is a file with its hash.
680
696
  files: list = list()
@@ -6,7 +6,6 @@ from atomicshop.print_api import print_api
6
6
  from .import_config import ImportConfig
7
7
  from .initialize_engines import ModuleCategory
8
8
  from .connection_thread_worker import thread_worker_main
9
- from ..filesystem import get_file_paths_and_relative_directories
10
9
  from .. import filesystem, queues
11
10
  from ..python_functions import get_current_python_version_string, check_python_version_compliance
12
11
  from ..wrappers.socketw.socket_wrapper import SocketWrapper
@@ -104,8 +103,8 @@ def initialize_mitm_server(config_static):
104
103
  system_logger.info("Importing engine modules.")
105
104
 
106
105
  # Get full paths of all the 'engine_config.ini' files.
107
- engine_config_path_list = get_file_paths_and_relative_directories(
108
- directory_fullpath=config_static.ENGINES_DIRECTORY_PATH,
106
+ engine_config_path_list = filesystem.get_file_paths_from_directory(
107
+ directory_path=config_static.ENGINES_DIRECTORY_PATH,
109
108
  file_name_check_pattern=config_static.ENGINE_CONFIG_FILE_NAME)
110
109
 
111
110
  # Iterate through all the 'engine_config.ini' file paths.
@@ -114,7 +113,7 @@ def initialize_mitm_server(config_static):
114
113
  for engine_config_path in engine_config_path_list:
115
114
  # Initialize engine.
116
115
  current_module = ModuleCategory(config_static.WORKING_DIRECTORY)
117
- current_module.fill_engine_fields_from_config(engine_config_path['path'])
116
+ current_module.fill_engine_fields_from_config(engine_config_path)
118
117
  current_module.initialize_engine(logs_path=config['log']['logs_path'],
119
118
  logger=system_logger)
120
119
 
@@ -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 and 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)
@@ -2,7 +2,6 @@ import os
2
2
  from typing import Literal
3
3
 
4
4
  from ... import filesystem, datetimes
5
- from ...basics import list_of_dicts
6
5
  from ...file_io import csvs
7
6
 
8
7
 
@@ -37,7 +36,7 @@ def get_logs(
37
36
  if remove_logs and move_to_path:
38
37
  raise ValueError('Both "remove_logs" and "move_to_path" cannot be True/specified at the same time.')
39
38
 
40
- logs_files: list = filesystem.get_file_paths_and_relative_directories(
39
+ logs_files: list = filesystem.get_file_paths_from_directory(
41
40
  path, file_name_check_pattern=pattern,
42
41
  add_last_modified_time=True, sort_by_last_modified_time=True)
43
42
 
@@ -47,12 +46,12 @@ def get_logs(
47
46
  for single_file in logs_files:
48
47
  if log_type == 'csv':
49
48
  if header_type_of_files == 'all':
50
- csv_content, _ = csvs.read_csv_to_list(single_file['path'], **print_kwargs)
49
+ csv_content, _ = csvs.read_csv_to_list(single_file['file_path'], **print_kwargs)
51
50
  logs_content.extend(csv_content)
52
51
  elif header_type_of_files == 'first':
53
52
  # The function gets empty header to read it from the CSV file, the returns the header that it read.
54
53
  # Then each time the header is fed once again to the function.
55
- csv_content, header = csvs.read_csv_to_list(single_file['path'], header=header, **print_kwargs)
54
+ csv_content, header = csvs.read_csv_to_list(single_file['file_path'], header=header, **print_kwargs)
56
55
  # Any way the first file will be read with header.
57
56
  logs_content.extend(csv_content)
58
57
 
@@ -63,7 +62,7 @@ def get_logs(
63
62
  if remove_logs:
64
63
  # Remove the statistics files.
65
64
  for single_file in logs_files:
66
- filesystem.remove_file(single_file['path'])
65
+ filesystem.remove_file(single_file['file_path'])
67
66
 
68
67
  if move_to_path:
69
68
  # Get formatted time stamp for file name.
@@ -76,8 +75,8 @@ def get_logs(
76
75
  filesystem.create_directory(move_to_path_with_timestamp)
77
76
  # Move the statistics files.
78
77
  for single_file in logs_files:
79
- single_file_name = filesystem.get_file_name(single_file['path'])
78
+ single_file_name = filesystem.get_file_name(single_file['file_path'])
80
79
  move_to_path_with_file = f'{move_to_path_with_timestamp}{os.sep}{single_file_name}'
81
- filesystem.move_file(single_file['path'], move_to_path_with_file)
80
+ filesystem.move_file(single_file['file_path'], move_to_path_with_file)
82
81
 
83
82
  return logs_content
@@ -3,7 +3,7 @@ import threading
3
3
  from .socket_client import SocketClient
4
4
  from ..configparserw import ConfigParserWrapper
5
5
  from ..loggingw import loggingw
6
- from ...filesystem import get_file_paths_and_relative_directories
6
+ from ...filesystem import get_file_paths_from_directory
7
7
  from ...file_io import jsons, file_io
8
8
 
9
9
 
@@ -57,14 +57,14 @@ def execute_test(config_static):
57
57
  loggingw.get_logger_with_stream_handler("network")
58
58
 
59
59
  # Get all the files in requests folder recursively.
60
- request_file_list = get_file_paths_and_relative_directories(config['requests_directory'])
60
+ request_file_list = get_file_paths_from_directory(config['requests_directory'])
61
61
  print(f"Found request files: {len(request_file_list)}")
62
62
 
63
63
  # Get contents of all request files to list of contents.
64
64
  requests_bytes_list: list = list()
65
65
  for request_file_path in request_file_list:
66
66
  if config['request_type'] == 'json':
67
- request_file_content = jsons.read_json_file(request_file_path['path'])
67
+ request_file_content = jsons.read_json_file(request_file_path)
68
68
 
69
69
  # If imported json is regular and not combined json.
70
70
  if isinstance(request_file_content, dict):
@@ -79,13 +79,13 @@ def execute_test(config_static):
79
79
  requests_bytes_list.extend(
80
80
  get_key_values_from_json(json_dict, config['request_json_hex_key_list']))
81
81
  elif config['request_type'] == 'string':
82
- request_file_content = file_io.read_file(request_file_path['path'])
82
+ request_file_content = file_io.read_file(request_file_path)
83
83
  # Convert string content to bytes and append to list.
84
84
  requests_bytes_list.append(request_file_content.encode())
85
85
  print(f"Extracted 1 request.")
86
86
  elif config['request_type'] == 'binary':
87
87
  # The content is already in bytes, so just appending.
88
- requests_bytes_list.append(file_io.read_file(request_file_path['path'], 'rb'))
88
+ requests_bytes_list.append(file_io.read_file(request_file_path, 'rb'))
89
89
  print(f"Extracted 1 request.")
90
90
 
91
91
  print(f"Finished parsing. Parsed requests: {len(requests_bytes_list)}")
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: atomicshop
3
- Version: 2.5.16
3
+ Version: 2.6.1
4
4
  Summary: Atomic functions and classes to make developer life easier
5
5
  Author: Denis Kras
6
6
  License: MIT License
@@ -1,4 +1,4 @@
1
- atomicshop/__init__.py,sha256=ayLlabN9C1kOn1T8udiljMqhA2XOEFO5ihTvhBJ00kA,123
1
+ atomicshop/__init__.py,sha256=eEODmu-TVbN7jQzj-QW2WqUEroxwfWlIzr-UPTPbi2E,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
@@ -12,7 +12,7 @@ atomicshop/diff_check.py,sha256=RON9cSTgy3jAnwUmAUkOyfF6bgrBKOq9Sbgyl3RYodw,1235
12
12
  atomicshop/dns.py,sha256=bNZOo5jVPzq7OT2qCPukXoK3zb1oOsyaelUwQEyK1SA,2500
13
13
  atomicshop/domains.py,sha256=Rxu6JhhMqFZRcoFs69IoEd1PtYca0lMCG6F1AomP7z4,3197
14
14
  atomicshop/emails.py,sha256=I0KyODQpIMEsNRi9YWSOL8EUPBiWyon3HRdIuSj3AEU,1410
15
- atomicshop/filesystem.py,sha256=NCf36h9AefZoT6v0o09089ITMo8qaH-DHZCJ4BafKok,29945
15
+ atomicshop/filesystem.py,sha256=82osUMOas8DqUtR7mpcRWAqdx5JTRJ3e-o1VxetSXZg,30923
16
16
  atomicshop/functions.py,sha256=VqLjxAxhaxUr-Ad8P1cw9bZGdZpbtqfCaXQyHf3CM9g,509
17
17
  atomicshop/hashing.py,sha256=k_HXR7FnPUzLUKk8EiewJ_gLFBlWncZluiBwzplFMWs,3548
18
18
  atomicshop/http_parse.py,sha256=nrf2rZcprLqtW8HVrV7TCZ1iTBcWRRy-mXIlAOzcaJs,9703
@@ -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=CMJfhDv6dI9K3IejpyKu-6qRlfeTphaOCd2RaLxXDyg,1034
37
38
  atomicshop/tempfiles.py,sha256=uq1ve2WlWehZ3NOTXJnpBBMt6HyCdBufqedF0HyzA6k,2517
38
39
  atomicshop/timer.py,sha256=KxBBgVM8po6pUJDW8TgY1UXj0iiDmRmL5XDCq0VHAfU,1670
39
40
  atomicshop/urls.py,sha256=CQl1j1kjEVDlAuYJqYD9XxPF1SUSgrmG8PjlcXNEKsQ,597
@@ -65,15 +66,15 @@ atomicshop/basics/bytes_arrays.py,sha256=M0o9OOx7TRcI2JQZSKpVLeBu5Q9jEaAwu7rE9_F
65
66
  atomicshop/basics/classes.py,sha256=sgzsYpI8MhauNvfB_mmznROpyPbfgbqaneTTEWE7g9s,7336
66
67
  atomicshop/basics/dicts.py,sha256=4DdkeVTzqr1Kh66vvIkzw4lz910SV0HMsEAGc7w5gug,8274
67
68
  atomicshop/basics/dicts_nested.py,sha256=StYxYnYPa0SEJr1lmEwAv5zfERWWqoULeyG8e0zRAwE,4107
68
- atomicshop/basics/enums.py,sha256=fY7a9oOKy9TWc-_ExbRK5UyGndU6uquj8yBxtnvYNtk,3567
69
+ atomicshop/basics/enums.py,sha256=CeV8MfqWHihK7vvV6Mbzq7rD9JykeQfrJeFdLVzfHI4,3547
69
70
  atomicshop/basics/exceptions.py,sha256=-1Gu8bHA3hrf11mmeaPuVE73jWV3EOyRgh2vSpWfveg,504
70
71
  atomicshop/basics/guids.py,sha256=iRx5n18ATZWhpo748BwEjuLWLsu9y3OwF5-Adp-Dtik,403
71
72
  atomicshop/basics/hexs.py,sha256=i8CTG-J0TGGa25yFSbWEvpVyHFnof_qSWUrmXY-ylKM,1054
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=GVeyF-r9Q6SAjpJ46eqkZQ4QUli554n-CAIE_W8pij8,958
76
- atomicshop/basics/numbers.py,sha256=FRjAH1Thk3z3ayxq0Ik6Wh93ELDRk1geyDYTv8amZBE,165
76
+ atomicshop/basics/multiprocesses.py,sha256=4Bq5fzONuvCLfmwP11u9TKWGerTJv0zlwuHVKFhV6ms,13778
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
@@ -84,7 +85,7 @@ atomicshop/etw/dns_trace.py,sha256=ZbEf1gptnUnJwaRURUW9ENDwC9Q41Zl6NtxgMNELJcg,5
84
85
  atomicshop/etw/etw.py,sha256=xVJNbfCq4KgRfsDnul6CrIdAMl9xRBixZ-hUyqiB2g4,2403
85
86
  atomicshop/file_io/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
86
87
  atomicshop/file_io/csvs.py,sha256=4R4Kij8FmxNwXFjDtlF_A0flAk0Hj5nZKlEnqC5VxgQ,3125
87
- atomicshop/file_io/docxs.py,sha256=2lue7_eAz0fI8X3vCn34lHarU5xGSm4-Yqr0PeUPt84,4359
88
+ atomicshop/file_io/docxs.py,sha256=3IFtaurVhvntcuCL59bpFlzGyKxvDmVUjUQTHWluOMY,4369
88
89
  atomicshop/file_io/file_io.py,sha256=s39zU5PRG-lqWFx6HNlZRLWMQJzpgIL0mkVyXdk8Jw4,7884
89
90
  atomicshop/file_io/jsons.py,sha256=4xCnC6MfajLouXUFl2aVXUPvftQVf2eS5DgydPZHF_c,4170
90
91
  atomicshop/file_io/tomls.py,sha256=oa0Wm8yMkPRXKN9jgBuTnKbioSOee4mABW5IMUFCYyU,3041
@@ -94,7 +95,7 @@ atomicshop/mitm/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
94
95
  atomicshop/mitm/connection_thread_worker.py,sha256=7f7T3t6ltndzb3125DgyRTzsD-oAbAfewDIhpNEeHRY,20630
95
96
  atomicshop/mitm/import_config.py,sha256=BPZ62ozMUaUKn7Crt6dhzvUgD3dSKd17kMfbJNObvlI,7486
96
97
  atomicshop/mitm/initialize_engines.py,sha256=qCtIjaR-sCbcliKKX_I65O6e4fqc-zDHELGglnL92cw,7687
97
- atomicshop/mitm/initialize_mitm_server.py,sha256=jM2djtClin-4Z7B6uq1D-XddmPZQT2Iu2_nn4EuT3iI,11307
98
+ atomicshop/mitm/initialize_mitm_server.py,sha256=8Rwq4OzA4VKpzWNhxn8-CkCY_UdPIK64J4UrtD7oE3M,11230
98
99
  atomicshop/mitm/message.py,sha256=u2U2f2SOHdBNU-6r1Ik2W14ai2EOwxUV4wVfGZA098k,1732
99
100
  atomicshop/mitm/shared_functions.py,sha256=NeHABBlY-tmQRooWGVl2jZQx1wSTKJtEqG7mMvF2Jqo,4268
100
101
  atomicshop/mitm/statistic_analyzer.py,sha256=1g5l6X-NbnHvh_TREJRumTDWgE4ixUNJ8pKGneKcf4Y,23524
@@ -162,8 +163,8 @@ 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=30uaJOJhPJExYptEmwc5HWScI2RbnDlNgybOsxW7klc,11609
166
- atomicshop/wrappers/loggingw/reading.py,sha256=cHco0EG8bEB6fJ7JxkFdV_d8J-voYRBCUzS-qVqv4aU,3697
166
+ atomicshop/wrappers/loggingw/loggingw.py,sha256=v9WAseZXB50LluT9rIUcRvvevg2nLVKPgz3dbGejfV0,12151
167
+ atomicshop/wrappers/loggingw/reading.py,sha256=xs7L6Jo-vedrhCVP7m-cJo0VhWmoSoK86avR4Tm0kG4,3675
167
168
  atomicshop/wrappers/playwrightw/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
168
169
  atomicshop/wrappers/playwrightw/_tryouts.py,sha256=l1BLkFsiIMNlgv7nfZd1XGEvXQkIQkIcg48__9OaC00,4920
169
170
  atomicshop/wrappers/playwrightw/base.py,sha256=zwHfbFZV7qqpmReJg5lEpKtOO23DRxEd61ZdoLBU_9Q,9833
@@ -188,12 +189,12 @@ atomicshop/wrappers/socketw/receiver.py,sha256=m8hXKOa8dqEQGUdcbYjshH8-j0CsMGRkg
188
189
  atomicshop/wrappers/socketw/sender.py,sha256=hHpBLc0LCfOIUErq2mc0ATfp0tDDQ5XhcYT4hRAZARU,3680
189
190
  atomicshop/wrappers/socketw/sni.py,sha256=GIm5uUJCh5i-pjY4FhSkoK4oo9uL_fFq1Mbr6PKXpBg,10014
190
191
  atomicshop/wrappers/socketw/socket_client.py,sha256=X3Bo83EVZwDwrSIji7UOT9UGYutn-pfBTQcls_Jd7N8,20235
191
- atomicshop/wrappers/socketw/socket_server_tester.py,sha256=VfNthyBvgI5tL9v3Qprh4CcRP0sqKnif-a7f0gev4lY,6335
192
+ atomicshop/wrappers/socketw/socket_server_tester.py,sha256=AhpurHJmP2kgzHaUbq5eyTx0UGBOJi74viowtpU5Jvs,6291
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.5.16.dist-info/LICENSE.txt,sha256=lLU7EYycfYcK2NR_1gfnhnRC8b8ccOTElACYplgZN88,1094
196
- atomicshop-2.5.16.dist-info/METADATA,sha256=02N26vDhqG2L4xhGjWCiug9P7OXAs6WlvUbzN9q6h7k,10268
197
- atomicshop-2.5.16.dist-info/WHEEL,sha256=Xo9-1PvkuimrydujYJAjF7pCkriuXBpUPEjma1nZyJ0,92
198
- atomicshop-2.5.16.dist-info/top_level.txt,sha256=EgKJB-7xcrAPeqTRF2laD_Np2gNGYkJkd4OyXqpJphA,11
199
- atomicshop-2.5.16.dist-info/RECORD,,
196
+ atomicshop-2.6.1.dist-info/LICENSE.txt,sha256=lLU7EYycfYcK2NR_1gfnhnRC8b8ccOTElACYplgZN88,1094
197
+ atomicshop-2.6.1.dist-info/METADATA,sha256=-WYBRbrqQqP3mICJe8ZuRix8y3SMBURo6A7wAD7Dbc4,10267
198
+ atomicshop-2.6.1.dist-info/WHEEL,sha256=oiQVh_5PnQM0E3gPdiz09WCNmwiHDMaGer_elqB3coM,92
199
+ atomicshop-2.6.1.dist-info/top_level.txt,sha256=EgKJB-7xcrAPeqTRF2laD_Np2gNGYkJkd4OyXqpJphA,11
200
+ atomicshop-2.6.1.dist-info/RECORD,,
@@ -1,5 +1,5 @@
1
1
  Wheel-Version: 1.0
2
- Generator: bdist_wheel (0.41.3)
2
+ Generator: bdist_wheel (0.42.0)
3
3
  Root-Is-Purelib: true
4
4
  Tag: py3-none-any
5
5