machineconfig 6.82__py3-none-any.whl → 8.51__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 (461) hide show
  1. machineconfig/cluster/remote/cloud_manager.py +1 -1
  2. machineconfig/cluster/remote/run_cluster.py +1 -1
  3. machineconfig/cluster/remote/run_remote.py +1 -1
  4. machineconfig/cluster/sessions_managers/utils/maker.py +29 -15
  5. machineconfig/cluster/sessions_managers/wt_local.py +17 -222
  6. machineconfig/cluster/sessions_managers/wt_local_manager.py +56 -194
  7. machineconfig/cluster/sessions_managers/wt_remote_manager.py +42 -198
  8. machineconfig/cluster/sessions_managers/wt_utils/manager_persistence.py +52 -0
  9. machineconfig/cluster/sessions_managers/wt_utils/monitoring_helpers.py +50 -0
  10. machineconfig/cluster/sessions_managers/wt_utils/status_reporting.py +76 -0
  11. machineconfig/cluster/sessions_managers/wt_utils/wt_helpers.py +199 -0
  12. machineconfig/cluster/sessions_managers/zellij_local.py +1 -1
  13. machineconfig/cluster/sessions_managers/zellij_local_manager.py +4 -2
  14. machineconfig/cluster/sessions_managers/zellij_remote_manager.py +3 -2
  15. machineconfig/cluster/sessions_managers/zellij_utils/process_monitor.py +2 -2
  16. machineconfig/jobs/installer/checks/check_installations.py +133 -0
  17. machineconfig/jobs/installer/checks/install_utils.py +132 -0
  18. machineconfig/jobs/installer/checks/report_utils.py +39 -0
  19. machineconfig/jobs/installer/checks/vt_utils.py +89 -0
  20. machineconfig/jobs/installer/installer_data.json +1500 -310
  21. machineconfig/jobs/installer/linux_scripts/docker.sh +6 -9
  22. machineconfig/jobs/installer/linux_scripts/q.sh +10 -7
  23. machineconfig/jobs/installer/linux_scripts/redis.sh +1 -0
  24. machineconfig/jobs/installer/package_groups.py +62 -91
  25. machineconfig/jobs/installer/powershell_scripts/install_fonts.ps1 +129 -34
  26. machineconfig/jobs/installer/{custom → python_scripts}/boxes.py +2 -3
  27. machineconfig/jobs/installer/{custom_dev → python_scripts}/brave.py +5 -3
  28. machineconfig/jobs/installer/python_scripts/cloudflare_warp_cli.py +23 -0
  29. machineconfig/jobs/installer/{custom_dev → python_scripts}/code.py +14 -9
  30. machineconfig/jobs/installer/{custom_dev → python_scripts}/dubdb_adbc.py +1 -1
  31. machineconfig/jobs/installer/python_scripts/hx.py +214 -0
  32. machineconfig/jobs/installer/{custom_dev → python_scripts}/nerdfont.py +2 -2
  33. machineconfig/jobs/installer/{custom_dev → python_scripts}/nerfont_windows_helper.py +32 -26
  34. machineconfig/jobs/installer/python_scripts/sysabc.py +145 -0
  35. machineconfig/jobs/installer/{custom_dev → python_scripts}/wezterm.py +2 -19
  36. machineconfig/jobs/installer/{custom_dev → python_scripts}/winget.py +10 -14
  37. machineconfig/jobs/installer/python_scripts/yazi.py +139 -0
  38. machineconfig/{scripts/python/nw → jobs/scripts/bash_scripts}/mount_nfs +0 -1
  39. machineconfig/jobs/scripts/powershell_scripts/cmatrix.ps1 +52 -0
  40. machineconfig/jobs/scripts/powershell_scripts/mount_ssh.ps1 +13 -0
  41. machineconfig/jobs/scripts/powershell_scripts/obs.ps1 +4 -0
  42. machineconfig/jobs/scripts_dynamic/a.py +428 -0
  43. machineconfig/logger.py +1 -2
  44. machineconfig/profile/create_helper.py +56 -18
  45. machineconfig/profile/create_links.py +79 -21
  46. machineconfig/profile/create_links_export.py +87 -36
  47. machineconfig/profile/create_shell_profile.py +92 -127
  48. machineconfig/profile/mapper_data.toml +45 -0
  49. machineconfig/profile/mapper_dotfiles.toml +249 -0
  50. machineconfig/scripts/__init__.py +0 -4
  51. machineconfig/scripts/linux/wrap_mcfg +46 -0
  52. machineconfig/scripts/nu/wrap_mcfg.nu +69 -0
  53. machineconfig/scripts/python/agents.py +85 -165
  54. machineconfig/scripts/python/ai/initai.py +4 -2
  55. machineconfig/scripts/python/ai/scripts/__init__.py +1 -0
  56. machineconfig/scripts/python/ai/scripts/command_runner.ps1 +33 -0
  57. machineconfig/scripts/python/ai/{command_runner → scripts}/command_runner.sh +1 -1
  58. machineconfig/scripts/python/ai/scripts/lint_and_type_check.ps1 +2 -0
  59. machineconfig/scripts/python/ai/scripts/lint_and_type_check.sh +8 -6
  60. machineconfig/scripts/python/ai/solutions/claude/claude.py +1 -1
  61. machineconfig/scripts/python/ai/solutions/cline/cline.py +1 -1
  62. machineconfig/scripts/python/ai/solutions/copilot/{chatmodes/Thinking-Beast-Mode.chatmode.md → agents/Thinking-Beast-Mode.agent.md} +0 -1
  63. machineconfig/scripts/python/ai/solutions/copilot/{chatmodes/Ultimate-Transparent-Thinking-Beast-Mode.chatmode.md → agents/Ultimate-Transparent-Thinking-Beast-Mode.agent.md} +0 -1
  64. machineconfig/scripts/python/ai/solutions/copilot/{chatmodes/deepResearch.chatmode.md → agents/deepResearch.agent.md} +2 -2
  65. machineconfig/scripts/python/ai/solutions/copilot/github_copilot.py +6 -6
  66. machineconfig/scripts/python/ai/solutions/copilot/instructions/python/dev.instructions.md +33 -0
  67. machineconfig/scripts/python/ai/solutions/copilot/instructions/python/watch_exec.prompt.md +20 -0
  68. machineconfig/scripts/python/ai/solutions/crush/crush.py +1 -1
  69. machineconfig/scripts/python/ai/solutions/cursor/cursors.py +1 -1
  70. machineconfig/scripts/python/ai/solutions/gemini/gemini.py +1 -1
  71. machineconfig/scripts/python/ai/solutions/gemini/settings.json +3 -0
  72. machineconfig/scripts/python/ai/{generate_files.py → utils/generate_files.py} +2 -2
  73. machineconfig/scripts/python/ai/{solutions → utils}/generic.py +2 -15
  74. machineconfig/scripts/python/ai/{vscode_tasks.py → utils/vscode_tasks.py} +13 -5
  75. machineconfig/scripts/python/cloud.py +58 -11
  76. machineconfig/scripts/python/croshell.py +10 -162
  77. machineconfig/scripts/python/devops.py +73 -36
  78. machineconfig/scripts/python/devops_navigator.py +16 -6
  79. machineconfig/scripts/python/fire_jobs.py +8 -222
  80. machineconfig/scripts/python/ftpx.py +7 -200
  81. machineconfig/scripts/python/graph/cli_graph.json +8743 -0
  82. machineconfig/scripts/python/{env_manager → helper_env}/path_manager_tui.py +2 -2
  83. machineconfig/scripts/python/helpers/helper_env/env_manager_tui.py +204 -0
  84. machineconfig/scripts/python/helpers/helper_env/path_manager_tui.py +228 -0
  85. machineconfig/scripts/python/{helpers_fire → helpers/helpers_agents}/agentic_frameworks/fire_crush.json +1 -1
  86. machineconfig/scripts/python/helpers/helpers_agents/agentic_frameworks/fire_crush.py +39 -0
  87. machineconfig/scripts/python/{helpers_fire → helpers/helpers_agents}/agentic_frameworks/fire_cursor_agents.py +3 -4
  88. machineconfig/scripts/python/helpers/helpers_agents/agentic_frameworks/fire_gemini.py +55 -0
  89. machineconfig/scripts/python/helpers/helpers_agents/agentic_frameworks/fire_qwen.py +30 -0
  90. machineconfig/scripts/python/helpers/helpers_agents/agents_impl.py +168 -0
  91. machineconfig/scripts/python/{helpers_fire → helpers/helpers_agents}/fire_agents_help_launch.py +38 -16
  92. machineconfig/scripts/python/{helpers_fire → helpers/helpers_agents}/fire_agents_helper_types.py +11 -14
  93. machineconfig/scripts/python/helpers/helpers_agents/privacy/configs/aichat/config.yaml +5 -0
  94. machineconfig/scripts/python/helpers/helpers_agents/privacy/configs/aider/.aider.conf.yml +2 -0
  95. machineconfig/scripts/python/helpers/helpers_agents/privacy/configs/copilot/config.yml +1 -0
  96. machineconfig/scripts/python/helpers/helpers_agents/privacy/configs/crush/crush.json +10 -0
  97. machineconfig/scripts/python/helpers/helpers_agents/privacy/configs/gemini/settings.json +12 -0
  98. machineconfig/scripts/python/helpers/helpers_agents/privacy/privacy.py +109 -0
  99. machineconfig/scripts/python/helpers/helpers_agents/templates/prompt.txt +10 -0
  100. machineconfig/scripts/python/helpers/helpers_agents/templates/template.sh +34 -0
  101. machineconfig/scripts/python/{helpers_cloud → helpers/helpers_cloud}/cloud_copy.py +32 -25
  102. machineconfig/scripts/python/{helpers_cloud → helpers/helpers_cloud}/cloud_mount.py +29 -22
  103. machineconfig/scripts/python/{helpers_cloud → helpers/helpers_cloud}/cloud_sync.py +9 -8
  104. machineconfig/scripts/python/{helpers_cloud → helpers/helpers_cloud}/helpers2.py +1 -1
  105. machineconfig/scripts/python/{helpers_croshell → helpers/helpers_croshell}/crosh.py +3 -3
  106. machineconfig/scripts/python/helpers/helpers_croshell/croshell_impl.py +225 -0
  107. machineconfig/scripts/python/{helpers_croshell → helpers/helpers_croshell}/scheduler.py +4 -4
  108. machineconfig/scripts/python/{helpers_croshell → helpers/helpers_croshell}/start_slidev.py +12 -12
  109. machineconfig/scripts/python/helpers/helpers_devops/backup_config.py +149 -0
  110. machineconfig/scripts/python/helpers/helpers_devops/cli_backup_retrieve.py +262 -0
  111. machineconfig/scripts/python/helpers/helpers_devops/cli_config.py +98 -0
  112. machineconfig/scripts/python/helpers/helpers_devops/cli_config_dotfile.py +274 -0
  113. machineconfig/scripts/python/helpers/helpers_devops/cli_data.py +67 -0
  114. machineconfig/scripts/python/helpers/helpers_devops/cli_nw.py +201 -0
  115. machineconfig/scripts/python/helpers/helpers_devops/cli_repos.py +274 -0
  116. machineconfig/scripts/python/helpers/helpers_devops/cli_self.py +197 -0
  117. machineconfig/scripts/python/helpers/helpers_devops/cli_share_file.py +151 -0
  118. machineconfig/scripts/python/helpers/helpers_devops/cli_share_server.py +125 -0
  119. machineconfig/scripts/python/{helpers_devops/cli_terminal.py → helpers/helpers_devops/cli_share_terminal.py} +26 -22
  120. machineconfig/scripts/python/helpers/helpers_devops/cli_ssh.py +167 -0
  121. machineconfig/scripts/python/{helpers_devops → helpers/helpers_devops}/devops_status.py +17 -23
  122. machineconfig/scripts/python/{helpers_devops → helpers/helpers_devops}/devops_update_repos.py +1 -1
  123. machineconfig/scripts/python/{interactive.py → helpers/helpers_devops/interactive.py} +78 -71
  124. machineconfig/scripts/python/helpers/helpers_devops/run_script.py +197 -0
  125. machineconfig/scripts/python/helpers/helpers_devops/themes/choose_starship_theme.ps1 +41 -0
  126. machineconfig/scripts/python/helpers/helpers_devops/themes/choose_starship_theme.sh +48 -0
  127. machineconfig/scripts/python/{helpers_devops → helpers/helpers_devops}/themes/choose_wezterm_theme.py +4 -4
  128. machineconfig/scripts/python/{helpers_fire/helpers4.py → helpers/helpers_fire_command/file_wrangler.py} +57 -20
  129. machineconfig/scripts/python/{helpers_fire_command → helpers/helpers_fire_command}/fire_jobs_args_helper.py +1 -0
  130. machineconfig/scripts/python/helpers/helpers_fire_command/fire_jobs_impl.py +233 -0
  131. machineconfig/scripts/python/{helpers_fire_command → helpers/helpers_fire_command}/fire_jobs_route_helper.py +26 -16
  132. machineconfig/scripts/python/helpers/helpers_msearch/__init__.py +5 -0
  133. machineconfig/scripts/python/helpers/helpers_msearch/msearch_impl.py +248 -0
  134. machineconfig/scripts/{linux → python/helpers/helpers_msearch/scripts_linux}/fzfg +6 -5
  135. machineconfig/scripts/python/helpers/helpers_msearch/scripts_linux/search_with_context.sh +48 -0
  136. machineconfig/scripts/python/helpers/helpers_msearch/scripts_windows/fzfg.ps1 +59 -0
  137. machineconfig/scripts/python/helpers/helpers_navigator/__init__.py +20 -0
  138. machineconfig/scripts/python/helpers/helpers_navigator/cli_graph_loader.py +234 -0
  139. machineconfig/scripts/python/{helpers_navigator → helpers/helpers_navigator}/command_builder.py +61 -13
  140. machineconfig/scripts/python/helpers/helpers_navigator/command_detail.py +153 -0
  141. machineconfig/scripts/python/helpers/helpers_navigator/command_tree.py +45 -0
  142. machineconfig/scripts/python/{helpers_navigator → helpers/helpers_navigator}/data_models.py +18 -11
  143. machineconfig/scripts/python/{helpers_navigator → helpers/helpers_navigator}/main_app.py +5 -5
  144. machineconfig/scripts/python/helpers/helpers_network/address.py +174 -0
  145. machineconfig/scripts/python/helpers/helpers_network/address_switch.py +78 -0
  146. machineconfig/scripts/python/helpers/helpers_network/ftpx_impl.py +276 -0
  147. machineconfig/scripts/python/{nw → helpers/helpers_network}/mount_nfs.py +2 -2
  148. machineconfig/scripts/python/{nw → helpers/helpers_network}/mount_ssh.py +3 -3
  149. machineconfig/scripts/python/helpers/helpers_network/ssh_add_identity.py +73 -0
  150. machineconfig/scripts/python/helpers/helpers_network/ssh_add_ssh_key.py +175 -0
  151. machineconfig/scripts/python/helpers/helpers_network/ssh_debug_linux.py +319 -0
  152. machineconfig/scripts/python/helpers/helpers_network/ssh_debug_windows.py +275 -0
  153. machineconfig/scripts/python/{nw → helpers/helpers_network}/wifi_conn.py +1 -53
  154. machineconfig/scripts/python/{helpers_repos → helpers/helpers_repos}/action.py +3 -3
  155. machineconfig/scripts/python/{helpers_repos → helpers/helpers_repos}/action_helper.py +3 -3
  156. machineconfig/scripts/python/{helpers_repos → helpers/helpers_repos}/clone.py +0 -1
  157. machineconfig/scripts/python/{helpers_repos → helpers/helpers_repos}/cloud_repo_sync.py +159 -48
  158. machineconfig/scripts/python/{helpers_repos → helpers/helpers_repos}/grource.py +4 -3
  159. machineconfig/scripts/python/{helpers_repos → helpers/helpers_repos}/record.py +33 -12
  160. machineconfig/scripts/python/helpers/helpers_repos/repo_analyzer_1.py +160 -0
  161. machineconfig/scripts/python/{helpers_repos/count_lines.py → helpers/helpers_repos/repo_analyzer_2.py} +156 -191
  162. machineconfig/scripts/python/{helpers_repos → helpers/helpers_repos}/update.py +0 -6
  163. machineconfig/scripts/python/helpers/helpers_search/ast_search.py +74 -0
  164. machineconfig/scripts/python/helpers/helpers_search/qr_code.py +166 -0
  165. machineconfig/scripts/python/helpers/helpers_search/repo_rag.py +325 -0
  166. machineconfig/scripts/python/helpers/helpers_search/script_help.py +81 -0
  167. machineconfig/scripts/python/helpers/helpers_search/symantic_search.py +25 -0
  168. machineconfig/scripts/python/helpers/helpers_sessions/__init__.py +0 -0
  169. machineconfig/scripts/python/helpers/helpers_sessions/sessions_impl.py +186 -0
  170. machineconfig/scripts/python/{helpers_sessions → helpers/helpers_sessions}/sessions_multiprocess.py +20 -14
  171. machineconfig/scripts/python/helpers/helpers_terminal/__init__.py +0 -0
  172. machineconfig/scripts/python/helpers/helpers_terminal/terminal_impl.py +96 -0
  173. machineconfig/scripts/python/helpers/helpers_utils/download.py +150 -0
  174. machineconfig/scripts/python/helpers/helpers_utils/pdf.py +96 -0
  175. machineconfig/scripts/python/helpers/helpers_utils/python.py +210 -0
  176. machineconfig/scripts/python/helpers/helpers_utils/specs.py +246 -0
  177. machineconfig/scripts/python/mcfg_entry.py +143 -0
  178. machineconfig/scripts/python/msearch.py +26 -0
  179. machineconfig/scripts/python/sessions.py +69 -135
  180. machineconfig/scripts/python/terminal.py +58 -0
  181. machineconfig/scripts/python/utils.py +115 -38
  182. machineconfig/scripts/windows/wrap_mcfg.ps1 +63 -0
  183. machineconfig/settings/atuin/config.toml +294 -0
  184. machineconfig/settings/atuin/themes/catppuccin-mocha-mauve.toml +12 -0
  185. machineconfig/settings/broot/conf.toml +1 -1
  186. machineconfig/settings/helix/config.toml +16 -0
  187. machineconfig/settings/helix/languages.toml +13 -4
  188. machineconfig/settings/helix/yazi-picker.sh +12 -0
  189. machineconfig/settings/lf/linux/exe/lfcd.sh +1 -0
  190. machineconfig/settings/lf/linux/exe/previewer.sh +3 -2
  191. machineconfig/settings/lf/windows/lfcd.ps1 +1 -1
  192. machineconfig/settings/lf/windows/lfrc +14 -16
  193. machineconfig/settings/linters/.ruff.toml +2 -1
  194. machineconfig/settings/marimo/marimo.toml +1 -1
  195. machineconfig/settings/marimo/snippets/globalize.py +34 -0
  196. machineconfig/settings/mprocs/windows/mprocs.yaml +2 -2
  197. machineconfig/settings/shells/bash/init.sh +47 -12
  198. machineconfig/settings/shells/ipy/profiles/default/startup/playext.py +1 -1
  199. machineconfig/settings/shells/nushell/config.nu +25 -33
  200. machineconfig/settings/shells/nushell/env.nu +21 -8
  201. machineconfig/settings/shells/nushell/init.nu +138 -0
  202. machineconfig/settings/shells/pwsh/init.ps1 +111 -17
  203. machineconfig/settings/shells/pwsh/search_pwsh_history.ps1 +99 -0
  204. machineconfig/settings/shells/starship/starship.toml +16 -0
  205. machineconfig/settings/shells/wezterm/wezterm.lua +6 -1
  206. machineconfig/settings/shells/wt/settings.json +27 -18
  207. machineconfig/settings/shells/zsh/init.sh +42 -23
  208. machineconfig/settings/television/cable_unix/alias.toml +8 -0
  209. machineconfig/settings/television/cable_unix/aws-buckets.toml +14 -0
  210. machineconfig/settings/television/cable_unix/aws-instances.toml +13 -0
  211. machineconfig/settings/television/cable_unix/bash-history.toml +8 -0
  212. machineconfig/settings/television/cable_unix/channels.toml +19 -0
  213. machineconfig/settings/television/cable_unix/dirs.toml +13 -0
  214. machineconfig/settings/television/cable_unix/distrobox-list.toml +42 -0
  215. machineconfig/settings/television/cable_unix/docker-images.toml +13 -0
  216. machineconfig/settings/television/cable_unix/dotfiles.toml +11 -0
  217. machineconfig/settings/television/cable_unix/env.toml +17 -0
  218. machineconfig/settings/television/cable_unix/files.toml +11 -0
  219. machineconfig/settings/television/cable_unix/fish-history.toml +8 -0
  220. machineconfig/settings/television/cable_unix/git-branch.toml +11 -0
  221. machineconfig/settings/television/cable_unix/git-diff.toml +10 -0
  222. machineconfig/settings/television/cable_unix/git-log.toml +12 -0
  223. machineconfig/settings/television/cable_unix/git-reflog.toml +12 -0
  224. machineconfig/settings/television/cable_unix/git-repos.toml +16 -0
  225. machineconfig/settings/television/cable_unix/guix.toml +20 -0
  226. machineconfig/settings/television/cable_unix/just-recipes.toml +18 -0
  227. machineconfig/settings/television/cable_unix/k8s-deployments.toml +36 -0
  228. machineconfig/settings/television/cable_unix/k8s-pods.toml +50 -0
  229. machineconfig/settings/television/cable_unix/k8s-services.toml +36 -0
  230. machineconfig/settings/television/cable_unix/man-pages.toml +24 -0
  231. machineconfig/settings/television/cable_unix/nu-history.toml +7 -0
  232. machineconfig/settings/television/cable_unix/procs.toml +20 -0
  233. machineconfig/settings/television/cable_unix/text.toml +17 -0
  234. machineconfig/settings/television/cable_unix/tldr.toml +18 -0
  235. machineconfig/settings/television/cable_unix/zsh-history.toml +9 -0
  236. machineconfig/settings/television/cable_windows/alias.toml +7 -0
  237. machineconfig/settings/television/cable_windows/dirs.toml +13 -0
  238. machineconfig/settings/television/cable_windows/docker-images.toml +13 -0
  239. machineconfig/settings/television/cable_windows/dotfiles.toml +11 -0
  240. machineconfig/settings/television/cable_windows/env.toml +17 -0
  241. machineconfig/settings/television/cable_windows/files.toml +14 -0
  242. machineconfig/settings/television/cable_windows/git-branch.toml +11 -0
  243. machineconfig/settings/television/cable_windows/git-diff.toml +10 -0
  244. machineconfig/settings/television/cable_windows/git-log.toml +11 -0
  245. machineconfig/settings/television/cable_windows/git-reflog.toml +11 -0
  246. machineconfig/settings/television/cable_windows/git-repos.toml +15 -0
  247. machineconfig/settings/television/cable_windows/nu-history.toml +7 -0
  248. machineconfig/settings/television/cable_windows/pwsh-history.toml +6 -0
  249. machineconfig/settings/television/cable_windows/text.toml +17 -0
  250. machineconfig/settings/tv/config.toml +234 -0
  251. machineconfig/settings/tv/themes/catppuccin-mocha-sky.toml +22 -0
  252. machineconfig/settings/wsl/.wslconfig +5 -30
  253. machineconfig/settings/wt/__init__.py +0 -0
  254. machineconfig/settings/yazi/init.lua +61 -0
  255. machineconfig/settings/yazi/keymap_linux.toml +94 -0
  256. machineconfig/settings/yazi/keymap_windows.toml +78 -0
  257. machineconfig/settings/yazi/shell/yazi_cd.ps1 +33 -0
  258. machineconfig/settings/yazi/shell/yazi_cd.sh +8 -0
  259. machineconfig/settings/yazi/theme.toml +4 -0
  260. machineconfig/settings/yazi/yazi_linux.toml +94 -0
  261. machineconfig/settings/yazi/yazi_windows.toml +58 -0
  262. machineconfig/settings/zellij/layouts/st.kdl +40 -9
  263. machineconfig/settings/zellij/layouts/st2.kdl +1 -1
  264. machineconfig/setup_linux/__init__.py +2 -2
  265. machineconfig/setup_linux/apps_desktop.sh +8 -27
  266. machineconfig/setup_linux/web_shortcuts/interactive.sh +27 -12
  267. machineconfig/setup_linux/web_shortcuts/live_from_github.sh +34 -0
  268. machineconfig/setup_mac/__init__.py +1 -4
  269. machineconfig/setup_mac/apps_gui.sh +248 -0
  270. machineconfig/setup_windows/__init__.py +2 -5
  271. machineconfig/setup_windows/uv.ps1 +8 -1
  272. machineconfig/setup_windows/web_shortcuts/interactive.ps1 +28 -12
  273. machineconfig/setup_windows/web_shortcuts/live_from_github.ps1 +31 -0
  274. machineconfig/setup_windows/web_shortcuts/quick_init.ps1 +17 -0
  275. machineconfig/type_hinting/sql/__init__.py +1 -0
  276. machineconfig/type_hinting/sql/base.py +216 -0
  277. machineconfig/type_hinting/sql/core_schema.py +64 -0
  278. machineconfig/type_hinting/sql/core_schema_typeddict.py +41 -0
  279. machineconfig/type_hinting/sql/typeddict_codegen.py +222 -0
  280. machineconfig/type_hinting/typedict/__init__.py +1 -0
  281. machineconfig/type_hinting/typedict/ast_utils.py +130 -0
  282. machineconfig/type_hinting/typedict/generator_helpers.py +319 -0
  283. machineconfig/type_hinting/typedict/generators.py +231 -0
  284. machineconfig/type_hinting/typedict/polars_schema.py +24 -0
  285. machineconfig/type_hinting/typedict/polars_schema_typeddict.py +63 -0
  286. machineconfig/utils/accessories.py +31 -4
  287. machineconfig/utils/code.py +163 -51
  288. machineconfig/utils/files/ascii_art.py +11 -15
  289. machineconfig/utils/files/headers.py +6 -7
  290. machineconfig/utils/files/read.py +8 -1
  291. machineconfig/utils/installer_utils/github_release_bulk.py +95 -138
  292. machineconfig/utils/installer_utils/github_release_scraper.py +99 -0
  293. machineconfig/utils/installer_utils/install_from_url.py +183 -0
  294. machineconfig/utils/installer_utils/installer_class.py +53 -102
  295. machineconfig/utils/installer_utils/installer_cli.py +161 -0
  296. machineconfig/utils/installer_utils/installer_helper.py +129 -0
  297. machineconfig/utils/installer_utils/{installer_abc.py → installer_locator_utils.py} +42 -91
  298. machineconfig/utils/{installer.py → installer_utils/installer_runner.py} +20 -65
  299. machineconfig/utils/io.py +94 -9
  300. machineconfig/utils/links.py +56 -38
  301. machineconfig/utils/meta.py +38 -21
  302. machineconfig/utils/options.py +81 -23
  303. machineconfig/utils/options_utils/__init__.py +0 -0
  304. machineconfig/utils/options_utils/options_tv_linux.py +211 -0
  305. machineconfig/utils/options_utils/options_tv_windows.py +88 -0
  306. machineconfig/utils/options_utils/tv_options.py +37 -0
  307. machineconfig/utils/path_extended.py +52 -102
  308. machineconfig/utils/path_helper.py +76 -23
  309. machineconfig/utils/procs.py +1 -1
  310. machineconfig/utils/scheduler.py +26 -53
  311. machineconfig/utils/scheduling.py +0 -2
  312. machineconfig/utils/schemas/fire_agents/fire_agents_input.py +1 -1
  313. machineconfig/utils/schemas/layouts/layout_types.py +1 -1
  314. machineconfig/utils/source_of_truth.py +6 -1
  315. machineconfig/utils/ssh.py +216 -419
  316. machineconfig/utils/ssh_utils/abc.py +5 -0
  317. machineconfig/utils/ssh_utils/copy_from_here.py +116 -0
  318. machineconfig/utils/ssh_utils/copy_to_here.py +303 -0
  319. machineconfig/utils/ssh_utils/utils.py +158 -0
  320. machineconfig/utils/ssh_utils/wsl.py +147 -0
  321. machineconfig/utils/ssh_utils/wsl_helper.py +217 -0
  322. machineconfig/utils/terminal.py +1 -0
  323. machineconfig/utils/upgrade_packages.py +107 -35
  324. machineconfig/utils/ve.py +12 -4
  325. machineconfig-8.51.dist-info/METADATA +140 -0
  326. machineconfig-8.51.dist-info/RECORD +543 -0
  327. {machineconfig-6.82.dist-info → machineconfig-8.51.dist-info}/entry_points.txt +4 -1
  328. machineconfig/jobs/installer/check_installations.py +0 -248
  329. machineconfig/jobs/installer/custom/hx.py +0 -140
  330. machineconfig/jobs/installer/linux_scripts/pgsql.sh +0 -41
  331. machineconfig/jobs/installer/linux_scripts/timescaledb.sh +0 -71
  332. machineconfig/jobs/installer/powershell_scripts/archive_pygraphviz.ps1 +0 -12
  333. machineconfig/jobs/installer/powershell_scripts/openssh-server_add_key.ps1 +0 -7
  334. machineconfig/jobs/installer/powershell_scripts/openssh-server_copy-ssh-id.ps1 +0 -14
  335. machineconfig/profile/backup.toml +0 -49
  336. machineconfig/profile/mapper.toml +0 -256
  337. machineconfig/scripts/linux/fzf2g +0 -21
  338. machineconfig/scripts/linux/fzfag +0 -17
  339. machineconfig/scripts/linux/fzffg +0 -25
  340. machineconfig/scripts/linux/fzfrga +0 -21
  341. machineconfig/scripts/linux/mcfgs +0 -38
  342. machineconfig/scripts/linux/other/share_smb +0 -1
  343. machineconfig/scripts/linux/other/switch_ip +0 -20
  344. machineconfig/scripts/linux/skrg +0 -4
  345. machineconfig/scripts/linux/warp-cli.sh +0 -122
  346. machineconfig/scripts/linux/z_ls +0 -104
  347. machineconfig/scripts/python/ai/command_runner/prompt.txt +0 -9
  348. machineconfig/scripts/python/helpers_devops/cli_config.py +0 -120
  349. machineconfig/scripts/python/helpers_devops/cli_config_dotfile.py +0 -77
  350. machineconfig/scripts/python/helpers_devops/cli_data.py +0 -25
  351. machineconfig/scripts/python/helpers_devops/cli_nw.py +0 -73
  352. machineconfig/scripts/python/helpers_devops/cli_repos.py +0 -181
  353. machineconfig/scripts/python/helpers_devops/cli_self.py +0 -122
  354. machineconfig/scripts/python/helpers_devops/cli_share_server.py +0 -104
  355. machineconfig/scripts/python/helpers_devops/cli_utils.py +0 -221
  356. machineconfig/scripts/python/helpers_devops/devops_backup_retrieve.py +0 -80
  357. machineconfig/scripts/python/helpers_devops/themes/choose_starship_theme.bash +0 -3
  358. machineconfig/scripts/python/helpers_fire/agentic_frameworks/fire_crush.py +0 -37
  359. machineconfig/scripts/python/helpers_fire/agentic_frameworks/fire_gemini.py +0 -44
  360. machineconfig/scripts/python/helpers_fire/agentic_frameworks/fire_qwen.py +0 -43
  361. machineconfig/scripts/python/helpers_fire/prompt.txt +0 -2
  362. machineconfig/scripts/python/helpers_fire/template.sh +0 -15
  363. machineconfig/scripts/python/helpers_navigator/__init__.py +0 -20
  364. machineconfig/scripts/python/helpers_navigator/command_detail.py +0 -44
  365. machineconfig/scripts/python/helpers_navigator/command_tree.py +0 -588
  366. machineconfig/scripts/python/helpers_repos/count_lines_frontend.py +0 -17
  367. machineconfig/scripts/python/helpers_repos/entrypoint.py +0 -76
  368. machineconfig/scripts/python/helpers_repos/secure_repo.py +0 -15
  369. machineconfig/scripts/python/mcfg.py +0 -48
  370. machineconfig/scripts/python/nw/add_ssh_key.py +0 -148
  371. machineconfig/scripts/python/nw/devops_add_identity.py +0 -82
  372. machineconfig/scripts/python/nw/devops_add_ssh_key.py +0 -134
  373. machineconfig/scripts/python/nw/ssh_debug_linux.py +0 -391
  374. machineconfig/scripts/python/nw/ssh_debug_windows.py +0 -338
  375. machineconfig/scripts/python/nw/wsl_windows_transfer.py +0 -66
  376. machineconfig/scripts/windows/fzfb.ps1 +0 -3
  377. machineconfig/scripts/windows/fzfg.ps1 +0 -2
  378. machineconfig/scripts/windows/fzfrga.bat +0 -20
  379. machineconfig/scripts/windows/mcfgs.ps1 +0 -17
  380. machineconfig/scripts/windows/mounts/mount_ssh.ps1 +0 -13
  381. machineconfig/settings/lf/linux/exe/fzf_nano.sh +0 -16
  382. machineconfig/settings/lf/windows/fzf_edit.ps1 +0 -6
  383. machineconfig/settings/lf/windows/tst.ps1 +0 -1
  384. machineconfig/settings/yazi/yazi.toml +0 -4
  385. machineconfig/setup_linux/apps.sh +0 -66
  386. machineconfig/setup_linux/others/cli_installation.sh +0 -137
  387. machineconfig/setup_linux/others/mint_keyboard_shortcuts.sh +0 -30
  388. machineconfig/setup_linux/ssh/openssh_all.sh +0 -25
  389. machineconfig/setup_linux/ssh/openssh_wsl.sh +0 -38
  390. machineconfig/setup_mac/apps.sh +0 -73
  391. machineconfig/setup_mac/ssh/openssh_setup.sh +0 -114
  392. machineconfig/setup_windows/apps.ps1 +0 -62
  393. machineconfig/setup_windows/others/obs.ps1 +0 -4
  394. machineconfig/setup_windows/ssh/add-sshkey.ps1 +0 -29
  395. machineconfig/setup_windows/ssh/add_identity.ps1 +0 -11
  396. machineconfig/setup_windows/ssh/openssh-server.ps1 +0 -37
  397. machineconfig/utils/installer_utils/installer.py +0 -225
  398. machineconfig/utils/tst.py +0 -20
  399. machineconfig-6.82.dist-info/METADATA +0 -82
  400. machineconfig-6.82.dist-info/RECORD +0 -441
  401. machineconfig/jobs/installer/{custom_dev → checks}/__init__.py +0 -0
  402. machineconfig/jobs/installer/linux_scripts/{warp-cli.sh → cloudflare_warp_cli.sh} +0 -0
  403. machineconfig/{scripts/python/helpers_cloud → jobs/installer/python_scripts}/__init__.py +0 -0
  404. machineconfig/jobs/installer/{custom_dev → python_scripts}/alacritty.py +0 -0
  405. machineconfig/jobs/installer/{custom_dev → python_scripts}/bypass_paywall.py +0 -0
  406. machineconfig/jobs/installer/{custom_dev → python_scripts}/cursor.py +0 -0
  407. machineconfig/jobs/installer/{custom_dev → python_scripts}/espanso.py +0 -0
  408. machineconfig/jobs/installer/{custom → python_scripts}/gh.py +0 -0
  409. machineconfig/jobs/installer/{custom_dev → python_scripts}/goes.py +0 -0
  410. machineconfig/jobs/installer/{custom_dev → python_scripts}/lvim.py +0 -0
  411. machineconfig/jobs/installer/{custom_dev → python_scripts}/redis.py +0 -0
  412. machineconfig/{setup_linux/others → jobs/scripts/bash_scripts}/android.sh +0 -0
  413. machineconfig/jobs/{installer/linux_scripts → scripts/bash_scripts}/lid.sh +0 -0
  414. machineconfig/{scripts/python/nw → jobs/scripts/bash_scripts}/mount_drive +0 -0
  415. machineconfig/{scripts/python/nw → jobs/scripts/bash_scripts}/mount_nw_drive +0 -0
  416. machineconfig/{scripts/python/nw → jobs/scripts/bash_scripts}/mount_smb +0 -0
  417. machineconfig/{scripts/linux/other → jobs/scripts/bash_scripts}/share_cloud.sh +0 -0
  418. machineconfig/{scripts/linux/other → jobs/scripts/bash_scripts}/share_nfs +0 -0
  419. machineconfig/{scripts/linux/other → jobs/scripts/bash_scripts}/start_docker +0 -0
  420. machineconfig/{scripts → jobs/scripts/powershell_scripts}/Restore-ThunderbirdProfile.ps1 +0 -0
  421. machineconfig/{setup_windows/others → jobs/scripts/powershell_scripts}/docker.ps1 +0 -0
  422. machineconfig/{scripts/windows/mounts → jobs/scripts/powershell_scripts}/mount_nfs.ps1 +0 -0
  423. machineconfig/{scripts/windows/mounts → jobs/scripts/powershell_scripts}/mount_nw.ps1 +0 -0
  424. machineconfig/{scripts/windows/mounts → jobs/scripts/powershell_scripts}/mount_smb.ps1 +0 -0
  425. machineconfig/{setup_windows/others → jobs/scripts/powershell_scripts}/power_options.ps1 +0 -0
  426. machineconfig/{scripts/windows/mounts → jobs/scripts/powershell_scripts}/share_cloud.cmd +0 -0
  427. machineconfig/{scripts/windows/mounts → jobs/scripts/powershell_scripts}/share_smb.ps1 +0 -0
  428. machineconfig/{scripts/windows/mounts → jobs/scripts/powershell_scripts}/unlock_bitlocker.ps1 +0 -0
  429. machineconfig/scripts/python/{helpers_croshell → ai/utils}/__init__.py +0 -0
  430. machineconfig/scripts/python/ai/{solutions/_shared.py → utils/shared.py} +0 -0
  431. machineconfig/scripts/python/{helpers_devops → graph}/__init__.py +0 -0
  432. machineconfig/scripts/python/{helpers_devops/themes → helpers}/__init__.py +0 -0
  433. machineconfig/scripts/python/{env_manager → helpers/helper_env}/__init__.py +0 -0
  434. machineconfig/scripts/python/{env_manager → helpers/helper_env}/path_manager_backend.py +0 -0
  435. machineconfig/scripts/python/{helpers_fire → helpers/helpers_agents}/__init__.py +0 -0
  436. machineconfig/scripts/python/{helpers_fire → helpers/helpers_agents}/agentic_frameworks/__init__.py +0 -0
  437. machineconfig/scripts/python/{helpers_fire → helpers/helpers_agents}/fire_agents_help_search.py +0 -0
  438. machineconfig/scripts/python/{helpers_fire → helpers/helpers_agents}/fire_agents_load_balancer.py +0 -0
  439. machineconfig/scripts/python/{helpers_fire → helpers/helpers_agents/templates}/template.ps1 +0 -0
  440. machineconfig/scripts/python/{helpers_fire_command → helpers/helpers_cloud}/__init__.py +0 -0
  441. machineconfig/scripts/python/{helpers_cloud → helpers/helpers_cloud}/cloud_helpers.py +1 -1
  442. /machineconfig/scripts/python/{helpers_cloud → helpers/helpers_cloud}/helpers5.py +0 -0
  443. /machineconfig/scripts/python/{helpers_sessions → helpers/helpers_croshell}/__init__.py +0 -0
  444. /machineconfig/scripts/python/{helpers_croshell → helpers/helpers_croshell}/pomodoro.py +0 -0
  445. /machineconfig/scripts/python/{helpers_croshell → helpers/helpers_croshell}/viewer.py +0 -0
  446. /machineconfig/scripts/python/{helpers_croshell → helpers/helpers_croshell}/viewer_template.py +0 -0
  447. /machineconfig/scripts/python/{nw → helpers/helpers_devops}/__init__.py +0 -0
  448. /machineconfig/{setup_windows/wt_and_pwsh → scripts/python/helpers/helpers_devops/themes}/__init__.py +0 -0
  449. /machineconfig/scripts/python/{helpers_devops → helpers/helpers_devops}/themes/choose_pwsh_theme.ps1 +0 -0
  450. /machineconfig/scripts/python/{helpers_devops/themes/choose_starship_theme.ps1 → helpers/helpers_fire_command/__init__.py} +0 -0
  451. /machineconfig/scripts/python/{helpers_fire_command → helpers/helpers_fire_command}/cloud_manager.py +0 -0
  452. /machineconfig/scripts/python/{helpers_fire_command/fire_jobs_streamlit_helper.py → helpers/helpers_fire_command/f.py} +0 -0
  453. /machineconfig/{settings/shells/pwsh/profile.ps1 → scripts/python/helpers/helpers_fire_command/fire_jobs_streamlit_helper.py} +0 -0
  454. /machineconfig/scripts/python/{helpers_navigator → helpers/helpers_navigator}/search_bar.py +0 -0
  455. /machineconfig/{settings/yazi/keymap.toml → scripts/python/helpers/helpers_network/__init__.py} +0 -0
  456. /machineconfig/scripts/python/{nw → helpers/helpers_network}/mount_nw_drive.py +0 -0
  457. /machineconfig/scripts/python/{nw → helpers/helpers_network}/onetimeshare.py +0 -0
  458. /machineconfig/scripts/python/{helpers_repos → helpers/helpers_repos}/sync.py +0 -0
  459. /machineconfig/{setup_windows/wt_and_pwsh → settings/wt}/set_wt_settings.py +0 -0
  460. {machineconfig-6.82.dist-info → machineconfig-8.51.dist-info}/WHEEL +0 -0
  461. {machineconfig-6.82.dist-info → machineconfig-8.51.dist-info}/top_level.txt +0 -0
