machineconfig 7.50__py3-none-any.whl → 8.14__py3-none-any.whl

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

Potentially problematic release.


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

Files changed (298) hide show
  1. machineconfig/cluster/remote/cloud_manager.py +1 -1
  2. machineconfig/cluster/sessions_managers/utils/maker.py +23 -11
  3. machineconfig/cluster/sessions_managers/wt_local_manager.py +22 -19
  4. machineconfig/cluster/sessions_managers/wt_remote_manager.py +3 -1
  5. machineconfig/cluster/sessions_managers/zellij_local_manager.py +3 -1
  6. machineconfig/cluster/sessions_managers/zellij_remote_manager.py +3 -2
  7. machineconfig/cluster/sessions_managers/zellij_utils/process_monitor.py +2 -2
  8. machineconfig/jobs/installer/installer_data.json +1185 -165
  9. machineconfig/jobs/installer/linux_scripts/q.sh +10 -7
  10. machineconfig/jobs/installer/linux_scripts/redis.sh +1 -0
  11. machineconfig/jobs/installer/package_groups.py +52 -84
  12. machineconfig/jobs/installer/powershell_scripts/install_fonts.ps1 +129 -34
  13. machineconfig/jobs/installer/{custom → python_scripts}/boxes.py +2 -2
  14. machineconfig/jobs/installer/{custom_dev → python_scripts}/brave.py +5 -3
  15. machineconfig/jobs/installer/python_scripts/cloudflare_warp_cli.py +23 -0
  16. machineconfig/jobs/installer/{custom_dev → python_scripts}/code.py +4 -1
  17. machineconfig/jobs/installer/{custom_dev → python_scripts}/dubdb_adbc.py +1 -1
  18. machineconfig/jobs/installer/{custom → python_scripts}/hx.py +16 -12
  19. machineconfig/jobs/installer/{custom_dev → python_scripts}/nerdfont.py +2 -2
  20. machineconfig/jobs/installer/{custom_dev → python_scripts}/nerfont_windows_helper.py +27 -22
  21. machineconfig/jobs/installer/python_scripts/sysabc.py +139 -0
  22. machineconfig/jobs/installer/{custom_dev → python_scripts}/wezterm.py +2 -19
  23. machineconfig/jobs/installer/{custom_dev → python_scripts}/winget.py +10 -14
  24. machineconfig/jobs/installer/python_scripts/yazi.py +121 -0
  25. machineconfig/{scripts/python/nw → jobs/scripts/bash_scripts}/mount_nfs +0 -1
  26. machineconfig/jobs/scripts/powershell_scripts/mount_ssh.ps1 +13 -0
  27. machineconfig/jobs/scripts/powershell_scripts/obs.ps1 +4 -0
  28. machineconfig/jobs/scripts_dynamic/a.py +25 -0
  29. machineconfig/logger.py +0 -1
  30. machineconfig/profile/create_helper.py +21 -22
  31. machineconfig/profile/create_links_export.py +25 -11
  32. machineconfig/profile/create_shell_profile.py +14 -3
  33. machineconfig/profile/mapper.toml +8 -6
  34. machineconfig/scripts/__init__.py +0 -4
  35. machineconfig/scripts/linux/wrap_mcfg +20 -21
  36. machineconfig/scripts/python/agents.py +74 -50
  37. machineconfig/scripts/python/ai/initai.py +1 -1
  38. machineconfig/scripts/python/ai/scripts/command_runner.ps1 +33 -0
  39. machineconfig/scripts/python/ai/{command_runner → scripts}/command_runner.sh +1 -1
  40. machineconfig/scripts/python/ai/scripts/lint_and_type_check.sh +1 -1
  41. machineconfig/scripts/python/ai/solutions/copilot/{chatmodes/Thinking-Beast-Mode.chatmode.md → agents/Thinking-Beast-Mode.agent.md} +0 -1
  42. machineconfig/scripts/python/ai/solutions/copilot/{chatmodes/Ultimate-Transparent-Thinking-Beast-Mode.chatmode.md → agents/Ultimate-Transparent-Thinking-Beast-Mode.agent.md} +0 -1
  43. machineconfig/scripts/python/ai/solutions/copilot/{chatmodes/deepResearch.chatmode.md → agents/deepResearch.agent.md} +2 -2
  44. machineconfig/scripts/python/ai/solutions/copilot/github_copilot.py +5 -5
  45. machineconfig/scripts/python/ai/solutions/copilot/instructions/python/dev.instructions.md +4 -0
  46. machineconfig/scripts/python/ai/solutions/copilot/instructions/python/watch_exec.prompt.md +20 -0
  47. machineconfig/scripts/python/ai/solutions/generic.py +1 -1
  48. machineconfig/scripts/python/ai/{generate_files.py → utils/generate_files.py} +2 -2
  49. machineconfig/scripts/python/cloud.py +6 -6
  50. machineconfig/scripts/python/croshell.py +67 -60
  51. machineconfig/scripts/python/devops.py +41 -21
  52. machineconfig/scripts/python/devops_navigator.py +0 -4
  53. machineconfig/scripts/python/env_manager/env_manager_tui.py +204 -0
  54. machineconfig/scripts/python/env_manager/path_manager_tui.py +1 -1
  55. machineconfig/scripts/python/fire_jobs.py +95 -67
  56. machineconfig/scripts/python/ftpx.py +44 -17
  57. machineconfig/scripts/python/helpers/ast_search.py +74 -0
  58. machineconfig/scripts/python/helpers/qr_code.py +166 -0
  59. machineconfig/scripts/python/helpers/repo_rag.py +325 -0
  60. machineconfig/scripts/python/helpers/symantic_search.py +25 -0
  61. machineconfig/scripts/python/helpers_agents/agentic_frameworks/fire_crush.json +1 -1
  62. machineconfig/scripts/python/helpers_agents/agentic_frameworks/fire_crush.py +9 -7
  63. machineconfig/scripts/python/helpers_agents/agentic_frameworks/fire_gemini.py +21 -8
  64. machineconfig/scripts/python/helpers_agents/agentic_frameworks/fire_qwen.py +0 -12
  65. machineconfig/scripts/python/helpers_agents/fire_agents_help_launch.py +30 -11
  66. machineconfig/scripts/python/helpers_agents/fire_agents_helper_types.py +9 -2
  67. machineconfig/scripts/python/helpers_agents/privacy/configs/aichat/config.yaml +5 -0
  68. machineconfig/scripts/python/helpers_agents/privacy/configs/aider/.aider.conf.yml +2 -0
  69. machineconfig/scripts/python/helpers_agents/privacy/configs/copilot/config.yml +1 -0
  70. machineconfig/scripts/python/helpers_agents/privacy/configs/crush/crush.json +10 -0
  71. machineconfig/scripts/python/helpers_agents/privacy/configs/gemini/settings.json +12 -0
  72. machineconfig/scripts/python/helpers_agents/privacy/privacy.py +109 -0
  73. machineconfig/scripts/python/helpers_agents/templates/prompt.txt +8 -4
  74. machineconfig/scripts/python/helpers_agents/templates/template.sh +18 -8
  75. machineconfig/scripts/python/helpers_cloud/cloud_copy.py +28 -21
  76. machineconfig/scripts/python/helpers_cloud/cloud_helpers.py +1 -1
  77. machineconfig/scripts/python/helpers_cloud/cloud_mount.py +19 -17
  78. machineconfig/scripts/python/helpers_cloud/cloud_sync.py +8 -7
  79. machineconfig/scripts/python/helpers_croshell/crosh.py +3 -3
  80. machineconfig/scripts/python/helpers_croshell/start_slidev.py +6 -7
  81. machineconfig/scripts/python/helpers_devops/cli_config.py +19 -25
  82. machineconfig/scripts/python/helpers_devops/cli_config_dotfile.py +22 -13
  83. machineconfig/scripts/python/helpers_devops/cli_nw.py +113 -26
  84. machineconfig/scripts/python/helpers_devops/cli_repos.py +37 -11
  85. machineconfig/scripts/python/helpers_devops/cli_self.py +95 -42
  86. machineconfig/scripts/python/helpers_devops/cli_share_file.py +9 -9
  87. machineconfig/scripts/python/helpers_devops/cli_share_server.py +13 -12
  88. machineconfig/scripts/python/helpers_devops/{cli_terminal.py → cli_share_terminal.py} +15 -17
  89. machineconfig/scripts/python/helpers_devops/devops_backup_retrieve.py +4 -4
  90. machineconfig/scripts/python/helpers_devops/devops_status.py +7 -19
  91. machineconfig/scripts/python/helpers_devops/run_script.py +180 -0
  92. machineconfig/scripts/python/helpers_devops/themes/choose_wezterm_theme.py +1 -1
  93. machineconfig/scripts/python/helpers_fire_command/file_wrangler.py +2 -19
  94. machineconfig/scripts/python/helpers_fire_command/fire_jobs_args_helper.py +1 -0
  95. machineconfig/scripts/python/helpers_fire_command/fire_jobs_route_helper.py +25 -15
  96. machineconfig/scripts/python/helpers_msearch/scripts_linux/fzfg +3 -3
  97. machineconfig/scripts/python/helpers_msearch/scripts_windows/fzfg.ps1 +58 -1
  98. machineconfig/scripts/python/helpers_navigator/command_tree.py +50 -18
  99. machineconfig/scripts/python/helpers_network/address.py +176 -0
  100. machineconfig/scripts/python/helpers_network/address_switch.py +78 -0
  101. machineconfig/scripts/python/{nw → helpers_network}/mount_nfs.py +2 -2
  102. machineconfig/scripts/python/{nw → helpers_network}/mount_ssh.py +1 -1
  103. machineconfig/scripts/python/{nw/devops_add_identity.py → helpers_network/ssh_add_identity.py} +35 -1
  104. machineconfig/scripts/python/{nw/devops_add_ssh_key.py → helpers_network/ssh_add_ssh_key.py} +26 -7
  105. machineconfig/scripts/python/{nw → helpers_network}/ssh_debug_linux.py +7 -7
  106. machineconfig/scripts/python/{nw → helpers_network}/ssh_debug_windows.py +4 -4
  107. machineconfig/scripts/python/helpers_repos/clone.py +0 -1
  108. machineconfig/scripts/python/helpers_repos/cloud_repo_sync.py +13 -5
  109. machineconfig/scripts/python/helpers_repos/entrypoint.py +2 -1
  110. machineconfig/scripts/python/helpers_repos/record.py +2 -1
  111. machineconfig/scripts/python/helpers_repos/repo_analyzer_1.py +160 -0
  112. machineconfig/scripts/python/helpers_repos/{count_lines.py → repo_analyzer_2.py} +113 -192
  113. machineconfig/scripts/python/helpers_sessions/sessions_multiprocess.py +19 -13
  114. machineconfig/scripts/python/helpers_utils/download.py +150 -0
  115. machineconfig/scripts/python/helpers_utils/pdf.py +96 -0
  116. machineconfig/scripts/python/helpers_utils/python.py +187 -0
  117. machineconfig/scripts/python/interactive.py +30 -31
  118. machineconfig/scripts/python/{machineconfig.py → mcfg_entry.py} +4 -5
  119. machineconfig/scripts/python/msearch.py +57 -6
  120. machineconfig/scripts/python/sessions.py +100 -31
  121. machineconfig/scripts/python/terminal.py +26 -17
  122. machineconfig/scripts/python/utils.py +17 -15
  123. machineconfig/scripts/windows/wrap_mcfg.ps1 +6 -3
  124. machineconfig/settings/lf/windows/lfcd.ps1 +1 -1
  125. machineconfig/settings/linters/.ruff.toml +1 -1
  126. machineconfig/settings/shells/bash/init.sh +29 -2
  127. machineconfig/settings/shells/ipy/profiles/default/startup/playext.py +1 -1
  128. machineconfig/settings/shells/nushell/config.nu +2 -2
  129. machineconfig/settings/shells/nushell/env.nu +45 -6
  130. machineconfig/settings/shells/nushell/init.nu +282 -95
  131. machineconfig/settings/shells/pwsh/init.ps1 +1 -0
  132. machineconfig/settings/shells/wezterm/wezterm.lua +2 -0
  133. machineconfig/settings/shells/zsh/init.sh +1 -8
  134. machineconfig/settings/television/cable_unix/alias.toml +8 -0
  135. machineconfig/settings/television/cable_unix/aws-buckets.toml +14 -0
  136. machineconfig/settings/television/cable_unix/aws-instances.toml +13 -0
  137. machineconfig/settings/television/cable_unix/bash-history.toml +8 -0
  138. machineconfig/settings/television/cable_unix/channels.toml +19 -0
  139. machineconfig/settings/television/cable_unix/dirs.toml +13 -0
  140. machineconfig/settings/television/cable_unix/distrobox-list.toml +42 -0
  141. machineconfig/settings/television/cable_unix/docker-images.toml +13 -0
  142. machineconfig/settings/television/cable_unix/dotfiles.toml +11 -0
  143. machineconfig/settings/television/cable_unix/env.toml +17 -0
  144. machineconfig/settings/television/cable_unix/files.toml +11 -0
  145. machineconfig/settings/television/cable_unix/fish-history.toml +8 -0
  146. machineconfig/settings/television/cable_unix/git-branch.toml +11 -0
  147. machineconfig/settings/television/cable_unix/git-diff.toml +10 -0
  148. machineconfig/settings/television/cable_unix/git-log.toml +12 -0
  149. machineconfig/settings/television/cable_unix/git-reflog.toml +12 -0
  150. machineconfig/settings/television/cable_unix/git-repos.toml +16 -0
  151. machineconfig/settings/television/cable_unix/guix.toml +20 -0
  152. machineconfig/settings/television/cable_unix/just-recipes.toml +18 -0
  153. machineconfig/settings/television/cable_unix/k8s-deployments.toml +36 -0
  154. machineconfig/settings/television/cable_unix/k8s-pods.toml +50 -0
  155. machineconfig/settings/television/cable_unix/k8s-services.toml +36 -0
  156. machineconfig/settings/television/cable_unix/man-pages.toml +24 -0
  157. machineconfig/settings/television/cable_unix/nu-history.toml +7 -0
  158. machineconfig/settings/television/cable_unix/procs.toml +20 -0
  159. machineconfig/settings/television/cable_unix/text.toml +17 -0
  160. machineconfig/settings/television/cable_unix/tldr.toml +18 -0
  161. machineconfig/settings/television/cable_unix/zsh-history.toml +9 -0
  162. machineconfig/settings/television/cable_windows/alias.toml +7 -0
  163. machineconfig/settings/television/cable_windows/dirs.toml +13 -0
  164. machineconfig/settings/television/cable_windows/docker-images.toml +13 -0
  165. machineconfig/settings/television/cable_windows/dotfiles.toml +11 -0
  166. machineconfig/settings/television/cable_windows/env.toml +17 -0
  167. machineconfig/settings/television/cable_windows/files.toml +14 -0
  168. machineconfig/settings/television/cable_windows/git-branch.toml +11 -0
  169. machineconfig/settings/television/cable_windows/git-diff.toml +10 -0
  170. machineconfig/settings/television/cable_windows/git-log.toml +11 -0
  171. machineconfig/settings/television/cable_windows/git-reflog.toml +11 -0
  172. machineconfig/settings/television/cable_windows/git-repos.toml +15 -0
  173. machineconfig/settings/television/cable_windows/nu-history.toml +7 -0
  174. machineconfig/settings/television/cable_windows/pwsh-history.toml +6 -0
  175. machineconfig/settings/television/cable_windows/text.toml +17 -0
  176. machineconfig/settings/wt/__init__.py +0 -0
  177. machineconfig/settings/yazi/init.lua +49 -24
  178. machineconfig/settings/yazi/keymap_linux.toml +19 -4
  179. machineconfig/settings/yazi/keymap_windows.toml +0 -1
  180. machineconfig/settings/yazi/shell/yazi_cd.ps1 +29 -5
  181. machineconfig/settings/yazi/theme.toml +4 -0
  182. machineconfig/settings/yazi/yazi_linux.toml +84 -0
  183. machineconfig/settings/yazi/yazi_windows.toml +58 -0
  184. machineconfig/settings/zellij/layouts/st.kdl +39 -8
  185. machineconfig/setup_linux/__init__.py +1 -2
  186. machineconfig/setup_linux/apps_desktop.sh +8 -27
  187. machineconfig/setup_linux/web_shortcuts/interactive.sh +12 -10
  188. machineconfig/setup_linux/web_shortcuts/live_from_github.sh +31 -0
  189. machineconfig/setup_mac/__init__.py +2 -3
  190. machineconfig/setup_windows/__init__.py +3 -5
  191. machineconfig/setup_windows/ssh/openssh-server.ps1 +1 -1
  192. machineconfig/setup_windows/uv.ps1 +8 -1
  193. machineconfig/setup_windows/web_shortcuts/interactive.ps1 +12 -10
  194. machineconfig/setup_windows/web_shortcuts/live_from_github.ps1 +30 -0
  195. machineconfig/setup_windows/web_shortcuts/quick_init.ps1 +17 -0
  196. machineconfig/utils/accessories.py +7 -4
  197. machineconfig/utils/code.py +69 -27
  198. machineconfig/utils/files/headers.py +2 -2
  199. machineconfig/utils/installer_utils/github_release_bulk.py +156 -119
  200. machineconfig/utils/installer_utils/install_from_url.py +183 -0
  201. machineconfig/utils/installer_utils/installer_class.py +43 -100
  202. machineconfig/utils/installer_utils/installer_cli.py +175 -0
  203. machineconfig/utils/installer_utils/installer_helper.py +129 -0
  204. machineconfig/utils/installer_utils/{installer_abc.py → installer_locator_utils.py} +36 -85
  205. machineconfig/utils/{installer.py → installer_utils/installer_runner.py} +16 -59
  206. machineconfig/utils/io.py +0 -1
  207. machineconfig/utils/links.py +2 -2
  208. machineconfig/utils/meta.py +30 -16
  209. machineconfig/utils/options.py +42 -24
  210. machineconfig/utils/options_tv.py +119 -0
  211. machineconfig/utils/path_extended.py +42 -20
  212. machineconfig/utils/path_helper.py +75 -22
  213. machineconfig/utils/procs.py +1 -1
  214. machineconfig/utils/scheduler.py +20 -53
  215. machineconfig/utils/schemas/layouts/layout_types.py +1 -1
  216. machineconfig/utils/ssh.py +159 -418
  217. machineconfig/utils/ssh_utils/abc.py +5 -0
  218. machineconfig/utils/ssh_utils/copy_from_here.py +111 -0
  219. machineconfig/utils/ssh_utils/copy_to_here.py +303 -0
  220. machineconfig/utils/ssh_utils/utils.py +142 -0
  221. machineconfig/utils/ssh_utils/wsl.py +210 -0
  222. machineconfig/utils/terminal.py +1 -0
  223. machineconfig/utils/upgrade_packages.py +6 -1
  224. machineconfig/utils/ve.py +12 -4
  225. machineconfig-8.14.dist-info/METADATA +132 -0
  226. {machineconfig-7.50.dist-info → machineconfig-8.14.dist-info}/RECORD +264 -215
  227. {machineconfig-7.50.dist-info → machineconfig-8.14.dist-info}/entry_points.txt +2 -4
  228. machineconfig/jobs/installer/linux_scripts/pgsql.sh +0 -41
  229. machineconfig/jobs/installer/linux_scripts/timescaledb.sh +0 -71
  230. machineconfig/jobs/installer/powershell_scripts/archive_pygraphviz.ps1 +0 -12
  231. machineconfig/jobs/installer/powershell_scripts/openssh-server_add_key.ps1 +0 -7
  232. machineconfig/jobs/installer/powershell_scripts/openssh-server_copy-ssh-id.ps1 +0 -14
  233. machineconfig/scripts/linux/other/switch_ip +0 -20
  234. machineconfig/scripts/python/ai/command_runner/prompt.txt +0 -9
  235. machineconfig/scripts/python/define.py +0 -31
  236. machineconfig/scripts/python/explore.py +0 -49
  237. machineconfig/scripts/python/helpers_devops/cli_utils.py +0 -246
  238. machineconfig/scripts/python/helpers_msearch/scripts_linux/fzfag +0 -17
  239. machineconfig/scripts/python/helpers_msearch/scripts_linux/fzfrga +0 -21
  240. machineconfig/scripts/python/helpers_msearch/scripts_linux/skrg +0 -4
  241. machineconfig/scripts/python/helpers_msearch/scripts_windows/fzfb.ps1 +0 -3
  242. machineconfig/scripts/python/helpers_msearch/scripts_windows/fzfrga.bat +0 -20
  243. machineconfig/scripts/python/helpers_repos/count_lines_frontend.py +0 -17
  244. machineconfig/scripts/python/nw/add_ssh_key.py +0 -148
  245. machineconfig/scripts/python/nw/wsl_windows_transfer.py +0 -66
  246. machineconfig/scripts/windows/mounts/mount_ssh.ps1 +0 -13
  247. machineconfig/settings/lf/linux/exe/fzf_nano.sh +0 -16
  248. machineconfig/settings/lf/windows/fzf_edit.ps1 +0 -6
  249. machineconfig/settings/lf/windows/tst.ps1 +0 -1
  250. machineconfig/settings/yazi/yazi.toml +0 -17
  251. machineconfig/setup_linux/apps.sh +0 -66
  252. machineconfig/setup_linux/others/cli_installation.sh +0 -137
  253. machineconfig/setup_linux/others/mint_keyboard_shortcuts.sh +0 -30
  254. machineconfig/setup_linux/ssh/openssh_all.sh +0 -25
  255. machineconfig/setup_linux/ssh/openssh_wsl.sh +0 -38
  256. machineconfig/setup_mac/apps.sh +0 -73
  257. machineconfig/setup_windows/apps.ps1 +0 -62
  258. machineconfig/setup_windows/others/obs.ps1 +0 -4
  259. machineconfig/setup_windows/ssh/add_identity.ps1 +0 -11
  260. machineconfig/utils/installer_utils/installer.py +0 -221
  261. machineconfig-7.50.dist-info/METADATA +0 -92
  262. /machineconfig/jobs/installer/linux_scripts/{warp-cli.sh → cloudflare_warp_cli.sh} +0 -0
  263. /machineconfig/jobs/installer/{custom_dev → python_scripts}/__init__.py +0 -0
  264. /machineconfig/jobs/installer/{custom_dev → python_scripts}/alacritty.py +0 -0
  265. /machineconfig/jobs/installer/{custom_dev → python_scripts}/bypass_paywall.py +0 -0
  266. /machineconfig/jobs/installer/{custom_dev → python_scripts}/cursor.py +0 -0
  267. /machineconfig/jobs/installer/{custom_dev → python_scripts}/espanso.py +0 -0
  268. /machineconfig/jobs/installer/{custom → python_scripts}/gh.py +0 -0
  269. /machineconfig/jobs/installer/{custom_dev → python_scripts}/goes.py +0 -0
  270. /machineconfig/jobs/installer/{custom_dev → python_scripts}/lvim.py +0 -0
  271. /machineconfig/jobs/installer/{custom_dev → python_scripts}/redis.py +0 -0
  272. /machineconfig/{setup_linux/others → jobs/scripts/bash_scripts}/android.sh +0 -0
  273. /machineconfig/jobs/{installer/linux_scripts → scripts/bash_scripts}/lid.sh +0 -0
  274. /machineconfig/{scripts/python/nw → jobs/scripts/bash_scripts}/mount_drive +0 -0
  275. /machineconfig/{scripts/python/nw → jobs/scripts/bash_scripts}/mount_nw_drive +0 -0
  276. /machineconfig/{scripts/python/nw → jobs/scripts/bash_scripts}/mount_smb +0 -0
  277. /machineconfig/{scripts/linux/other → jobs/scripts/bash_scripts}/share_cloud.sh +0 -0
  278. /machineconfig/{scripts/linux/other → jobs/scripts/bash_scripts}/share_nfs +0 -0
  279. /machineconfig/{scripts/linux/other → jobs/scripts/bash_scripts}/start_docker +0 -0
  280. /machineconfig/{scripts → jobs/scripts/powershell_scripts}/Restore-ThunderbirdProfile.ps1 +0 -0
  281. /machineconfig/{setup_windows/others → jobs/scripts/powershell_scripts}/docker.ps1 +0 -0
  282. /machineconfig/{scripts/windows/mounts → jobs/scripts/powershell_scripts}/mount_nfs.ps1 +0 -0
  283. /machineconfig/{scripts/windows/mounts → jobs/scripts/powershell_scripts}/mount_nw.ps1 +0 -0
  284. /machineconfig/{scripts/windows/mounts → jobs/scripts/powershell_scripts}/mount_smb.ps1 +0 -0
  285. /machineconfig/{setup_windows/others → jobs/scripts/powershell_scripts}/power_options.ps1 +0 -0
  286. /machineconfig/{scripts/windows/mounts → jobs/scripts/powershell_scripts}/share_cloud.cmd +0 -0
  287. /machineconfig/{scripts/windows/mounts → jobs/scripts/powershell_scripts}/share_smb.ps1 +0 -0
  288. /machineconfig/{scripts/windows/mounts → jobs/scripts/powershell_scripts}/unlock_bitlocker.ps1 +0 -0
  289. /machineconfig/scripts/python/{nw → ai/utils}/__init__.py +0 -0
  290. /machineconfig/scripts/python/ai/{vscode_tasks.py → utils/vscode_tasks.py} +0 -0
  291. /machineconfig/{settings/shells/pwsh/profile.ps1 → scripts/python/helpers_fire_command/f.py} +0 -0
  292. /machineconfig/{setup_windows/wt_and_pwsh → scripts/python/helpers_network}/__init__.py +0 -0
  293. /machineconfig/scripts/python/{nw → helpers_network}/mount_nw_drive.py +0 -0
  294. /machineconfig/scripts/python/{nw → helpers_network}/onetimeshare.py +0 -0
  295. /machineconfig/scripts/python/{nw → helpers_network}/wifi_conn.py +0 -0
  296. /machineconfig/{setup_windows/wt_and_pwsh → settings/wt}/set_wt_settings.py +0 -0
  297. {machineconfig-7.50.dist-info → machineconfig-8.14.dist-info}/WHEEL +0 -0
  298. {machineconfig-7.50.dist-info → machineconfig-8.14.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,119 @@
1
+
2
+
3
+ #!/usr/bin/env python3
4
+ import base64
5
+ import pathlib
6
+ import subprocess
7
+ import tempfile
8
+ import os
9
+
10
+
11
+ def main(options_to_preview_mapping: dict[str, str]) -> str | None:
12
+ keys = list(options_to_preview_mapping.keys())
13
+ if not keys:
14
+ return None
15
+ with tempfile.TemporaryDirectory(prefix="tv_channel_") as tmpdir:
16
+ tempdir = pathlib.Path(tmpdir)
17
+ entries: list[str] = []
18
+ index_map: dict[int, str] = {}
19
+ preview_map_path = tempdir / "previews.tsv"
20
+ preview_rows: list[str] = []
21
+ for idx, key in enumerate(keys):
22
+ display_key = key.replace("\t", " ").replace("\n", " ")
23
+ entries.append(f"{idx}\t{display_key}")
24
+ index_map[idx] = key
25
+ encoded_preview = base64.b64encode(options_to_preview_mapping[key].encode("utf-8")).decode("ascii")
26
+ preview_rows.append(f"{idx}\t{encoded_preview}")
27
+ preview_map_path.write_text("\n".join(preview_rows), encoding="utf-8")
28
+ entries_path = tempdir / "entries.tsv"
29
+ entries_path.write_text("\n".join(entries), encoding="utf-8")
30
+ preview_script = tempdir / "preview.sh"
31
+ preview_script.write_text(
32
+ """#!/usr/bin/env bash
33
+ set -euo pipefail
34
+
35
+ idx="$1"
36
+ script_dir="$(cd -- "$(dirname -- "$0")" && pwd)"
37
+ previews_file="${script_dir}/previews.tsv"
38
+
39
+ if [[ ! -f "${previews_file}" ]]; then
40
+ exit 0
41
+ fi
42
+
43
+ encoded_preview="$(awk -F '\t' -v idx="${idx}" '($1==idx){print $2; exit}' "${previews_file}" || true)"
44
+
45
+ if [[ -z "${encoded_preview}" ]]; then
46
+ exit 0
47
+ fi
48
+
49
+ preview_content="$(printf '%s' "${encoded_preview}" | base64 --decode)"
50
+
51
+ if command -v bat >/dev/null 2>&1; then
52
+ printf '%s' "${preview_content}" | glow -
53
+ elif command -v bat >/dev/null 2>&1; then
54
+ printf '%s' "${preview_content}" | bat --language=markdown --color=always --style=plain --paging=never
55
+ elif command -v glow >/dev/null 2>&1; then
56
+ printf '%s' "${preview_content}" | glow -
57
+ else
58
+ printf '%s' "${preview_content}"
59
+ fi
60
+ """,
61
+ encoding="utf-8"
62
+ )
63
+ preview_script.chmod(0o755)
64
+ channel_config = f"""[metadata]
65
+ name = "temp_options"
66
+ description = "Temporary channel for selecting options"
67
+
68
+ [source]
69
+ command = "cat '{entries_path}'"
70
+ display = "{{split:\\t:1}}"
71
+ output = "{{split:\\t:0}}"
72
+
73
+ [preview]
74
+ command = "{preview_script} {{split:\\t:0}}"
75
+
76
+ [ui.preview_panel]
77
+ size = 50
78
+ """
79
+ channel_path = tempdir / "temp_options.toml"
80
+ channel_path.write_text(channel_config, encoding="utf-8")
81
+ env = os.environ.copy()
82
+ tv_config_dir = pathlib.Path.home() / ".config" / "television"
83
+ if not tv_config_dir.exists():
84
+ tv_config_dir = pathlib.Path(os.getenv("XDG_CONFIG_HOME", str(pathlib.Path.home() / ".config"))) / "television"
85
+ cable_dir = tv_config_dir / "cable"
86
+ cable_dir.mkdir(parents=True, exist_ok=True)
87
+ temp_channel_link = cable_dir / "temp_options.toml"
88
+ if temp_channel_link.exists() or temp_channel_link.is_symlink():
89
+ temp_channel_link.unlink()
90
+ temp_channel_link.symlink_to(channel_path)
91
+ output_file = tempdir / "selection.txt"
92
+ try:
93
+ result = subprocess.run(["tv", "temp_options"], check=False, stdout=output_file.open("w"), text=True, env=env)
94
+ finally:
95
+ if temp_channel_link.exists() or temp_channel_link.is_symlink():
96
+ temp_channel_link.unlink()
97
+ if result.returncode not in (0, 130):
98
+ raise SystemExit(result.returncode)
99
+ if result.returncode == 130:
100
+ return None
101
+ if not output_file.exists():
102
+ return None
103
+ selected = output_file.read_text().strip()
104
+ if not selected:
105
+ return None
106
+ try:
107
+ index = int(selected)
108
+ except ValueError:
109
+ return None
110
+ return index_map.get(index)
111
+
112
+
113
+ if __name__ == "__main__":
114
+ demo_mapping = {
115
+ "Option 1": "# Option 1\nThis is the preview for option 1.",
116
+ "Option 2": "# Option 2\nThis is the preview for option 2.",
117
+ "Option 3": "# Option 3\nThis is the preview for option 3."
118
+ }
119
+ main(demo_mapping)
@@ -16,6 +16,8 @@ OPLike: TypeAlias = Union[str, "PathExtended", Path, None]
16
16
  PLike: TypeAlias = Union[str, "PathExtended", Path]
17
17
  FILE_MODE: TypeAlias = Literal["r", "w", "x", "a"]
18
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"]
19
21
 
20
22
 
21
23
  def _is_user_admin() -> bool:
@@ -152,7 +154,6 @@ class PathExtended(type(Path()), Path): # type: ignore # pylint: disable=E0241
152
154
  # ======================================= File Editing / Reading ===================================
153
155
  def download(self, folder: OPLike = None, name: Optional[str] = None, allow_redirects: bool = True, timeout: Optional[int] = None, params: Any = None) -> "PathExtended":
154
156
  import requests
155
-
156
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').
157
158
  assert response.status_code == 200, f"Download failed with status code {response.status_code}\n{response.text}"
158
159
  if name is not None:
@@ -480,9 +481,6 @@ class PathExtended(type(Path()), Path): # type: ignore # pylint: disable=E0241
480
481
  **kwargs: Any,
481
482
  ) -> "PathExtended":
