atomicshop 2.16.27__py3-none-any.whl → 2.16.29__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/archiver/zips.py +5 -6
- atomicshop/basics/strings.py +2 -2
- atomicshop/dns.py +8 -6
- atomicshop/file_io/file_io.py +7 -7
- atomicshop/filesystem.py +6 -7
- atomicshop/http_parse.py +12 -18
- atomicshop/mitm/connection_thread_worker.py +183 -227
- atomicshop/mitm/engines/__parent/parser___parent.py +1 -4
- atomicshop/mitm/engines/__parent/recorder___parent.py +1 -1
- atomicshop/mitm/message.py +0 -17
- atomicshop/mitm/mitm_main.py +29 -27
- atomicshop/print_api.py +13 -49
- atomicshop/system_resource_monitor.py +8 -8
- atomicshop/system_resources.py +8 -8
- atomicshop/web.py +10 -10
- atomicshop/wrappers/loggingw/filters.py +23 -0
- atomicshop/wrappers/loggingw/formatters.py +12 -0
- atomicshop/wrappers/loggingw/handlers.py +30 -0
- atomicshop/wrappers/loggingw/loggingw.py +135 -8
- atomicshop/wrappers/playwrightw/engine.py +6 -7
- atomicshop/wrappers/playwrightw/waits.py +9 -7
- atomicshop/wrappers/socketw/dns_server.py +1 -1
- atomicshop/wrappers/socketw/sender.py +36 -27
- atomicshop/wrappers/socketw/socket_client.py +6 -5
- atomicshop/wrappers/socketw/socket_wrapper.py +45 -7
- {atomicshop-2.16.27.dist-info → atomicshop-2.16.29.dist-info}/METADATA +1 -1
- {atomicshop-2.16.27.dist-info → atomicshop-2.16.29.dist-info}/RECORD +31 -31
- {atomicshop-2.16.27.dist-info → atomicshop-2.16.29.dist-info}/LICENSE.txt +0 -0
- {atomicshop-2.16.27.dist-info → atomicshop-2.16.29.dist-info}/WHEEL +0 -0
- {atomicshop-2.16.27.dist-info → atomicshop-2.16.29.dist-info}/top_level.txt +0 -0
atomicshop/mitm/mitm_main.py
CHANGED
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import logging
|
|
2
1
|
import threading
|
|
3
2
|
import multiprocessing
|
|
4
3
|
import time
|
|
@@ -6,12 +5,11 @@ import datetime
|
|
|
6
5
|
|
|
7
6
|
import atomicshop # Importing atomicshop package to get the version of the package.
|
|
8
7
|
|
|
9
|
-
from .. import filesystem, queues, dns, on_exit
|
|
8
|
+
from .. import filesystem, queues, dns, on_exit, print_api
|
|
10
9
|
from ..permissions import permissions
|
|
11
10
|
from ..python_functions import get_current_python_version_string, check_python_version_compliance
|
|
12
11
|
from ..wrappers.socketw import socket_wrapper, dns_server, base
|
|
13
12
|
from ..wrappers.loggingw import loggingw
|
|
14
|
-
from ..print_api import print_api
|
|
15
13
|
|
|
16
14
|
from .initialize_engines import ModuleCategory
|
|
17
15
|
from .connection_thread_worker import thread_worker_main
|
|
@@ -33,14 +31,14 @@ MITM_ERROR_LOGGER: loggingw.ExceptionCsvLogger = None
|
|
|
33
31
|
def exit_cleanup():
|
|
34
32
|
if permissions.is_admin():
|
|
35
33
|
is_dns_dynamic, current_dns_gateway = dns.get_default_dns_gateway()
|
|
36
|
-
print_api(f'Current DNS Gateway: {current_dns_gateway}')
|
|
34
|
+
print_api.print_api(f'Current DNS Gateway: {current_dns_gateway}')
|
|
37
35
|
|
|
38
36
|
if is_dns_dynamic != NETWORK_INTERFACE_IS_DYNAMIC or \
|
|
39
37
|
(not is_dns_dynamic and current_dns_gateway != NETWORK_INTERFACE_IPV4_ADDRESS_LIST):
|
|
40
38
|
dns.set_connection_dns_gateway_dynamic(use_default_connection=True)
|
|
41
|
-
print_api("Returned default DNS gateway...", color='blue')
|
|
39
|
+
print_api.print_api("Returned default DNS gateway...", color='blue')
|
|
42
40
|
|
|
43
|
-
print_api(RECS_PROCESS_INSTANCE.is_alive())
|
|
41
|
+
print_api.print_api(RECS_PROCESS_INSTANCE.is_alive())
|
|
44
42
|
RECS_PROCESS_INSTANCE.terminate()
|
|
45
43
|
RECS_PROCESS_INSTANCE.join()
|
|
46
44
|
|
|
@@ -59,7 +57,8 @@ def mitm_server(config_file_path: str):
|
|
|
59
57
|
return result
|
|
60
58
|
|
|
61
59
|
global MITM_ERROR_LOGGER
|
|
62
|
-
MITM_ERROR_LOGGER = loggingw.ExceptionCsvLogger(
|
|
60
|
+
MITM_ERROR_LOGGER = loggingw.ExceptionCsvLogger(
|
|
61
|
+
logger_name=EXCEPTIONS_CSV_LOGGER_NAME, directory_path=config_static.LogRec.logs_path)
|
|
63
62
|
|
|
64
63
|
# Create folders.
|
|
65
64
|
filesystem.create_directory(config_static.LogRec.logs_path)
|
|
@@ -159,70 +158,72 @@ def mitm_server(config_file_path: str):
|
|
|
159
158
|
# === EOF Initialize Reference Module ==========================================================================
|
|
160
159
|
# === Engine logging ===========================================================================================
|
|
161
160
|
# Printing the parsers using "start=1" for index to start counting from "1" and not "0"
|
|
162
|
-
print_api(f"[*] Found Engines:", logger=system_logger)
|
|
161
|
+
print_api.print_api(f"[*] Found Engines:", logger=system_logger)
|
|
163
162
|
for index, engine in enumerate(engines_list, start=1):
|
|
164
163
|
message = f"[*] {index}: {engine.engine_name} | {engine.domain_list}"
|
|
165
|
-
print_api(message, logger=system_logger)
|
|
164
|
+
print_api.print_api(message, logger=system_logger)
|
|
166
165
|
|
|
167
166
|
message = (f"[*] Modules: {engine.parser_class_object.__name__}, "
|
|
168
167
|
f"{engine.responder_class_object.__name__}, "
|
|
169
168
|
f"{engine.recorder_class_object.__name__}")
|
|
170
|
-
print_api(message, logger=system_logger)
|
|
169
|
+
print_api.print_api(message, logger=system_logger)
|
|
171
170
|
|
|
172
171
|
if config_static.DNSServer.enable:
|
|
173
|
-
print_api("DNS Server is enabled.", logger=system_logger)
|
|
172
|
+
print_api.print_api("DNS Server is enabled.", logger=system_logger)
|
|
174
173
|
|
|
175
174
|
# If engines were found and dns is set to route by the engine domains.
|
|
176
175
|
if engines_list and config_static.DNSServer.resolve_to_tcp_server_only_engine_domains:
|
|
177
|
-
print_api(
|
|
176
|
+
print_api.print_api(
|
|
177
|
+
"Engine domains will be routed by the DNS server to Built-in TCP Server.", logger=system_logger)
|
|
178
178
|
# If engines were found, but the dns isn't set to route to engines.
|
|
179
179
|
elif engines_list and not config_static.DNSServer.resolve_to_tcp_server_only_engine_domains:
|
|
180
180
|
message = f"[*] Engine domains found, but the DNS routing is set not to use them for routing."
|
|
181
|
-
print_api(message, color="yellow", logger=system_logger)
|
|
181
|
+
print_api.print_api(message, color="yellow", logger=system_logger)
|
|
182
182
|
elif not engines_list and config_static.DNSServer.resolve_to_tcp_server_only_engine_domains:
|
|
183
183
|
error_message = (
|
|
184
184
|
f"No engines were found in: [{config_static.MainConfig.ENGINES_DIRECTORY_PATH}]\n"
|
|
185
185
|
f"But the DNS routing is set to use them for routing.\n"
|
|
186
186
|
f"Please check your DNS configuration in the 'config.ini' file.")
|
|
187
|
-
print_api(error_message, color="red")
|
|
187
|
+
print_api.print_api(error_message, color="red")
|
|
188
188
|
return 1
|
|
189
189
|
|
|
190
190
|
if config_static.DNSServer.resolve_to_tcp_server_all_domains:
|
|
191
|
-
print_api(
|
|
191
|
+
print_api.print_api(
|
|
192
|
+
"All domains will be routed by the DNS server to Built-in TCP Server.", logger=system_logger)
|
|
192
193
|
|
|
193
194
|
if config_static.DNSServer.resolve_regular:
|
|
194
|
-
print_api(
|
|
195
|
+
print_api.print_api(
|
|
195
196
|
"Regular DNS resolving is enabled. Built-in TCP server will not be routed to",
|
|
196
197
|
logger=system_logger, color="yellow")
|
|
197
198
|
else:
|
|
198
|
-
print_api("DNS Server is disabled.", logger=system_logger, color="yellow")
|
|
199
|
+
print_api.print_api("DNS Server is disabled.", logger=system_logger, color="yellow")
|
|
199
200
|
|
|
200
201
|
if config_static.TCPServer.enable:
|
|
201
|
-
print_api("TCP Server is enabled.", logger=system_logger)
|
|
202
|
+
print_api.print_api("TCP Server is enabled.", logger=system_logger)
|
|
202
203
|
|
|
203
204
|
if engines_list and not config_static.TCPServer.engines_usage:
|
|
204
205
|
message = \
|
|
205
206
|
f"Engines found, but the TCP server is set not to use them for processing. General responses only."
|
|
206
|
-
print_api(message, color="yellow", logger=system_logger)
|
|
207
|
+
print_api.print_api(message, color="yellow", logger=system_logger)
|
|
207
208
|
elif engines_list and config_static.TCPServer.engines_usage:
|
|
208
209
|
message = f"Engines found, and the TCP server is set to use them for processing."
|
|
209
|
-
print_api(message, logger=system_logger)
|
|
210
|
+
print_api.print_api(message, logger=system_logger)
|
|
210
211
|
elif not engines_list and config_static.TCPServer.engines_usage:
|
|
211
212
|
error_message = (
|
|
212
213
|
f"No engines were found in: [{config_static.MainConfig.ENGINES_DIRECTORY_PATH}]\n"
|
|
213
214
|
f"But the TCP server is set to use them for processing.\n"
|
|
214
215
|
f"Please check your TCP configuration in the 'config.ini' file.")
|
|
215
|
-
print_api(error_message, color="red")
|
|
216
|
+
print_api.print_api(error_message, color="red")
|
|
216
217
|
return 1
|
|
217
218
|
else:
|
|
218
|
-
print_api("TCP Server is disabled.", logger=system_logger, color="yellow")
|
|
219
|
+
print_api.print_api("TCP Server is disabled.", logger=system_logger, color="yellow")
|
|
219
220
|
|
|
220
221
|
# === EOF Engine Logging =======================================================================================
|
|
221
222
|
|
|
222
223
|
# Assigning all the engines domains to all time domains, that will be responsible for adding new domains.
|
|
223
224
|
config_static.Certificates.domains_all_times = list(domains_engine_list_full)
|
|
224
225
|
|
|
225
|
-
print_api("Press [Ctrl]+[C] to stop.", color='blue')
|
|
226
|
+
print_api.print_api("Press [Ctrl]+[C] to stop.", color='blue')
|
|
226
227
|
|
|
227
228
|
# Create request domain queue.
|
|
228
229
|
domain_queue = queues.NonBlockQueue()
|
|
@@ -250,7 +251,7 @@ def mitm_server(config_file_path: str):
|
|
|
250
251
|
logger=network_logger
|
|
251
252
|
)
|
|
252
253
|
except (dns_server.DnsPortInUseError, dns_server.DnsConfigurationValuesError) as e:
|
|
253
|
-
print_api(e, error_type=True, color="red", logger=system_logger)
|
|
254
|
+
print_api.print_api(e, error_type=True, color="red", logger=system_logger)
|
|
254
255
|
# Wait for the message to be printed and saved to file.
|
|
255
256
|
time.sleep(1)
|
|
256
257
|
return 1
|
|
@@ -296,6 +297,7 @@ def mitm_server(config_file_path: str):
|
|
|
296
297
|
ssh_pass=config_static.ProcessName.ssh_pass,
|
|
297
298
|
ssh_script_to_execute=config_static.ProcessName.ssh_script_to_execute,
|
|
298
299
|
logger=listener_logger,
|
|
300
|
+
exceptions_logger=MITM_ERROR_LOGGER,
|
|
299
301
|
statistics_logs_directory=config_static.LogRec.logs_path,
|
|
300
302
|
forwarding_dns_service_ipv4_list___only_for_localhost=(
|
|
301
303
|
config_static.TCPServer.forwarding_dns_service_ipv4_list___only_for_localhost),
|
|
@@ -303,12 +305,12 @@ def mitm_server(config_file_path: str):
|
|
|
303
305
|
request_domain_from_dns_server_queue=domain_queue
|
|
304
306
|
)
|
|
305
307
|
except socket_wrapper.SocketWrapperPortInUseError as e:
|
|
306
|
-
print_api(e, error_type=True, color="red", logger=system_logger)
|
|
308
|
+
print_api.print_api(e, error_type=True, color="red", logger=system_logger)
|
|
307
309
|
# Wait for the message to be printed and saved to file.
|
|
308
310
|
time.sleep(1)
|
|
309
311
|
return 1
|
|
310
312
|
except socket_wrapper.SocketWrapperConfigurationValuesError as e:
|
|
311
|
-
print_api(e, error_type=True, color="red", logger=system_logger, logger_method='critical')
|
|
313
|
+
print_api.print_api(e, error_type=True, color="red", logger=system_logger, logger_method='critical')
|
|
312
314
|
# Wait for the message to be printed and saved to file.
|
|
313
315
|
time.sleep(1)
|
|
314
316
|
return 1
|
|
@@ -386,7 +388,7 @@ def mitm_server_main(config_file_path: str):
|
|
|
386
388
|
# Main function should return integer with error code, 0 is successful.
|
|
387
389
|
return mitm_server(config_file_path)
|
|
388
390
|
except KeyboardInterrupt:
|
|
389
|
-
print_api("Server Stopped by [KeyboardInterrupt].", color='blue')
|
|
391
|
+
print_api.print_api("Server Stopped by [KeyboardInterrupt].", color='blue')
|
|
390
392
|
exit_cleanup()
|
|
391
393
|
return 0
|
|
392
394
|
except Exception as e:
|
atomicshop/print_api.py
CHANGED
|
@@ -1,18 +1,18 @@
|
|
|
1
1
|
import sys
|
|
2
2
|
import logging
|
|
3
3
|
|
|
4
|
-
from .basics
|
|
4
|
+
from .basics import ansi_escape_codes
|
|
5
|
+
from .wrappers.loggingw import loggingw
|
|
5
6
|
from .basics import tracebacks
|
|
6
7
|
|
|
7
8
|
|
|
8
|
-
# noinspection PyUnusedLocal,PyIncorrectDocstring
|
|
9
9
|
def print_api(
|
|
10
10
|
message: any,
|
|
11
11
|
color: any = None,
|
|
12
12
|
print_end: str = '\n',
|
|
13
13
|
rtl: bool = False,
|
|
14
14
|
error_type: bool = False,
|
|
15
|
-
logger:
|
|
15
|
+
logger: logging.Logger = None,
|
|
16
16
|
logger_method: str = 'info',
|
|
17
17
|
stdout: bool = True,
|
|
18
18
|
stderr: bool = True,
|
|
@@ -20,8 +20,6 @@ def print_api(
|
|
|
20
20
|
traceback_string: bool = False,
|
|
21
21
|
oneline: bool = False,
|
|
22
22
|
oneline_end: str = '',
|
|
23
|
-
# raise_exception: bool = True,
|
|
24
|
-
# exit_on_error: bool = False,
|
|
25
23
|
**kwargs: object) -> None:
|
|
26
24
|
"""
|
|
27
25
|
Function of custom api that is responsible for printing messages to console.
|
|
@@ -83,10 +81,6 @@ def print_api(
|
|
|
83
81
|
|
|
84
82
|
# This section takes care of different types of string manipulations for message.
|
|
85
83
|
|
|
86
|
-
# If 'exit_on_error' is set to 'True', we'll add 'exit_message' on new line after 'message'.
|
|
87
|
-
# if error_type and exit_on_error and raise_exception:
|
|
88
|
-
# message = message + '\n' + exit_message
|
|
89
|
-
|
|
90
84
|
# If 'rtl' is set to 'True', we'll add Right-To-Left text conversion to 'message'.
|
|
91
85
|
if rtl:
|
|
92
86
|
# Lazy importing of 'bidi' library. It's not a problem since python caches the library after first import.
|
|
@@ -118,22 +112,8 @@ def print_api(
|
|
|
118
112
|
elif logger_method == 'critical' and not color:
|
|
119
113
|
color = 'red'
|
|
120
114
|
|
|
121
|
-
if color
|
|
122
|
-
message = get_colors_basic_dict(color) + message + ColorsBasic.END
|
|
123
|
-
elif color and logger:
|
|
124
|
-
# Save the original formatter
|
|
125
|
-
original_formatter = None
|
|
126
|
-
|
|
127
|
-
# Find the stream handler and change its formatter
|
|
128
|
-
for handler in logger.handlers:
|
|
129
|
-
if isinstance(handler, logging.StreamHandler):
|
|
130
|
-
# Save the original formatter
|
|
131
|
-
original_formatter = handler.formatter
|
|
132
|
-
|
|
133
|
-
# Create a colored formatter for errors
|
|
134
|
-
color_formatter = logging.Formatter(
|
|
135
|
-
get_colors_basic_dict(color) + original_formatter + ColorsBasic.END)
|
|
136
|
-
handler.setFormatter(color_formatter)
|
|
115
|
+
if color is not None and logger is None:
|
|
116
|
+
message = ansi_escape_codes.get_colors_basic_dict(color) + message + ansi_escape_codes.ColorsBasic.END
|
|
137
117
|
|
|
138
118
|
# If 'online' is set to 'True', we'll output message as oneline.
|
|
139
119
|
if oneline:
|
|
@@ -146,22 +126,20 @@ def print_api(
|
|
|
146
126
|
if logger:
|
|
147
127
|
# Emit to logger only if 'print_end' is default, since we can't take responsibility for anything else.
|
|
148
128
|
if print_end == '\n':
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
129
|
+
if stdcolor and color is not None:
|
|
130
|
+
# Use logger to output message.
|
|
131
|
+
# with loggingw.temporary_change_logger_stream_handler_color(logger, color=color):
|
|
132
|
+
with loggingw.temporary_change_logger_stream_handler_emit_color(logger, color):
|
|
133
|
+
getattr(logger, logger_method)(message)
|
|
134
|
+
else:
|
|
135
|
+
# Use logger to output message.
|
|
136
|
+
getattr(logger, logger_method)(message)
|
|
157
137
|
# If logger wasn't passed.
|
|
158
138
|
else:
|
|
159
139
|
# Use print to output the message.
|
|
160
140
|
print(message, end=print_end)
|
|
161
141
|
|
|
162
142
|
# = Main Section with printing cases ===============================================================================
|
|
163
|
-
# exit_message: str = 'Exiting...'
|
|
164
|
-
|
|
165
143
|
# Convert message to string.
|
|
166
144
|
message = str(message)
|
|
167
145
|
|
|
@@ -175,20 +153,6 @@ def print_api(
|
|
|
175
153
|
if error_type:
|
|
176
154
|
print_or_logger()
|
|
177
155
|
|
|
178
|
-
# ==================================
|
|
179
|
-
# This section is responsible for ending the script.
|
|
180
|
-
|
|
181
|
-
# Check if we're inside exception. In this case each of 3 entries in 'sys.exc_info()' tuple will not equal
|
|
182
|
-
# to 'None', so picked only the first one.
|
|
183
|
-
# if sys.exc_info()[0] and not exit_on_error:
|
|
184
|
-
# # If 'raise_exception' is set to 'True', we'll end the script with exception.
|
|
185
|
-
# if pass_exception:
|
|
186
|
-
# pass
|
|
187
|
-
|
|
188
|
-
# If 'exit_on_error' is set to 'True', we'll end the script.
|
|
189
|
-
# if exit_on_error and error_type:
|
|
190
|
-
# sys.exit()
|
|
191
|
-
|
|
192
156
|
|
|
193
157
|
def print_status(
|
|
194
158
|
prefix_string: str,
|
|
@@ -2,8 +2,7 @@ from typing import Union
|
|
|
2
2
|
import threading
|
|
3
3
|
import multiprocessing.managers
|
|
4
4
|
|
|
5
|
-
from .
|
|
6
|
-
from . import system_resources
|
|
5
|
+
from . import system_resources, print_api
|
|
7
6
|
|
|
8
7
|
|
|
9
8
|
class SystemResourceMonitor:
|
|
@@ -109,7 +108,7 @@ class SystemResourceMonitor:
|
|
|
109
108
|
self.thread: Union[threading.Thread, None] = None
|
|
110
109
|
# Sets the running state of the monitoring process. Needed to stop the monitoring and queue threads.
|
|
111
110
|
self.running: bool = False
|
|
112
|
-
# The shared results dictionary.
|
|
111
|
+
# The shared results' dictionary.
|
|
113
112
|
self.results: dict = {}
|
|
114
113
|
|
|
115
114
|
def start(self, print_kwargs: dict = None):
|
|
@@ -128,7 +127,8 @@ class SystemResourceMonitor:
|
|
|
128
127
|
"""
|
|
129
128
|
|
|
130
129
|
while self.running:
|
|
131
|
-
# Get the results of the system resources check function and store them in
|
|
130
|
+
# Get the results of the system resources check function and store them in
|
|
131
|
+
# temporary results' dictionary.
|
|
132
132
|
results = system_resources.check_system_resources(
|
|
133
133
|
interval=interval, get_cpu=get_cpu, get_memory=get_memory,
|
|
134
134
|
get_disk_io_bytes=get_disk_io_bytes, get_disk_files_count=get_disk_files_count,
|
|
@@ -149,9 +149,9 @@ class SystemResourceMonitor:
|
|
|
149
149
|
for queue in queue_list:
|
|
150
150
|
queue.put(results)
|
|
151
151
|
|
|
152
|
-
# Update the shared results dictionary with the temporary results dictionary.
|
|
152
|
+
# Update the shared results dictionary with the temporary results' dictionary.
|
|
153
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.
|
|
154
|
+
# So we update the shared results dictionary with the temporary results' dictionary.
|
|
155
155
|
if manager_dict is not None:
|
|
156
156
|
manager_dict.update(results)
|
|
157
157
|
|
|
@@ -169,7 +169,7 @@ class SystemResourceMonitor:
|
|
|
169
169
|
self.thread.daemon = True
|
|
170
170
|
self.thread.start()
|
|
171
171
|
else:
|
|
172
|
-
print_api("Monitoring is already running.", color='yellow', **print_kwargs)
|
|
172
|
+
print_api.print_api("Monitoring is already running.", color='yellow', **print_kwargs)
|
|
173
173
|
|
|
174
174
|
def get_results(self) -> dict:
|
|
175
175
|
"""
|
|
@@ -258,7 +258,7 @@ def start_monitoring(
|
|
|
258
258
|
)
|
|
259
259
|
SYSTEM_RESOURCES_MONITOR.start()
|
|
260
260
|
else:
|
|
261
|
-
print_api("System resources monitoring is already running.", color='yellow', **(print_kwargs or {}))
|
|
261
|
+
print_api.print_api("System resources monitoring is already running.", color='yellow', **(print_kwargs or {}))
|
|
262
262
|
|
|
263
263
|
|
|
264
264
|
def stop_monitoring():
|
atomicshop/system_resources.py
CHANGED
|
@@ -5,9 +5,8 @@ import shutil
|
|
|
5
5
|
import threading
|
|
6
6
|
import multiprocessing.managers
|
|
7
7
|
|
|
8
|
-
from .print_api import print_api
|
|
9
8
|
from .wrappers.psutilw import cpus, memories, disks
|
|
10
|
-
from . import system_resource_monitor
|
|
9
|
+
from . import system_resource_monitor, print_api
|
|
11
10
|
|
|
12
11
|
|
|
13
12
|
def check_system_resources(
|
|
@@ -129,13 +128,13 @@ def wait_for_resource_availability(
|
|
|
129
128
|
|
|
130
129
|
if result['cpu_usage'] < cpu_percent_max and result['memory_usage'] < memory_percent_max:
|
|
131
130
|
break
|
|
132
|
-
print_api(
|
|
131
|
+
print_api.print_api(
|
|
133
132
|
f"Waiting for resources to be available... "
|
|
134
133
|
f"CPU: {result['cpu_usage']}%, Memory: {result['memory_usage']}%", color='yellow')
|
|
135
134
|
time.sleep(wait_time) # Wait for 'wait_time' seconds before checking again
|
|
136
135
|
|
|
137
136
|
|
|
138
|
-
def
|
|
137
|
+
def _test_disk_speed_with_monitoring(
|
|
139
138
|
file_settings: list[dict],
|
|
140
139
|
remove_file_after_each_copy: bool = False,
|
|
141
140
|
target_directory=None,
|
|
@@ -144,6 +143,7 @@ def test_disk_speed_with_monitoring(
|
|
|
144
143
|
print_kwargs: dict = None
|
|
145
144
|
):
|
|
146
145
|
"""
|
|
146
|
+
THIS IS NOT TESTED.
|
|
147
147
|
Generates files and performs write and read operations in the specified target directory,
|
|
148
148
|
while monitoring disk I/O speeds in a separate thread. Returns the maximum read and write rates,
|
|
149
149
|
and the total operation time.
|
|
@@ -171,7 +171,7 @@ def test_disk_speed_with_monitoring(
|
|
|
171
171
|
if monitoring:
|
|
172
172
|
system_resource_monitor.start_monitoring(
|
|
173
173
|
interval=1, get_cpu=False, get_memory=False, get_disk_io_bytes=True, get_disk_used_percent=False,
|
|
174
|
-
get_disk_files_count=True, calculate_maximum_changed_disk_io=True
|
|
174
|
+
get_disk_files_count=True, calculate_maximum_changed_disk_io=True)
|
|
175
175
|
|
|
176
176
|
if target_directory is None:
|
|
177
177
|
target_directory = tempfile.mkdtemp()
|
|
@@ -196,7 +196,7 @@ def test_disk_speed_with_monitoring(
|
|
|
196
196
|
shutil.copy(src_file_path, dest_directory)
|
|
197
197
|
|
|
198
198
|
target_file_path = os.path.join(dest_directory, os.path.basename(src_file_path))
|
|
199
|
-
print_api(f"Copied: {target_file_path}", **(print_kwargs or {}))
|
|
199
|
+
print_api.print_api(f"Copied: {target_file_path}", **(print_kwargs or {}))
|
|
200
200
|
|
|
201
201
|
# Measure read speed.
|
|
202
202
|
with open(target_file_path, "rb") as file:
|
|
@@ -212,7 +212,7 @@ def test_disk_speed_with_monitoring(
|
|
|
212
212
|
|
|
213
213
|
overall_end_time = time.time()
|
|
214
214
|
total_execution_time = overall_end_time - overall_start_time
|
|
215
|
-
print_api(f"Total execution time: {total_execution_time}", **(print_kwargs or {}))
|
|
215
|
+
print_api.print_api(f"Total execution time: {total_execution_time}", **(print_kwargs or {}))
|
|
216
216
|
|
|
217
217
|
# Cleanup. Remove all created files and directories.
|
|
218
218
|
shutil.rmtree(source_directory)
|
|
@@ -220,7 +220,7 @@ def test_disk_speed_with_monitoring(
|
|
|
220
220
|
|
|
221
221
|
if monitoring:
|
|
222
222
|
# Stop the I/O monitoring.
|
|
223
|
-
max_io_changes = system_resource_monitor.
|
|
223
|
+
max_io_changes = system_resource_monitor.get_results()['maximum_disk_io']
|
|
224
224
|
system_resource_monitor.stop_monitoring()
|
|
225
225
|
|
|
226
226
|
return total_execution_time, max_io_changes
|
atomicshop/web.py
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
import os
|
|
2
2
|
import urllib.request
|
|
3
3
|
import ssl
|
|
4
|
+
# noinspection PyPackageRequirements
|
|
4
5
|
import certifi
|
|
5
6
|
|
|
6
|
-
from .print_api import print_api
|
|
7
7
|
from .archiver import zips
|
|
8
8
|
from .urls import url_parser
|
|
9
9
|
from .file_io import file_io
|
|
10
10
|
from .wrappers.playwrightw import scenarios
|
|
11
|
-
from . import filesystem
|
|
11
|
+
from . import filesystem, print_api
|
|
12
12
|
|
|
13
13
|
|
|
14
14
|
# https://www.useragents.me/
|
|
@@ -28,10 +28,10 @@ def is_status_ok(status_code: int, **kwargs) -> bool:
|
|
|
28
28
|
"""
|
|
29
29
|
|
|
30
30
|
if status_code != 200:
|
|
31
|
-
print_api(f'URL Error, status code: {str(status_code)}', error_type=True, **kwargs)
|
|
31
|
+
print_api.print_api(f'URL Error, status code: {str(status_code)}', error_type=True, **kwargs)
|
|
32
32
|
return False
|
|
33
33
|
else:
|
|
34
|
-
print_api('URL Status: 200 OK', color="green", **kwargs)
|
|
34
|
+
print_api.print_api('URL Status: 200 OK', color="green", **kwargs)
|
|
35
35
|
return True
|
|
36
36
|
|
|
37
37
|
|
|
@@ -165,10 +165,10 @@ def download(
|
|
|
165
165
|
|
|
166
166
|
def print_to_console(print_end=None):
|
|
167
167
|
if file_size_bytes_int:
|
|
168
|
-
print_api(
|
|
168
|
+
print_api.print_api(
|
|
169
169
|
f'Downloaded bytes: {aggregated_bytes_int} / {file_size_bytes_int}', print_end=print_end, **kwargs)
|
|
170
170
|
else:
|
|
171
|
-
print_api(f'Downloaded bytes: {aggregated_bytes_int}', print_end=print_end, **kwargs)
|
|
171
|
+
print_api.print_api(f'Downloaded bytes: {aggregated_bytes_int}', print_end=print_end, **kwargs)
|
|
172
172
|
|
|
173
173
|
# Size of the buffer to read each time from url.
|
|
174
174
|
buffer_size: int = 4096
|
|
@@ -185,8 +185,8 @@ def download(
|
|
|
185
185
|
# Build full path to file.
|
|
186
186
|
file_path: str = f'{target_directory}{os.sep}{file_name}'
|
|
187
187
|
|
|
188
|
-
print_api(f'Downloading: {file_url}', **kwargs)
|
|
189
|
-
print_api(f'To: {file_path}', **kwargs)
|
|
188
|
+
print_api.print_api(f'Downloading: {file_url}', **kwargs)
|
|
189
|
+
print_api.print_api(f'To: {file_path}', **kwargs)
|
|
190
190
|
|
|
191
191
|
# In order to use 'urllib.request', it is not enough to 'import urllib', you need to 'import urllib.request'.
|
|
192
192
|
# Open the URL for data gathering with SSL context from certifi
|
|
@@ -223,10 +223,10 @@ def download(
|
|
|
223
223
|
print_to_console()
|
|
224
224
|
break
|
|
225
225
|
if aggregated_bytes_int == file_size_bytes_int:
|
|
226
|
-
print_api(f'Successfully Downloaded to: {file_path}', color="green", **kwargs)
|
|
226
|
+
print_api.print_api(f'Successfully Downloaded to: {file_path}', color="green", **kwargs)
|
|
227
227
|
else:
|
|
228
228
|
message = f'Download failed: {aggregated_bytes_int} / {file_size_bytes_int}. File: {file_path}'
|
|
229
|
-
print_api(
|
|
229
|
+
print_api.print_api(
|
|
230
230
|
message, error_type=True, color="red", **kwargs)
|
|
231
231
|
|
|
232
232
|
return file_path
|
|
@@ -1,12 +1,18 @@
|
|
|
1
1
|
import logging
|
|
2
|
+
import threading
|
|
2
3
|
import os
|
|
3
4
|
|
|
4
5
|
|
|
6
|
+
from ...basics import ansi_escape_codes
|
|
7
|
+
|
|
8
|
+
|
|
5
9
|
class HeaderFilter(logging.Filter):
|
|
6
10
|
"""
|
|
7
11
|
A logging.Filter that writes a header to a log file if the file is empty (
|
|
8
12
|
i.e., no log records have been written, i.e.2, on file rotation).
|
|
9
13
|
"""
|
|
14
|
+
|
|
15
|
+
# noinspection PyPep8Naming
|
|
10
16
|
def __init__(self, header, baseFilename):
|
|
11
17
|
super().__init__()
|
|
12
18
|
self.header = header
|
|
@@ -27,6 +33,23 @@ class HeaderFilter(logging.Filter):
|
|
|
27
33
|
return True
|
|
28
34
|
|
|
29
35
|
|
|
36
|
+
class ThreadColorLogFilter(logging.Filter):
|
|
37
|
+
"""
|
|
38
|
+
A logging.Filter that adds color to log records based on the thread that emitted the log record.
|
|
39
|
+
"""
|
|
40
|
+
def __init__(self, color: str, thread_id):
|
|
41
|
+
super().__init__()
|
|
42
|
+
self.color = color
|
|
43
|
+
self.thread_id = thread_id
|
|
44
|
+
|
|
45
|
+
def filter(self, record):
|
|
46
|
+
if threading.get_ident() == self.thread_id:
|
|
47
|
+
record.msg = (
|
|
48
|
+
ansi_escape_codes.get_colors_basic_dict(self.color) + record.msg +
|
|
49
|
+
ansi_escape_codes.ColorsBasic.END)
|
|
50
|
+
return True
|
|
51
|
+
|
|
52
|
+
|
|
30
53
|
"""
|
|
31
54
|
A logging.Filter in Python's logging module is an object that provides a way to perform fine-grained
|
|
32
55
|
filtering of log records.
|
|
@@ -155,3 +155,15 @@ def get_logging_formatter_from_string(
|
|
|
155
155
|
return NanosecondsFormatter(formatter, style=style, datefmt=datefmt, use_nanoseconds=use_nanoseconds)
|
|
156
156
|
else:
|
|
157
157
|
return logging.Formatter(formatter, style=style, datefmt=datefmt)
|
|
158
|
+
|
|
159
|
+
|
|
160
|
+
def get_formatter_string(formatter) -> str:
|
|
161
|
+
"""
|
|
162
|
+
Function to get the formatter string from the 'logging.Formatter'.
|
|
163
|
+
|
|
164
|
+
:param formatter: logging.Formatter, formatter to convert to string.
|
|
165
|
+
:return: str, formatter string.
|
|
166
|
+
"""
|
|
167
|
+
|
|
168
|
+
# noinspection PyProtectedMember
|
|
169
|
+
return formatter._fmt
|
|
@@ -8,6 +8,7 @@ import queue
|
|
|
8
8
|
from typing import Literal, Union
|
|
9
9
|
import threading
|
|
10
10
|
from datetime import datetime
|
|
11
|
+
import contextlib
|
|
11
12
|
|
|
12
13
|
from . import loggers, formatters, filters, consts
|
|
13
14
|
from ... import datetimes, filesystem
|
|
@@ -472,3 +473,32 @@ def add_filter_to_handler(handler: logging.Handler, filter_object: logging.Filte
|
|
|
472
473
|
"""
|
|
473
474
|
|
|
474
475
|
handler.addFilter(filter_object)
|
|
476
|
+
|
|
477
|
+
|
|
478
|
+
def get_formatter_string(handler: logging.Handler) -> str:
|
|
479
|
+
"""
|
|
480
|
+
Function to get the formatter string from the handler.
|
|
481
|
+
:param handler: Handler to get the formatter from.
|
|
482
|
+
:return: Formatter string.
|
|
483
|
+
"""
|
|
484
|
+
|
|
485
|
+
return formatters.get_formatter_string(handler.formatter)
|
|
486
|
+
|
|
487
|
+
|
|
488
|
+
@contextlib.contextmanager
|
|
489
|
+
def temporary_change_formatter(handler: logging.Handler, formatter_string: str):
|
|
490
|
+
"""
|
|
491
|
+
Context manager to temporarily change the formatter of the handler.
|
|
492
|
+
|
|
493
|
+
Example:
|
|
494
|
+
with temporary_change_formatter(handler, formatter_string):
|
|
495
|
+
# Do something with the temporary formatter.
|
|
496
|
+
pass
|
|
497
|
+
"""
|
|
498
|
+
original_formatter = handler.formatter
|
|
499
|
+
|
|
500
|
+
try:
|
|
501
|
+
handler.setFormatter(logging.Formatter(formatter_string))
|
|
502
|
+
yield
|
|
503
|
+
finally:
|
|
504
|
+
handler.setFormatter(original_formatter)
|