@@ -1,4 +1,5 @@
1
1
  from machineconfig.utils.accessories import randstr
2
+ from machineconfig.utils.io import decrypt, encrypt
2
3
 
3
4
  from datetime import datetime
4
5
  import time
@@ -10,10 +11,13 @@ from platform import system
10
11
  from typing import Any, Optional, Union, Callable, TypeAlias, Literal
11
12
 
12
13
 
14
+
13
15
  OPLike: TypeAlias = Union[str, "PathExtended", Path, None]
14
16
  PLike: TypeAlias = Union[str, "PathExtended", Path]
15
17
  FILE_MODE: TypeAlias = Literal["r", "w", "x", "a"]
16
18
  SHUTIL_FORMATS: TypeAlias = Literal["zip", "tar", "gztar", "bztar", "xztar"]
19
+ DECOMPRESS_SUPPORTED_FORMATS = [".tar.gz", ".tgz", ".tar", ".gz", ".tar.bz", ".tbz", ".tar.xz", ".zip", ".7z",
20
+ ".tar.bz2", ".tbz2", ".xz"]
17
21
 
18
22
 
19
23
  def _is_user_admin() -> bool:
@@ -54,81 +58,6 @@ def _run_shell_command(
54
58
  )
55
59
 
56
60
 
57
- def pwd2key(password: str, salt: Optional[bytes] = None, iterations: int = 10) -> bytes: # Derive a secret key from a given password and salt"""
58
- import base64
59
-
60
- if salt is None:
61
- import hashlib
62
-
63
- m = hashlib.sha256()
64
- m.update(password.encode(encoding="utf-8"))
65
- return base64.urlsafe_b64encode(s=m.digest()) # make url-safe bytes required by Ferent.
66
- from cryptography.hazmat.primitives import hashes
67
- from cryptography.hazmat.primitives.kdf.pbkdf2 import PBKDF2HMAC
68
-
69
- return base64.urlsafe_b64encode(PBKDF2HMAC(algorithm=hashes.SHA256(), length=32, salt=salt, iterations=iterations, backend=None).derive(password.encode()))
70
-
71
-
72
- def encrypt(msg: bytes, key: Optional[bytes] = None, pwd: Optional[str] = None, salted: bool = True, iteration: Optional[int] = None, gen_key: bool = False) -> bytes:
73
- import base64
74
- from cryptography.fernet import Fernet
75
-
76
- salt, iteration = None, None
77
- if pwd is not None: # generate it from password
78
- assert (key is None) and (type(pwd) is str), "❌ You can either pass key or pwd, or none of them, but not both."
79
- import secrets
80
-
81
- iteration = iteration or secrets.randbelow(exclusive_upper_bound=1_000_000)
82
- salt = secrets.token_bytes(nbytes=16) if salted else None
83
- key_resolved = pwd2key(password=pwd, salt=salt, iterations=iteration)
84
- elif key is None:
85
- if gen_key:
86
- key_resolved = Fernet.generate_key()
87
- Path.home().joinpath("dotfiles/creds/data/encrypted_files_key.bytes").write_bytes(key_resolved)
88
- else:
89
- try:
90
- key_resolved = Path.home().joinpath("dotfiles/creds/data/encrypted_files_key.bytes").read_bytes()
91
- print(f"⚠️ Using key from: {Path.home().joinpath('dotfiles/creds/data/encrypted_files_key.bytes')}")
92
- except FileNotFoundError as err:
93
- print("\n" * 3, "~" * 50, """Consider Loading up your dotfiles or pass `gen_key=True` to make and save one.""", "~" * 50, "\n" * 3)
94
- raise FileNotFoundError(err) from err
95
- elif isinstance(key, (str, PathExtended, Path)):
96
- key_resolved = Path(key).read_bytes() # a path to a key file was passed, read it:
97
- elif type(key) is bytes:
98
- key_resolved = key # key passed explicitly
99
- else:
100
- raise TypeError("❌ Key must be either a path, bytes object or None.")
101
- code = Fernet(key=key_resolved).encrypt(msg)
102
- if pwd is not None and salt is not None and iteration is not None:
103
- return base64.urlsafe_b64encode(b"%b%b%b" % (salt, iteration.to_bytes(4, "big"), base64.urlsafe_b64decode(code)))
104
- return code
105
-
106
-
107
- def decrypt(token: bytes, key: Optional[bytes] = None, pwd: Optional[str] = None, salted: bool = True) -> bytes:
108
- import base64
109
-
110
- if pwd is not None:
111
- assert key is None, "❌ You can either pass key or pwd, or none of them, but not both."
112
- if salted:
113
- decoded = base64.urlsafe_b64decode(token)
114
- salt, iterations, token = decoded[:16], decoded[16:20], base64.urlsafe_b64encode(decoded[20:])
115
- key_resolved = pwd2key(password=pwd, salt=salt, iterations=int.from_bytes(bytes=iterations, byteorder="big"))
116
- else:
117
- key_resolved = pwd2key(password=pwd) # trailing `;` prevents IPython from caching the result.
118
- elif type(key) is bytes:
119
- assert pwd is None, "❌ You can either pass key or pwd, or none of them, but not both."
120
- key_resolved = key # passsed explicitly
121
- elif key is None:
122
- key_resolved = Path.home().joinpath("dotfiles/creds/data/encrypted_files_key.bytes").read_bytes() # read from file
123
- elif isinstance(key, (str, Path)):
124
- key_resolved = Path(key).read_bytes() # passed a path to a file containing kwy
125
- else:
126
- raise TypeError(f"❌ Key must be either str, P, Path, bytes or None. Recieved: {type(key)}")
127
- from cryptography.fernet import Fernet
128
-
129
- return Fernet(key=key_resolved).decrypt(token)
130
-
131
-
132
61
  def validate_name(astring: str, replace: str = "_") -> str:
133
62
  import re
134
63
 
@@ -174,7 +103,7 @@ class PathExtended(type(Path()), Path): # type: ignore # pylint: disable=E0241
174
103
  slf = self.expanduser().resolve()
175
104
  if content:
176
105
  assert self.is_dir(), NotADirectoryError(f"💥 When `content` flag is set to True, path must be a directory. It is not: `{repr(self)}`")
177
- [x.move(folder=path.parent, content=False, overwrite=overwrite) for x in self.search("*")]
106
+ [x.move(folder=path.parent, content=False, overwrite=overwrite) for x in self.glob("*")]
178
107
  return path # contents live within this directory.
179
108
  if overwrite:
180
109
  tmp_path = slf.rename(path.parent.absolute() / randstr())
@@ -225,7 +154,6 @@ class PathExtended(type(Path()), Path): # type: ignore # pylint: disable=E0241
225
154
  # ======================================= File Editing / Reading ===================================
226
155
  def download(self, folder: OPLike = None, name: Optional[str] = None, allow_redirects: bool = True, timeout: Optional[int] = None, params: Any = None) -> "PathExtended":
227
156
  import requests
228
-
229
157
  response = requests.get(self.as_url_str(), allow_redirects=allow_redirects, timeout=timeout, params=params) # Alternative: from urllib import request; request.urlopen(url).read().decode('utf-8').
