atomicshop 2.12.14__py3-none-any.whl → 2.12.16__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of atomicshop might be problematic. Click here for more details.

atomicshop/__init__.py CHANGED
@@ -1,4 +1,4 @@
1
1
  """Atomic Basic functions and classes to make developer life easier"""
2
2
 
3
3
  __author__ = "Den Kras"
4
- __version__ = '2.12.14'
4
+ __version__ = '2.12.16'
@@ -30,8 +30,10 @@ def read_csv_to_list_of_dicts_by_header(
30
30
  :param file_mode: string, file reading mode. Examples: 'r', 'rb'. Default is 'r'.
31
31
  :param encoding: string, encoding of the file. Default is 'None'.
32
32
  :param header: list, list of strings that will be the header of the CSV file. Default is 'None'.
33
- If you want to use the header from the CSV file, use 'None'. In this case, the first row of the CSV file will
34
- be the header.
33
+ None: the header from the CSV file will be used. The first row of the CSV file will be the header.
34
+ Meaning, that the first line will be skipped and the second line will be the first row of the content.
35
+ List: the list will be used as header.
36
+ All the lines of the CSV file will be considered as content.
35
37
  :param file_object: file object of the 'open()' function in the decorator. Decorator executes the 'with open()'
36
38
  statement and passes to this function. That's why the default is 'None', since we get it from the decorator.
37
39
  :return: list.
@@ -1,4 +1,5 @@
1
1
  from typing import Literal, Union
2
+ import queue
2
3
 
3
4
  from .checks import dns, network, hash, process_running
4
5
  from .. import filesystem, scheduling
@@ -177,8 +178,6 @@ class ChangeMonitor:
177
178
  self.fetch_engine = None
178
179
  self.thread_looper = scheduling.ThreadLooper()
179
180
 
180
- self.statistics_queue = None
181
-
182
181
  def _set_input_file_path(self, check_object_index: int = 0):
183
182
  if self.first_cycle:
184
183
  # If 'input_file_directory' and 'input_file_name' are specified, we'll use a filename to store.
@@ -32,8 +32,8 @@ def _execute_cycle(change_monitor_instance, print_kwargs: dict = None):
32
32
 
33
33
  # Since the 'operation_type' is 'hit_statistics', we'll set the 'statistics_queue' to the 'statistics_queue' of
34
34
  # the 'diff_check_list[0]'.
35
- if change_monitor_instance.diff_check_list[0].operation_type == 'hit_statistics':
36
- change_monitor_instance.statistics_queue = change_monitor_instance.diff_check_list[0].statistics_queue
35
+ # if change_monitor_instance.diff_check_list[0].operation_type == 'hit_statistics':
36
+ # change_monitor_instance.statistics_queue = change_monitor_instance.diff_check_list[0].statistics_queue
37
37
 
38
38
  if change_monitor_instance.generate_input_file_name:
39
39
  original_name = 'known_domains'
@@ -7,6 +7,7 @@ from ...file_io import csvs
7
7
 
8
8
 
9
9
  READING_EXISTING_LINES: list = []
10
+ EXISTING_LOGS_FILE_COUNT: int = 0
10
11
 
11
12
 
12
13
  def get_logs_paths(
@@ -80,7 +81,8 @@ def get_logs_paths(
80
81
  current_file_name: str = Path(single_file['file_path']).name
81
82
  # Get the datetime object from the file name by the date pattern.
82
83
  try:
83
- datetime_object = datetimes.get_datetime_from_complex_string_by_pattern(current_file_name, date_pattern)
84
+ datetime_object = datetimes.get_datetime_from_complex_string_by_pattern(
85
+ current_file_name, date_pattern)
84
86
  timestamp_float = datetime_object.timestamp()
85
87
  # ValueError will be raised if the date pattern does not match the file name.
86
88
  except ValueError:
@@ -210,7 +212,8 @@ def get_latest_lines(
210
212
  log_file_path: str,
211
213
  date_pattern: str = None,
212
214
  log_type: Literal['csv'] = 'csv',
213
- get_previous_file: bool = False
215
+ get_previous_file: bool = False,
216
+ header: list = None
214
217
  ) -> tuple:
215
218
  """
216
219
  This function gets the latest lines from the log file.
@@ -225,6 +228,11 @@ def get_latest_lines(
225
228
  Meaning, once the day will change, the function will get the log file from the previous day in the third entry
226
229
  of the return tuple. This happens only once each 24 hours. Not from the time the function was called, but from
227
230
  the time the day changed.
231
+ :param header: List of strings that will be the header of the CSV file. Default is 'None'.
232
+ None: the header from the CSV file will be used. The first row of the CSV file will be the header.
233
+ Meaning, that the first line will be skipped and the second line will be the first row of the content.
234
+ List: the list will be used as header.
235
+ All the lines of the CSV file will be considered as content.
228
236
  return: List of new lines.
229
237
 
230
238
  Usage:
@@ -243,6 +251,31 @@ def get_latest_lines(
243
251
  time.sleep(1)
244
252
  """
245
253
 
254
+ def extract_new_lines_only(content_lines: list):
255
+ new_lines: list = []
256
+ for row in content_lines:
257
+ # If the row is not in the existing lines, then add it to the new lines.
258
+ if row not in READING_EXISTING_LINES:
259
+ new_lines.append(row)
260
+
261
+ if new_lines:
262
+ READING_EXISTING_LINES.extend(new_lines)
263
+
264
+ return new_lines
265
+
266
+ global EXISTING_LOGS_FILE_COUNT
267
+
268
+ # If the existing logs file count is 0, it means that this is the first check. We need to get the current count.
269
+ if EXISTING_LOGS_FILE_COUNT == 0:
270
+ EXISTING_LOGS_FILE_COUNT = len(get_logs_paths(
271
+ log_file_path=log_file_path,
272
+ log_type='csv'
273
+ ))
274
+
275
+ # If the count is still 0, then there are no logs to read.
276
+ if EXISTING_LOGS_FILE_COUNT == 0:
277
+ return [], [], header
278
+
246
279
  if log_type != 'csv':
247
280
  raise ValueError('Only "csv" log type is supported.')
248
281
 
@@ -256,9 +289,6 @@ def get_latest_lines(
256
289
  latest_only=True
257
290
  )
258
291
 
259
- if not latest_statistics_file_path_object:
260
- return [], [], [], []
261
-
262
292
  latest_statistics_file_path: str = latest_statistics_file_path_object[0]['file_path']
263
293
 
264
294
  # Get the previous day statistics file path.
@@ -273,32 +303,36 @@ def get_latest_lines(
273
303
  except KeyError:
274
304
  pass
275
305
 
276
- current_lines, _ = csvs.read_csv_to_list_of_dicts_by_header(latest_statistics_file_path, stdout=False)
277
- if len(current_lines) > len(READING_EXISTING_LINES):
278
- # return current_lines
279
- pass
280
- elif len(current_lines) == len(READING_EXISTING_LINES):
281
- # return None
282
- pass
283
- elif len(current_lines) < len(READING_EXISTING_LINES):
284
- current_lines, _ = csvs.read_csv_to_list_of_dicts_by_header(
285
- previous_day_statistics_file_path, stdout=False)
286
- # Handle case where source CSV is empty (rotation period)
287
- READING_EXISTING_LINES.clear() # Clear existing lines to start fresh after rotation
306
+ # Count all the rotated files.
307
+ current_log_files_count: int = len(get_logs_paths(
308
+ log_file_path=log_file_path,
309
+ log_type='csv'
310
+ ))
311
+
312
+ # If the count of the log files is greater than the existing logs file count, it means that the rotation happened.
313
+ # We will read the previous day statistics file.
314
+ new_lines_from_previous_file: list = []
315
+ if current_log_files_count > EXISTING_LOGS_FILE_COUNT:
316
+ current_lines, header = csvs.read_csv_to_list_of_dicts_by_header(
317
+ previous_day_statistics_file_path, header=header, stdout=False)
288
318
 
289
319
  if get_previous_file:
290
320
  previous_file_lines = current_lines
291
321
 
292
- # return current_lines
322
+ EXISTING_LOGS_FILE_COUNT = current_log_files_count
293
323
 
294
- new_lines: list = []
295
- if current_lines:
296
- for row in current_lines:
297
- # If the row is not in the existing lines, then add it to the new lines.
298
- if row not in READING_EXISTING_LINES:
299
- new_lines.append(row)
324
+ new_lines_from_previous_file = extract_new_lines_only(current_lines)
300
325
 
301
- if new_lines:
302
- READING_EXISTING_LINES.extend(new_lines)
326
+ # empty the previous file lines, since the file is rotated.
327
+ READING_EXISTING_LINES.clear()
328
+
329
+ current_lines, header = csvs.read_csv_to_list_of_dicts_by_header(
330
+ latest_statistics_file_path, header=header, stdout=False)
331
+
332
+ new_lines = extract_new_lines_only(current_lines)
333
+
334
+ # If we have new lines from the previous file, we will add the new lines from the latest file.
335
+ if new_lines_from_previous_file:
336
+ new_lines = new_lines_from_previous_file + new_lines
303
337
 
304
- return new_lines, current_lines, READING_EXISTING_LINES, previous_file_lines
338
+ return new_lines, previous_file_lines, header
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: atomicshop
3
- Version: 2.12.14
3
+ Version: 2.12.16
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=tw0lYy9Sp2JgTrAihCaPpbykgJv4vMC4CT3cyGXNrfY,124
1
+ atomicshop/__init__.py,sha256=Z-gJW-h7oTdZn_6KXbNYPQPfdC6kDWJvf5xxT1uoArA,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
@@ -104,7 +104,7 @@ atomicshop/etw/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
104
104
  atomicshop/etw/dns_trace.py,sha256=I4OZsiZUDyj7B4fKTOqsB1tcX1DUMw9uh4CwXlcmHfY,5571
105
105
  atomicshop/etw/etw.py,sha256=xVJNbfCq4KgRfsDnul6CrIdAMl9xRBixZ-hUyqiB2g4,2403
106
106
  atomicshop/file_io/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
107
- atomicshop/file_io/csvs.py,sha256=oc4ijOHYzayx89DfW2_cktrf81kcGVFKUvKQDAljVrA,5300
107
+ atomicshop/file_io/csvs.py,sha256=WOtDyVFhhA1RD3yrU9P33kDY1EKFEz8UmVCUkqYKuog,5503
108
108
  atomicshop/file_io/docxs.py,sha256=6tcYFGp0vRsHR47VwcRqwhdt2DQOwrAUYhrwN996n9U,5117
109
109
  atomicshop/file_io/file_io.py,sha256=FR84ihjGlr7Eqejo-_js4nBICVst31axD0bwX19S2eM,6385
110
110
  atomicshop/file_io/jsons.py,sha256=q9ZU8slBKnHLrtn3TnbK1qxrRpj5ZvCm6AlsFzoANjo,5303
@@ -132,9 +132,9 @@ atomicshop/mitm/engines/__reference_general/parser___reference_general.py,sha256
132
132
  atomicshop/mitm/engines/__reference_general/recorder___reference_general.py,sha256=KENDVf9OwXD9gwSh4B1XxACCe7iHYjrvnW1t6F64wdE,695
133
133
  atomicshop/mitm/engines/__reference_general/responder___reference_general.py,sha256=1AM49UaFTKA0AHw-k3SV3uH3QbG-o6ux0c-GoWkKNU0,6993
134
134
  atomicshop/monitor/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
135
- atomicshop/monitor/change_monitor.py,sha256=NgadgPynRohII4m5oawWfQXTTj5lUx8gj38Tuk1sWOg,12247
135
+ atomicshop/monitor/change_monitor.py,sha256=FUAolHTWVFfC14K2cTMK1NE6ORp37A0fCrfwNbxmbIs,12221
136
136
  atomicshop/monitor/checks/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
137
- atomicshop/monitor/checks/dns.py,sha256=QOjvIQZndETomgTuY1PcEbUJkZkRtr6GcRV3Tfbu89c,4866
137
+ atomicshop/monitor/checks/dns.py,sha256=wX53eGX2F5_lBDLL5D6dFb3XThdt3iwoYKnP05WZKfc,4870
138
138
  atomicshop/monitor/checks/hash.py,sha256=A6bJ7F5Qv_brdEh3sGhOyfviab2dsnvbXUufyBk5C1U,1951
139
139
  atomicshop/monitor/checks/network.py,sha256=I9f3KyNnlx97E8igGZXpVJl4MlUp9iU6aSbILCKqbA0,3820
140
140
  atomicshop/monitor/checks/process_running.py,sha256=948Sify4P2KFTE1ZrLHKLwd1B1HOgWmC11x3b6MCvz0,1892
@@ -216,7 +216,7 @@ atomicshop/wrappers/loggingw/formatters.py,sha256=mUtcJJfmhLNrwUVYShXTmdu40dBaJu
216
216
  atomicshop/wrappers/loggingw/handlers.py,sha256=qm5Fbu8eDmlstMduUe5nKUlJU5IazFkSnQizz8Qt2os,5479
217
217
  atomicshop/wrappers/loggingw/loggers.py,sha256=DHOOTAtqkwn1xgvLHSkOiBm6yFGNuQy1kvbhG-TDog8,2374
218
218
  atomicshop/wrappers/loggingw/loggingw.py,sha256=v9WAseZXB50LluT9rIUcRvvevg2nLVKPgz3dbGejfV0,12151
219
- atomicshop/wrappers/loggingw/reading.py,sha256=iw7tIN8rBFIJ7zKKPHhAGWRK4I_OE79qMg9EYsN2HkE,13462
219
+ atomicshop/wrappers/loggingw/reading.py,sha256=CtYOwOLFHj_hqYyZx-dKUo5ZDrn3cO-f7vU4EX515xI,14980
220
220
  atomicshop/wrappers/nodejsw/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
221
221
  atomicshop/wrappers/nodejsw/install_nodejs.py,sha256=QZg-R2iTQt7kFb8wNtnTmwraSGwvUs34JIasdbNa7ZU,5154
222
222
  atomicshop/wrappers/playwrightw/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
@@ -251,8 +251,8 @@ atomicshop/wrappers/socketw/socket_server_tester.py,sha256=AhpurHJmP2kgzHaUbq5ey
251
251
  atomicshop/wrappers/socketw/socket_wrapper.py,sha256=aXBwlEIJhFT0-c4i8iNlFx2It9VpCEpsv--5Oqcpxao,11624
252
252
  atomicshop/wrappers/socketw/ssl_base.py,sha256=k4V3gwkbq10MvOH4btU4onLX2GNOsSfUAdcHmL1rpVE,2274
253
253
  atomicshop/wrappers/socketw/statistics_csv.py,sha256=t3dtDEfN47CfYVi0CW6Kc2QHTEeZVyYhc57IYYh5nmA,826
254
- atomicshop-2.12.14.dist-info/LICENSE.txt,sha256=lLU7EYycfYcK2NR_1gfnhnRC8b8ccOTElACYplgZN88,1094
255
- atomicshop-2.12.14.dist-info/METADATA,sha256=xYvYxNyhyTZ2kOm4aS6UZGYdPWIZy3TAX1lKCXp39us,10479
256
- atomicshop-2.12.14.dist-info/WHEEL,sha256=GJ7t_kWBFywbagK5eo9IoUwLW6oyOeTKmQ-9iHFVNxQ,92
257
- atomicshop-2.12.14.dist-info/top_level.txt,sha256=EgKJB-7xcrAPeqTRF2laD_Np2gNGYkJkd4OyXqpJphA,11
258
- atomicshop-2.12.14.dist-info/RECORD,,
254
+ atomicshop-2.12.16.dist-info/LICENSE.txt,sha256=lLU7EYycfYcK2NR_1gfnhnRC8b8ccOTElACYplgZN88,1094
255
+ atomicshop-2.12.16.dist-info/METADATA,sha256=Sxe0EOSeHGX8jfjldfji7N3m_tORqIzRpxLiy7npPCY,10479
256
+ atomicshop-2.12.16.dist-info/WHEEL,sha256=GJ7t_kWBFywbagK5eo9IoUwLW6oyOeTKmQ-9iHFVNxQ,92
257
+ atomicshop-2.12.16.dist-info/top_level.txt,sha256=EgKJB-7xcrAPeqTRF2laD_Np2gNGYkJkd4OyXqpJphA,11
258
+ atomicshop-2.12.16.dist-info/RECORD,,