atomicshop 2.19.9__py3-none-any.whl → 2.19.11__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.19.9'
4
+ __version__ = '2.19.11'
@@ -41,6 +41,9 @@ def main():
41
41
  print_api("Initializing Robocorp Browser.")
42
42
  subprocess.check_call(["rfbrowser", "init"])
43
43
 
44
+ print_api("Installing Additional modules.")
45
+ subprocess.check_call(["pip", "install", "--upgrade", "matplotlib", "imagehash"])
46
+
44
47
  print_api("Installing Tesseract OCR.")
45
48
  github_wrapper = githubw.GitHubWrapper(
46
49
  user_name="tesseract-ocr",
atomicshop/etws/trace.py CHANGED
@@ -83,7 +83,7 @@ class EventTrace(etw.ETW):
83
83
 
84
84
  self.self_hosted_poller: bool = False
85
85
  if self.enable_process_poller:
86
- if not self.process_pool_shared_dict_proxy:
86
+ if self.process_pool_shared_dict_proxy is None:
87
87
  self.self_hosted_poller = True
88
88
  self.process_poller = simple_process_pool.SimpleProcessPool()
89
89
  self.multiprocessing_manager: multiprocessing.managers.SyncManager = multiprocessing.Manager()
@@ -98,7 +98,7 @@ class EventTrace(etw.ETW):
98
98
  )
99
99
 
100
100
  def start(self):
101
- if self.enable_process_poller:
101
+ if self.enable_process_poller and self.self_hosted_poller:
102
102
  self.process_poller.start()
103
103
 
104
104
  # Check if the session name already exists.
@@ -123,11 +123,10 @@ class EventTrace(etw.ETW):
123
123
  def stop(self):
124
124
  super().stop()
125
125
 
126
- if self.enable_process_poller:
126
+ if self.self_hosted_poller:
127
127
  self.process_poller.stop()
128
128
 
129
- if self.self_hosted_poller:
130
- self.multiprocessing_manager.shutdown()
129
+ self.multiprocessing_manager.shutdown()
131
130
 
132
131
  def emit(self):
133
132
  """
@@ -146,32 +145,21 @@ class EventTrace(etw.ETW):
146
145
  :return: etw event object.
147
146
  """
148
147
 
149
- # Get the processes first, since we need the process name and command line.
150
- # If they're not ready, we will get just pids from DNS tracing.
151
- if self.enable_process_poller:
152
- self._get_processes_from_poller()
153
-
154
148
  event: tuple = self.event_queue.get()
155
149
 
156
150
  event_dict: dict = {
157
151
  'EventId': event[0],
158
- 'EventHeader': event[1],
159
- 'pid': event[1]['EventHeader']['ProcessId']
152
+ 'EventHeader': event[1]
160
153
  }
161
154
 
155
+ if 'ProcessId' not in event[1]:
156
+ event_dict['pid'] = event[1]['EventHeader']['ProcessId']
157
+ else:
158
+ event_dict['pid'] = event[1]['ProcessId']
159
+
162
160
  if self.enable_process_poller:
163
161
  process_info: dict = self.pid_process_converter.get_process_by_pid(event_dict['pid'])
164
162
  event_dict['name'] = process_info['name']
165
163
  event_dict['cmdline'] = process_info['cmdline']
166
164
 
167
165
  return event_dict
168
-
169
- def _get_processes_from_poller(self):
170
- processes: dict = {}
171
- while not processes:
172
- processes = self.process_poller.get_processes()
173
-
174
- if isinstance(processes, BaseException):
175
- raise processes
176
-
177
- return processes
@@ -47,7 +47,7 @@ class DnsRequestResponseTrace:
47
47
 
48
48
 