230
158
  assert response.status_code == 200, f"Download failed with status code {response.status_code}\n{response.text}"
231
159
  if name is not None:
@@ -246,7 +174,8 @@ class PathExtended(type(Path()), Path): # type: ignore # pylint: disable=E0241
246
174
  appended_name = f"""{name}_{len(self.parent.search(f"*{self.name.split('.')[0]}*"))}"""
247
175
  return self.append(name=appended_name, index=False, verbose=verbose, suffix=suffix, **kwargs)
248
176
  full_name = name or ("_" + str(timestamp()))
249
- full_suffix = suffix or "".join(("bruh" + self).suffixes)
177
+ whatever = ("bruh" + self)
178
+ full_suffix = suffix or "".join(whatever.suffixes)
250
179
  subpath = self.name.split(".")[0] + full_name + full_suffix
251
180
  dest = self.parent.joinpath(subpath)
252
181
  res = PathExtended(dest)
@@ -366,7 +295,7 @@ class PathExtended(type(Path()), Path): # type: ignore # pylint: disable=E0241
366
295
  target = "BROKEN LINK " + str(self) # avoid infinite recursions for broken links.
367
296
  return "🔗 Symlink '" + str(self) + "' ==> " + (str(target) if target == self else str(target))
368
297
  elif self.is_absolute():
