atomicshop 2.16.30__py3-none-any.whl → 2.16.32__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.

@@ -118,51 +118,12 @@ class SystemResourceMonitor:
118
118
  :return:
119
119
  """
120
120
 
121
- def run_check_system_resources(
122
- interval, get_cpu, get_memory, get_disk_io_bytes, get_disk_files_count, get_disk_busy_time,
123
- get_disk_used_percent, calculate_maximum_changed_disk_io, maximum_disk_io, queue_list, manager_dict):
124
- """
125
- Continuously update the system resources in the shared results dictionary.
126
- This function runs in a separate process.
127
- """
128
-
129
- while self.running:
130
- # Get the results of the system resources check function and store them in
131
- # temporary results' dictionary.
132
- results = system_resources.check_system_resources(
133
- interval=interval, get_cpu=get_cpu, get_memory=get_memory,
134
- get_disk_io_bytes=get_disk_io_bytes, get_disk_files_count=get_disk_files_count,
135
- get_disk_busy_time=get_disk_busy_time, get_disk_used_percent=get_disk_used_percent)
136
-
137
- if calculate_maximum_changed_disk_io:
138
- if results['disk_io_read'] > maximum_disk_io['read_bytes_per_sec']:
139
- maximum_disk_io['read_bytes_per_sec'] = results['disk_io_read']
140
- if results['disk_io_write'] > maximum_disk_io['write_bytes_per_sec']:
141
- maximum_disk_io['write_bytes_per_sec'] = results['disk_io_write']
142
- if results['disk_files_count_read'] > maximum_disk_io['read_files_count_per_sec']:
143
- maximum_disk_io['read_files_count_per_sec'] = results['disk_files_count_read']
144
- if results['disk_files_count_write'] > maximum_disk_io['write_files_count_per_sec']:
145
- maximum_disk_io['write_files_count_per_sec'] = results['disk_files_count_write']
146
- results['maximum_disk_io'] = maximum_disk_io
147
-
148
- if queue_list is not None:
149
- for queue in queue_list:
150
- queue.put(results)
151
-
152
- # Update the shared results dictionary with the temporary results' dictionary.
153
- # This is done in separate steps to avoid overwriting the special 'multiprocessing.Manager.dict' object.
154
- # So we update the shared results dictionary with the temporary results' dictionary.
155
- if manager_dict is not None:
156
- manager_dict.update(results)
157
-
158
- self.results = results
159
-
160
121
  if print_kwargs is None:
161
122
  print_kwargs = {}
162
123
 
163
124
  if self.thread is None:
164
125
  self.running = True
165
- self.thread = threading.Thread(target=run_check_system_resources, args=(
126
+ self.thread = threading.Thread(target=self.run_check_system_resources, args=(
166
127
  self.interval, self.get_cpu, self.get_memory, self.get_disk_io_bytes, self.get_disk_files_count,
167
128
  self.get_disk_busy_time, self.get_disk_used_percent, self.calculate_maximum_changed_disk_io,
168
129
  self.maximum_disk_io, self.queue_list, self.manager_dict))
@@ -171,6 +132,46 @@ class SystemResourceMonitor:
171
132
  else:
172
133
  print_api.print_api("Monitoring is already running.", color='yellow', **print_kwargs)
173
134
 
135
+ def run_check_system_resources(
136
+ self,
137
+ interval, get_cpu, get_memory, get_disk_io_bytes, get_disk_files_count, get_disk_busy_time,
138
+ get_disk_used_percent, calculate_maximum_changed_disk_io, maximum_disk_io, queue_list, manager_dict):
139
+ """
140
+ Continuously update the system resources in the shared results dictionary.
141
+ This function runs in a separate process.
142
+ """
143
+
144
+ while self.running:
145
+ # Get the results of the system resources check function and store them in
146
+ # temporary results' dictionary.
147
+ results = system_resources.check_system_resources(
148
+ interval=interval, get_cpu=get_cpu, get_memory=get_memory,
149
+ get_disk_io_bytes=get_disk_io_bytes, get_disk_files_count=get_disk_files_count,
150
+ get_disk_busy_time=get_disk_busy_time, get_disk_used_percent=get_disk_used_percent)
151
+
152
+ if calculate_maximum_changed_disk_io:
153
+ if results['disk_io_read'] > maximum_disk_io['read_bytes_per_sec']:
154
+ maximum_disk_io['read_bytes_per_sec'] = results['disk_io_read']
155
+ if results['disk_io_write'] > maximum_disk_io['write_bytes_per_sec']:
156
+ maximum_disk_io['write_bytes_per_sec'] = results['disk_io_write']
157
+ if results['disk_files_count_read'] > maximum_disk_io['read_files_count_per_sec']:
158
+ maximum_disk_io['read_files_count_per_sec'] = results['disk_files_count_read']
159
+ if results['disk_files_count_write'] > maximum_disk_io['write_files_count_per_sec']:
160
+ maximum_disk_io['write_files_count_per_sec'] = results['disk_files_count_write']
161
+ results['maximum_disk_io'] = maximum_disk_io
162
+
163
+ if queue_list is not None:
164
+ for queue in queue_list:
165
+ queue.put(results)
166
+
167
+ # Update the shared results dictionary with the temporary results' dictionary.
168
+ # This is done in separate steps to avoid overwriting the special 'multiprocessing.Manager.dict' object.
169
+ # So we update the shared results dictionary with the temporary results' dictionary.
170
+ if manager_dict is not None:
171
+ manager_dict.update(results)
172
+
173
+ self.results = results
174
+
174
175
  def get_results(self) -> dict:
175
176
  """
176
177
  Retrieve the latest results.