482
483
  path_resolved, slf = self._resolve_path(folder, name, path, self.name).expanduser().resolve(), self.expanduser().resolve()
483
- # if use_7z: # benefits over regular zip and encrypt: can handle very large files with low memory footprint
484
- # path_resolved = path_resolved + '.7z' if not path_resolved.suffix == '.7z' else path_resolved
485
- # with install_n_import("py7zr").SevenZipFile(file=path_resolved, mode=mode, password=pwd) as archive: archive.writeall(path=str(slf), arcname=None)
486
484
  arcname_obj = PathExtended(arcname or slf.name)
487
485
  if arcname_obj.name != slf.name:
488
486
  arcname_obj /= slf.name # arcname has to start from somewhere and end with filename
@@ -555,15 +553,6 @@ class PathExtended(type(Path()), Path): # type: ignore # pylint: disable=E0241
555
553
  folder = folder if not content else folder.parent
556
554
  if slf.suffix == ".7z":
557
555
  raise NotImplementedError("I have not implemented this yet")
558
- # if overwrite: P(folder).delete(sure=True)
559
- # result = folder
560
- # import py7zr
561
- # with py7zr.SevenZipFile(file=slf, mode='r', password=pwd) as archive:
562
- # if pattern is not None:
563
- # import re
564
- # pat = re.compile(pattern)
565
- # archive.extract(path=folder, targets=[f for f in archive.getnames() if pat.match(f)])
566
- # else: archive.extractall(path=folder)
567
556
  else:
568
557
  if overwrite:
569
558
  if not content:
@@ -698,21 +687,54 @@ class PathExtended(type(Path()), Path): # type: ignore # pylint: disable=E0241
698
687
  return ret
699
688
 
700
689
  def decompress(self, folder: OPLike = None, name: Optional[str] = None, path: OPLike = None, inplace: bool = False, orig: bool = False, verbose: bool = True) -> "PathExtended":
701
- if ".tar.gz" in str(self) or ".tgz" in str(self):
690
+ if str(self).endswith(".tar.gz") or str(self).endswith(".tgz"):
702
691
  # res = self.ungz_untar(folder=folder, path=path, name=name, inplace=inplace, verbose=verbose, orig=orig)
703
692
  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
704
- elif ".gz" in str(self):
693
+ elif str(self).endswith(".tar"):
694
+ res = self.untar(folder=folder, name=name, path=path, inplace=inplace, orig=orig, verbose=verbose)
695
+ elif str(self).endswith(".gz"):
705
696
  res = self.ungz(folder=folder, path=path, name=name, inplace=inplace, verbose=verbose, orig=orig)
706
- elif ".tar.bz" in str(self) or "tbz" in str(self):
697
+ elif str(self).endswith(".tar.bz") or str(self).endswith(".tbz") or str(self).endswith(".tar.bz2"):
707
698
  res = self.unbz(name=f"tmp_{randstr()}.tar", inplace=inplace)