49
49
  dns_trace_w = dns_trace.DnsTrace(
50
- attrs=['pid', 'name', 'cmdline', 'domain', 'query_type'],
50
+ attrs=['pid', 'name', 'cmdline', 'query', 'query_type'],
51
51
  session_name='MyDnsTrace',
52
52
  close_existing_session_name=True,
53
53
  enable_process_poller=True
@@ -0,0 +1,130 @@
1
+ import multiprocessing.managers
2
+
3
+ from .. import trace, const, providers
4
+ from ...basics import dicts
5
+ from ... import dns, ip_addresses
6
+
7
+
8
+ ETW_DEFAULT_SESSION_NAME: str = 'AtomicShopTcpTrace'
9
+
10
+ PROVIDER_NAME: str = "Microsoft-Windows-TCPIP"
11
+ PROVIDER_GUID: str = '{' + providers.get_provider_guid_by_name(PROVIDER_NAME) + '}'
12
+ REQUEST_RESP_EVENT_ID: int = 1033
13
+
14
+
15
+ class TcpIpNewConnectionsTrace:
16
+ """
17
+ TcpIpNewConnectionsTrace class use to trace new connection events from Windows Event Tracing:
18
+ Provider: Microsoft-Windows-TCPIP
19
+ EventId: 1033
20
+ """
21
+ def __init__(
22
+ self,
23
+ attrs: list = None,
24
+ session_name: str = None,
25
+ close_existing_session_name: bool = True,
26
+ process_pool_shared_dict_proxy: multiprocessing.managers.DictProxy = None
27
+ ):
28
+ """
29
+ :param attrs: List of attributes to return. If None, all attributes will be returned.
30
+ :param session_name: The name of the session to create. If not provided, a UUID will be generated.
31
+ :param close_existing_session_name: Boolean to close existing session names.
32
+ True: if ETW session with 'session_name' exists, you will be notified and the session will be closed.
33
+ Then the new session with this name will be created.
34
+ False: if ETW session with 'session_name' exists, you will be notified and the new session will not be
35
+ created. Instead, the existing session will be used. If there is a buffer from the previous session,
36
+ you will get the events from the buffer.
37
+ :param process_pool_shared_dict_proxy: multiprocessing.managers.DictProxy, multiprocessing shared dict proxy
38
+ that contains current processes.
39
+ Check the 'atomicshop\process_poller\simple_process_pool.py' SimpleProcessPool class for more information.
40
+
41
+ For this specific class it means that you can run the process poller outside of this class and pass the
42
+ 'process_pool_shared_dict_proxy' to this class. Then you can get the process name and command line for
43
+ the DNS events from the 'process_pool_shared_dict_proxy' and use it also in other classes.
44
+
45
+ -------------------------------------------------
46
+
47
+ Usage Example:
48
+ from atomicshop.etw import tcp_trace
49
+
50
+
51
+ tcp_trace_w = tcp_trace.TcpIpNewConnectionsTrace(
52
+ attrs=['pid', 'name', 'cmdline', 'domain', 'query_type'],
53
+ session_name='MyTcpTrace',
54
+ close_existing_session_name=True,
55
+ enable_process_poller=True
56
+ )
57
+ tcp_trace_w.start()
58
+ while True:
59
+ tcp_dict = tcp_trace_w.emit()
60
+ print(tcp_dict)
61
+ tcp_trace_w.stop()
62
+ """
63
+
64
+ self.attrs = attrs
65
+ self.process_pool_shared_dict_proxy: multiprocessing.managers.DictProxy = process_pool_shared_dict_proxy
66
+
67
+ if not session_name:
68
+ session_name = ETW_DEFAULT_SESSION_NAME
69
+
70
+ self.event_trace = trace.EventTrace(
71
+ providers=[(PROVIDER_NAME, PROVIDER_GUID)],
72
+ # lambda x: self.event_queue.put(x),
73
+ event_id_filters=[REQUEST_RESP_EVENT_ID],
74
+ session_name=session_name,
75
+ close_existing_session_name=close_existing_session_name,
76
+ enable_process_poller=True,
77
+ process_pool_shared_dict_proxy=self.process_pool_shared_dict_proxy
78
+ )
79
+
80
+ def start(self):
81
+ self.event_trace.start()
82
+
83
+ def stop(self):
84
+ self.event_trace.stop()
85
+
86
+ def emit(self):
87
+ """
88
+ Function that will return the next event from the queue.
89
+ The queue is blocking, so if there is no event in the queue, the function will wait until there is one.
90
+
91
+ Usage Example:
92
+ while True:
93
+ tcp_dict = tcp_trace.emit()
94
+ print(tcp_dict)
95
+
96
+ :return: Dictionary with the event data.
97
+ """
98
+
99
+ # Get the event from ETW as is.
100
+ event = self.event_trace.emit()
101
+
102
+ local_address_port: str = event['EventHeader']['LocalAddress']
103
+ remote_address_port: str = event['EventHeader']['RemoteAddress']
104
+
105
+ if 'ffff' in local_address_port:
106
+ pass
107
+
108
+ local_address, local_port = local_address_port.rsplit(':', 1)
109
+ local_address = local_address.replace('[', '').replace(']', '')
110
+
111
+ remote_address, remote_port = remote_address_port.rsplit(':', 1)
112
+ remote_address = remote_address.replace('[', '').replace(']', '')
113
+
114
+ event_dict: dict = {
115
+ 'event_id': event['EventId'],
116
+ 'local_ip': local_address,
117
+ 'local_port': local_port,
118
+ 'remote_ip': remote_address,
119
+ 'remote_port': remote_port,
120
+ 'status': event['EventHeader']['Status'],
121
+ 'pid': event['pid'],
122
+ 'name': event['name'],
123
+ 'cmdline': event['cmdline']
124
+ }
125
+
126
+ if self.attrs:
127
+ event_dict = dicts.reorder_keys(
128
+ event_dict, self.attrs, skip_keys_not_in_list=True)
129
+
130
+ return event_dict
@@ -1,8 +1,8 @@
1
1
  import os
2
2
  from datetime import datetime
3
- import json
4
3
  import queue
5
4
  import threading
5
+ from pathlib import Path
6
6
 
7
7
  from ...shared_functions import build_module_names, create_custom_logger
8
8
  from ... import message, recs_files
@@ -48,14 +48,9 @@ class RecorderParent:
48
48
  self.engine_record_path = self.record_path + os.sep + self.engine_name
49
49
 
50
50
  def build_record_full_file_path(self):
51
- # current date and time in object
52
- now = datetime.now()
53
- # Formatting the date and time and converting it to string object
54
- day_time_format: str = now.strftime(recs_files.REC_FILE_DATE_TIME_FORMAT)
55
-
56
51
  # If HTTP Path is not defined, 'http_path' will be empty, and it will not interfere with file name.
57
52
  self.record_file_path: str = (
58
- f"{self.engine_record_path}{os.sep}{day_time_format}_th{self.class_client_message.thread_id}_"
53
+ f"{self.engine_record_path}{os.sep}th{self.class_client_message.thread_id}_"
59
54
  f"{self.class_client_message.server_name}{self.file_extension}")
60
55
 
61
56
  def convert_messages(self):
@@ -100,11 +95,22 @@ class RecorderParent:
100
95
 
101
96
 
102
97
  def save_message_worker(
103
- record_file_path: str,
98
+ record_file_path_no_date: str,
104
99
  message_queue: queue.Queue,
105
100
  logger
106
101
  ):
107
102
  """Worker function to process messages from the queue and write them to the file."""
103
+ file_created: bool = False
104
+
105
+ original_file_path_object: Path = Path(record_file_path_no_date)
106
+ original_file_stem: str = original_file_path_object.stem
107
+ original_file_extension: str = original_file_path_object.suffix
108
+ original_file_directory: str = str(original_file_path_object.parent)
109
+
110
+ original_datetime_string: str = get_datetime_string()
111
+
112
+ record_file_path: str = f'{original_file_directory}{os.sep}{original_datetime_string}_{original_file_stem}{original_file_extension}'
113
+
108
114
  while True:
109
115
  # Get a message from the queue
110
116
  record_message_dict = message_queue.get()
@@ -113,6 +119,14 @@ def save_message_worker(
113
119
  if record_message_dict is None:
114
120
  break
115
121
 
122
+ # If the file not created yet, create it and change the creation flag.
123
+ if not file_created and not os.path.exists(record_file_path):
124
+ file_created = True
125
+ # If the file was created, and it doesn't exist, change the path recording file path to notify about it.
126
+ elif file_created and not os.path.exists(record_file_path):
127
+ current_datetime_string: str = get_datetime_string()
128
+ record_file_path = f'{original_file_directory}{os.sep}{current_datetime_string}_{original_file_stem}_partof_{original_datetime_string}{original_file_extension}'
129
+
116
130
  try:
117
131
  jsons.append_to_json(
118
132
  record_message_dict, record_file_path, indent=2,
@@ -126,3 +140,11 @@ def save_message_worker(
126
140
 
127
141
  # Indicate task completion
128
142
  message_queue.task_done()
143
+
144
+
145
+ def get_datetime_string():
146
+ # current date and time in object
147
+ now = datetime.now()
148
+ # Formatting the date and time and converting it to string object
149
+ day_time_format: str = now.strftime(recs_files.REC_FILE_DATE_TIME_FORMAT)
150
+ return day_time_format
@@ -23,6 +23,40 @@ class SimpleProcessPool:
23
23
  The idea is similar to the process_poller.process_pool.ProcessPool class, but this class is simpler and uses
24
24
  only the pywin32 tracing of the Windows Event Log Process Creation and Process Termination events.
25
25
  The simple process pool is used to get things simpler than the process_pool.ProcessPool class.
26
+
27
+ Example of starting the process pool in multiprocess:
28
+ import sys
29
+
30
+ from atomicshop.process_poller import simple_process_pool
31
+
32
+
33
+ def start_process_pool(process_pool_shared_dict_proxy):
34
+ process_poller = simple_process_pool.SimpleProcessPool(
35
+ process_pool_shared_dict_proxy=process_pool_shared_dict_proxy)
36
+ process_poller.start()
37
+
38
+ try:
39
+ # Keep the process alive.
40
+ while True:
41
+ time.sleep(1)
42
+ except KeyboardInterrupt:
43
+ process_poller.stop()
44
+
45
+
46
+ def main():
47
+ # Create the shared multiprocessing dictionary of the process pool.
48
+ manager = multiprocessing.Manager()
49
+ multiprocess_dict_proxy = manager.dict()
50
+
51
+ # Start the process pool in a separate process.
52
+ pool_process = multiprocessing.Process(target=start_process_pool, args=(multiprocess_dict_proxy,))
53
+ pool_process.start()
54
+
55
+ # Pass the shared dict proxy to other functions.
56
+
57
+
58
+ if __name__ == '__main__':
59
+ sys.exit(main())
26
60
  """
27
61
 
28
62
  def __init__(
@@ -79,7 +113,7 @@ class SimpleProcessPool:
79
113
  self._processes = get_process_list.GetProcessList(
80
114
  get_method='pywin32', connect_on_init=True).get_processes(as_dict=True)
81
115
 
82
- thread_get_queue = threading.Thread(target=self._start_main_thread)
116
+ thread_get_queue = threading.Thread(target=self._start_main_thread, args=(self.process_pool_shared_dict_proxy,))
83
117
  thread_get_queue.daemon = True
84
118
  thread_get_queue.start()
85
119
 
@@ -93,7 +127,7 @@ class SimpleProcessPool:
93
127
  def get_processes(self):
94
128
  return self._processes
95
129
 
96
- def _start_main_thread(self):
130
+ def _start_main_thread(self, process_pool_shared_dict_proxy):
97
131
  get_instance = process_create.ProcessCreateSubscriber()
98
132
  get_instance.start()
99
133
 
@@ -109,9 +143,9 @@ class SimpleProcessPool:
109
143
  }
110
144
 
111
145
  # Update the multiprocessing shared dict proxy.
112
- if self.process_pool_shared_dict_proxy:
113
- self.process_pool_shared_dict_proxy.clear()
114
- self.process_pool_shared_dict_proxy.update(self._processes)
146
+ if process_pool_shared_dict_proxy is not None:
147
+ process_pool_shared_dict_proxy.clear()
148
+ process_pool_shared_dict_proxy.update(self._processes)
115
149
 
116
150
  # print_api(f'Process [{process_id}] added to the pool.', color='blue')
117
151
 
@@ -186,6 +220,7 @@ class PidProcessConverter:
186
220
  process_dict: dict = dict()
187
221
  while counter < WAIT_FOR_PROCESS_POLLER_PID_COUNTS:
188
222
  if pid not in self.process_pool_shared_dict_proxy:
223
+ # print(dict(self.process_pool_shared_dict_proxy))
189
224
  time.sleep(0.1)
190
225
  counter += 1
191
226
  else:
@@ -193,6 +228,7 @@ class PidProcessConverter:
193
228
  break
194
229
 
195
230
  if counter == WAIT_FOR_PROCESS_POLLER_PID_COUNTS and not process_dict:
231
+ print_api(f"Error: The PID [{pid}] is not in the pool, trying DLL snapshot.", color='yellow')
196
232
  # Last resort, try to get the process name by current process snapshot.
197
233
  processes = self.get_process_with_dll_instance.get_process_details(as_dict=True)
198
234
  if pid not in processes:
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: atomicshop
3
- Version: 2.19.9
3
+ Version: 2.19.11
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=miL9aLeTH24dv_rrq3_DNotYp3c4Vv78Z3CWjZQyXrA,123
1
+ atomicshop/__init__.py,sha256=mHi1iDugkcLgj5LyCc_4EL-QVNq95QCoQWv522BGF1c,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
@@ -57,7 +57,7 @@ atomicshop/a_installs/win/fibratus.py,sha256=TU4e9gdZ_zI73C40uueJ59pD3qmN-UFGdX5
57
57
  atomicshop/a_installs/win/mongodb.py,sha256=AqyItXu19aaoe49pppDxtEkXey6PMy0PoT2Y_RmPpPE,179
58
58
  atomicshop/a_installs/win/nodejs.py,sha256=U519Dyt4bsQPbEg_PwnZL5tsbfqDr1BbhxwoQFZsSKo,200
59
59
  atomicshop/a_installs/win/pycharm.py,sha256=j_RSd7aDOyC3yDd-_GUTMLlQTmDrqtVFG--oUfGLiZk,140
60
- atomicshop/a_installs/win/robocorp.py,sha256=2E28iaRlAZROoxmXwiXv8rqTjVcdBT2UJ3B8nxrtmkc,2245
60
+ atomicshop/a_installs/win/robocorp.py,sha256=ExdMR705fW4iyNDZnH9YZMrio4FYEwNH_8nEP1GWkjM,2383
61
61
  atomicshop/a_installs/win/wsl_ubuntu_lts.py,sha256=dZbPRLNKFeMd6MotjkE6UDY9cOiIaaclIdR1kGYWI50,139
62
62
  atomicshop/a_mains/dns_gateway_setting.py,sha256=ncc2rFQCChxlNP59UshwmTonLqC6MWblrVAzbbz-13M,149
63
63
  atomicshop/a_mains/github_wrapper.py,sha256=F-PoZknVCxWPN0PTO6l7ZNiaYvo7OVFKFI_zlPt56ps,169
@@ -117,10 +117,11 @@ atomicshop/etws/_pywintrace_fix.py,sha256=nHrtnAb796eOZ6FlCqcsuRh_TSqSPp6JXLN6TB
117
117
  atomicshop/etws/const.py,sha256=v3x_IdCYeSKbCGywiZFOZln80ldpwKW5nuMDuUe51Jg,1257
118
118
  atomicshop/etws/providers.py,sha256=CXNx8pYdjtpLIpA66IwrnE64XhY4U5ExnFBMLEb8Uzk,547
119
119
  atomicshop/etws/sessions.py,sha256=b_KeiOvgOBJezJokN81TRlrvJiQNJlIWN4Z6UVjuxP0,1335
120
- atomicshop/etws/trace.py,sha256=LC5b_WGwk5LTVggnQ55F4Iklis7B7hVFWusOt1jEHnI,8068
120
+ atomicshop/etws/trace.py,sha256=p-5wegZ-5SuJ3UsprCCnlor8g2LPkF9ZOynLCYaEvXQ,7647
121
121
  atomicshop/etws/traces/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
122
- atomicshop/etws/traces/trace_dns.py,sha256=0a8zoq59NyJqy6Z6lf1qkvxrHcrCSnyYEAfLfBdJIuI,6880
122
+ atomicshop/etws/traces/trace_dns.py,sha256=SWeex1mK7rrMzCmmL3qiGaD_jzbRiiwJ_mhMZz5TwJc,6879
123
123
  atomicshop/etws/traces/trace_sysmon_process_creation.py,sha256=OM-bkK38uYMwWLZKNOTDa0Xdk3sO6sqsxoMUIiPvm5g,4656
124
+ atomicshop/etws/traces/trace_tcp.py,sha256=pQF4A_qM-HjEhzMQUyTmUqOWdvSaqqAg5PwnkVn2fy4,5236
124
125
  atomicshop/file_io/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
125
126
  atomicshop/file_io/csvs.py,sha256=zv0kKjRT-ZWRi0WpMIUQ_FKyP9Dt0f5Bc98Qsj6ClPU,9495
126
127
  atomicshop/file_io/docxs.py,sha256=Nyt3hSpzwqUKZEP5p5efqNpjFs9XqkK40Kp7BbbPo7E,6245
@@ -145,7 +146,7 @@ atomicshop/mitm/engines/create_module_template.py,sha256=TAzsA4eLD2wYr7auuL4Nf_7
145
146
  atomicshop/mitm/engines/create_module_template_example.py,sha256=X5xhvbV6-g9jU_bQVhf_crZmaH50LRWz3bS-faQ18ds,489
146
147
  atomicshop/mitm/engines/__parent/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
147
148
  atomicshop/mitm/engines/__parent/parser___parent.py,sha256=HHaCXhScl3OlPjz6eUxsDpJaZyk6BNuDMc9xCkeo2Ws,661
148
- atomicshop/mitm/engines/__parent/recorder___parent.py,sha256=vG2h46CojK4jIinXmME2VwJFSWKygh4ayMwZyejwwI0,4846
149
+ atomicshop/mitm/engines/__parent/recorder___parent.py,sha256=JbbcpV6j4odvREmvcXQlzKr5_hwLiEHhF0O414PlTes,6010
149
150
  atomicshop/mitm/engines/__parent/responder___parent.py,sha256=yEgR33CkAd1b9jyH5E8I4E16upqjlcK3WLo3BFHdjyk,9157
150
151
  atomicshop/mitm/engines/__reference_general/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
151
152
  atomicshop/mitm/engines/__reference_general/parser___reference_general.py,sha256=57MEPZMAjTO6xBDZ-yt6lgGJyqRrP0Do5Gk_cgCiPns,2998
@@ -168,7 +169,7 @@ atomicshop/permissions/ubuntu_permissions.py,sha256=n8z1vcIXDts4zLVue33dtJiTopjg
168
169
  atomicshop/permissions/win_permissions.py,sha256=eDQm1jfK9x_hkbLqIJjFTwfqinAWQ0iSr0kW3XrF1BE,1272
169
170
  atomicshop/process_poller/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
170
171
  atomicshop/process_poller/process_pool.py,sha256=4Qs427qd7OcBxu5PMFU5PTmyuxRy0vgj2GLsRt0IoEw,9565
171
- atomicshop/process_poller/simple_process_pool.py,sha256=tbeuw30MvNFbore1YooEra1ozZvFR8maKbcGNlBpBKc,8484
172
+ atomicshop/process_poller/simple_process_pool.py,sha256=E0w66imLQQ0phHuTQfTaApOTurX0duE9vw1trjUY7rI,9894
172
173
  atomicshop/process_poller/tracer_base.py,sha256=IOiHcnmF-MccOSCErixN5mve9RifZ9cPnGVHCIRchrs,1091
173
174
  atomicshop/process_poller/pollers/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
174
175
  atomicshop/process_poller/pollers/psutil_pywin32wmi_dll.py,sha256=XRRfOIy62iOYU8IKRcyECWiL0rqQ35DeYbPsv_SHDVM,4510
@@ -327,8 +328,8 @@ atomicshop/wrappers/socketw/statistics_csv.py,sha256=fgMzDXI0cybwUEqAxprRmY3lqbh
327
328
  atomicshop/wrappers/winregw/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
328
329
  atomicshop/wrappers/winregw/winreg_installed_software.py,sha256=Qzmyktvob1qp6Tjk2DjLfAqr_yXV0sgWzdMW_9kwNjY,2345
329
330
  atomicshop/wrappers/winregw/winreg_network.py,sha256=AENV88H1qDidrcpyM9OwEZxX5svfi-Jb4N6FkS1xtqA,8851
330
- atomicshop-2.19.9.dist-info/LICENSE.txt,sha256=lLU7EYycfYcK2NR_1gfnhnRC8b8ccOTElACYplgZN88,1094
331
- atomicshop-2.19.9.dist-info/METADATA,sha256=Q4n9PKQsRSE0ite3_TvSdyFuO7agblLmWIMekjlvmx4,10630
332
- atomicshop-2.19.9.dist-info/WHEEL,sha256=GJ7t_kWBFywbagK5eo9IoUwLW6oyOeTKmQ-9iHFVNxQ,92
333
- atomicshop-2.19.9.dist-info/top_level.txt,sha256=EgKJB-7xcrAPeqTRF2laD_Np2gNGYkJkd4OyXqpJphA,11
334
- atomicshop-2.19.9.dist-info/RECORD,,
331
+ atomicshop-2.19.11.dist-info/LICENSE.txt,sha256=lLU7EYycfYcK2NR_1gfnhnRC8b8ccOTElACYplgZN88,1094
332
+ atomicshop-2.19.11.dist-info/METADATA,sha256=tSnPcFSBceRSRX3c335xVMPu5zruA6fmE8ifV12MW-8,10631
333
+ atomicshop-2.19.11.dist-info/WHEEL,sha256=GJ7t_kWBFywbagK5eo9IoUwLW6oyOeTKmQ-9iHFVNxQ,92
334
+ atomicshop-2.19.11.dist-info/top_level.txt,sha256=EgKJB-7xcrAPeqTRF2laD_Np2gNGYkJkd4OyXqpJphA,11
335
+ atomicshop-2.19.11.dist-info/RECORD,,