@@ -0,0 +1,39 @@
1
+ import ctypes
2
+
3
+
4
+ class NotWindowsConsoleError(Exception):
5
+ pass
6
+
7
+
8
+ # Define QuickEdit mode bit (0x0040)
9
+ ENABLE_QUICK_EDIT = 0x0040
10
+
11
+
12
+ def disable_quick_edit():
13
+ """
14
+ Disables QuickEdit mode in the Windows Command Prompt.
15
+ This prevents the console from being paused when the user selects text.
16
+ NO ADMIN REQUIRED
17
+ """
18
+
19
+ kernel32 = ctypes.windll.kernel32
20
+ h_stdin = kernel32.GetStdHandle(-10) # -10 is STD_INPUT_HANDLE
21
+
22
+ # Get current console mode
23
+ mode = ctypes.c_uint()
24
+ if kernel32.GetConsoleMode(h_stdin, ctypes.byref(mode)) == 0:
25
+ try:
26
+ raise ctypes.WinError()
27
+ except OSError as e:
28
+ # This means that the code is not running in console window.
29
+ if e.errno == 9 and e.winerror == 6:
30
+ raise NotWindowsConsoleError("This code is not running in a Windows console.")
31
+ else:
32
+ raise e
33
+
34
+ # Disable QuickEdit Mode by clearing the corresponding bit
35
+ mode.value &= ~ENABLE_QUICK_EDIT
36
+
37
+ # Set the new console mode
38
+ if kernel32.SetConsoleMode(h_stdin, mode) == 0:
39
+ raise ctypes.WinError()
@@ -8,7 +8,7 @@ import threading
8
8
  from . import loggers, handlers
9
9
  from ...file_io import csvs
10
10
  from ...basics import tracebacks, ansi_escape_codes
11
- from ...import print_api
11
+ from ... import print_api
12
12
 
13
13
 
14
14
  class LoggingwLoggerAlreadyExistsError(Exception):
@@ -13,6 +13,7 @@ def get_logs_paths(
13
13
  date_format: str = None,
14
14
  latest_only: bool = False,
15
15
  previous_day_only: bool = False,
16
+ yesterday_only: bool = False,
16
17
  specific_date: str = None
17
18
  ) -> list[filesystem.AtomicPath]:
18
19
  """
@@ -37,24 +38,37 @@ def get_logs_paths(
37
38
  date_format = '%Y-%m-%d'
38
39
  :param latest_only: Boolean, if True, only the latest log file path will be returned.
39
40
  :param previous_day_only: Boolean, if True, only the log file path from the previous day will be returned.
41
+ :param yesterday_only: Boolean, if True, only the log file path from yesterday will be returned.
42
+ There's a difference between 'previous_day_only' and 'yesterday_only'.
43
+ 'previous_day_only' will get the log file from the previous day in the list of files that were found.
44
+ Since that doesn't guarantee that the log file from the previous day is yesterday, we have 'yesterday_only'.
40
45
  :param specific_date: Specific date to get the log file path.
41
46
  If specified, the function will get the log file by the specific date.
42
47
  Meaning that 'date_format' must be specified.
43
-
44
48
  """
45
49
 
46
- if latest_only or previous_day_only or specific_date:
47
- booleans.check_3_booleans_when_only_1_can_be_true(
48
- (latest_only, 'latest_only'),
49
- (previous_day_only, 'previous_day_only'),
50
- (specific_date, 'specific_date'))
50
+ booleans.is_only_1_true_in_list(
51
+ booleans_list_of_tuples=[
52
+ (latest_only, 'latest_only'),
53
+ (previous_day_only, 'previous_day_only'),
54
+ (yesterday_only, 'yesterday_only'),
55
+ (specific_date, 'specific_date'),
56
+ ],
57
+ raise_if_all_false=False
58
+ )
51
59
 
52
60
  if not date_format and specific_date:
53
61
  raise ValueError('If "specific_date" is specified, "date_format" must be specified.')
54
62
 
55
63
  # Get the file_name_pattern from the file name. Build the file_name_pattern.
64
+ # For some reason if the file name will be '.zip', then the file stem will be '.zip' and the extension will be ''.
56
65
  log_file_name: str = Path(log_file_path).stem
57
66
  log_file_extension: str = Path(log_file_path).suffix
67
+
68
+ if not log_file_extension and '.' in log_file_name:
69
+ log_file_name, log_file_extension = log_file_name.rsplit('.')
70
+ log_file_extension = f'.{log_file_extension}'
71
+
58
72
  file_name_pattern: str = f'{log_file_name}*{log_file_extension}'
59
73
 
60
74
  # Get the directory path from the file path.