708
699
  return res.untar(folder=folder, name=name, path=path, inplace=True, orig=orig, verbose=verbose)
709
- elif ".tar.xz" in str(self):
700
+ elif str(self).endswith(".tar.xz"):
710
701
  # res = self.unxz_untar(folder=folder, path=path, name=name, inplace=inplace, verbose=verbose, orig=orig)
711
702
  res = self.unxz(inplace=inplace).untar(folder=folder, name=name, path=path, inplace=True, orig=orig, verbose=verbose)
712
- elif ".zip" in str(self):
703
+ elif str(self).endswith(".zip"):
713
704
  res = self.unzip(folder=folder, path=path, name=name, inplace=inplace, verbose=verbose, orig=orig)
705
+ elif str(self).endswith(".7z"):
706
+ def unzip_7z(archive_path: str, dest_dir: Optional[str] = None) -> Path:
707
+ """
708
+ Uncompresses a .7z archive to a directory and returns the Path to the extraction directory.
709
+
710
+ :param archive_path: path to the .7z archive file
711
+ :param dest_dir: optional path to directory to extract into; if None a temporary dir will be created
712
+ :return: pathlib.Path pointing to the destination directory where contents were extracted
713
+ :raises: FileNotFoundError if archive does not exist; py7zr.Bad7zFile or other error if extraction fails
714
+ """
715
+ import py7zr # type: ignore
716
+ import tempfile
717
+ from pathlib import Path
718
+ archive_path_obj = Path(archive_path)
719
+ if not archive_path_obj.is_file():
720
+ raise FileNotFoundError(f"Archive file not found: {archive_path_obj!r}")
721
+ if dest_dir is None:
722
+ # create a temporary directory
723
+ dest = Path(tempfile.mkdtemp(prefix=f"unzip7z_{archive_path_obj.stem}_"))
724
+ else:
725
+ dest = Path(dest_dir)
726
+ dest.mkdir(parents=True, exist_ok=True)
727
+ # Perform extraction
728
+ with py7zr.SevenZipFile(str(archive_path_obj), mode='r') as archive:
729
+ archive.extractall(path=str(dest))
730
+ # Return the extraction directory path
731
+ return dest
732
+ from machineconfig.utils.code import run_lambda_function
733
+ destination_dir = str(self.expanduser().resolve()).replace(".7z", "")
734
+ run_lambda_function(lambda: unzip_7z(archive_path=str(self), dest_dir=destination_dir), uv_project_dir=None, uv_with=["py7zr"])
735
+ res = PathExtended(destination_dir)
714
736
  else:
715
- res = self
737
+ raise ValueError(f"Cannot decompress file with unknown extension: {self}")
716
738
  return res
717
739
 
718
740
  def encrypt(
@@ -788,7 +810,7 @@ class PathExtended(type(Path()), Path): # type: ignore # pylint: disable=E0241
788
810
  path = self
789
811
  else:
790
812
  try:
791
- path = self.rel2home()
813
+ path = PathExtended(self.expanduser().absolute().relative_to(Path.home()))
792
814
  except ValueError as ve:
793
815
  if strict:
794
816
  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,12 +65,12 @@ 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]))
@@ -81,35 +79,44 @@ def match_file_name(sub_string: str, search_root: PathExtended, suffixes: set[st
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,20 @@ 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
+ self.logger.warning(f"""🔄 CACHE UPDATE ⚠️ {self.name} cache: Updating cache from source func. """ + f""" ⏱️ Age = {age} > {self.expire}""" if not fresh else f""" ⏱️ Age = {age}. Fresh flag raised.""")
180
170
  t0 = time.time()
181
171
  self.cache = self.source_func()
182
172
  self.logger.warning(f"⏱️ Cache population took {time.time() - t0:.2f} seconds.")
183
173
  self.time_produced = datetime.now()
184
174
  else:
185
- self.logger.warning(f"""
186
- ✅ ════════════════════ USING CACHE ════════════════════
187
- 📦 {self.name} cache: Using cached values
188
- ⏱️ Lag = {age}""")
175
+ self.logger.warning(f"""✅ USING CACHE 📦 {self.name} cache: Using cached values ⏱️ Lag = {age} < {self.expire} < {tolerance_seconds} seconds.""")
189
176
  return self.cache
190
177
 
191
178
  @staticmethod
@@ -215,28 +202,18 @@ class Cache[T](): # This class helps to accelrate access to latest data coming
215
202
  if self.path.exists(): # prefer to read from disk over source func as a default source of cache.
216
203
  age = datetime.now() - datetime.fromtimestamp(self.path.stat().st_mtime)
217
204
  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}""")
205
+ self.logger.warning(f"""🔄 CACHE STALE 📦 {self.name} cache: Populating fresh cache from source func. """ + f"""⏱️ Age = {age} > Expiry {self.expire} """ if not fresh else """⚠️ Fresh flag raised.""")
222
206
  t0 = time.time()
223
207
  self.cache = self.source_func() # fresh data.
224
208
  self.logger.warning(f"⏱️ Cache population took {time.time() - t0:.2f} seconds.")
225
209
  self.time_produced = datetime.now()
226
210
  self.save(self.cache, self.path)
227
211
  return self.cache
228
-
229
- msg1 = f"""
230
- 📦 ════════════════════ CACHE OPERATION ════════════════════
231
- 🔄 {self.name} cache: Reading cached values from `{self.path}`
232
- ⏱️ Lag = {age}"""
212
+ msg1 = f"""📦 CACHE OPERATION 🔄 {self.name} cache: Reading cached values from `{self.path}` ⏱️ Lag = {age}"""
233
213
  try:
234
214
  self.cache = self.reader(self.path)
235
215
  except Exception as ex:
236
- msg2 = f"""
237
- ❌ ════════════════════ CACHE ERROR ════════════════════
238
- ⚠️ {self.name} cache: Cache file is corrupted
239
- 🔍 Error: {ex}"""
216
+ msg2 = f"""❌ CACHE ERROR ⚠️ {self.name} cache: Cache file is corrupted 🔍 Error: {ex}"""
240
217
  self.logger.warning(msg1 + msg2)
241
218
  t0 = time.time()
242
219
  self.cache = self.source_func()
@@ -245,11 +222,7 @@ class Cache[T](): # This class helps to accelrate access to latest data coming
245
222
  self.save(self.cache, self.path)
246
223
  return self.cache
247
224
  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}""")