369
- return self._type() + " '" + str(self.clickable()) + "'" + (" | " + datetime.fromtimestamp(self.stat().st_ctime).isoformat()[:-7].replace("T", " ") if self.exists() else "") + (f" | {self.size()} Mb" if self.is_file() else "")
298
+ return self._type() + " '" + str(self.clickable()) + "'" + (" | " + datetime.fromtimestamp(self.stat().st_ctime).isoformat()[:-7].replace("T", " ") if self.exists() else "") + (f" | {round(self.stat().st_size / (1024**2), 1)} Mb" if self.is_file() else "")
370
299
  elif "http" in str(self):
371
300
  return "🕸️ URL " + str(self.as_url_str())
372
301
  else:
@@ -548,14 +477,10 @@ class PathExtended(type(Path()), Path): # type: ignore # pylint: disable=E0241
548
477
  verbose: bool = True,
549
478
  content: bool = False,
550
479
  orig: bool = False,
551
- pwd: Optional[str] = None,
552
480
  mode: FILE_MODE = "w",
553
481
  **kwargs: Any,
554
482
  ) -> "PathExtended":
555
483
  path_resolved, slf = self._resolve_path(folder, name, path, self.name).expanduser().resolve(), self.expanduser().resolve()
556
- # if use_7z: # benefits over regular zip and encrypt: can handle very large files with low memory footprint
557
- # path_resolved = path_resolved + '.7z' if not path_resolved.suffix == '.7z' else path_resolved
558
- # with install_n_import("py7zr").SevenZipFile(file=path_resolved, mode=mode, password=pwd) as archive: archive.writeall(path=str(slf), arcname=None)
559
484
  arcname_obj = PathExtended(arcname or slf.name)