@@ -111,15 +125,18 @@ def get_logs_paths(
111
125
  if logs_files:
112
126
  if latest_only:
113
127
  logs_files = [logs_files[-1]]
114
-
115
- if previous_day_only:
116
- # Check if there is a previous day log file.
128
+ elif previous_day_only:
117
129
  if len(logs_files) == 1:
118
130
  logs_files = []
119
131
  else:
120
132
  logs_files = [logs_files[-2]]
121
-
122
- if specific_date:
133
+ elif yesterday_only:
134
+ # Get yesterday's date.
135
+ yesterday_date_string = (datetime.datetime.now() - datetime.timedelta(days=1)).strftime(date_format)
136
+ # Check if there is a yesterday log file.
137
+ logs_files = [single_file
138
+ for single_file in logs_files if single_file.datetime_string == yesterday_date_string]
139
+ elif specific_date:
123
140
  # Check if there is a specific date log file.
124
141
  logs_files = [single_file for single_file in logs_files if single_file.datetime_string == specific_date]
125
142
 
@@ -394,9 +394,14 @@ def find(
394
394
  query: dict = None,
395
395
  page: int = None,
396
396
  items: int = None,
397
- sorting: dict[str, Literal[
398
- 'asc', 'desc',
399
- 1, -1]] = None,
397
+ sorting: Union[
398
+ dict[str, Literal[
399
+ 'asc', 'desc',
400
+ 'ASC', 'DESC',
401
+ 1, -1]],
402
+ list[tuple[
403
+ str, Literal[1, -1]]],
404
+ None] = None,
400
405
  convert_object_id_to_str: bool = False,
401
406
  key_convert_to_dict: list[str] = None,
402
407
  mongo_client: pymongo.MongoClient = None,
@@ -445,29 +450,40 @@ def find(
445
450
  $nin: Will search for a value not in a list of values.
446
451
  Example for searching for a value that is not in a list of values:
447
452
  query = {'field_name': {'$nin': ['value1', 'value2', 'value3']}}
448
-
453
+ $exists: Will search for entries where the field exists or not.
454
+ Example for searching for entries where the field exists:
455
+ query = {'field_name': {'$exists': True}}
456
+ Example for searching for entries where the field does not exist:
457
+ query = {'field_name': {'$exists': False}}
458
+ $ne: Will search for entries where the field is not equal to the value.
459
+ Example for searching for entries where the field is not equal to the value:
460
+ query = {'field_name': {'$ne': 'value'}}
449
461
 
450
462
  :param page: int, the page number (Optional).
451
463
  :param items: int, the number of results per page (Optional).
452
- :param sorting: dict, the name of the field and the order to sort the containers by.
453
- You can use several fields to sort the containers by several fields.
454
- In this case the containers will be sorted by the first field, then by the second field, etc.
455
- You can also use only singular field to sort the containers by only one field.
456
- Usage:
457
- {
458
- field_name: order
459
- }
460
- Example:
461
- {
462
- 'vendor': 'asc',
463
- 'model': 'desc'
464
- }
464
+ :param sorting: dict or list of tuples:
465
+ dict, the name of the field and the order to sort the containers by.
466
+ You can use several fields to sort the containers by several fields.
467
+ In this case the containers will be sorted by the first field, then by the second field, etc.
468
+ You can also use only singular field to sort the containers by only one field.
469
+ Usage:
470
+ {
471
+ field_name: order
472
+ }
473
+ Example:
474
+ {
475
+ 'vendor': 'asc',
476
+ 'model': 'desc'
477
+ }
465
478
 
466
- Or example using integers:
467
- {
468
- 'vendor': 1,
469
- 'model': -1
470
- }
479
+ Or example using integers:
480
+ {
481
+ 'vendor': 1,
482
+ 'model': -1
483
+ }
484
+
485
+ list of tuples, each tuple will contain [0] string of the field name and [1] the integer value of the order
486
+ to sort by, this is pymongo default, 1 for ascending and -1 for descending.
471
487
  :param convert_object_id_to_str: bool, if True, the '_id' field will be converted to a string.
472
488
  The '_id' field is an ObjectId type, which is a complex object, it can be converted to a string for simpler
473
489
  processing.
@@ -486,9 +502,9 @@ def find(
486
502
  elif items and not page:
487
503
  page = 1
488
504
 
489
- if sorting:
505
+ if sorting and isinstance(sorting, dict):
490
506
  for key_to_sort_by, order in sorting.items():
491
- if order not in ['asc', 'desc', 1, -1]:
507
+ if order.lower() not in ['asc', 'desc', 1, -1]:
492
508
  raise ValueError("The order must be 'asc', 'desc', 1 or -1.")
493
509
 
494
510
  if not mongo_client:
@@ -510,13 +526,16 @@ def find(
510
526
 
511
527
  if sorting:
512
528
  sorting_list_of_tuples: list[tuple[str, int]] = []
513
- for key_to_sort_by, order in sorting.items():
514
- if order == 'asc':
515
- order = pymongo.ASCENDING
516
- elif order == 'desc':
517
- order = pymongo.DESCENDING
518
-
519
- sorting_list_of_tuples.append((key_to_sort_by, order))
529
+ if isinstance(sorting, dict):
530
+ for key_to_sort_by, order in sorting.items():
531
+ if order.lower() == 'asc':
532
+ order = pymongo.ASCENDING
533
+ elif order.lower() == 'desc':
534
+ order = pymongo.DESCENDING
535
+
536
+ sorting_list_of_tuples.append((key_to_sort_by, order))
537
+ elif sorting and isinstance(sorting, list):
538
+ sorting_list_of_tuples = sorting
520
539
 
521
540
  collection_items = collection_items.sort(sorting_list_of_tuples)
522
541
 
@@ -84,10 +84,13 @@ def install_nodejs_ubuntu(
84
84
  :return:
85
85
  """
86
86
 
87
- booleans.check_3_booleans_when_only_1_can_be_true(
88
- (install_latest_version, 'install_latest_version'),
89
- (install_lts, 'install_lts'),
90
- (install_by_version_number, 'install_by_version_number')
87
+ booleans.is_only_1_true_in_list(
88
+ booleans_list_of_tuples=[
89
+ (install_latest_version, 'install_latest_version'),
90
+ (install_lts, 'install_lts'),
91
+ (install_by_version_number, 'install_by_version_number')
92
+ ],
93
+ raise_if_all_false=True
91
94
  )
92
95
 
93
96
  # Check if Node.js is already installed.
@@ -261,11 +261,14 @@ class DnsServer:
261
261
 
262
262
  def test_config(self):
263
263
  try:
264
- booleans.check_3_booleans_when_only_1_can_be_true(
265
- (self.resolve_to_tcp_server_only_tcp_resolve_domains,
266
- 'resolve_to_tcp_server_only_tcp_resolve_domains'),
267
- (self.resolve_to_tcp_server_all_domains, 'resolve_to_tcp_server_all_domains'),
268
- (self.resolve_regular, 'resolve_regular')
264
+ booleans.is_only_1_true_in_list(
265
+ booleans_list_of_tuples=[
266
+ (self.resolve_to_tcp_server_only_tcp_resolve_domains,
267
+ 'resolve_to_tcp_server_only_tcp_resolve_domains'),
268
+ (self.resolve_to_tcp_server_all_domains, 'resolve_to_tcp_server_all_domains'),
269
+ (self.resolve_regular, 'resolve_regular')
270
+ ],
271
+ raise_if_all_false=True
269
272
  )
270
273
  except ValueError as e:
271
274
  raise DnsConfigurationValuesError(e)
@@ -68,39 +68,32 @@ class Sender:
68
68
 
69
69
  # At this point the sending loop finished successfully
70
70
  self.logger.info(f"Sent the message to destination.")
71
- except ConnectionResetError as e:
72
- destination_address, destination_port = base.get_destination_address_from_socket(self.ssl_socket)
73
- if self.ssl_socket.server_hostname:
74
- destination_address = self.ssl_socket.server_hostname
75
- destination: str = f'{destination_address}:{destination_port}'
76
-
77
- error_class_type = str(type(e)).replace("<class '", '').replace("'>", '')
78
- exception_error = tracebacks.get_as_string(one_line=True)
79
- error_message = (f"Socket Send: {destination}: Error, Couldn't reach the server - Connection was reset | "
80
- f"{error_class_type}: {exception_error}")
81
- except (ssl.SSLEOFError, ssl.SSLZeroReturnError, ssl.SSLWantWriteError, TimeoutError) as e:
82
- destination_address, destination_port = base.get_destination_address_from_socket(self.ssl_socket)
83
- if self.ssl_socket.server_hostname:
84
- destination_address = self.ssl_socket.server_hostname
85
- destination: str = f'{destination_address}:{destination_port}'
86
-
87
- error_class_type = str(type(e)).replace("<class '", '').replace("'>", '')
88
- exception_error = tracebacks.get_as_string(one_line=True)
89
- error_message = f"Socket Send: {destination}: {error_class_type}: {exception_error}"
90
71
  except Exception as e:
91
- destination_address, destination_port = base.get_destination_address_from_socket(self.ssl_socket)
72
+ source_tuple, destination_tuple = base.get_source_destination(self.ssl_socket)
73
+ source_address, source_port = source_tuple
74
+ destination_address, destination_port = destination_tuple
92
75
  if self.ssl_socket.server_hostname:
93
76
  destination_address = self.ssl_socket.server_hostname
94
- destination: str = f'{destination_address}:{destination_port}'
77
+ destination: str = f'[{source_address}:{source_port}<->{destination_address}:{destination_port}]'
95
78
 
96
79
  error_class_type = str(type(e)).replace("<class '", '').replace("'>", '')
97
80
  exception_error = tracebacks.get_as_string(one_line=True)
81
+
98
82
  if 'ssl' in error_class_type.lower():
99
- error_message = (f"Socket Send: {destination}: "
100
- f"SSL UNDOCUMENTED Exception: {error_class_type}{exception_error}")
83
+ if error_class_type in ['ssl.SSLEOFError', 'ssl.SSLZeroReturnError', 'ssl.SSLWantWriteError']:
84
+ error_message = f"Socket Send: {destination}: {error_class_type}: {exception_error}"
85
+ else:
86
+ error_message = (f"Socket Send: {destination}: "
87
+ f"SSL UNDOCUMENTED Exception: {error_class_type}{exception_error}")
101
88
  else:
102
- error_message = (f"Socket Send: {destination}: "
103
- f"Error, UNDOCUMENTED Exception: {error_class_type}{exception_error}")
89
+ if error_class_type == 'ConnectionResetError':
90
+ error_message = (f"Socket Send: {destination}: "
91
+ f"Error, Couldn't reach the server - Connection was reset | "
92
+ f"{error_class_type}: {exception_error}")
93
+ elif error_class_type in ['TimeoutError']:
94
+ error_message = f"Socket Send: {destination}: {error_class_type}: {exception_error}"
95
+ else:
96
+ raise e
104
97
 
105
98
  if error_message:
106
99
  print_api(error_message, logger=self.logger, logger_method='error')
@@ -263,11 +263,15 @@ class SocketWrapper:
263
263
  raise SocketWrapperConfigurationValuesError(message)
264
264
 
265
265
  try:
266
- booleans.check_3_booleans_when_only_1_can_be_true(
267
- (self.default_server_certificate_usage, 'default_server_certificate_usage'),
268
- (self.sni_create_server_certificate_for_each_domain,
269
- 'sni_create_server_certificate_for_each_domain'),
270
- (self.custom_server_certificate_usage, 'custom_server_certificate_usage'))
266
+ booleans.is_only_1_true_in_list(
267
+ booleans_list_of_tuples=[
268
+ (self.default_server_certificate_usage, 'default_server_certificate_usage'),
269
+ (self.sni_create_server_certificate_for_each_domain,
270
+ 'sni_create_server_certificate_for_each_domain'),
271
+ (self.custom_server_certificate_usage, 'custom_server_certificate_usage')
272
+ ],
273
+ raise_if_all_false=True
274
+ )
271
275
  except ValueError as e:
272
276
  raise SocketWrapperConfigurationValuesError(str(e))
273
277
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: atomicshop
3
- Version: 2.16.30
3
+ Version: 2.16.32
4
4
  Summary: Atomic functions and classes to make developer life easier
5
5
  Author: Denis Kras
6
6
  License: MIT License
@@ -1,11 +1,11 @@
1
- atomicshop/__init__.py,sha256=ZRwxdpiCNZUwHXRtBUzWN6sTrKE1qIh258JoD4OfSDc,124
1
+ atomicshop/__init__.py,sha256=CTcwR9Fze6eeaSRpctGxH5Awdz0-la2J3f5qJFeP0jA,124
2
2
  atomicshop/_basics_temp.py,sha256=6cu2dd6r2dLrd1BRNcVDKTHlsHs_26Gpw8QS6v32lQ0,3699
3
3
  atomicshop/_create_pdf_demo.py,sha256=Yi-PGZuMg0RKvQmLqVeLIZYadqEZwUm-4A9JxBl_vYA,3713
4
4
  atomicshop/_patch_import.py,sha256=ENp55sKVJ0e6-4lBvZnpz9PQCt3Otbur7F6aXDlyje4,6334
5
5
  atomicshop/appointment_management.py,sha256=BsYH_PClTGLVazcuNjt30--hpXKYjSmHp1R1iQbM4Hc,7330
6
6
  atomicshop/certificates.py,sha256=MEGj7t3Nt2CHE7yzXrvFTLCOKZG9tJ6Ok5JC2BsFRis,7603
7
7
  atomicshop/command_line_processing.py,sha256=u5yT9Ger_cu7ni5ID0VFlRbVD46ARHeNC9tRM-_YXrQ,1038
8
- atomicshop/config_init.py,sha256=BSxc2FhytQPv06g5z9wbAXuA6oYCAsAJLxu_mTExhwI,2491
8
+ atomicshop/config_init.py,sha256=50kD2lXP8sgwPekcmAbfADcY46YvXkF-6XIdA7W_638,2501
9
9
  atomicshop/console_output.py,sha256=AOSJjrRryE97PAGtgDL03IBtWSi02aNol8noDnW3k6M,4667
10
10
  atomicshop/console_user_response.py,sha256=31HIy9QGXa7f-GVR8MzJauQ79E_ZqAeagF3Ks4GGdDU,3234
11
11
  atomicshop/datetimes.py,sha256=IQZ66lmta-ZqxYbyHzm_9eugbJFSilXK1e0kfMgoXGg,18371
@@ -25,7 +25,7 @@ atomicshop/ip_addresses.py,sha256=Hvi4TumEFoTEpKWaq5WNF-YzcRzt24IxmNgv-Mgax1s,11
25
25
  atomicshop/keyboard_press.py,sha256=1W5kRtOB75fulVx-uF2yarBhW0_IzdI1k73AnvXstk0,452
26
26
  atomicshop/on_exit.py,sha256=Rpg2SaF0aginuO7JYwA49YJYnS8F6K2jUqhjH65WzuU,6889
27
27
  atomicshop/pbtkmultifile_argparse.py,sha256=aEk8nhvoQVu-xyfZosK3ma17CwIgOjzO1erXXdjwtS4,4574
28
- atomicshop/print_api.py,sha256=OT4C7wsCDB3ZvXPWNTwWCIjDF6lRxlYQVINKNa7Oi1s,11254
28
+ atomicshop/print_api.py,sha256=REkd1W3--g1Av4_nH3M2CvQCIEDecfsT7spMXgIRUJE,11158
29
29
  atomicshop/process.py,sha256=PeLvyixXaCfftdUF3oMbohI1L4MdLtvQVDx2V1Tz_Rk,16662
30
30
  atomicshop/python_file_patcher.py,sha256=-uhbUX-um5k-If_XXuOfCr8wMzZ3QE6h9N8xGWw6W_o,5486
31
31
  atomicshop/python_functions.py,sha256=zJg4ogUwECxrDD7xdDN5JikIUctITM5lsyabr_ZNsRw,4435
@@ -37,7 +37,7 @@ atomicshop/sound.py,sha256=tHiQQbFBk7EYN3pAfGNcxfF9oNsoYnZgu9z9iq8hxQE,24352
37
37
  atomicshop/speech_recognize.py,sha256=55-dIjgkpF93mvJnJuxSFuft5H5eRvGNlUj9BeIOZxk,5903
38
38
  atomicshop/ssh_remote.py,sha256=Mxixqs2-xGy1bhbcP0LKqjxKTNPz1Gmzz8PzO8aLB4c,17345
39
39
  atomicshop/sys_functions.py,sha256=MTBxRve5bh58SPvhX3gMiGqHlSBuI_rdNN1NnnBBWqI,906
40
- atomicshop/system_resource_monitor.py,sha256=JW3Wo0u109_tfBcjR1yJWAFAURT80cHsZ3hLHwM__vs,13740
40
+ atomicshop/system_resource_monitor.py,sha256=5sM3Ad4IZI8ahpKM3Wu4B0a3TD-N2Y795_kSkIv94lk,13632
41
41
  atomicshop/system_resources.py,sha256=iKUvVSaXR47inmr3cTYsgNfclT38dRia2oupnlhIpK4,9290
42
42
  atomicshop/tempfiles.py,sha256=uq1ve2WlWehZ3NOTXJnpBBMt6HyCdBufqedF0HyzA6k,2517
43
43
  atomicshop/timer.py,sha256=7Zw1KRV0acHCRATMnanyX2MLBb63Hc-6us3rCZ9dNlY,2345
@@ -82,7 +82,7 @@ atomicshop/archiver/zips.py,sha256=0Z_1MWs7YRiCBVpyaG8llnzRguHSO4R51KDMN3FJZt8,1
82
82
  atomicshop/basics/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
83
83
  atomicshop/basics/ansi_escape_codes.py,sha256=WtIkm-BjSZS5J5irDUdAMBNvdX-qXFZcTX98jcBMpJE,3140
84
84
  atomicshop/basics/argparse_template.py,sha256=horwgSf3MX1ZgRnYxtmmQuz9OU_vKrKggF65gmjlmfg,5836
85
- atomicshop/basics/booleans.py,sha256=QM0pibMmEKRKtBlpW9M5hkfD4S4rzirde0f8TSTnScE,2198
85
+ atomicshop/basics/booleans.py,sha256=V36NaMf8AffhCom_ovQeOZlYcdtGyIcQwWKki6h7O0M,1745
86
86
  atomicshop/basics/bytes_arrays.py,sha256=WvSRDhIGt1ywF95t-yNgpxLm1nlZUbM1Dz6QckcyE8Y,5915
87
87
  atomicshop/basics/classes.py,sha256=T0Bm13hKvkXG3med68ptL7XuoWiCi3TE-K5TMINDlrY,10655
88
88
  atomicshop/basics/dicts.py,sha256=DeYHIh940pMMBrFhpXt4dsigFVYzTrlqWymNo4Pq_Js,14049
@@ -114,9 +114,9 @@ atomicshop/etws/traces/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3
114
114
  atomicshop/etws/traces/trace_dns.py,sha256=WvOZm7KNdP4r6ofkZhUGi9WjtYlkV3mUp_yxita3Qg4,6399
115
115
  atomicshop/etws/traces/trace_sysmon_process_creation.py,sha256=OM-bkK38uYMwWLZKNOTDa0Xdk3sO6sqsxoMUIiPvm5g,4656
116
116
  atomicshop/file_io/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
117
- atomicshop/file_io/csvs.py,sha256=XFZ-kvg2nWLXUpFh_FyPwOXB_TYLFRrHpS5hWMblTi8,9353
117
+ atomicshop/file_io/csvs.py,sha256=jBdm3_z5cMyvxLxJnGcybUAptHAbyL0r0tlLqY0sdTQ,9327
118
118
  atomicshop/file_io/docxs.py,sha256=ffJhnmM_WyD8mCoq2dGdpfahdIrGTPy96QVlH5EWjeI,5754
119
- atomicshop/file_io/file_io.py,sha256=hovI_WFn3YixQDAXLulZG8GxW7whog-AC5KeK-03-xI,7164
119
+ atomicshop/file_io/file_io.py,sha256=5Kl0P6vF4GQVdwew1lzHLb-db9qiMvDjTgccbi5P-zk,7167
120
120
  atomicshop/file_io/jsons.py,sha256=q9ZU8slBKnHLrtn3TnbK1qxrRpj5ZvCm6AlsFzoANjo,5303
121
121
  atomicshop/file_io/tomls.py,sha256=ol8EvQPf9sryTmZUf1v55BYSUQ6ml7HVVBHpNKbsIlA,9768
122
122
  atomicshop/file_io/xlsxs.py,sha256=v_dyg9GD4LqgWi6wA1QuWRZ8zG4ZwB6Dz52ytdcmmmI,2184
@@ -125,19 +125,19 @@ atomicshop/mitm/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
125
125
  atomicshop/mitm/config_static.py,sha256=ROAtbibSWSsF3BraUbhu-QO3MPIFqYY5KUKgsQbiSkk,7813
126
126
  atomicshop/mitm/config_toml_editor.py,sha256=2p1CMcktWRR_NW-SmyDwylu63ad5e0-w1QPMa8ZLDBw,1635
127
127
  atomicshop/mitm/connection_thread_worker.py,sha256=fybUBcZckgF7TC_P1z2yIYGH6ATX7jQEfsQSBuddt2s,16531
128
- atomicshop/mitm/import_config.py,sha256=_nu8mgA-M4s6dZ8_QWx3x0aVb75upvsCuX_PIUg4X2w,8345
128
+ atomicshop/mitm/import_config.py,sha256=ZKQXxbtjVqzN9fpRrMwPNQREecH06RG8F_nXZAKTUJM,8182
129
129
  atomicshop/mitm/initialize_engines.py,sha256=VyJE8QnzlgD3QbX5inz5o6rC3zQ3is9CeTL7-B10g1w,8292
130
130
  atomicshop/mitm/message.py,sha256=URR5JKSuAT8XmGIkyprEjlPW2GW4ef_gfUz_GgcFseE,2184
131
- atomicshop/mitm/mitm_main.py,sha256=wEW0UAqxnn9kI4oO5zyNtG04Glmi3hR-C-0W6SpxVWY,22446
132
- atomicshop/mitm/recs_files.py,sha256=VjgtJF7vy365mBjctwB2bpDYoLMkEeogzF8kbb01dAk,2977
133
- atomicshop/mitm/shared_functions.py,sha256=jjCDZVQCwQ8hf9QNMe3T8W3ISkfZo4Mm2HtXOJLZYgI,1999
134
- atomicshop/mitm/statistic_analyzer.py,sha256=mBmwEe68WAjnIskGndQTRldnsAsDHuaOW0O7UXlM3Pc,26702
131
+ atomicshop/mitm/mitm_main.py,sha256=ICQS8-4-owDhPUIQohymLShzgCZwgq7jUocZHX1J3Zo,22592
132
+ atomicshop/mitm/recs_files.py,sha256=mMyO1kPB-VkS_pbWCDhZHKdbWzlPbYSout61QuzHOao,3077
133
+ atomicshop/mitm/shared_functions.py,sha256=l6oEyv4ug5D_03V3QLADYoocbcL2Ml_dYVW2WKM21l4,1818
134
+ atomicshop/mitm/statistic_analyzer.py,sha256=5_sAYGX2Xunzo_pS2W5WijNCwr_BlGJbbOO462y_wN4,27533
135
135
  atomicshop/mitm/engines/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
136
136
  atomicshop/mitm/engines/create_module_template.py,sha256=tRjVSm1sD6FzML71Qbuwvita0qsusdFGm8NZLsZ-XMs,4853
137
137
  atomicshop/mitm/engines/create_module_template_example.py,sha256=X5xhvbV6-g9jU_bQVhf_crZmaH50LRWz3bS-faQ18ds,489
138
138
  atomicshop/mitm/engines/__parent/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
139
139
  atomicshop/mitm/engines/__parent/parser___parent.py,sha256=RK2wviepP0oeq7zuLpgkvqvTJtc0r0a7hDGWdV0dGc4,657
140
- atomicshop/mitm/engines/__parent/recorder___parent.py,sha256=xPc_5BGDubPfgNa4z8qBtm8MacDlas_yQNkfNsji46k,4677
140
+ atomicshop/mitm/engines/__parent/recorder___parent.py,sha256=xJ3YVa8XYwcKqCwUIEXf6_UGnCbpRsvoicUNe0WxMfs,3782
141
141
  atomicshop/mitm/engines/__parent/responder___parent.py,sha256=7WQeR3UmMnN74bDwn-0nz2OfhXJ3-ClXpNGUFZ7wJUE,12004
142
142
  atomicshop/mitm/engines/__reference_general/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
143
143
  atomicshop/mitm/engines/__reference_general/parser___reference_general.py,sha256=57MEPZMAjTO6xBDZ-yt6lgGJyqRrP0Do5Gk_cgCiPns,2998
@@ -145,7 +145,7 @@ atomicshop/mitm/engines/__reference_general/recorder___reference_general.py,sha2
145
145
  atomicshop/mitm/engines/__reference_general/responder___reference_general.py,sha256=IUyQYMPeEhIARfALWiKPFeXagSQD6lRzAxUdi4ZIT88,7010
146
146
  atomicshop/mitm/statistic_analyzer_helper/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
147
147
  atomicshop/mitm/statistic_analyzer_helper/analyzer_helper.py,sha256=pk6L1t1ea1kvlBoR9QEJptOmaX-mumhwLsP2GCKukbk,5920
148
- atomicshop/mitm/statistic_analyzer_helper/moving_average_helper.py,sha256=XkJBAKD20j4rBpTWuhRJG3ONDWsktOh3PfOqzVDSORo,17883
148
+ atomicshop/mitm/statistic_analyzer_helper/moving_average_helper.py,sha256=Fw-1lH1NOTinMsJnCbCgMHfdoH5Vav388puKm3DmdEs,19746
149
149
  atomicshop/monitor/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
150
150
  atomicshop/monitor/change_monitor.py,sha256=K5NlVp99XIDDPnQQMdru4BDmua_DtcDIhVAzkTOvD5s,7673
151
151
  atomicshop/monitor/checks/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
@@ -194,6 +194,7 @@ atomicshop/wrappers/certauthw/certauth.py,sha256=hKedW0DOWlEigSNm8wu4SqHkCQsGJ1t
194
194
  atomicshop/wrappers/certauthw/certauthw.py,sha256=4WvhjANI7Kzqrr_nKmtA8Kf7B6rute_5wfP65gwQrjw,8082
195
195
  atomicshop/wrappers/ctyping/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
196
196
  atomicshop/wrappers/ctyping/process_winapi.py,sha256=QcXL-ETtlSSkoT8F7pYle97ubGWsjYp8cx8HxkVMgAc,2762
197
+ atomicshop/wrappers/ctyping/win_console.py,sha256=uTtjkz9rY559AaV0dhyZYUSSEe9cn6Du2DgurdMtX-M,1158
197
198
  atomicshop/wrappers/ctyping/etw_winapi/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
198
199
  atomicshop/wrappers/ctyping/etw_winapi/const.py,sha256=stZHZ7tSiSAs04ikr7uH-Td_yBXxsF-bp2Q0F3K2fsM,9543
199
200
  atomicshop/wrappers/ctyping/etw_winapi/etw_functions.py,sha256=Iwd0wIuoxpjMaaOfZZtT1bPtDTsMO8jjItBE5bvkocM,11546
@@ -249,14 +250,14 @@ atomicshop/wrappers/loggingw/filters.py,sha256=48UVhJHemCS0agXmQP8dHvAHM8r9DFphJ
249
250
  atomicshop/wrappers/loggingw/formatters.py,sha256=ZY12IokVY1G_Wzn2Zlv9qjK-e8CtIK6yUgUfPHvH2BU,5802
250
251
  atomicshop/wrappers/loggingw/handlers.py,sha256=vxaSSnlJGs9NKJvYROKtNjaFTqePdHy0sz-GwN5aNPw,19035
251
252
  atomicshop/wrappers/loggingw/loggers.py,sha256=mmM__XR3W4QC82wbsDRG_M4_0JYGGEP0Qn0WCOSp-go,2910
252
- atomicshop/wrappers/loggingw/loggingw.py,sha256=hHCCNJTCI45vGMoNFqQQip5svqffh4-vJ1AnZ7yeE0M,21329
253
- atomicshop/wrappers/loggingw/reading.py,sha256=ERBSiQbEksySKpXpu2E_6k9dZ6MPH95ZIsmdjWW9MUE,16436
253
+ atomicshop/wrappers/loggingw/loggingw.py,sha256=64r5XZSAwJ5GfkN7JqAvuLFlJRdf79n0jr_FriaaaCw,21330
254
+ atomicshop/wrappers/loggingw/reading.py,sha256=sCNlgqLNH5XdKqOOjjEox7CvViMHzs6h7-hwCnx4NKk,17566
254
255
  atomicshop/wrappers/mongodbw/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
255
256
  atomicshop/wrappers/mongodbw/install_mongodb.py,sha256=3ZPqrXxj3lC-PnAKGXclylLuOqsbyXYeUpb5iGjdeUU,6626
256
257
  atomicshop/wrappers/mongodbw/mongo_infra.py,sha256=IjEF0jPzQz866MpTm7rnksnyyWQeUT_B2h2DA9ryAio,2034
257
- atomicshop/wrappers/mongodbw/mongodbw.py,sha256=v_5YYgbgT0F-k2I-hDHQCMPhpry8OonsPclubJk2NG0,31509
258
+ atomicshop/wrappers/mongodbw/mongodbw.py,sha256=oM2pS-M0EI7HhewWY0ri_Ri9U5GOBo0CehPmo4Yas3o,32736
258
259
  atomicshop/wrappers/nodejsw/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
259
- atomicshop/wrappers/nodejsw/install_nodejs.py,sha256=QZg-R2iTQt7kFb8wNtnTmwraSGwvUs34JIasdbNa7ZU,5154
260
+ atomicshop/wrappers/nodejsw/install_nodejs.py,sha256=TKGa3jSlSqZTL2NA0nMkWDFtlkz7rxGGn44ywCg7MN8,5228
260
261
  atomicshop/wrappers/playwrightw/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
261
262
  atomicshop/wrappers/playwrightw/_tryouts.py,sha256=l1BLkFsiIMNlgv7nfZd1XGEvXQkIQkIcg48__9OaC00,4920
262
263
  atomicshop/wrappers/playwrightw/base.py,sha256=WeRpx8otdXuKSr-BjY-uCJTze21kbPpfitoOjKQz5-g,9818
@@ -296,21 +297,21 @@ atomicshop/wrappers/socketw/accepter.py,sha256=hZZKVYlF3LOHQJsSIEKXZUf6QXXWm-Atq
296
297
  atomicshop/wrappers/socketw/base.py,sha256=evoOIxg5Xff3THJnrVX00D5HobaOpDp6_e_gso7TJmA,2191
297
298
  atomicshop/wrappers/socketw/certificator.py,sha256=3CpQKtcW68FSbH6LVSEZTqWBS6Yg_-3K0x4nFkId4UY,12236
298
299
  atomicshop/wrappers/socketw/creator.py,sha256=3_OraDkw2DAWZfoSdY3svCGMOIxpjLEEY7NxWd7M5P4,9873
299
- atomicshop/wrappers/socketw/dns_server.py,sha256=F-t2ZOrMAS0hZ5AaoTsIEbe7jj0tUathp8gs4CTNDqM,48967
300
+ atomicshop/wrappers/socketw/dns_server.py,sha256=VHV6s7vd0zqqW3dhE6li-260YRzmEB5ZUXqYJ9p0vVA,49069
300
301
  atomicshop/wrappers/socketw/exception_wrapper.py,sha256=B-X5SHLSUIWToihH2MKnOB1F4A81_X0DpLLfnYKYbEc,7067
301
302
  atomicshop/wrappers/socketw/get_process.py,sha256=zKEqh98cB9UDLFhtxVpperfXsCjyIMNANHilDD06p0U,6094
302
303
  atomicshop/wrappers/socketw/receiver.py,sha256=XVvWOoeCo3vA0O5p19ryi-hcDIyx382WNG7WzMNVeYk,9322
303
- atomicshop/wrappers/socketw/sender.py,sha256=DIkseEsgrcT3wU-orZ4falPTQPG9tsGt4ASQCnXTG5s,5620
304
+ atomicshop/wrappers/socketw/sender.py,sha256=5HPrgTS2pA1g-jbG1TUtR7drHT1Z_8UevlRCTwW7dgY,5007
304
305
  atomicshop/wrappers/socketw/sni.py,sha256=J1kPnQ77XwKN1pO5aOI1c_VfhuivCm95OOaQxMpPuZ0,17627
305
306
  atomicshop/wrappers/socketw/socket_client.py,sha256=XC-YaqA1wu0rvWQ9Q99DWLxcycKPkPc72pSnflzalfo,20320
306
307
  atomicshop/wrappers/socketw/socket_server_tester.py,sha256=Qobmh4XV8ZxLUaw-eW4ESKAbeSLecCKn2OWFzMhadk0,6420
307
- atomicshop/wrappers/socketw/socket_wrapper.py,sha256=jOIux6eedupRtiEKQeaPSBt7xJbJixpBbK1zNcQUDqU,35451
308
+ atomicshop/wrappers/socketw/socket_wrapper.py,sha256=WtylpezgIIBuz-A6PfM0hO1sm9Exd4j3qhDXcFc74-E,35567
308
309
  atomicshop/wrappers/socketw/ssl_base.py,sha256=kmiif84kMhBr5yjQW17p935sfjR5JKG0LxIwBA4iVvU,2275
309
310
  atomicshop/wrappers/socketw/statistics_csv.py,sha256=w1AH-zf4mBuT4euf28UKij9ihM-b1BRU9Qfby0QDdqI,2957
310
311
  atomicshop/wrappers/winregw/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
311
312
  atomicshop/wrappers/winregw/winreg_network.py,sha256=bQ8Jql8bVGBJ0dt3VQ56lga_1LBOMLI3Km_otvvbU6c,7138
312
- atomicshop-2.16.30.dist-info/LICENSE.txt,sha256=lLU7EYycfYcK2NR_1gfnhnRC8b8ccOTElACYplgZN88,1094
313
- atomicshop-2.16.30.dist-info/METADATA,sha256=TE56Q_3IHpOLBlD1Tp4N45ZpofIIs0cJmWDd9y4o6mQ,10473
314
- atomicshop-2.16.30.dist-info/WHEEL,sha256=GJ7t_kWBFywbagK5eo9IoUwLW6oyOeTKmQ-9iHFVNxQ,92
315
- atomicshop-2.16.30.dist-info/top_level.txt,sha256=EgKJB-7xcrAPeqTRF2laD_Np2gNGYkJkd4OyXqpJphA,11
316
- atomicshop-2.16.30.dist-info/RECORD,,
313
+ atomicshop-2.16.32.dist-info/LICENSE.txt,sha256=lLU7EYycfYcK2NR_1gfnhnRC8b8ccOTElACYplgZN88,1094
314
+ atomicshop-2.16.32.dist-info/METADATA,sha256=9y8KcvM3GJNgsSJQ2aDxHl6YGVSkAV6KWlkAO3t9HTQ,10473
315
+ atomicshop-2.16.32.dist-info/WHEEL,sha256=GJ7t_kWBFywbagK5eo9IoUwLW6oyOeTKmQ-9iHFVNxQ,92
316
+ atomicshop-2.16.32.dist-info/top_level.txt,sha256=EgKJB-7xcrAPeqTRF2laD_Np2gNGYkJkd4OyXqpJphA,11
317
+ atomicshop-2.16.32.dist-info/RECORD,,