225
+ self.logger.warning(f"""🆕 NEW CACHE 🔄 {self.name} cache: Populating fresh cache from source func ℹ️ Reason: Previous cache never existed.""")
253
226
  t0 = time.time()
254
227
  self.cache = self.source_func() # fresh data.
255
228
  self.logger.warning(f"⏱️ Cache population took {time.time() - t0:.2f} seconds.")
@@ -258,20 +231,14 @@ class Cache[T](): # This class helps to accelrate access to latest data coming
258
231
  else: # memory cache exists
259
232
  age = datetime.now() - self.time_produced
260
233
  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}""")
234
+ self.logger.warning(f"""🔄 CACHE UPDATE ⚠️ {self.name} cache: Updating cache from source func. ⏱️ Age = {age} > {self.expire}""")
265
235
  t0 = time.time()
266
236
  self.cache = self.source_func()
267
237
  self.logger.warning(f"⏱️ Cache population took {time.time() - t0:.2f} seconds.")
268
238
  self.time_produced = datetime.now()
269
239
  self.save(self.cache, self.path)
270
240
  else:
271
- self.logger.warning(f"""
272
- ✅ ════════════════════ USING CACHE ════════════════════
273
- 📦 {self.name} cache: Using cached values
274
- ⏱️ Lag = {age}""")
241
+ self.logger.warning(f"""✅ USING CACHE 📦 {self.name} cache: Using cached values ⏱️ Lag = {age} < {self.expire} < {tolerance_seconds} seconds.""")
275
242
  return self.cache
276
243
 
277
244
  @staticmethod
@@ -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):