560
485
  if arcname_obj.name != slf.name:
561
486
  arcname_obj /= slf.name # arcname has to start from somewhere and end with filename
@@ -568,7 +493,6 @@ class PathExtended(type(Path()), Path): # type: ignore # pylint: disable=E0241
568
493
  path_resolved = PathExtended(op_zip)
569
494
  else:
570
495
  import shutil
571
-
572
496
  if content:
573
497
  root_dir, base_dir = slf, "."
574
498
  else:
@@ -576,7 +500,7 @@ class PathExtended(type(Path()), Path): # type: ignore # pylint: disable=E0241
576
500
  base_name = str(path_resolved)[:-4] if str(path_resolved).endswith(".zip") else str(path_resolved)
577
501
  op_zip = shutil.make_archive(base_name=base_name, format="zip", root_dir=str(root_dir), base_dir=str(base_dir), verbose=False, **kwargs)
578
502
  path_resolved = PathExtended(op_zip)
579
- msg = f"ZIPPED {repr(slf)} ==> {repr(path)}"
503
+ msg = f"ZIPPED {repr(slf)} ==> {repr(path_resolved)}"
580
504
  res_out = PathExtended(path_resolved)
581
505
  ret = self if orig else res_out
582
506
  delayed_msg = ""
@@ -613,7 +537,9 @@ class PathExtended(type(Path()), Path): # type: ignore # pylint: disable=E0241
613
537
  assert merge is False, "I have not implemented this yet"
614
538
  assert path is None, "I have not implemented this yet"
615
539
  if tmp:
616
- return self.unzip(folder=PathExtended.tmp().joinpath("tmp_unzips").joinpath(randstr()), content=True).joinpath(self.stem)
540
+ tmp_root = PathExtended("~/tmp_results").expanduser()
541
+ tmp_root.mkdir(parents=True, exist_ok=True)
542
+ return self.unzip(folder=tmp_root.joinpath("tmp_unzips").joinpath(randstr()), content=True).joinpath(self.stem)
617
543
  slf = zipfile__ = self.expanduser().resolve()
618
544
  if any(ztype in str(slf.parent) for ztype in (".zip", ".7z")): # path include a zip archive in the middle.
619
545
  tmp__ = [item for item in (".zip", ".7z", "") if item in str(slf)]
@@ -628,15 +554,6 @@ class PathExtended(type(Path()), Path): # type: ignore # pylint: disable=E0241
628
554
  folder = folder if not content else folder.parent
629
555
  if slf.suffix == ".7z":
630
556
  raise NotImplementedError("I have not implemented this yet")
631
- # if overwrite: P(folder).delete(sure=True)
632
- # result = folder
633
- # import py7zr
634
- # with py7zr.SevenZipFile(file=slf, mode='r', password=pwd) as archive:
635
- # if pattern is not None:
636
- # import re
637
- # pat = re.compile(pattern)
638
- # archive.extract(path=folder, targets=[f for f in archive.getnames() if pat.match(f)])
639
- # else: archive.extractall(path=folder)
640
557
  else:
641
558
  if overwrite:
642
559
  if not content:
@@ -771,21 +688,54 @@ class PathExtended(type(Path()), Path): # type: ignore # pylint: disable=E0241
771
688
  return ret
772
689
 
773
690
  def decompress(self, folder: OPLike = None, name: Optional[str] = None, path: OPLike = None, inplace: bool = False, orig: bool = False, verbose: bool = True) -> "PathExtended":
774
- if ".tar.gz" in str(self) or ".tgz" in str(self):
691
+ if str(self).endswith(".tar.gz") or str(self).endswith(".tgz"):
775
692
  # res = self.ungz_untar(folder=folder, path=path, name=name, inplace=inplace, verbose=verbose, orig=orig)
776
693
  return self.ungz(name=f"tmp_{randstr()}.tar", inplace=inplace).untar(folder=folder, name=name, path=path, inplace=True, orig=orig, verbose=verbose) # this works for .tgz suffix as well as .tar.gz
777
- elif ".gz" in str(self):
694
+ elif str(self).endswith(".tar"):
695
+ res = self.untar(folder=folder, name=name, path=path, inplace=inplace, orig=orig, verbose=verbose)
696
+ elif str(self).endswith(".gz"):
778
697
  res = self.ungz(folder=folder, path=path, name=name, inplace=inplace, verbose=verbose, orig=orig)
779
- elif ".tar.bz" in str(self) or "tbz" in str(self):
698
+ elif str(self).endswith(".tar.bz") or str(self).endswith(".tbz") or str(self).endswith(".tar.bz2"):
780
699
  res = self.unbz(name=f"tmp_{randstr()}.tar", inplace=inplace)
781
700
  return res.untar(folder=folder, name=name, path=path, inplace=True, orig=orig, verbose=verbose)
782
- elif ".tar.xz" in str(self):
701
+ elif str(self).endswith(".tar.xz"):
783
702
  # res = self.unxz_untar(folder=folder, path=path, name=name, inplace=inplace, verbose=verbose, orig=orig)
784
703
  res = self.unxz(inplace=inplace).untar(folder=folder, name=name, path=path, inplace=True, orig=orig, verbose=verbose)
785
- elif ".zip" in str(self):
704
+ elif str(self).endswith(".zip"):
786
705
  res = self.unzip(folder=folder, path=path, name=name, inplace=inplace, verbose=verbose, orig=orig)
706
+ elif str(self).endswith(".7z"):
707
+ def unzip_7z(archive_path: str, dest_dir: Optional[str] = None) -> Path:
708
+ """
709
+ Uncompresses a .7z archive to a directory and returns the Path to the extraction directory.
710
+
711
+ :param archive_path: path to the .7z archive file
712
+ :param dest_dir: optional path to directory to extract into; if None a temporary dir will be created
713
+ :return: pathlib.Path pointing to the destination directory where contents were extracted
714
+ :raises: FileNotFoundError if archive does not exist; py7zr.Bad7zFile or other error if extraction fails
715
+ """
716
+ import py7zr # type: ignore
717
+ import tempfile
718
+ from pathlib import Path
719
+ archive_path_obj = Path(archive_path)
720
+ if not archive_path_obj.is_file():
721
+ raise FileNotFoundError(f"Archive file not found: {archive_path_obj!r}")
722
+ if dest_dir is None:
723
+ # create a temporary directory
724
+ dest = Path(tempfile.mkdtemp(prefix=f"unzip7z_{archive_path_obj.stem}_"))
725
+ else:
726
+ dest = Path(dest_dir)
727
+ dest.mkdir(parents=True, exist_ok=True)
728
+ # Perform extraction
729
+ with py7zr.SevenZipFile(str(archive_path_obj), mode='r') as archive:
730
+ archive.extractall(path=str(dest))
731
+ # Return the extraction directory path
732
+ return dest
733
+ from machineconfig.utils.code import run_lambda_function
734
+ destination_dir = str(self.expanduser().resolve()).replace(".7z", "")
735
+ run_lambda_function(lambda: unzip_7z(archive_path=str(self), dest_dir=destination_dir), uv_project_dir=None, uv_with=["py7zr"])
736
+ res = PathExtended(destination_dir)
787
737
  else:
788
- res = self
738
+ raise ValueError(f"Cannot decompress file with unknown extension: {self}")
789
739
  return res
790
740
 
