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

@@ -1,83 +1,34 @@
1
- import os
2
1
  import logging
3
- import queue
2
+ import os
3
+ from typing import Literal, Union
4
4
 
5
5
  from . import loggers, handlers, formatters
6
6
 
7
7
 
8
- def get_logger_with_level(logger_name: str, logging_level="DEBUG") -> logging.Logger:
9
- """
10
- Function to get a logger and set logging level.
11
-
12
- :param logger_name: Name of the logger.
13
- :param logging_level: 'int' or 'str', Logging level to set to the logger.
14
- None: if None, the logger level will not be set.
15
- :return: Logger.
16
- """
17
-
18
- # Get the logger.
19
- logger: logging.Logger = loggers.get_logger(logger_name)
20
- # Set the logger level if it is not None.
21
- if logging_level:
22
- loggers.set_logging_level(logger, logging_level)
23
-
24
- return logger
25
-
26
-
27
- def get_logger_with_stream_handler(
28
- logger_name: str, logging_level="DEBUG",
29
- formatter: str = "%(levelname)s | %(threadName)s | %(name)s | %(message)s"
30
- ) -> logging.Logger:
31
- """
32
- Function to get a logger and add StreamHandler to it.
33
-
34
- :param logger_name: Name of the logger.
35
- :param logging_level: 'int' or 'str', Logging level to set to the logger.
36
- None: if None, the logger level will not be set.
37
- :param formatter: Formatter to use for StreamHandler. It is template of how a message will look like.
38
- :return: Logger.
39
- """
40
-
41
- # Get the logger.
42
- logger: logging.Logger = loggers.get_logger(logger_name)
43
- # Set the logger level if it is not None.
44
- if logging_level:
45
- loggers.set_logging_level(logger, logging_level)
46
- # Add StreamHandler to the logger.
47
- add_stream_handler(logger, logging_level, formatter)
48
-
49
- return logger
50
-
51
-
52
- def get_logger_with_timedfilehandler(
8
+ def create_logger(
53
9
  logger_name: str,
54
- directory_path, file_name: str = None, file_extension: str = '.txt',
55
- logging_level="DEBUG", formatter='default',
56
- formatter_message_only: bool = False, disable_duplicate_ms: bool = False,
57
- when: str = "midnight", interval: int = 1, delay: bool = True, encoding=None
58
- ) -> logging.Logger:
59
- logger = get_logger_with_level(logger_name, logging_level)
60
- add_timedfilehandler_with_queuehandler(
61
- logger, directory_path, file_name, file_extension, logging_level, formatter,
62
- formatter_message_only, disable_duplicate_ms, when, interval, delay, encoding
63
- )
64
-
65
- return logger
66
-
67
-
68
- def get_logger_with_stream_handler_and_timedfilehandler(
69
- logger_name: str,
70
- directory_path,
71
- file_name: str = None,
72
- file_extension: str = '.txt',
10
+ file_path: str = None,
11
+ directory_path: str = None,
12
+ add_stream: bool = False,
13
+ add_timedfile: bool = False,
14
+ file_type: Literal[
15
+ 'txt',
16
+ 'csv',
17
+ 'json'] = 'txt',
73
18
  logging_level="DEBUG",
74
- formatter_filehandler='default',
75
- formatter_streamhandler: str = "%(levelname)s | %(threadName)s | %(name)s | %(message)s",
76
- formatter_message_only: bool = False,
77
- disable_duplicate_ms: bool = False,
19
+ formatter_streamhandler: Union[
20
+ Literal['MESSAGE', 'DEFAULT'],
21
+ str,
22
+ None] = None,
23
+ formatter_filehandler: Union[
24
+ Literal['MESSAGE', 'DEFAULT'],
25
+ str,
26
+ None] = None,
27
+ formatter_streamhandler_use_nanoseconds: bool = True,
28
+ formatter_filehandler_use_nanoseconds: bool = True,
78
29
  when: str = "midnight",
79
30
  interval: int = 1,
80
- delay: bool = True,
31
+ delay: bool = False,
81
32
  encoding=None,
82
33
  header: str = None
83
34
  ) -> logging.Logger:
@@ -85,26 +36,37 @@ def get_logger_with_stream_handler_and_timedfilehandler(
85
36
  Function to get a logger and add StreamHandler and TimedRotatingFileHandler to it.
86
37
 
87
38
  :param logger_name: Name of the logger.
88
- :param directory_path: string, Path to the directory where the log file will be created.
89
- :param file_name: string, Name of the log file without file extension, since we add it through separate argument.
90
- If not provided, logger name will be used.
91
- :param file_extension: string, Extension of the log file. Default is '.txt'.
92
- '.txt': Text file.
93
- '.csv': CSV file.
94
- '.json': JSON file.
39
+ :param file_path: full path to the log file. If you don't want to use the file, set it to None.
40
+ You can set the directory_path only and then the 'logger_name' will be used as the file name with the
41
+ 'file_type' as the file extension.
42
+ :param directory_path: full path to the directory where the log file will be saved.
43
+ :param add_stream: bool, If set to True, StreamHandler will be added to the logger.
44
+ :param add_timedfile: bool, If set to True, TimedRotatingFileHandler will be added to the logger.
45
+ :param file_type: string, file type of the log file. Default is 'txt'.
46
+ 'txt': Text file.
47
+ 'csv': CSV file.
48
+ 'json': JSON file.
95
49
  :param logging_level: str or int, Logging level for the handler, that will use the logger while initiated.
50
+ :param formatter_streamhandler: string, Formatter to use for StreamHandler. It is template of how a message will
51
+ look like.
52
+ None: No formatter will be used.
53
+ 'DEFAULT': Default formatter will be used:
54
+ "%(levelname)s | %(threadName)s | %(name)s | %(message)s"
55
+ 'MESSAGE': Formatter will be used only for the 'message' part.
56
+ string: Custom formatter, regular syntax for logging.Formatter.
96
57
  :param formatter_filehandler: string, Formatter to use for handler. It is template of how a message will look like.
97
58
  None: No formatter will be used.
98
- 'default': Default formatter will be used for each file extension:
99
- .txt: "%(asctime)s | %(levelname)s | %(threadName)s | %(name)s | %(message)s"
100
- .csv: "%(asctime)s,%(levelname)s,%(threadName)s,%(name)s,%(message)s"
101
- .json: '{"time": "%(asctime)s", "level": "%(levelname)s", "thread": "%(threadName)s",
59
+ 'DEFAULT': Default formatter will be used for each file extension:
60
+ txt: "%(asctime)s | %(levelname)s | %(threadName)s | %(name)s | %(message)s"
61
+ csv: "%(asctime)s,%(levelname)s,%(threadName)s,%(name)s,%(message)s"
62
+ json: '{"time": "%(asctime)s", "level": "%(levelname)s", "thread": "%(threadName)s",
102
63
  "logger": "%(name)s", "message": "%(message)s"}'
103
- :param formatter_streamhandler: string, Formatter to use for StreamHandler. It is template of how a message will
104
- look like.
105
- :param formatter_message_only: bool, If set to True, formatter will be used only for the 'message' part.
106
- :param disable_duplicate_ms: bool, If set to True, duplicate milliseconds will be removed from formatter
107
- 'asctime' element.
64
+ 'MESSAGE': Formatter will be used only for the 'message' part.
65
+ string: Custom formatter, regular syntax for logging.Formatter.
66
+ :param formatter_streamhandler_use_nanoseconds: bool, If set to True, the nanoseconds will be used
67
+ in the formatter in case you provide 'asctime' element.
68
+ :param formatter_filehandler_use_nanoseconds: bool, If set to True, the nanoseconds will be used
69
+ in the formatter in case you provide 'asctime' element.
108
70
  :param when: string, When to rotate the log file. Default is 'midnight'.
109
71
  [when="midnight"] is set to rotate the filename at midnight. This means that the current file name will be
110
72
  added Yesterday's date to the end of the file and today's file will continue to write at the same
@@ -119,6 +81,7 @@ def get_logger_with_stream_handler_and_timedfilehandler(
119
81
  :param encoding: string, Encoding to use for the log file. Default is None.
120
82
  :param header: string, Header to write to the log file.
121
83
  Example: "time,host,error"
84
+ Useful for 'csv' file type format.
122
85
 
123
86
  :return: Logger.
124
87
 
@@ -130,198 +93,97 @@ def get_logger_with_stream_handler_and_timedfilehandler(
130
93
 
131
94
  def main():
132
95
  header: str = "time,host,error"
133
- output_directory: str = "D:\\logs"
134
-
135
- error_logger = loggingw.get_logger_with_stream_handler_and_timedfilehandler(
136
- logger_name="errors", directory_path=output_directory,
137
- file_extension=".csv", formatter_message_only=True, header=header
96
+ output_log_file: str = "D:\\logs\\log_file.csv"
97
+
98
+ error_logger = loggingw.create_logger(
99
+ logger_name=f'{self.__class__.__name__}_CSV',
100
+ file_path=output_log_file,
101
+ add_timedfile=True,
102
+ file_type='csv',
103
+ formatter_filehandler='MESSAGE',
104
+ header=header
138
105
  )
139
106
 
140
- error_logger.info(f"{datetime.now()},host1,/path/to/file,error message")
107
+ error_logger.info(error_message)
141
108
 
142
109
 
143
110
  if __name__ == "__main__":
144
111
  main()
145
- """
146
- logger = get_logger_with_level(logger_name, logging_level)
147
- add_stream_handler(logger, logging_level, formatter_streamhandler, formatter_message_only)
148
- add_timedfilehandler_with_queuehandler(
149
- logger, directory_path, file_name, file_extension, logging_level, formatter_filehandler,
150
- formatter_message_only, disable_duplicate_ms, when, interval, delay, encoding, header
151
- )
152
-
153
- return logger
154
112
 
113
+ ------------------------------
155
114
 
156
- def add_stream_handler(
157
- logger: logging.Logger, logging_level: str = "DEBUG",
158
- formatter: str = "%(levelname)s | %(threadName)s | %(name)s | %(message)s",
159
- formatter_message_only: bool = False
160
- ):
161
- """
162
- Function to add StreamHandler to logger.
163
- Stream formatter will output messages to the console.
164
-
165
- :param logger: Logger to add the handler to.
166
- :param logging_level: Logging level for the handler, that will use the logger while initiated.
167
- :param formatter: Formatter to use for StreamHandler. It is template of how a message will look like.
168
- None: No formatter will be used.
169
- 'default': Default formatter will be used:
170
- "%(levelname)s | %(threadName)s | %(name)s | %(message)s"
171
- :param formatter_message_only: bool, If set to True, formatter will be used only for the 'message' part.
172
- """
173
-
174
- # Getting the StreamHandler.
175
- stream_handler = handlers.get_stream_handler()
176
- # Setting log level for the handler, that will use the logger while initiated.
177
- loggers.set_logging_level(stream_handler, logging_level)
178
-
179
- # If formatter_message_only is set to True, then formatter will be used only for the 'message' part.
180
- if formatter_message_only:
181
- formatter = "%(message)s"
115
+ Example to use StreamHandler to output to console and TimedRotatingFileHandler to write to file:
116
+ from atomicshop.wrappers.loggingw import loggingw
182
117
 
183
- # If formatter was provided, then it will be used.
184
- if formatter:
185
- logging_formatter = formatters.get_logging_formatter_from_string(formatter)
186
- handlers.set_formatter(stream_handler, logging_formatter)
187
118
 
188
- # Adding the handler to the main logger
189
- loggers.add_handler(logger, stream_handler)
119
+ def main():
120
+ header: str = "time,host,error"
121
+ output_log_file: str = "D:\\logs\\log_file.txt"
122
+
123
+ error_logger = loggingw.create_logger(
124
+ logger_name=f'{self.__class__.__name__}',
125
+ file_path=output_log_file,
126
+ add_stream=True,
127
+ add_timedfile=True,
128
+ file_type='txt',
129
+ formatter_streamhandler='DEFAULT',
130
+ formatter_filehandler='DEFAULT'
131
+ )
190
132
 
191
- # Disable propagation from the 'root' logger, so we will not see the messages twice.
192
- loggers.set_propagation(logger)
133
+ error_logger.info(f"{datetime.now()},host1,/path/to/file,error message")
193
134
 
194
135
 
195
- def add_timedfilehandler_with_queuehandler(
196
- logger: logging.Logger,
197
- directory_path: str,
198
- file_name_no_extension: str = None,
199
- file_extension: str = '.txt',
200
- logging_level="DEBUG",
201
- formatter='default',
202
- formatter_message_only: bool = False,
203
- disable_duplicate_ms: bool = False,
204
- when: str = 'midnight',
205
- interval: int = 1,
206
- delay: bool = True,
207
- encoding=None,
208
- header: str = None
209
- ):
210
- """
211
- Function to add TimedRotatingFileHandler and QueueHandler to logger.
212
- TimedRotatingFileHandler will output messages to the file through QueueHandler.
213
- This is needed, since TimedRotatingFileHandler is not thread-safe, though official docs say it is.
214
-
215
- :param logger: Logger to add the handler to.
216
- :param directory_path: string, Path to the directory where the log file will be created.
217
- :param file_name_no_extension: string, Name of the log file without file extension, since we add it through
218
- separate argument. If not provided, logger name will be used.
219
- :param file_extension: string, Extension of the log file. Default is '.txt'.
220
- :param logging_level: str or int, Logging level for the handler, that will use the logger while initiated.
221
- :param formatter: string, Formatter to use for handler. It is template of how a message will look like.
222
- None: No formatter will be used.
223
- 'default': Default formatter will be used for each file extension:
224
- .txt: "%(asctime)s | %(levelname)s | %(threadName)s | %(name)s | %(message)s"
225
- .csv: "%(asctime)s,%(levelname)s,%(threadName)s,%(name)s,%(message)s"
226
- .json: '{"time": "%(asctime)s", "level": "%(levelname)s", "thread": "%(threadName)s",
227
- "logger": "%(name)s", "message": "%(message)s"}'
228
- :param formatter_message_only: bool, If set to True, formatter will be used only for the 'message' part.
229
- :param disable_duplicate_ms: bool, If set to True, duplicate milliseconds will be removed from formatter
230
- 'asctime' element.
231
- :param when: string, When to rotate the log file. Default is 'midnight'.
232
- [when="midnight"] is set to rotate the filename at midnight. This means that the current file name will be
233
- added Yesterday's date to the end of the file and today's file will continue to write at the same
234
- filename. Also, if the script finished working on 25.11.2021, the name of the log file will be "test.log"
235
- If you run the script again on 28.11.2021, the logging module will take the last modification date of
236
- the file "test.log" and assign a date to it: test.log.2021_11_25
237
- The log filename of 28.11.2021 will be called "test.log" again.
238
- :param interval: int, Interval to rotate the log file. Default is 1.
239
- If 'when="midnight"' and 'interval=1', then the log file will be rotated every midnight.
240
- If 'when="midnight"' and 'interval=2', then the log file will be rotated every 2nd midnights.
241
- :param delay: bool, If set to True, the log file will be created only if there's something to write.
242
- :param encoding: string, Encoding to use for the log file. Default is None.
243
- :param header: string, Header to write to the log file.
244
- Example: "time,host,error"
136
+ if __name__ == "__main__":
137
+ main()
245
138
  """
246
139
 
247
- # If file name wasn't provided we will use the logger name instead.
248
- if not file_name_no_extension:
249
- file_name_no_extension = logger.name
250
-
251
- # Set log file path.
252
- log_file_path = f'{directory_path}{os.sep}{file_name_no_extension}{file_extension}'
253
-
254
- # Setting the TimedRotatingFileHandler, without adding it to the logger.
255
- # It will be added to the QueueListener, which will use the TimedRotatingFileHandler to write logs.
256
- # This is needed since there's a bug in TimedRotatingFileHandler, which won't let it be used with
257
- # threads the same way it would be used for multiprocess.
258
-
259
- # Creating file handler with log filename. At this stage the log file is created and locked by the handler,
260
- # Unless we use "delay=True" to tell the class to write the file only if there's something to write.
261
-
262
- if file_extension == ".csv":
263
- # If file extension is CSV, we'll set the header to the file.
264
- # This is needed since the CSV file will be rotated, and we'll need to set the header each time.
265
- # We'll use the custom TimedRotatingFileHandlerWithHeader class.
266
- file_handler = handlers.get_timed_rotating_file_handler_with_header(
267
- log_file_path, when=when, interval=interval, delay=delay, encoding=encoding, header=header)
268
- else:
269
- file_handler = handlers.get_timed_rotating_file_handler(
270
- log_file_path, when=when, interval=interval, delay=delay, encoding=encoding)
271
-
272
- loggers.set_logging_level(file_handler, logging_level)
273
-
274
- if formatter == "default":
275
- # Create file formatter based on extension
276
- if file_extension == ".txt":
277
- formatter = formatters.DEFAULT_FORMATTER_TXT_FILE
278
- elif file_extension == ".csv":
279
- formatter = formatters.DEFAULT_FORMATTER_CSV_FILE
280
- elif file_extension == ".json":
281
- formatter = "%(message)s"
140
+ if not directory_path and not file_path:
141
+ raise ValueError("You need to provide 'directory_path' or 'file_path'.")
142
+ if directory_path and file_path:
143
+ raise ValueError("You can't provide both 'directory_path' and 'file_path'.")
282
144
 
283
- # If 'formatter_message_only' is set to 'True', we'll use the formatter only for the message part.
284
- if formatter_message_only:
285
- formatter = "%(message)s"
145
+ if directory_path:
146
+ if directory_path.endswith(os.sep):
147
+ directory_path = directory_path[:-1]
286
148
 
287
- # If formatter was passed to the function we'll add it to handler.
288
- if formatter:
289
- # Convert string to Formatter object. Moved to newer styling of python 3: style='{'
290
- logging_formatter = formatters.get_logging_formatter_from_string(
291
- formatter, disable_duplicate_ms=disable_duplicate_ms)
292
- # Setting the formatter in file handler.
293
- handlers.set_formatter(file_handler, logging_formatter)
149
+ file_path = f"{directory_path}{os.sep}{logger_name}.{file_type}"
294
150
 
295
- # This function will change the suffix behavior of the rotated file name.
296
- handlers.change_rotated_filename(file_handler, file_extension)
151
+ logger = get_logger_with_level(logger_name, logging_level)
297
152
 
298
- queue_handler = start_queue_listener_for_file_handler_and_get_queue_handler(file_handler)
299
- loggers.set_logging_level(queue_handler, logging_level)
153
+ if add_stream:
154
+ handlers.add_stream_handler(
155
+ logger=logger, logging_level=logging_level, formatter=formatter_streamhandler,
156
+ formatter_use_nanoseconds=formatter_streamhandler_use_nanoseconds)
300
157
 
301
- # Add the QueueHandler to the logger.
302
- loggers.add_handler(logger, queue_handler)
158
+ if add_timedfile:
159
+ handlers.add_timedfilehandler_with_queuehandler(
160
+ logger=logger, file_path=file_path, logging_level=logging_level, formatter=formatter_filehandler,
161
+ formatter_use_nanoseconds=formatter_filehandler_use_nanoseconds, file_type=file_type,
162
+ when=when, interval=interval, delay=delay, encoding=encoding, header=header)
303
163
 
304
- # Disable propagation from the 'root' logger, so we will not see the messages twice.
305
- loggers.set_propagation(logger)
164
+ return logger
306
165
 
307
166
 
308
- def start_queue_listener_for_file_handler_and_get_queue_handler(file_handler):
167
+ def get_logger_with_level(
168
+ logger_name: str,
169
+ logging_level="DEBUG"
170
+ ) -> logging.Logger:
309
171
  """
310
- Function to start QueueListener, which will put the logs from FileHandler to the Queue.
311
- QueueHandler will get the logs from the Queue and put them to the file that was set in the FileHandler.
172
+ Function to get a logger and set logging level.
312
173
 
313
- :param file_handler: FileHandler object.
314
- :return: QueueHandler object.
174
+ :param logger_name: Name of the logger.
175
+ :param logging_level: 'int' or 'str', Logging level to set to the logger.
176
+ None: if None, the logger level will not be set.
177
+ :return: Logger.
315
178
  """
316
179
 
317
- # Create the Queue between threads. "-1" means that there can infinite number of items that can be
318
- # put in the Queue. if integer is bigger than 0, it means that this will be the maximum
319
- # number of items.
320
- queue_object = queue.Queue(-1)
321
- # Create QueueListener, which will put the logs from FileHandler to the Queue and put the logs to the queue.
322
- handlers.start_queue_listener_for_file_handler(file_handler, queue_object)
180
+ # Get the logger.
181
+ logger: logging.Logger = loggers.get_logger(logger_name)
182
+ # Set the logger level if it is not None.
183
+ if logging_level:
184
+ loggers.set_logging_level(logger, logging_level)
323
185
 
324
- return handlers.get_queue_handler(queue_object)
186
+ return logger
325
187
 
326
188
 
327
189
  def disable_default_logger():
@@ -340,3 +202,22 @@ def disable_default_logger():
340
202
 
341
203
  # Disabling the default logger in Python
342
204
  logging.disable(logging.CRITICAL)
205
+
206
+
207
+ def get_datetime_format_string_from_logger_file_handlers(logger: logging.Logger) -> list:
208
+ """
209
+ Function to get datetime format string from the logger's file handlers.
210
+ This is useful when you want to know the datetime format string that is used on file rotation.
211
+ :param logger: Logger to get the datetime format string from.
212
+ :return: List of datetime format strings.
213
+ """
214
+
215
+ datetime_format_strings = []
216
+
217
+ for handler in logger.handlers:
218
+ if isinstance(handler, logging.FileHandler):
219
+ date_time_format_string = handlers.extract_datetime_format_from_file_handler(handler)
220
+ if date_time_format_string:
221
+ datetime_format_strings.append(date_time_format_string)
222
+
223
+ return datetime_format_strings
@@ -75,8 +75,8 @@ def get_logs_paths(
75
75
 
76
76
  # Get the datetime object from the file name by the date pattern.
77
77
  try:
78
- datetime_object, date_string, timestamp_float = datetimes.get_datetime_from_complex_string_by_pattern(
79
- current_file_name, date_pattern)
78
+ datetime_object, date_string, timestamp_float = (
79
+ datetimes.get_datetime_from_complex_string_by_pattern(current_file_name, date_pattern))
80
80
  # ValueError will be raised if the date pattern does not match the file name.
81
81
  except ValueError:
82
82
  timestamp_float = 0
@@ -0,0 +1,40 @@
1
+ from typing import Union
2
+ import shlex
3
+
4
+ import psutil
5
+
6
+
7
+ def get_process_using_port(port: int) -> Union[dict, None]:
8
+ """
9
+ Function to find the process using the port.
10
+ :param port: Port number.
11
+ :return: dict['pid', 'name', 'cmdline'] or None.
12
+ """
13
+ for proc in psutil.process_iter(['pid', 'name', 'cmdline']):
14
+ try:
15
+ connections = proc.connections(kind='inet')
16
+ for conn in connections:
17
+ if conn.laddr.port == port:
18
+ return {
19
+ 'pid': proc.info['pid'],
20
+ 'name': proc.info['name'],
21
+ 'cmdline': shlex.join(proc.info['cmdline'])
22
+ }
23
+ except (psutil.NoSuchProcess, psutil.AccessDenied, psutil.ZombieProcess):
24
+ pass
25
+ return None
26
+
27
+
28
+ def get_processes_using_port_list(ports: list) -> Union[dict, None]:
29
+ """
30
+ Function to find the process using the port.
31
+ :param ports: List of port numbers.
32
+ :return: dict[port: {'pid', 'name', 'cmdline'}] or None.
33
+ """
34
+ port_process_map = {}
35
+ for port in ports:
36
+ process_info = get_process_using_port(port)
37
+ if process_info:
38
+ port_process_map[port] = process_info
39
+
40
+ return port_process_map
@@ -6,11 +6,16 @@ import socket
6
6
 
7
7
  from ...print_api import print_api
8
8
  from ..loggingw import loggingw
9
+ from ..psutilw import networks
9
10
 
10
11
  import dnslib
11
12
  from dnslib import DNSRecord, DNSHeader, RR, A
12
13
 
13
14
 
15
+ class DnsPortInUseError(Exception):
16
+ pass
17
+
18
+
14
19
  class DnsServer:
15
20
  """
16
21
  DnsServer class is responsible to handle DNS Requests on port 53 based on configuration and send DNS Response back.
@@ -56,8 +61,12 @@ class DnsServer:
56
61
 
57
62
  # Logger that logs all the DNS Requests and responses in DNS format. These entries will not present in
58
63
  # network log of TCP Server module.
59
- self.dns_full_logger = loggingw.get_logger_with_timedfilehandler(
60
- logger_name="dns", directory_path=self.config['log']['logs_path'], disable_duplicate_ms=True)
64
+ self.dns_full_logger = loggingw.create_logger(
65
+ logger_name="dns",
66
+ directory_path=self.config['log']['logs_path'],
67
+ add_timedfile=True,
68
+ formatter_filehandler='DEFAULT'
69
+ )
61
70
 
62
71
  def thread_worker_empty_dns_cache(self, function_sleep_time: int):
63
72
  """
@@ -78,6 +87,11 @@ class DnsServer:
78
87
  :return: None.
79
88
  """
80
89
 
90
+ port_in_use = networks.get_processes_using_port_list([self.config['dns']['listening_port']])
91
+ if port_in_use:
92
+ for port, process_info in port_in_use.items():
93
+ raise DnsPortInUseError(f"Port [{port}] is already in use by process: {process_info}")
94
+
81
95
  self.logger.info("DNS Server Module Started.")
82
96
 
83
97
  # Define objects for global usage
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: atomicshop
3
- Version: 2.14.4
3
+ Version: 2.14.6
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=tunTjRW84u7Nao5t0Z6ZWFYrQDUW_zun_a86yEIubts,123
1
+ atomicshop/__init__.py,sha256=hybMlQ9qVeOgdPaVMdVvrp-rXkVt1Ifm1_zQ95KG2kM,123
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
@@ -8,7 +8,7 @@ atomicshop/command_line_processing.py,sha256=u5yT9Ger_cu7ni5ID0VFlRbVD46ARHeNC9t
8
8
  atomicshop/config_init.py,sha256=z2RXD_mw9nQlAOpuGry1h9QT-2LhNscXgGAktN3dCVQ,2497
9
9
  atomicshop/console_output.py,sha256=AOSJjrRryE97PAGtgDL03IBtWSi02aNol8noDnW3k6M,4667
10
10
  atomicshop/console_user_response.py,sha256=31HIy9QGXa7f-GVR8MzJauQ79E_ZqAeagF3Ks4GGdDU,3234
11
- atomicshop/datetimes.py,sha256=wZ75JS6Aq5kTQrCSrjCwBrT-KPO7Xu9_BRWKrY8uU3c,15645
11
+ atomicshop/datetimes.py,sha256=Rmn-Ag36xRI1xbyoMs2fe1PB5hzb_UHEIwRVPppz0M0,18278
12
12
  atomicshop/diff_check.py,sha256=RJvzJhyYAZyRPKVDk1dS7UwZCx0kq__WDZ6N0rNfZUY,27110
13
13
  atomicshop/dns.py,sha256=h4uZKoz4wbBlLOOduL1GtRcTm-YpiPnGOEGxUm7hhOI,2140
14
14
  atomicshop/domains.py,sha256=Rxu6JhhMqFZRcoFs69IoEd1PtYca0lMCG6F1AomP7z4,3197
@@ -26,7 +26,7 @@ atomicshop/keyboard_press.py,sha256=1W5kRtOB75fulVx-uF2yarBhW0_IzdI1k73AnvXstk0,
26
26
  atomicshop/on_exit.py,sha256=Wf1iy2e0b0Zu7oRxrct3VkLdQ_x9B32-z_JerKTt9Z0,5493
27
27
  atomicshop/pbtkmultifile_argparse.py,sha256=aEk8nhvoQVu-xyfZosK3ma17CwIgOjzO1erXXdjwtS4,4574
28
28
  atomicshop/permissions.py,sha256=P6tiUKV-Gw-c3ePEVsst9bqWaHJbB4ZlJB4xbDYVpEs,4436
29
- atomicshop/print_api.py,sha256=DhbCQd0MWZZ5GYEk4oTu1opRFC-b31g1VWZgTGewG2Y,11568
29
+ atomicshop/print_api.py,sha256=j0bZ9b2rFKCcr0TVx1ARraVKeEs6JaaSgIlBdndy1nI,11600
30
30
  atomicshop/process.py,sha256=U2gyRl0bw2138y-rOMABMVptRvAL81ZfX1JyfxJI_Oo,15973
31
31
  atomicshop/python_file_patcher.py,sha256=kd3rBWvTcosLEk-7TycNdfKW9fZbe161iVwmH4niUo0,5515
32
32
  atomicshop/python_functions.py,sha256=zJg4ogUwECxrDD7xdDN5JikIUctITM5lsyabr_ZNsRw,4435
@@ -120,10 +120,11 @@ atomicshop/file_io/xlsxs.py,sha256=v_dyg9GD4LqgWi6wA1QuWRZ8zG4ZwB6Dz52ytdcmmmI,2
120
120
  atomicshop/file_io/xmls.py,sha256=zh3SuK-dNaFq2NDNhx6ivcf4GYCfGM8M10PcEwDSpxk,2104
121
121
  atomicshop/mains/installs/pycharm.py,sha256=uYTfME7hOeNkAsOZxDDPj2hDqmkxrFqVV6Nv6xnYNVk,141
122
122
  atomicshop/mitm/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
123
+ atomicshop/mitm/config_editor.py,sha256=9ZwD6NGqgsr1f85NyFwWwM7FDut2vGQ4xari3vS9UT0,1130
123
124
  atomicshop/mitm/connection_thread_worker.py,sha256=PQ8bwOgrPudYP5oPnSi_DWaKXOi038M8TMImlLkxuPI,20486
124
125
  atomicshop/mitm/import_config.py,sha256=_V-IVJ7a1L6E-VOR4CDfZj-S1odbsIlBe13ij0NlpqY,7974
125
- atomicshop/mitm/initialize_engines.py,sha256=UGdT5DKYNri3MNOxESP7oeSxYiUDrVilJ4jic_nwdew,8055
126
- atomicshop/mitm/initialize_mitm_server.py,sha256=5JGkyvAvz1sJVeRGMJWSQiQ-VOdrU-NJn633oxQe0cw,13143
126
+ atomicshop/mitm/initialize_engines.py,sha256=YnXPK1UKrmULnfL4zLo2LOpKWq-aGKzc9p3n8tfcYCM,8170
127
+ atomicshop/mitm/initialize_mitm_server.py,sha256=0xjHleUFecU8nyhzf5z8On-nZtL26A80prH4GHSqNc8,14611
127
128
  atomicshop/mitm/message.py,sha256=u2U2f2SOHdBNU-6r1Ik2W14ai2EOwxUV4wVfGZA098k,1732
128
129
  atomicshop/mitm/shared_functions.py,sha256=PaK_sbnEA5zo9k2ktEOKLmvo-6wRUunxzSNRr41uXIQ,1924
129
130
  atomicshop/mitm/statistic_analyzer.py,sha256=ctsf-MBIUvG4-R0K4gFQyi_b42-VCq-5s7hgO9jMOes,38415
@@ -233,11 +234,11 @@ atomicshop/wrappers/factw/rest/statistics.py,sha256=vznwzKP1gEF7uXz3HsuV66BU9wrp
233
234
  atomicshop/wrappers/factw/rest/status.py,sha256=4O3xS1poafwyUiLDkhyx4oMMe4PBwABuRPpOMnMKgIU,641
234
235
  atomicshop/wrappers/fibratusw/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
235
236
  atomicshop/wrappers/fibratusw/install.py,sha256=PLVymDe0HuOvU0r2lje8BkQAgtiOWEeRO7n-1zKuL7A,3287
236
- atomicshop/wrappers/loggingw/formatters.py,sha256=mUtcJJfmhLNrwUVYShXTmdu40dBaJu4TS8FiuTXI7ys,7189
237
- atomicshop/wrappers/loggingw/handlers.py,sha256=2A_3Qy1B0RvVWZmQocAB6CmpqlXoKJ-yi6iBWG2jNLo,8274
237
+ atomicshop/wrappers/loggingw/formatters.py,sha256=808R7K3e3ZJD2BXfqI6UMOyXGrCgt9SYh2Uv7sL_1KQ,7432
238
+ atomicshop/wrappers/loggingw/handlers.py,sha256=0n4Bqr9yQ7GiQOBYtSVFtCFBeEUfcvkaAFYgWY1E3Tg,18014
238
239
  atomicshop/wrappers/loggingw/loggers.py,sha256=DHOOTAtqkwn1xgvLHSkOiBm6yFGNuQy1kvbhG-TDog8,2374
239
- atomicshop/wrappers/loggingw/loggingw.py,sha256=m6YySEedP3_4Ik1S_uGMxETSbmRkmMYmAZxhHBlXSlo,16616
240
- atomicshop/wrappers/loggingw/reading.py,sha256=wse-38zUDHB3HUB28R8Ah_Ig3Wxt2tChapKtu-yyy2E,17036
240
+ atomicshop/wrappers/loggingw/loggingw.py,sha256=irzlIYXTcCpSVjmb6NU6GJGCIy3V48ZVKNvKOlH70CU,9417
241
+ atomicshop/wrappers/loggingw/reading.py,sha256=yh7uNPxEdn6KsxSKrYny2C57XdI25F5gaByz77CO_pw,17038
241
242
  atomicshop/wrappers/nodejsw/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
242
243
  atomicshop/wrappers/nodejsw/install_nodejs.py,sha256=QZg-R2iTQt7kFb8wNtnTmwraSGwvUs34JIasdbNa7ZU,5154
243
244
  atomicshop/wrappers/playwrightw/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
@@ -253,6 +254,7 @@ atomicshop/wrappers/playwrightw/waits.py,sha256=308fdOu6YDqQ7K7xywj7R27sSmFanPBQ
253
254
  atomicshop/wrappers/psutilw/cpus.py,sha256=w6LPBMINqS-T_X8vzdYkLS2Wzuve28Ydp_GafTCngrc,236
254
255
  atomicshop/wrappers/psutilw/disks.py,sha256=3ZSVoommKH1TWo37j_83frB-NqXF4Nf5q5mBCX8G4jE,9221
255
256
  atomicshop/wrappers/psutilw/memories.py,sha256=_S0aL8iaoIHebd1vOFrY_T9aROM5Jx2D5CvDh_4j0Vc,528
257
+ atomicshop/wrappers/psutilw/networks.py,sha256=Q2EtyemncDhDsNYZREME0nOIxM-jQqIktFN3i5HtSog,1294
256
258
  atomicshop/wrappers/psutilw/psutilw.py,sha256=q3EwgprqyrR4zLCjl4l5DHFOQoukEvQMIPjNB504oQ0,21262
257
259
  atomicshop/wrappers/psycopgw/psycopgw.py,sha256=XJvVf0oAUjCHkrYfKeFuGCpfn0Oxj3u4SbKMKA1508E,7118
258
260
  atomicshop/wrappers/pywin32w/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
@@ -270,7 +272,7 @@ atomicshop/wrappers/socketw/accepter.py,sha256=HQC1EyZmyUtVEfFbaBkHCE-VZp6RWyd9m
270
272
  atomicshop/wrappers/socketw/base.py,sha256=1vvg8EhRGvnxdrRAm1VJSLCXkm2SZDHRjdpTuhkH3Mg,1844
271
273
  atomicshop/wrappers/socketw/certificator.py,sha256=SxCKFyBlwzs4uohugfBokOYQpZJyH8KY46m87Q23n6w,9017
272
274
  atomicshop/wrappers/socketw/creator.py,sha256=C-l57G854HAtWJonVbgfQge290-Dg0Ov4aurJAWIKls,11199
273
- atomicshop/wrappers/socketw/dns_server.py,sha256=laMR_opplvytVTvVcztNoDChZGMCDR31fDQejrCNaEI,42032
275
+ atomicshop/wrappers/socketw/dns_server.py,sha256=u4RSDIK4UR1aKOulwSGscchxYa7pTlPxMO-StHuBMag,42464
274
276
  atomicshop/wrappers/socketw/exception_wrapper.py,sha256=_YDnzyEcUnV6VISU3bk-UPdnsMvHjKJBHwxLMTsxQu8,8495
275
277
  atomicshop/wrappers/socketw/get_process.py,sha256=APw_oOXsuR5KljYesd4J8MuzR-kaw2ez3MN3oD_h9Qc,5226
276
278
  atomicshop/wrappers/socketw/receiver.py,sha256=m8hXKOa8dqEQGUdcbYjshH8-j0CsMGRkge2ifYKhaAw,9050
@@ -281,8 +283,8 @@ atomicshop/wrappers/socketw/socket_server_tester.py,sha256=AhpurHJmP2kgzHaUbq5ey
281
283
  atomicshop/wrappers/socketw/socket_wrapper.py,sha256=aXBwlEIJhFT0-c4i8iNlFx2It9VpCEpsv--5Oqcpxao,11624
282
284
  atomicshop/wrappers/socketw/ssl_base.py,sha256=k4V3gwkbq10MvOH4btU4onLX2GNOsSfUAdcHmL1rpVE,2274
283
285
  atomicshop/wrappers/socketw/statistics_csv.py,sha256=t3dtDEfN47CfYVi0CW6Kc2QHTEeZVyYhc57IYYh5nmA,826
284
- atomicshop-2.14.4.dist-info/LICENSE.txt,sha256=lLU7EYycfYcK2NR_1gfnhnRC8b8ccOTElACYplgZN88,1094
285
- atomicshop-2.14.4.dist-info/METADATA,sha256=fjxtj_SzmyjVK6o_Z08jX-lLJoz7m_vYNPvn0fCoFYU,10478
286
- atomicshop-2.14.4.dist-info/WHEEL,sha256=GJ7t_kWBFywbagK5eo9IoUwLW6oyOeTKmQ-9iHFVNxQ,92
287
- atomicshop-2.14.4.dist-info/top_level.txt,sha256=EgKJB-7xcrAPeqTRF2laD_Np2gNGYkJkd4OyXqpJphA,11
288
- atomicshop-2.14.4.dist-info/RECORD,,
286
+ atomicshop-2.14.6.dist-info/LICENSE.txt,sha256=lLU7EYycfYcK2NR_1gfnhnRC8b8ccOTElACYplgZN88,1094
287
+ atomicshop-2.14.6.dist-info/METADATA,sha256=GxNk1sCw7qnOT6BX5QRiy9KCqX1KQfwt4lU0ESSxaos,10478
288
+ atomicshop-2.14.6.dist-info/WHEEL,sha256=GJ7t_kWBFywbagK5eo9IoUwLW6oyOeTKmQ-9iHFVNxQ,92
289
+ atomicshop-2.14.6.dist-info/top_level.txt,sha256=EgKJB-7xcrAPeqTRF2laD_Np2gNGYkJkd4OyXqpJphA,11
290
+ atomicshop-2.14.6.dist-info/RECORD,,