atomicshop 2.11.47__py3-none-any.whl → 3.10.5__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.
Files changed (268) hide show
  1. atomicshop/__init__.py +1 -1
  2. atomicshop/{addons/mains → a_mains}/FACT/update_extract.py +3 -2
  3. atomicshop/a_mains/addons/process_list/compile.cmd +7 -0
  4. atomicshop/a_mains/addons/process_list/compiled/Win10x64/process_list.dll +0 -0
  5. atomicshop/a_mains/addons/process_list/compiled/Win10x64/process_list.exp +0 -0
  6. atomicshop/a_mains/addons/process_list/compiled/Win10x64/process_list.lib +0 -0
  7. atomicshop/{addons → a_mains/addons}/process_list/process_list.cpp +8 -1
  8. atomicshop/a_mains/dns_gateway_setting.py +11 -0
  9. atomicshop/a_mains/get_local_tcp_ports.py +85 -0
  10. atomicshop/a_mains/github_wrapper.py +11 -0
  11. atomicshop/a_mains/install_ca_certificate.py +172 -0
  12. atomicshop/{addons/mains → a_mains}/msi_unpacker.py +3 -1
  13. atomicshop/a_mains/process_from_port.py +119 -0
  14. atomicshop/a_mains/set_default_dns_gateway.py +90 -0
  15. atomicshop/a_mains/update_config_toml.py +38 -0
  16. atomicshop/appointment_management.py +5 -3
  17. atomicshop/basics/ansi_escape_codes.py +3 -1
  18. atomicshop/basics/argparse_template.py +2 -0
  19. atomicshop/basics/booleans.py +27 -30
  20. atomicshop/basics/bytes_arrays.py +43 -0
  21. atomicshop/basics/classes.py +149 -1
  22. atomicshop/basics/dicts.py +12 -0
  23. atomicshop/basics/enums.py +2 -2
  24. atomicshop/basics/exceptions.py +5 -1
  25. atomicshop/basics/list_of_classes.py +29 -0
  26. atomicshop/basics/list_of_dicts.py +69 -5
  27. atomicshop/basics/lists.py +14 -0
  28. atomicshop/basics/multiprocesses.py +374 -50
  29. atomicshop/basics/package_module.py +10 -0
  30. atomicshop/basics/strings.py +160 -7
  31. atomicshop/basics/threads.py +14 -0
  32. atomicshop/basics/tracebacks.py +13 -4
  33. atomicshop/certificates.py +153 -52
  34. atomicshop/config_init.py +12 -7
  35. atomicshop/console_user_response.py +7 -14
  36. atomicshop/consoles.py +9 -0
  37. atomicshop/datetimes.py +98 -0
  38. atomicshop/diff_check.py +340 -40
  39. atomicshop/dns.py +128 -12
  40. atomicshop/etws/_pywintrace_fix.py +17 -0
  41. atomicshop/etws/const.py +38 -0
  42. atomicshop/etws/providers.py +21 -0
  43. atomicshop/etws/sessions.py +43 -0
  44. atomicshop/etws/trace.py +168 -0
  45. atomicshop/etws/traces/trace_dns.py +162 -0
  46. atomicshop/etws/traces/trace_sysmon_process_creation.py +126 -0
  47. atomicshop/etws/traces/trace_tcp.py +130 -0
  48. atomicshop/file_io/csvs.py +222 -24
  49. atomicshop/file_io/docxs.py +35 -18
  50. atomicshop/file_io/file_io.py +35 -19
  51. atomicshop/file_io/jsons.py +49 -0
  52. atomicshop/file_io/tomls.py +139 -0
  53. atomicshop/filesystem.py +864 -293
  54. atomicshop/get_process_list.py +133 -0
  55. atomicshop/{process_name_cmd.py → get_process_name_cmd_dll.py} +52 -19
  56. atomicshop/http_parse.py +149 -93
  57. atomicshop/ip_addresses.py +6 -1
  58. atomicshop/mitm/centered_settings.py +132 -0
  59. atomicshop/mitm/config_static.py +207 -0
  60. atomicshop/mitm/config_toml_editor.py +55 -0
  61. atomicshop/mitm/connection_thread_worker.py +875 -357
  62. atomicshop/mitm/engines/__parent/parser___parent.py +4 -17
  63. atomicshop/mitm/engines/__parent/recorder___parent.py +108 -51
  64. atomicshop/mitm/engines/__parent/requester___parent.py +116 -0
  65. atomicshop/mitm/engines/__parent/responder___parent.py +75 -114
  66. atomicshop/mitm/engines/__reference_general/parser___reference_general.py +10 -7
  67. atomicshop/mitm/engines/__reference_general/recorder___reference_general.py +5 -5
  68. atomicshop/mitm/engines/__reference_general/requester___reference_general.py +47 -0
  69. atomicshop/mitm/engines/__reference_general/responder___reference_general.py +95 -13
  70. atomicshop/mitm/engines/create_module_template.py +58 -14
  71. atomicshop/mitm/import_config.py +359 -139
  72. atomicshop/mitm/initialize_engines.py +160 -74
  73. atomicshop/mitm/message.py +64 -23
  74. atomicshop/mitm/mitm_main.py +892 -0
  75. atomicshop/mitm/recs_files.py +183 -0
  76. atomicshop/mitm/shared_functions.py +4 -10
  77. atomicshop/mitm/ssh_tester.py +82 -0
  78. atomicshop/mitm/statistic_analyzer.py +257 -166
  79. atomicshop/mitm/statistic_analyzer_helper/analyzer_helper.py +136 -0
  80. atomicshop/mitm/statistic_analyzer_helper/moving_average_helper.py +525 -0
  81. atomicshop/monitor/change_monitor.py +96 -120
  82. atomicshop/monitor/checks/dns.py +139 -70
  83. atomicshop/monitor/checks/file.py +77 -0
  84. atomicshop/monitor/checks/network.py +81 -77
  85. atomicshop/monitor/checks/process_running.py +33 -34
  86. atomicshop/monitor/checks/url.py +94 -0
  87. atomicshop/networks.py +671 -0
  88. atomicshop/on_exit.py +205 -0
  89. atomicshop/package_mains_processor.py +84 -0
  90. atomicshop/permissions/permissions.py +22 -0
  91. atomicshop/permissions/ubuntu_permissions.py +239 -0
  92. atomicshop/permissions/win_permissions.py +33 -0
  93. atomicshop/print_api.py +24 -41
  94. atomicshop/process.py +63 -17
  95. atomicshop/process_poller/__init__.py +0 -0
  96. atomicshop/process_poller/pollers/__init__.py +0 -0
  97. atomicshop/process_poller/pollers/psutil_pywin32wmi_dll.py +95 -0
  98. atomicshop/process_poller/process_pool.py +207 -0
  99. atomicshop/process_poller/simple_process_pool.py +311 -0
  100. atomicshop/process_poller/tracer_base.py +45 -0
  101. atomicshop/process_poller/tracers/__init__.py +0 -0
  102. atomicshop/process_poller/tracers/event_log.py +46 -0
  103. atomicshop/process_poller/tracers/sysmon_etw.py +68 -0
  104. atomicshop/python_file_patcher.py +1 -1
  105. atomicshop/python_functions.py +27 -75
  106. atomicshop/question_answer_engine.py +2 -2
  107. atomicshop/scheduling.py +24 -5
  108. atomicshop/sound.py +4 -2
  109. atomicshop/speech_recognize.py +8 -0
  110. atomicshop/ssh_remote.py +158 -172
  111. atomicshop/startup/__init__.py +0 -0
  112. atomicshop/startup/win/__init__.py +0 -0
  113. atomicshop/startup/win/startup_folder.py +53 -0
  114. atomicshop/startup/win/task_scheduler.py +119 -0
  115. atomicshop/system_resource_monitor.py +61 -46
  116. atomicshop/system_resources.py +8 -8
  117. atomicshop/tempfiles.py +1 -2
  118. atomicshop/timer.py +30 -11
  119. atomicshop/urls.py +41 -0
  120. atomicshop/venvs.py +28 -0
  121. atomicshop/versioning.py +27 -0
  122. atomicshop/web.py +110 -25
  123. atomicshop/web_apis/__init__.py +0 -0
  124. atomicshop/web_apis/google_custom_search.py +44 -0
  125. atomicshop/web_apis/google_llm.py +188 -0
  126. atomicshop/websocket_parse.py +450 -0
  127. atomicshop/wrappers/certauthw/certauth.py +1 -0
  128. atomicshop/wrappers/cryptographyw.py +29 -8
  129. atomicshop/wrappers/ctyping/etw_winapi/__init__.py +0 -0
  130. atomicshop/wrappers/ctyping/etw_winapi/const.py +335 -0
  131. atomicshop/wrappers/ctyping/etw_winapi/etw_functions.py +393 -0
  132. atomicshop/wrappers/ctyping/file_details_winapi.py +67 -0
  133. atomicshop/wrappers/ctyping/msi_windows_installer/cabs.py +2 -1
  134. atomicshop/wrappers/ctyping/msi_windows_installer/extract_msi_main.py +13 -9
  135. atomicshop/wrappers/ctyping/msi_windows_installer/tables.py +35 -0
  136. atomicshop/wrappers/ctyping/setup_device.py +466 -0
  137. atomicshop/wrappers/ctyping/win_console.py +39 -0
  138. atomicshop/wrappers/dockerw/dockerw.py +113 -2
  139. atomicshop/wrappers/elasticsearchw/config_basic.py +0 -12
  140. atomicshop/wrappers/elasticsearchw/elastic_infra.py +75 -0
  141. atomicshop/wrappers/elasticsearchw/elasticsearchw.py +2 -20
  142. atomicshop/wrappers/factw/get_file_data.py +12 -5
  143. atomicshop/wrappers/factw/install/install_after_restart.py +89 -5
  144. atomicshop/wrappers/factw/install/pre_install_and_install_before_restart.py +20 -14
  145. atomicshop/wrappers/factw/postgresql/firmware.py +4 -6
  146. atomicshop/wrappers/githubw.py +583 -51
  147. atomicshop/wrappers/loggingw/consts.py +49 -0
  148. atomicshop/wrappers/loggingw/filters.py +102 -0
  149. atomicshop/wrappers/loggingw/formatters.py +58 -71
  150. atomicshop/wrappers/loggingw/handlers.py +459 -40
  151. atomicshop/wrappers/loggingw/loggers.py +19 -0
  152. atomicshop/wrappers/loggingw/loggingw.py +1010 -178
  153. atomicshop/wrappers/loggingw/reading.py +344 -19
  154. atomicshop/wrappers/mongodbw/__init__.py +0 -0
  155. atomicshop/wrappers/mongodbw/mongo_infra.py +31 -0
  156. atomicshop/wrappers/mongodbw/mongodbw.py +1432 -0
  157. atomicshop/wrappers/netshw.py +271 -0
  158. atomicshop/wrappers/playwrightw/engine.py +34 -19
  159. atomicshop/wrappers/playwrightw/infra.py +5 -0
  160. atomicshop/wrappers/playwrightw/javascript.py +7 -3
  161. atomicshop/wrappers/playwrightw/keyboard.py +14 -0
  162. atomicshop/wrappers/playwrightw/scenarios.py +172 -5
  163. atomicshop/wrappers/playwrightw/waits.py +9 -7
  164. atomicshop/wrappers/powershell_networking.py +80 -0
  165. atomicshop/wrappers/psutilw/processes.py +81 -0
  166. atomicshop/wrappers/psutilw/psutil_networks.py +85 -0
  167. atomicshop/wrappers/psutilw/psutilw.py +9 -0
  168. atomicshop/wrappers/pyopensslw.py +9 -2
  169. atomicshop/wrappers/pywin32w/__init__.py +0 -0
  170. atomicshop/wrappers/pywin32w/cert_store.py +116 -0
  171. atomicshop/wrappers/pywin32w/console.py +34 -0
  172. atomicshop/wrappers/pywin32w/win_event_log/__init__.py +0 -0
  173. atomicshop/wrappers/pywin32w/win_event_log/fetch.py +174 -0
  174. atomicshop/wrappers/pywin32w/win_event_log/subscribe.py +212 -0
  175. atomicshop/wrappers/pywin32w/win_event_log/subscribes/__init__.py +0 -0
  176. atomicshop/wrappers/pywin32w/win_event_log/subscribes/process_create.py +57 -0
  177. atomicshop/wrappers/pywin32w/win_event_log/subscribes/process_terminate.py +49 -0
  178. atomicshop/wrappers/pywin32w/win_event_log/subscribes/schannel_logging.py +97 -0
  179. atomicshop/wrappers/pywin32w/winshell.py +19 -0
  180. atomicshop/wrappers/pywin32w/wmis/__init__.py +0 -0
  181. atomicshop/wrappers/pywin32w/wmis/msft_netipaddress.py +113 -0
  182. atomicshop/wrappers/pywin32w/wmis/win32_networkadapterconfiguration.py +259 -0
  183. atomicshop/wrappers/pywin32w/wmis/win32networkadapter.py +112 -0
  184. atomicshop/wrappers/pywin32w/wmis/wmi_helpers.py +236 -0
  185. atomicshop/wrappers/socketw/accepter.py +21 -7
  186. atomicshop/wrappers/socketw/certificator.py +216 -150
  187. atomicshop/wrappers/socketw/creator.py +190 -50
  188. atomicshop/wrappers/socketw/dns_server.py +500 -173
  189. atomicshop/wrappers/socketw/exception_wrapper.py +45 -52
  190. atomicshop/wrappers/socketw/process_getter.py +86 -0
  191. atomicshop/wrappers/socketw/receiver.py +144 -102
  192. atomicshop/wrappers/socketw/sender.py +65 -35
  193. atomicshop/wrappers/socketw/sni.py +334 -165
  194. atomicshop/wrappers/socketw/socket_base.py +134 -0
  195. atomicshop/wrappers/socketw/socket_client.py +137 -95
  196. atomicshop/wrappers/socketw/socket_server_tester.py +14 -9
  197. atomicshop/wrappers/socketw/socket_wrapper.py +717 -116
  198. atomicshop/wrappers/socketw/ssl_base.py +15 -14
  199. atomicshop/wrappers/socketw/statistics_csv.py +148 -17
  200. atomicshop/wrappers/sysmonw.py +157 -0
  201. atomicshop/wrappers/ubuntu_terminal.py +65 -26
  202. atomicshop/wrappers/win_auditw.py +189 -0
  203. atomicshop/wrappers/winregw/__init__.py +0 -0
  204. atomicshop/wrappers/winregw/winreg_installed_software.py +58 -0
  205. atomicshop/wrappers/winregw/winreg_network.py +232 -0
  206. {atomicshop-2.11.47.dist-info → atomicshop-3.10.5.dist-info}/METADATA +31 -49
  207. atomicshop-3.10.5.dist-info/RECORD +306 -0
  208. {atomicshop-2.11.47.dist-info → atomicshop-3.10.5.dist-info}/WHEEL +1 -1
  209. atomicshop/_basics_temp.py +0 -101
  210. atomicshop/addons/a_setup_scripts/install_psycopg2_ubuntu.sh +0 -3
  211. atomicshop/addons/a_setup_scripts/install_pywintrace_0.3.cmd +0 -2
  212. atomicshop/addons/mains/install_docker_rootless_ubuntu.py +0 -11
  213. atomicshop/addons/mains/install_docker_ubuntu_main_sudo.py +0 -11
  214. atomicshop/addons/mains/install_elastic_search_and_kibana_ubuntu.py +0 -10
  215. atomicshop/addons/mains/install_wsl_ubuntu_lts_admin.py +0 -9
  216. atomicshop/addons/package_setup/CreateWheel.cmd +0 -7
  217. atomicshop/addons/package_setup/Setup in Edit mode.cmd +0 -6
  218. atomicshop/addons/package_setup/Setup.cmd +0 -7
  219. atomicshop/addons/process_list/compile.cmd +0 -2
  220. atomicshop/addons/process_list/compiled/Win10x64/process_list.dll +0 -0
  221. atomicshop/addons/process_list/compiled/Win10x64/process_list.exp +0 -0
  222. atomicshop/addons/process_list/compiled/Win10x64/process_list.lib +0 -0
  223. atomicshop/archiver/_search_in_zip.py +0 -189
  224. atomicshop/archiver/archiver.py +0 -34
  225. atomicshop/archiver/search_in_archive.py +0 -250
  226. atomicshop/archiver/sevenz_app_w.py +0 -86
  227. atomicshop/archiver/sevenzs.py +0 -44
  228. atomicshop/archiver/zips.py +0 -293
  229. atomicshop/etw/dns_trace.py +0 -118
  230. atomicshop/etw/etw.py +0 -61
  231. atomicshop/file_types.py +0 -24
  232. atomicshop/mitm/engines/create_module_template_example.py +0 -13
  233. atomicshop/mitm/initialize_mitm_server.py +0 -240
  234. atomicshop/monitor/checks/hash.py +0 -44
  235. atomicshop/monitor/checks/hash_checks/file.py +0 -55
  236. atomicshop/monitor/checks/hash_checks/url.py +0 -62
  237. atomicshop/pbtkmultifile_argparse.py +0 -88
  238. atomicshop/permissions.py +0 -110
  239. atomicshop/process_poller.py +0 -237
  240. atomicshop/script_as_string_processor.py +0 -38
  241. atomicshop/ssh_scripts/process_from_ipv4.py +0 -37
  242. atomicshop/ssh_scripts/process_from_port.py +0 -27
  243. atomicshop/wrappers/_process_wrapper_curl.py +0 -27
  244. atomicshop/wrappers/_process_wrapper_tar.py +0 -21
  245. atomicshop/wrappers/dockerw/install_docker.py +0 -209
  246. atomicshop/wrappers/elasticsearchw/infrastructure.py +0 -265
  247. atomicshop/wrappers/elasticsearchw/install_elastic.py +0 -232
  248. atomicshop/wrappers/ffmpegw.py +0 -125
  249. atomicshop/wrappers/loggingw/checks.py +0 -20
  250. atomicshop/wrappers/nodejsw/install_nodejs.py +0 -139
  251. atomicshop/wrappers/process_wrapper_pbtk.py +0 -16
  252. atomicshop/wrappers/socketw/base.py +0 -59
  253. atomicshop/wrappers/socketw/get_process.py +0 -107
  254. atomicshop/wrappers/wslw.py +0 -191
  255. atomicshop-2.11.47.dist-info/RECORD +0 -251
  256. /atomicshop/{addons/mains → a_mains}/FACT/factw_fact_extractor_docker_image_main_sudo.py +0 -0
  257. /atomicshop/{addons → a_mains/addons}/PlayWrightCodegen.cmd +0 -0
  258. /atomicshop/{addons → a_mains/addons}/ScriptExecution.cmd +0 -0
  259. /atomicshop/{addons/mains → a_mains/addons}/inits/init_to_import_all_modules.py +0 -0
  260. /atomicshop/{addons → a_mains/addons}/process_list/ReadMe.txt +0 -0
  261. /atomicshop/{addons/mains → a_mains}/search_for_hyperlinks_in_docx.py +0 -0
  262. /atomicshop/{archiver → etws}/__init__.py +0 -0
  263. /atomicshop/{etw → etws/traces}/__init__.py +0 -0
  264. /atomicshop/{monitor/checks/hash_checks → mitm/statistic_analyzer_helper}/__init__.py +0 -0
  265. /atomicshop/{wrappers/nodejsw → permissions}/__init__.py +0 -0
  266. /atomicshop/wrappers/pywin32w/{wmi_win32process.py → wmis/win32process.py} +0 -0
  267. {atomicshop-2.11.47.dist-info → atomicshop-3.10.5.dist-info/licenses}/LICENSE.txt +0 -0
  268. {atomicshop-2.11.47.dist-info → atomicshop-3.10.5.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,119 @@
1
+ import os
2
+ import datetime
3
+
4
+ import win32com.client
5
+ import pythoncom
6
+
7
+
8
+ TRIGGER_ONE_TIME: int = 1
9
+ TRIGGER_DAILY: int = 2
10
+ TRIGGER_AT_SYSTEM_STARTUP: int = 8
11
+ TRIGGER_ON_LOGON: int = 9
12
+
13
+
14
+ def create_on_logon_task_with_system_privileges(exe_file_path: str, task_name: str, user_id: str = None):
15
+ """
16
+ This function will add a task to the Windows Task Scheduler with system privileges.
17
+
18
+ :param exe_file_path: The path to your executable file.
19
+ :param task_name: The name of the task to create in the Task Scheduler.
20
+ :param user_id: The user ID to run the task as.
21
+ None: the task will run for every user that logs on.
22
+ "SYSTEM": is a common user ID to run tasks with system privileges.
23
+ :return: True if the task was added successfully, False otherwise.
24
+ """
25
+
26
+ scheduler = win32com.client.Dispatch('Schedule.Service')
27
+ scheduler.Connect()
28
+
29
+ root_folder = scheduler.GetFolder('\\')
30
+ task_def = scheduler.NewTask(0)
31
+
32
+ # Set up registration information for the task
33
+ reg_info = task_def.RegistrationInfo
34
+ reg_info.Description = f'Task to run {os.path.basename(exe_file_path)} at logon'
35
+ reg_info.Author = 'Your Name'
36
+
37
+ # Set up the principal for the task
38
+ principal = task_def.Principal
39
+ if user_id is not None:
40
+ principal.UserId = user_id
41
+ # principal.LogonType = 3 # TaskLogonTypeInteractiveToken, Only run when the user is logged on.
42
+ principal.LogonType = 1 # 1 is for password not required
43
+ principal.RunLevel = 1 # TaskRunLevelHighest
44
+
45
+ # Create the logon trigger
46
+ trigger = task_def.Triggers.Create(TRIGGER_ON_LOGON)
47
+ if user_id:
48
+ trigger.UserId = user_id
49
+ trigger.Id = "LogonTriggerId"
50
+ trigger.Enabled = True
51
+ trigger.StartBoundary = datetime.datetime.now().isoformat() # Set start boundary to current time in ISO format
52
+
53
+ # Create the action to run the executable
54
+ action = task_def.Actions.Create(0) # 0 stands for TASK_ACTION_EXEC
55
+ action.Path = exe_file_path
56
+ action.WorkingDirectory = os.path.dirname(exe_file_path)
57
+ action.Arguments = ''
58
+
59
+ # Set task settings
60
+ settings = task_def.Settings
61
+ settings.Enabled = True
62
+ settings.StartWhenAvailable = True
63
+ settings.Hidden = False
64
+ settings.StopIfGoingOnBatteries = False
65
+ settings.DisallowStartIfOnBatteries = False
66
+ # Sets the limit to zero, which means the task will run indefinitely. The default is 3 days.
67
+ settings.ExecutionTimeLimit = 'PT0S'
68
+
69
+ # Register the task
70
+ root_folder.RegisterTaskDefinition(
71
+ task_name, task_def, 6, # 6 is for CREATE_OR_UPDATE
72
+ None, # No user (runs in system context)
73
+ None, # No password
74
+ 3
75
+ )
76
+
77
+
78
+ def is_task_in_scheduler(task_name: str, scheduler_instance=None) -> bool:
79
+ """
80
+ This function will check if the task is in the Windows Task Scheduler.
81
+
82
+ :param task_name: The name of the task to check in the Task Scheduler.
83
+ :param scheduler_instance: The instance of the Task Scheduler to use.
84
+ If None, a new instance will be created.
85
+ :return: True if the task is in the Task Scheduler, False otherwise.
86
+ """
87
+
88
+ if scheduler_instance is None:
89
+ scheduler_instance = win32com.client.Dispatch('Schedule.Service')
90
+ scheduler_instance.Connect()
91
+
92
+ try:
93
+ root_folder = scheduler_instance.GetFolder('\\')
94
+ root_folder.GetTask(task_name)
95
+ return True
96
+ except pythoncom.com_error as e:
97
+ if e.hresult == -2147352567 and e.excepinfo[5] == -2147024894: # HRESULT code for "Task does not exist"
98
+ return False
99
+ else:
100
+ raise
101
+
102
+
103
+ def remove_task_from_scheduler(task_name: str) -> bool:
104
+ """
105
+ This function will remove the task from the Windows Task Scheduler.
106
+
107
+ :param task_name: The name of the task to remove from the Task Scheduler.
108
+ :return: True if the task was removed successfully, False otherwise.
109
+ """
110
+
111
+ scheduler_instance = win32com.client.Dispatch('Schedule.Service')
112
+ scheduler_instance.Connect()
113
+
114
+ if not is_task_in_scheduler(task_name, scheduler_instance=scheduler_instance):
115
+ return False
116
+ else:
117
+ root_folder = scheduler_instance.GetFolder('\\')
118
+ root_folder.GetTask(task_name)
119
+ return True
@@ -2,8 +2,7 @@ from typing import Union
2
2
  import threading
3
3
  import multiprocessing.managers
4
4
 
5
- from .print_api import print_api
6
- from . import system_resources
5
+ from . import system_resources, print_api
7
6
 
8
7
 
9
8
  class SystemResourceMonitor:
@@ -109,66 +108,77 @@ 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
- def start(self, print_kwargs: dict = None):
114
+ def start(
115
+ self,
116
+ print_kwargs: dict = None,
117
+ thread_as_daemon: bool = True
118
+ ):
116
119
  """
117
120
  Start the monitoring process.
118
121
  :param print_kwargs:
122
+ :param thread_as_daemon: bool, set the thread as daemon. If you're running the monitoring process in the main
123
+ process, set it to True. If you're running the monitoring process in a separate process, set it to False.
124
+ In child processes created by multiprocessing.Process, the thread works differently. You might not
125
+ get the desired result.
119
126
  :return:
120
127
  """
121
128
 
122
- def run_check_system_resources(
123
- interval, get_cpu, get_memory, get_disk_io_bytes, get_disk_files_count, get_disk_busy_time,
124
- get_disk_used_percent, calculate_maximum_changed_disk_io, maximum_disk_io, queue_list, manager_dict):
125
- """
126
- Continuously update the system resources in the shared results dictionary.
127
- This function runs in a separate process.
128
- """
129
-
130
- while self.running:
131
- # Get the results of the system resources check function and store them in temporary results dictionary.
132
- results = system_resources.check_system_resources(
133
- interval=interval, get_cpu=get_cpu, get_memory=get_memory,
134
- get_disk_io_bytes=get_disk_io_bytes, get_disk_files_count=get_disk_files_count,
135
- get_disk_busy_time=get_disk_busy_time, get_disk_used_percent=get_disk_used_percent)
136
-
137
- if calculate_maximum_changed_disk_io:
138
- if results['disk_io_read'] > maximum_disk_io['read_bytes_per_sec']:
139
- maximum_disk_io['read_bytes_per_sec'] = results['disk_io_read']
140
- if results['disk_io_write'] > maximum_disk_io['write_bytes_per_sec']:
141
- maximum_disk_io['write_bytes_per_sec'] = results['disk_io_write']
142
- if results['disk_files_count_read'] > maximum_disk_io['read_files_count_per_sec']:
143
- maximum_disk_io['read_files_count_per_sec'] = results['disk_files_count_read']
144
- if results['disk_files_count_write'] > maximum_disk_io['write_files_count_per_sec']:
145
- maximum_disk_io['write_files_count_per_sec'] = results['disk_files_count_write']
146
- results['maximum_disk_io'] = maximum_disk_io
147
-
148
- if queue_list is not None:
149
- for queue in queue_list:
150
- queue.put(results)
151
-
152
- # Update the shared results dictionary with the temporary results dictionary.
153
- # This is done in separate steps to avoid overwriting the special 'multiprocessing.Manager.dict' object.
154
- # So we update the shared results dictionary with the temporary results dictionary.
155
- if manager_dict is not None:
156
- manager_dict.update(results)
157
-
158
- self.results = results
159
-
160
129
  if print_kwargs is None:
161
130
  print_kwargs = {}
162
131
 
163
132
  if self.thread is None:
164
133
  self.running = True
165
- self.thread = threading.Thread(target=run_check_system_resources, args=(
134
+ self.thread = threading.Thread(target=self.run_check_system_resources, args=(
166
135
  self.interval, self.get_cpu, self.get_memory, self.get_disk_io_bytes, self.get_disk_files_count,
167
136
  self.get_disk_busy_time, self.get_disk_used_percent, self.calculate_maximum_changed_disk_io,
168
137
  self.maximum_disk_io, self.queue_list, self.manager_dict))
138
+ self.thread.daemon = thread_as_daemon
169
139
  self.thread.start()
170
140
  else:
171
- print_api("Monitoring is already running.", color='yellow', **print_kwargs)
141
+ print_api.print_api("Monitoring is already running.", color='yellow', **print_kwargs)
142
+
143
+ def run_check_system_resources(
144
+ self,
145
+ interval, get_cpu, get_memory, get_disk_io_bytes, get_disk_files_count, get_disk_busy_time,
146
+ get_disk_used_percent, calculate_maximum_changed_disk_io, maximum_disk_io, queue_list, manager_dict):
147
+ """
148
+ Continuously update the system resources in the shared results dictionary.
149
+ This function runs in a separate process.
150
+ """
151
+
152
+ while self.running:
153
+ # Get the results of the system resources check function and store them in
154
+ # temporary results' dictionary.
155
+ results = system_resources.check_system_resources(
156
+ interval=interval, get_cpu=get_cpu, get_memory=get_memory,
157
+ get_disk_io_bytes=get_disk_io_bytes, get_disk_files_count=get_disk_files_count,
158
+ get_disk_busy_time=get_disk_busy_time, get_disk_used_percent=get_disk_used_percent)
159
+
160
+ if calculate_maximum_changed_disk_io:
161
+ if results['disk_io_read'] > maximum_disk_io['read_bytes_per_sec']:
162
+ maximum_disk_io['read_bytes_per_sec'] = results['disk_io_read']
163
+ if results['disk_io_write'] > maximum_disk_io['write_bytes_per_sec']:
164
+ maximum_disk_io['write_bytes_per_sec'] = results['disk_io_write']
165
+ if results['disk_files_count_read'] > maximum_disk_io['read_files_count_per_sec']:
166
+ maximum_disk_io['read_files_count_per_sec'] = results['disk_files_count_read']
167
+ if results['disk_files_count_write'] > maximum_disk_io['write_files_count_per_sec']:
168
+ maximum_disk_io['write_files_count_per_sec'] = results['disk_files_count_write']
169
+ results['maximum_disk_io'] = maximum_disk_io
170
+
171
+ if queue_list is not None:
172
+ for queue in queue_list:
173
+ queue.put(results)
174
+
175
+ # Update the shared results dictionary with the temporary results' dictionary.
176
+ # This is done in separate steps to avoid overwriting the special 'multiprocessing.Manager.dict' object.
177
+ # So we update the shared results dictionary with the temporary results' dictionary.
178
+ if manager_dict is not None:
179
+ manager_dict.update(results)
180
+
181
+ self.results = results
172
182
 
173
183
  def get_results(self) -> dict:
174
184
  """
@@ -203,6 +213,7 @@ def start_monitoring(
203
213
  calculate_maximum_changed_disk_io: bool = False,
204
214
  queue_list: list = None,
205
215
  manager_dict: multiprocessing.managers.DictProxy = None, # multiprocessing.Manager().dict()
216
+ get_results_thread_as_daemon: bool = True,
206
217
  print_kwargs: dict = None
207
218
  ):
208
219
  """
@@ -233,6 +244,10 @@ def start_monitoring(
233
244
  multiprocessing.Process(
234
245
  target=system_resource_monitor.start_monitoring, kwargs={'manager_dict': shared_dict}).start()
235
246
 
247
+ :param get_results_thread_as_daemon: bool, set the thread as daemon. If you're running the monitoring process in the
248
+ main process, set it to True. If you're running the monitoring process in a separate process, set it to False.
249
+ In child processes created by multiprocessing.Process, the thread works differently.
250
+ You might not get the desired result.
236
251
  :param print_kwargs: dict, print kwargs.
237
252
  :return:
238
253
  """
@@ -255,9 +270,9 @@ def start_monitoring(
255
270
  queue_list=queue_list,
256
271
  manager_dict=manager_dict
257
272
  )
258
- SYSTEM_RESOURCES_MONITOR.start()
273
+ SYSTEM_RESOURCES_MONITOR.start(thread_as_daemon=get_results_thread_as_daemon)
259
274
  else:
260
- print_api("System resources monitoring is already running.", color='yellow', **(print_kwargs or {}))
275
+ print_api.print_api("System resources monitoring is already running.", color='yellow', **(print_kwargs or {}))
261
276
 
262
277
 
263
278
  def stop_monitoring():
@@ -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 test_disk_speed_with_monitoring(
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, use_queue=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.get_result()['maximum_disk_io']
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/tempfiles.py CHANGED
@@ -1,4 +1,3 @@
1
- # v1.0.3 - 01.04.2021 - 15:30
2
1
  import os
3
2
  import datetime
4
3
  import tempfile
@@ -59,4 +58,4 @@ class TempFile:
59
58
  self.file_path: str = self.directory + os.sep + self.file_name
60
59
 
61
60
  def remove(self):
62
- os.remove(self.file_path)
61
+ os.remove(self.file_path)
atomicshop/timer.py CHANGED
@@ -7,7 +7,10 @@ class TimerError(Exception):
7
7
 
8
8
  class Timer:
9
9
  """ Custom timer class to measure elapsed time. Returns time in seconds (float) or nanoseconds with setting. """
10
- def __init__(self, nanoseconds: bool = False):
10
+ def __init__(
11
+ self,
12
+ nanoseconds: bool = False
13
+ ):
11
14
  """
12
15
  Set up timer in seconds or nanoseconds
13
16
  Seconds are returned as float, nanoseconds as int.
@@ -17,6 +20,9 @@ class Timer:
17
20
  self._start_time = None
18
21
  self._nanoseconds: bool = nanoseconds
19
22
 
23
+ self.running: bool = False
24
+ self.last_measure = None
25
+
20
26
  def start(self):
21
27
  """Start a new timer"""
22
28
 
@@ -28,6 +34,8 @@ class Timer:
28
34
  else:
29
35
  self._start_time = time.perf_counter()
30
36
 
37
+ self.running = True
38
+
31
39
  def restart(self):
32
40
  """Reset the timer"""
33
41
 
@@ -37,20 +45,31 @@ class Timer:
37
45
  def measure(self):
38
46
  """Measure the elapsed time"""
39
47
 
40
- if self._start_time is None:
41
- raise TimerError(f"Timer is not running. Use .start() to start it")
48
+ # if self._start_time is None and self.last_measure is None:
49
+ # raise TimerError(f"Timer is not running. Use .start() to start it")
42
50
 
43
- if self._nanoseconds:
44
- elapsed_time = time.perf_counter_ns() - self._start_time
45
- else:
46
- elapsed_time = time.perf_counter() - self._start_time
51
+ # If the timer is running, measure the elapsed time. If not, return the last measured time.
52
+ if self.running:
53
+ if self._nanoseconds:
54
+ self.last_measure = time.perf_counter_ns() - self._start_time
55
+ else:
56
+ self.last_measure = time.perf_counter() - self._start_time
47
57
 
48
- return elapsed_time
58
+ return self.last_measure
59
+
60
+ def stop(self, measure: bool = True):
61
+ """
62
+ Stop the timer, and report the elapsed time
63
+
64
+ :param measure: True to measure the elapsed time, False to stop the timer without measuring.
65
+ Measuring, means that the timer will return the elapsed time and 'self.last_measure' will be updated.
66
+ """
49
67
 
50
- def stop(self):
51
- """Stop the timer, and report the elapsed time"""
68
+ elapsed_time = None
69
+ if measure:
70
+ elapsed_time = self.measure()
52
71
 
53
- elapsed_time = self.measure()
54
72
  self._start_time = None
73
+ self.running = False
55
74
 
56
75
  return elapsed_time
atomicshop/urls.py CHANGED
@@ -1,4 +1,5 @@
1
1
  from urllib.parse import urlparse
2
+ import re
2
3
 
3
4
 
4
5
  def url_parser(url):
@@ -7,6 +8,11 @@ def url_parser(url):
7
8
  directories = parts.path.strip('/').split('/')
8
9
  queries = parts.query.strip('&').split('&')
9
10
 
11
+ if len(directories) > 1 and '.' in directories[-1]:
12
+ file = directories[-1]
13
+ else:
14
+ file = ''
15
+
10
16
  elements = {
11
17
  'scheme': parts.scheme,
12
18
  'netloc': parts.netloc,
@@ -16,6 +22,41 @@ def url_parser(url):
16
22
  'fragment': parts.fragment,
17
23
  'directories': directories,
18
24
  'queries': queries,
25
+ 'file': file
19
26
  }
20
27
 
21
28
  return elements
29
+
30
+
31
+ def is_valid_url(url):
32
+ """
33
+ Check if a URL is valid.
34
+ :param url:
35
+ :return:
36
+ """
37
+
38
+ parsed = urlparse(url)
39
+ return all([parsed.scheme, parsed.netloc])
40
+
41
+
42
+ def find_urls_in_text(text: str) -> list[str]:
43
+ """
44
+ Find URLs in text
45
+
46
+ :param text: string, text to search for URLs.
47
+ :return: list of strings, URLs found in text.
48
+ """
49
+
50
+ url_pattern = re.compile(
51
+ r'http[s]?://(?:[a-zA-Z]|[0-9]|[$-_@.&+]|[!*\\(\\),]|(?:%[0-9a-fA-F][0-9a-fA-F]))+'
52
+ )
53
+ urls = url_pattern.findall(text)
54
+
55
+ # Filter URLs to remove common false positives
56
+ cleaned_urls = []
57
+ for u in urls:
58
+ cleaned_url = u.strip('",.:;!?)(')
59
+ if is_valid_url(cleaned_url):
60
+ cleaned_urls.append(cleaned_url)
61
+
62
+ return cleaned_urls
atomicshop/venvs.py ADDED
@@ -0,0 +1,28 @@
1
+ import sys
2
+ import os
3
+ from typing import Union
4
+
5
+
6
+ def is_running_venv() -> Union[str, None]:
7
+ """
8
+ Check if the script is running in a virtual environment.
9
+
10
+ :return: string of the virtual environment path if it is running in a virtual environment, None otherwise.
11
+ """
12
+ if hasattr(sys, 'real_prefix') or (hasattr(sys, 'base_prefix') and sys.base_prefix != sys.prefix):
13
+ return sys.prefix
14
+ else:
15
+ return None
16
+
17
+
18
+ def add_venv_to_path():
19
+ """
20
+ Add the virtual environment to the PATH environment variable.
21
+ """
22
+
23
+ venv_environment = is_running_venv()
24
+ if venv_environment:
25
+ # We're in a virtual environment, so modify the PATH
26
+ venv_bin = os.path.join(venv_environment, 'bin')
27
+ # Prepend the virtual environment's bin directory to the existing PATH
28
+ os.environ['PATH'] = f"{venv_bin}:{os.environ['PATH']}"
@@ -0,0 +1,27 @@
1
+ from typing import Union
2
+
3
+
4
+ def is_target_newer(
5
+ base_version: Union[str, tuple],
6
+ target_version: Union[str, tuple]
7
+ ):
8
+ """
9
+ Check if the target version is newer than the base version.
10
+ Example: is_target_newer('1.0.0', '1.0.1') -> True
11
+ Example: is_target_newer('1.0.0', '1.0.0') -> False
12
+ Example: is_target_newer('1.0.1', '1.0.0') -> False
13
+ Example: is_target_newer('1.0.1', '1.0.2') -> True
14
+ Example: is_target_newer((1,0,1), (1,1,0)) -> True
15
+
16
+ :param base_version: The base version to compare against.
17
+ :param target_version: The target version to compare.
18
+ """
19
+
20
+ # Convert string to tuple if string was passed.
21
+ if isinstance(base_version, str):
22
+ base_version = tuple(map(int, base_version.split('.')))
23
+ if isinstance(target_version, str):
24
+ target_version = tuple(map(int, target_version.split('.')))
25
+
26
+ # Compare the versions.
27
+ return target_version > base_version