791
741
  def encrypt(
@@ -861,7 +811,7 @@ class PathExtended(type(Path()), Path): # type: ignore # pylint: disable=E0241
861
811
  path = self
862
812
  else:
863
813
  try:
864
- path = self.rel2home()
814
+ path = PathExtended(self.expanduser().absolute().relative_to(Path.home()))
865
815
  except ValueError as ve:
866
816
  if strict:
867
817
  raise ve
@@ -1,18 +1,16 @@
1
- from machineconfig.utils.path_extended import PathExtended
2
- from machineconfig.utils.options import choose_from_options
3
1
  from machineconfig.utils.source_of_truth import EXCLUDE_DIRS
4
2
  from rich.console import Console
5
3
  from rich.panel import Panel
6
4
  import platform
7
5
  import subprocess
8
6
  from pathlib import Path
9
-
7
+ from typing import Optional
10
8
 
11
9
  console = Console()
12
10
 
13
11
 
14
- def sanitize_path(a_path: str) -> PathExtended:
15
- path = PathExtended(a_path)
12
+ def sanitize_path(a_path: str) -> Path:
13
+ path = Path(a_path)
16
14
  if Path.cwd() == Path.home() and not path.exists():
17
15
  result = input("Current working directory is home, and passed path is not full path, are you sure you want to continue, [y]/n? ") or "y"
18
16
  if result == "y":
@@ -23,13 +21,13 @@ def sanitize_path(a_path: str) -> PathExtended:
23
21
  if platform.system() == "Windows": # path copied from Linux/Mac to Windows
24
22
  # For Linux: /home/username, for Mac: /Users/username
25
23
  skip_parts = 3 if path.as_posix().startswith("/home") else 3 # Both have 3 parts to skip
26
- path = PathExtended.home().joinpath(*path.parts[skip_parts:])
24
+ path = Path.home().joinpath(*path.parts[skip_parts:])
27
25
  assert path.exists(), f"File not found: {path}"
28
26
  source_os = "Linux" if path.as_posix().startswith("/home") else "macOS"
29
27
  console.print(Panel(f"🔗 PATH MAPPING | {source_os} → Windows: `{a_path}` ➡️ `{path}`", title="Path Mapping", expand=False))
30
- elif platform.system() in ["Linux", "Darwin"] and PathExtended.home().as_posix() not in path.as_posix(): # copied between Unix-like systems with different username
28
+ elif platform.system() in ["Linux", "Darwin"] and Path.home().as_posix() not in path.as_posix(): # copied between Unix-like systems with different username
31
29
  skip_parts = 3 # Both /home/username and /Users/username have 3 parts to skip
32
- path = PathExtended.home().joinpath(*path.parts[skip_parts:])
30
+ path = Path.home().joinpath(*path.parts[skip_parts:])
33
31
  assert path.exists(), f"File not found: {path}"
34
32
  current_os = "Linux" if platform.system() == "Linux" else "macOS"
35
33
  source_os = "Linux" if path.as_posix().startswith("/home") else "macOS"
@@ -37,12 +35,12 @@ def sanitize_path(a_path: str) -> PathExtended:
37
35
  elif path.as_posix().startswith("C:"):
38
36
  if platform.system() in ["Linux", "Darwin"]: # path copied from Windows to Linux/Mac
39
37
  xx = str(a_path).replace("\\\\", "/")
40
- path = PathExtended.home().joinpath(*PathExtended(xx).parts[3:]) # exclude C:\\Users\\username
38
+ path = Path.home().joinpath(*Path(xx).parts[3:]) # exclude C:\\Users\\username
41
39
  assert path.exists(), f"File not found: {path}"
42
40
  target_os = "Linux" if platform.system() == "Linux" else "macOS"
43
41
  console.print(Panel(f"🔗 PATH MAPPING | Windows → {target_os}: `{a_path}` ➡️ `{path}`", title="Path Mapping", expand=False))
44
- elif platform.system() == "Windows" and PathExtended.home().as_posix() not in path.as_posix(): # copied from Windows to Windows with different username
45
- path = PathExtended.home().joinpath(*path.parts[2:])
42
+ elif platform.system() == "Windows" and Path.home().as_posix() not in path.as_posix(): # copied from Windows to Windows with different username
43
+ path = Path.home().joinpath(*path.parts[2:])
46
44
  assert path.exists(), f"File not found: {path}"
47
45
  console.print(Panel(f"🔗 PATH MAPPING | Windows → Windows: `{a_path}` ➡️ `{path}`", title="Path Mapping", expand=False))
48
46
  return path.expanduser().absolute()
@@ -67,49 +65,58 @@ def find_scripts(root: Path, name_substring: str, suffixes: set[str]) -> tuple[l
67
65
  return filename_matches, partial_path_matches
68
66
 
69
67
 
70
- def match_file_name(sub_string: str, search_root: PathExtended, suffixes: set[str]) -> PathExtended:
68
+ def match_file_name(sub_string: str, search_root: Path, suffixes: set[str]) -> Path:
71
69
  search_root_obj = search_root.absolute()
72
70
  # assume subscript is filename only, not a sub_path. There is no need to fzf over the paths.
73
71
  filename_matches, partial_path_matches = find_scripts(search_root_obj, sub_string, suffixes)
74
72
  if len(filename_matches) == 1:
75
- return PathExtended(filename_matches[0])
73
+ return Path(filename_matches[0])
76
74
  console.print(Panel(f"Partial filename {search_root_obj} match with case-insensitivity failed. This generated #{len(filename_matches)} results.", title="Search", expand=False))
77
75
  if len(filename_matches) < 20:
78
76
  print("\n".join([a_potential_match.as_posix() for a_potential_match in filename_matches]))
79
77
  if len(filename_matches) > 1:
80
- print("Try to narrow down filename_matches search by case-sensitivity.")
78
+ print(f"Try to narrow down filename_matches search by case-sensitivity, found {len(filename_matches)} results. First @ {filename_matches[0].as_posix()}")
81
79
  # let's see if avoiding .lower() helps narrowing down to one result
82
80
  reduced_scripts = [a_potential_match for a_potential_match in filename_matches if sub_string in a_potential_match.name]
83
81
  if len(reduced_scripts) == 1:
84
- return PathExtended(reduced_scripts[0])
82
+ return Path(reduced_scripts[0])
85
83
  elif len(reduced_scripts) > 1:
86
- choice = choose_from_options(multi=False, msg="Multiple matches found", options=reduced_scripts, fzf=True)
87
- return PathExtended(choice)
84
+ from machineconfig.utils.options import choose_from_options
85
+ choice = choose_from_options(multi=False, msg="Multiple matches found", options=reduced_scripts, tv=True)
86
+ return Path(choice)
88
87
  print(f"Result: This still generated {len(reduced_scripts)} results.")
89
88
  if len(reduced_scripts) < 10:
90
89
  print("\n".join([a_potential_match.as_posix() for a_potential_match in reduced_scripts]))
91
90
 
92
91
  console.print(Panel(f"Partial path match with case-insensitivity failed. This generated #{len(partial_path_matches)} results.", title="Search", expand=False))
93
92
  if len(partial_path_matches) == 1:
94
- return PathExtended(partial_path_matches[0])
93
+ return Path(partial_path_matches[0])
95
94
  elif len(partial_path_matches) > 1:
96
95
  print("Try to narrow down partial_path_matches search by case-sensitivity.")
97
96
  reduced_scripts = [a_potential_match for a_potential_match in partial_path_matches if sub_string in a_potential_match.as_posix()]
98
97
  if len(reduced_scripts) == 1:
99
- return PathExtended(reduced_scripts[0])
100
- print(f"Result: This still generated {len(reduced_scripts)} results.")
98
+ return Path(reduced_scripts[0])
99
+ print(f"Result: This still generated {len(reduced_scripts)} results.")
100
+
101
101
  try:
102
- fzf_cmd = f"cd '{search_root_obj}'; fd --type file --strip-cwd-prefix | fzf --ignore-case --exact --query={sub_string}"
102
+
103
+ if len(partial_path_matches) == 0:
104
+ print("No partial path matches found, trying to do fd with --no-ignore ...")
105
+ fzf_cmd = f"cd '{search_root_obj}'; fd --no-ignore --type file --strip-cwd-prefix | fzf --ignore-case --exact --query={sub_string}"
106
+ else:
107
+ fzf_cmd = f"cd '{search_root_obj}'; fd --type file --strip-cwd-prefix | fzf --ignore-case --exact --query={sub_string}"
103
108
  console.print(Panel(f"🔍 Second attempt: SEARCH STRATEGY | Using fd to search for '{sub_string}' in '{search_root_obj}' ...\n{fzf_cmd}", title="Search Strategy", expand=False))
104
109
  search_res_raw = subprocess.run(fzf_cmd, stdout=subprocess.PIPE, text=True, check=True, shell=True).stdout
105
- search_res = search_res_raw.strip().split("\\n")[:-1]
110
+ search_res = search_res_raw.strip().split("\n")
106
111
  except subprocess.CalledProcessError as cpe:
107
112
  console.print(Panel(f"❌ ERROR | FZF search failed with '{sub_string}' in '{search_root_obj}'.\n{cpe}", title="Error", expand=False))
108
113
  import sys
109
-
110
114
  sys.exit(f"💥 FILE NOT FOUND | Path {sub_string} does not exist @ root {search_root_obj}. No search results.")
111
115
  if len(search_res) == 1:
112
116
  return search_root_obj.joinpath(search_res_raw)
117
+ elif len(search_res) == 0:
118
+ msg = Panel(f"💥 FILE NOT FOUND | Path {sub_string} does not exist @ root {search_root_obj}. No search results", title="File Not Found", expand=False)
119
+ raise FileNotFoundError(msg)
113
120
 
114
121
  print(f"⚠️ WARNING | Multiple search results found for `{sub_string}`:\n'{search_res}'")
115
122
  cmd = f"cd '{search_root_obj}'; fd --type file | fzf --select-1 --query={sub_string}"
@@ -121,3 +128,49 @@ def match_file_name(sub_string: str, search_root: PathExtended, suffixes: set[st
121
128
  msg = Panel(f"💥 FILE NOT FOUND | Path {sub_string} does not exist @ root {search_root_obj}. No search results", title="File Not Found", expand=False)
122
129
  raise FileNotFoundError(msg) from cpe
123
130
  return search_root_obj.joinpath(res)
131
+
132
+
133
+ def search_for_files_of_interest(path_obj: Path, suffixes: set[str]) -> list[Path]:
134
+ if path_obj.is_file():
135
+ return [path_obj]
136
+ files: list[Path] = []
137
+ directories_to_visit: list[Path] = [path_obj]
138
+ while directories_to_visit:
139
+ current_dir = directories_to_visit.pop()
140
+ for entry in current_dir.iterdir():
141
+ if entry.is_dir():
142
+ if entry.name == ".venv":
143
+ continue
144
+ directories_to_visit.append(entry)
145
+ continue
146
+ if entry.suffix not in suffixes:
147
+ continue
148
+ if entry.suffix == ".py" and entry.name == "__init__.py":
149
+ continue
150
+ files.append(entry)
151
+ return files
152
+
153
+
154
+ def get_choice_file(path: str, suffixes: Optional[set[str]]):
155
+ path_obj = sanitize_path(path)
156
+ if suffixes is None:
157
+ import platform
158
+ if platform.system() == "Windows":
159
+ suffixes = {".py", ".ps1", ".sh"}
160
+ elif platform.system() in ["Linux", "Darwin"]:
161
+ suffixes = {".py", ".sh"}
162
+ else:
163
+ suffixes = {".py"}
164
+ if not path_obj.exists():
165
+ print(f"🔍 Searching for file matching `{path}` under `{Path.cwd()}`, but only if suffix matches {suffixes}")
166
+ choice_file = match_file_name(sub_string=path, search_root=Path.cwd(), suffixes=suffixes)
167
+ elif path_obj.is_dir():
168
+ print(f"🔍 Searching recursively for Python, PowerShell and Shell scripts in directory `{path_obj}`")
169
+ files = search_for_files_of_interest(path_obj, suffixes=suffixes)
170
+ print(f"🔍 Got #{len(files)} results.")
171
+ from machineconfig.utils.options import choose_from_options
172
+ choice_file = choose_from_options(multi=False, options=files, tv=True, msg="Choose one option")
173
+ choice_file = Path(choice_file)
174
+ else:
175
+ choice_file = path_obj
176
+ return choice_file
@@ -129,7 +129,7 @@ class ProcessManager:
129
129
  all_lines = formatted_data.split("\n")
130
130
  header_and_separator = all_lines[:2] # First two lines: header and separator
131
131
  options = all_lines[2:] # Skip header and separator, only process lines
132
- res = choose_from_options(options=all_lines, msg="📋 Select processes to manage:", fzf=True, multi=True)
132
+ res = choose_from_options(options=all_lines, msg="📋 Select processes to manage:", tv=True, multi=True)
133
133
  # Filter out header and separator if they were selected
134
134
  selected_lines = [line for line in res if line not in header_and_separator]
135
135
  indices = [options.index(val) for val in selected_lines]
@@ -1,31 +1,26 @@
1
1
 
2
2
  from pathlib import Path
3
3
  from typing import Callable, Optional, Union, Any, Protocol, List, TypeVar
4
- import logging
4
+ # import logging
5
5
  import time
6
6
  from datetime import datetime, timezone, timedelta
7
7
  from machineconfig.utils.io import from_pickle
8
8
 
9
9
 
10
10
  class LoggerTemplate(Protocol):
11
- handlers: List[logging.Handler]
12
-
13
- def debug(self, msg: str) -> None:
11
+ def trace(self, __message: str, *args: Any, **kwargs: Any) -> None:
12
+ pass # 5
13
+ def success(self, __message: str, *args: Any, **kwargs: Any) -> None:
14
+ pass # 25
15
+ def debug(self, __message: str, *args: Any, **kwargs: Any) -> None:
14
16
  pass # 10
15
-
16
- def info(self, msg: str) -> None:
17
+ def info(self, __message: str, *args: Any, **kwargs: Any) -> None:
17
18
  pass # 20
18
-
19
- def warning(self, msg: str) -> None:
19
+ def warning(self, __message: str, *args: Any, **kwargs: Any) -> None:
20
20
  pass # 30
21
-
22
- def error(self, msg: str) -> None:
21
+ def error(self, __message: str, *args: Any, **kwargs: Any) -> None:
23
22
  pass # 40
24
-
25
- def critical(self, msg: str) -> None:
26
- pass # 50
27
-
28
- def fatal(self, msg: str) -> None:
23
+ def critical(self, __message: str, *args: Any, **kwargs: Any) -> None:
29
24
  pass # 50
30
25
 
31
26
 
@@ -139,7 +134,7 @@ class Scheduler:
139
134
  def default_exception_handler(self, ex: Union[Exception, KeyboardInterrupt], during: str, sched: "Scheduler") -> None: # user decides on handling and continue, terminate, save checkpoint, etc. # Use signal library.
140
135
  print(sched)
141
136
  self.record_session_end(reason=f"during {during}, " + str(ex))
142
- self.logger.fatal(str(ex))
137
+ self.logger.critical(str(ex))
143
138
  raise ex
144
139
 
145
140
 
@@ -164,28 +159,23 @@ class CacheMemory[T]():
164
159
  if fresh or not hasattr(self, "cache"):
165
160
  why = "There was an explicit fresh order." if fresh else "Previous cache never existed."
166
161
  t0 = time.time()
167
- self.logger.warning(f"""
168
- 🆕 ════════════════════ NEW {self.name} CACHE ════════════════════
169
- ℹ️ Reason: {why}""")
162
+ self.logger.warning(f"""🆕 NEW CACHE 🔄 {self.name} CACHE ℹ️ Reason: {why}""")
170
163
  self.cache = self.source_func()
171
164
  self.logger.warning(f"⏱️ Cache population took {time.time() - t0:.2f} seconds.")
172
165
  self.time_produced = datetime.now()
173
166
  else:
174
167
  age = datetime.now() - self.time_produced
175
168
  if (age > self.expire) or (fresh and (age.total_seconds() > tolerance_seconds)):
176
- self.logger.warning(f"""
177
- 🔄 ════════════════════ CACHE UPDATE ════════════════════
178
- ⚠️ {self.name} cache: Updating cache from source func
179
- ⏱️ Age = {age} > {self.expire}""")
169
+ if not fresh:
170
+ self.logger.warning(f"""🔄 CACHE STALE 📦 {self.name} cache: Populating fresh cache from source func. """ + f"""⏱️ Age = {age} > Expiry {self.expire} """ )
171
+ else:
172
+ self.logger.warning(f"""⚠️ Fresh flag raised, age = {age} > {tolerance_seconds} seconds of tolerance. Updating {self.name} cache from source func.""")
180
173
  t0 = time.time()
181
174
  self.cache = self.source_func()
182
175
  self.logger.warning(f"⏱️ Cache population took {time.time() - t0:.2f} seconds.")
183
176
  self.time_produced = datetime.now()
184
177
  else:
185
- self.logger.warning(f"""
186
- ✅ ════════════════════ USING CACHE ════════════════════
187
- 📦 {self.name} cache: Using cached values
188
- ⏱️ Lag = {age}""")
178
+ self.logger.warning(f"""✅ USING CACHE 📦 {self.name} cache: Using cached values ⏱️ Lag = {age} < {self.expire} < {tolerance_seconds} seconds.""")
189
179
  return self.cache
190
180
 
191
181
  @staticmethod
@@ -215,28 +205,21 @@ class Cache[T](): # This class helps to accelrate access to latest data coming
215
205
  if self.path.exists(): # prefer to read from disk over source func as a default source of cache.
216
206
  age = datetime.now() - datetime.fromtimestamp(self.path.stat().st_mtime)
217
207
  if (age > self.expire) or (fresh and (age.total_seconds() > tolerance_seconds)): # cache is old or if fresh flag is raised
218
- self.logger.warning(f"""
219
- 🔄 ════════════════════ CACHE STALE ════════════════════
220
- 📦 {self.name} cache: Populating fresh cache from source func
221
- ⏱️ Lag = {age}""")
208
+ if not fresh:
209
+ self.logger.warning(f"""🔄 CACHE STALE 📦 {self.name} cache: Populating fresh cache from source func. """ + f"""⏱️ Age = {age} > Expiry {self.expire} """ )
210
+ else:
211
+ self.logger.warning(f"""⚠️ Fresh flag raised, age = {age} > {tolerance_seconds} seconds of tolerance. Updating {self.name} cache from source func.""")
222
212
  t0 = time.time()
223
213
  self.cache = self.source_func() # fresh data.
224
214
  self.logger.warning(f"⏱️ Cache population took {time.time() - t0:.2f} seconds.")
225
215
  self.time_produced = datetime.now()
226
216
  self.save(self.cache, self.path)
227
217
  return self.cache
228
-
229
- msg1 = f"""
230
- 📦 ════════════════════ CACHE OPERATION ════════════════════
231
- 🔄 {self.name} cache: Reading cached values from `{self.path}`
232
- ⏱️ Lag = {age}"""
218
+ msg1 = f"""📦 CACHE OPERATION 🔄 {self.name} cache: Reading cached values from `{self.path}` ⏱️ Lag = {age}"""
233
219
  try:
234
220
  self.cache = self.reader(self.path)
235
221
  except Exception as ex:
236
- msg2 = f"""
237
- ❌ ════════════════════ CACHE ERROR ════════════════════
238
- ⚠️ {self.name} cache: Cache file is corrupted
239
- 🔍 Error: {ex}"""
222
+ msg2 = f"""❌ CACHE ERROR ⚠️ {self.name} cache: Cache file is corrupted 🔍 Error: {ex}"""
240
223
  self.logger.warning(msg1 + msg2)
241
224
  t0 = time.time()
242
225
  self.cache = self.source_func()
@@ -245,11 +228,7 @@ class Cache[T](): # This class helps to accelrate access to latest data coming
245
228
  self.save(self.cache, self.path)
246
229
  return self.cache
247
230
  else: # disk cache does not exist, populate from source func.
248
- why = "Previous cache never existed."
249
- self.logger.warning(f"""
250
- 🆕 ════════════════════ NEW CACHE ════════════════════
251
- 🔄 {self.name} cache: Populating fresh cache from source func
252
- ℹ️ Reason: {why}""")
231
+ self.logger.warning(f"""🆕 NEW CACHE 🔄 {self.name} cache: Populating fresh cache from source func ℹ️ Reason: Previous cache never existed.""")
253
232
  t0 = time.time()
254
233
  self.cache = self.source_func() # fresh data.
255
234
  self.logger.warning(f"⏱️ Cache population took {time.time() - t0:.2f} seconds.")
@@ -258,20 +237,14 @@ class Cache[T](): # This class helps to accelrate access to latest data coming
258
237
  else: # memory cache exists
259
238
  age = datetime.now() - self.time_produced
260
239
  if (age > self.expire) or (fresh and (age.total_seconds() > tolerance_seconds)): # cache is old or if fresh flag is raised
261
- self.logger.warning(f"""
262
- 🔄 ════════════════════ CACHE UPDATE ════════════════════
263
- ⚠️ {self.name} cache: Updating cache from source func
264
- ⏱️ Age = {age} > {self.expire}""")
240
+ self.logger.warning(f"""🔄 CACHE UPDATE ⚠️ {self.name} cache: Updating cache from source func. ⏱️ Age = {age} > {self.expire}""")
265
241
  t0 = time.time()
266
242
  self.cache = self.source_func()
267
243
  self.logger.warning(f"⏱️ Cache population took {time.time() - t0:.2f} seconds.")
268
244
  self.time_produced = datetime.now()
269
245
  self.save(self.cache, self.path)
270
246
  else:
271
- self.logger.warning(f"""
272
- ✅ ════════════════════ USING CACHE ════════════════════
273
- 📦 {self.name} cache: Using cached values
274
- ⏱️ Lag = {age}""")
247
+ self.logger.warning(f"""✅ USING CACHE 📦 {self.name} cache: Using cached values ⏱️ Lag = {age} < {self.expire} < {tolerance_seconds} seconds.""")
275
248
  return self.cache
276
249
 
277
250
  @staticmethod
@@ -139,8 +139,6 @@
139
139
  # start: datetime
140
140
  # end: datetime
141
141
  # status: str
142
-
143
- # @classmethod
144
142
  # def from_path(cls, path: PathExtended, return_default_if_not_found: bool=False):
145
143
  # if not path.exists():
146
144
  # if return_default_if_not_found:
@@ -6,7 +6,7 @@ capturing all user inputs collected during interactive execution.
6
6
 
7
7
  from pathlib import Path
8
8
  from typing import TypedDict, Literal, NotRequired
9
- from machineconfig.scripts.python.helpers_fire.fire_agents_help_launch import AGENTS
9
+ from machineconfig.scripts.python.helpers.helpers_agents.fire_agents_help_launch import AGENTS
10
10
 
11
11
  SEARCH_STRATEGIES = Literal["file_path", "keyword_search", "filename_pattern"]
12
12
 
@@ -13,7 +13,7 @@ class TabConfig(TypedDict):
13
13
  tabName: str
14
14
  startDir: str
15
15
  command: str
16
- tabWeight: NotRequired[int] # Optional, defaults to 1 if not provided
16
+ tabWeight: NotRequired[int]
17
17
 
18
18
 
19
19
  class LayoutConfig(TypedDict):