machineconfig 5.15__py3-none-any.whl → 7.98__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 (472) hide show
  1. machineconfig/__init__.py +0 -28
  2. machineconfig/cluster/remote/cloud_manager.py +1 -1
  3. machineconfig/cluster/remote/distribute.py +0 -1
  4. machineconfig/cluster/remote/file_manager.py +0 -2
  5. machineconfig/cluster/remote/script_execution.py +0 -1
  6. machineconfig/cluster/sessions_managers/{utils → helpers}/enhanced_command_runner.py +4 -6
  7. machineconfig/cluster/sessions_managers/utils/load_balancer.py +1 -1
  8. machineconfig/cluster/sessions_managers/utils/maker.py +69 -0
  9. machineconfig/cluster/sessions_managers/wt_local.py +114 -289
  10. machineconfig/cluster/sessions_managers/wt_local_manager.py +70 -210
  11. machineconfig/cluster/sessions_managers/wt_remote.py +51 -43
  12. machineconfig/cluster/sessions_managers/wt_remote_manager.py +52 -198
  13. machineconfig/cluster/sessions_managers/wt_utils/layout_generator.py +6 -19
  14. machineconfig/cluster/sessions_managers/wt_utils/manager_persistence.py +52 -0
  15. machineconfig/cluster/sessions_managers/wt_utils/monitoring_helpers.py +50 -0
  16. machineconfig/cluster/sessions_managers/wt_utils/status_reporter.py +4 -2
  17. machineconfig/cluster/sessions_managers/wt_utils/status_reporting.py +76 -0
  18. machineconfig/cluster/sessions_managers/wt_utils/wt_helpers.py +199 -0
  19. machineconfig/cluster/sessions_managers/zellij_local.py +81 -375
  20. machineconfig/cluster/sessions_managers/zellij_local_manager.py +25 -170
  21. machineconfig/cluster/sessions_managers/zellij_remote.py +40 -41
  22. machineconfig/cluster/sessions_managers/zellij_remote_manager.py +16 -12
  23. machineconfig/cluster/sessions_managers/zellij_utils/example_usage.py +4 -8
  24. machineconfig/cluster/sessions_managers/zellij_utils/layout_generator.py +5 -20
  25. machineconfig/cluster/sessions_managers/zellij_utils/process_monitor.py +3 -9
  26. machineconfig/cluster/sessions_managers/zellij_utils/status_reporter.py +3 -1
  27. machineconfig/cluster/sessions_managers/zellij_utils/zellij_local_helper.py +298 -0
  28. machineconfig/cluster/sessions_managers/zellij_utils/zellij_local_helper_restart.py +77 -0
  29. machineconfig/cluster/sessions_managers/zellij_utils/zellij_local_helper_with_panes.py +228 -0
  30. machineconfig/cluster/sessions_managers/zellij_utils/zellij_local_manager_helper.py +165 -0
  31. machineconfig/jobs/{python → installer}/check_installations.py +2 -3
  32. machineconfig/jobs/installer/custom/boxes.py +61 -0
  33. machineconfig/jobs/installer/custom/hx.py +76 -19
  34. machineconfig/jobs/installer/custom/yazi.py +119 -0
  35. machineconfig/jobs/installer/custom_dev/alacritty.py +4 -4
  36. machineconfig/jobs/installer/custom_dev/brave.py +5 -9
  37. machineconfig/jobs/installer/custom_dev/cloudflare_warp_cli.py +23 -0
  38. machineconfig/jobs/installer/custom_dev/code.py +4 -1
  39. machineconfig/jobs/installer/custom_dev/dubdb_adbc.py +30 -0
  40. machineconfig/jobs/installer/custom_dev/nerdfont.py +1 -1
  41. machineconfig/jobs/installer/custom_dev/nerfont_windows_helper.py +33 -28
  42. machineconfig/jobs/installer/custom_dev/sysabc.py +139 -0
  43. machineconfig/jobs/installer/custom_dev/wezterm.py +2 -19
  44. machineconfig/jobs/installer/custom_dev/winget.py +10 -14
  45. machineconfig/jobs/installer/installer_data.json +1487 -229
  46. machineconfig/jobs/installer/linux_scripts/brave.sh +4 -14
  47. machineconfig/jobs/installer/linux_scripts/{warp-cli.sh → cloudflare_warp_cli.sh} +5 -17
  48. machineconfig/jobs/installer/linux_scripts/docker.sh +5 -17
  49. machineconfig/jobs/installer/linux_scripts/docker_start.sh +6 -14
  50. machineconfig/jobs/installer/linux_scripts/edge.sh +3 -11
  51. machineconfig/jobs/{linux/msc → installer/linux_scripts}/lid.sh +2 -8
  52. machineconfig/jobs/installer/linux_scripts/nerdfont.sh +5 -17
  53. machineconfig/jobs/{linux/msc → installer/linux_scripts}/network.sh +2 -8
  54. machineconfig/jobs/installer/linux_scripts/q.sh +10 -6
  55. machineconfig/jobs/installer/linux_scripts/redis.sh +6 -17
  56. machineconfig/jobs/installer/linux_scripts/vscode.sh +5 -17
  57. machineconfig/jobs/installer/linux_scripts/wezterm.sh +4 -12
  58. machineconfig/jobs/installer/package_groups.py +106 -177
  59. machineconfig/jobs/installer/powershell_scripts/install_fonts.ps1 +129 -34
  60. machineconfig/logger.py +0 -1
  61. machineconfig/profile/backup.toml +49 -0
  62. machineconfig/profile/bash_shell_profiles.md +11 -0
  63. machineconfig/profile/create_helper.py +62 -0
  64. machineconfig/profile/create_links.py +288 -0
  65. machineconfig/profile/create_links_export.py +100 -0
  66. machineconfig/profile/create_shell_profile.py +147 -0
  67. machineconfig/profile/mapper.toml +263 -0
  68. machineconfig/scripts/__init__.py +0 -4
  69. machineconfig/scripts/linux/{share_cloud.sh → other/share_cloud.sh} +14 -25
  70. machineconfig/scripts/linux/wrap_mcfg +46 -0
  71. machineconfig/scripts/nu/wrap_mcfg.nu +69 -0
  72. machineconfig/scripts/python/agents.py +123 -117
  73. machineconfig/scripts/python/ai/initai.py +3 -28
  74. machineconfig/scripts/python/ai/scripts/command_runner.ps1 +33 -0
  75. machineconfig/scripts/python/ai/scripts/command_runner.sh +9 -0
  76. machineconfig/scripts/python/ai/scripts/lint_and_type_check.ps1 +17 -18
  77. machineconfig/scripts/python/ai/scripts/lint_and_type_check.sh +17 -18
  78. machineconfig/scripts/python/ai/solutions/_shared.py +9 -1
  79. machineconfig/scripts/python/ai/solutions/copilot/{chatmodes/Thinking-Beast-Mode.chatmode.md → agents/Thinking-Beast-Mode.agent.md} +0 -1
  80. machineconfig/scripts/python/ai/solutions/copilot/{chatmodes/Ultimate-Transparent-Thinking-Beast-Mode.chatmode.md → agents/Ultimate-Transparent-Thinking-Beast-Mode.agent.md} +0 -1
  81. machineconfig/scripts/python/ai/solutions/copilot/{chatmodes/deepResearch.chatmode.md → agents/deepResearch.agent.md} +2 -2
  82. machineconfig/scripts/python/ai/solutions/copilot/github_copilot.py +5 -5
  83. machineconfig/scripts/python/ai/solutions/copilot/instructions/python/dev.instructions.md +5 -1
  84. machineconfig/scripts/python/ai/solutions/copilot/instructions/python/watch_exec.prompt.md +20 -0
  85. machineconfig/scripts/python/ai/solutions/copilot/prompts/pyright_fix.md +16 -0
  86. machineconfig/scripts/python/ai/solutions/generic.py +28 -5
  87. machineconfig/scripts/python/ai/utils/generate_files.py +348 -0
  88. machineconfig/scripts/python/ai/utils/vscode_tasks.py +37 -0
  89. machineconfig/scripts/python/cloud.py +29 -0
  90. machineconfig/scripts/python/croshell.py +137 -113
  91. machineconfig/scripts/python/devops.py +61 -101
  92. machineconfig/scripts/python/devops_navigator.py +6 -0
  93. machineconfig/scripts/python/env_manager/__init__.py +1 -0
  94. machineconfig/scripts/python/env_manager/env_manager_tui.py +204 -0
  95. machineconfig/scripts/python/env_manager/path_manager_backend.py +47 -0
  96. machineconfig/scripts/python/env_manager/path_manager_tui.py +228 -0
  97. machineconfig/scripts/python/fire_jobs.py +110 -150
  98. machineconfig/scripts/python/ftpx.py +51 -24
  99. machineconfig/scripts/python/helpers/ast_search.py +74 -0
  100. machineconfig/scripts/python/helpers/qr_code.py +166 -0
  101. machineconfig/scripts/python/helpers/repo_rag.py +325 -0
  102. machineconfig/scripts/python/helpers/run_py_script.py +79 -0
  103. machineconfig/scripts/python/helpers/symantic_search.py +25 -0
  104. machineconfig/scripts/python/helpers/tmp_py_scripts/a.py +26 -0
  105. machineconfig/scripts/python/helpers_agents/agentic_frameworks/fire_crush.json +14 -0
  106. machineconfig/scripts/python/helpers_agents/agentic_frameworks/fire_crush.py +39 -0
  107. machineconfig/scripts/python/helpers_agents/agentic_frameworks/fire_cursor_agents.py +22 -0
  108. machineconfig/scripts/python/helpers_agents/agentic_frameworks/fire_gemini.py +55 -0
  109. machineconfig/scripts/python/helpers_agents/agentic_frameworks/fire_qwen.py +30 -0
  110. machineconfig/scripts/python/helpers_agents/fire_agents_help_launch.py +126 -0
  111. machineconfig/scripts/python/helpers_agents/fire_agents_helper_types.py +41 -0
  112. machineconfig/scripts/python/helpers_agents/templates/prompt.txt +10 -0
  113. machineconfig/scripts/python/helpers_agents/templates/template.ps1 +14 -0
  114. machineconfig/scripts/python/helpers_agents/templates/template.sh +32 -0
  115. machineconfig/scripts/python/{cloud_copy.py → helpers_cloud/cloud_copy.py} +30 -23
  116. machineconfig/scripts/python/{cloud_mount.py → helpers_cloud/cloud_mount.py} +29 -35
  117. machineconfig/scripts/python/{cloud_sync.py → helpers_cloud/cloud_sync.py} +12 -18
  118. machineconfig/scripts/python/{helpers → helpers_cloud}/helpers2.py +1 -1
  119. machineconfig/scripts/python/helpers_croshell/crosh.py +39 -0
  120. machineconfig/scripts/python/{start_slidev.py → helpers_croshell/start_slidev.py} +8 -9
  121. machineconfig/scripts/python/helpers_devops/cli_config.py +105 -0
  122. machineconfig/scripts/python/helpers_devops/cli_config_dotfile.py +89 -0
  123. machineconfig/scripts/python/helpers_devops/cli_data.py +25 -0
  124. machineconfig/scripts/python/helpers_devops/cli_nw.py +214 -0
  125. machineconfig/scripts/python/helpers_devops/cli_repos.py +215 -0
  126. machineconfig/scripts/python/helpers_devops/cli_self.py +172 -0
  127. machineconfig/scripts/python/helpers_devops/cli_share_file.py +137 -0
  128. machineconfig/scripts/python/helpers_devops/cli_share_server.py +142 -0
  129. machineconfig/scripts/python/{share_terminal.py → helpers_devops/cli_share_terminal.py} +45 -35
  130. machineconfig/scripts/python/helpers_devops/cli_utils.py +96 -0
  131. machineconfig/scripts/python/{devops_backup_retrieve.py → helpers_devops/devops_backup_retrieve.py} +7 -10
  132. machineconfig/scripts/python/helpers_devops/devops_status.py +499 -0
  133. machineconfig/scripts/python/{devops_update_repos.py → helpers_devops/devops_update_repos.py} +68 -49
  134. machineconfig/scripts/python/helpers_devops/themes/choose_pwsh_theme.ps1 +81 -0
  135. machineconfig/scripts/python/helpers_devops/themes/choose_starship_theme.bash +3 -0
  136. machineconfig/scripts/python/{choose_wezterm_theme.py → helpers_devops/themes/choose_wezterm_theme.py} +3 -3
  137. machineconfig/scripts/python/helpers_fire_command/__init__.py +0 -0
  138. machineconfig/scripts/python/helpers_fire_command/f.py +0 -0
  139. machineconfig/scripts/python/{helpers/helpers4.py → helpers_fire_command/file_wrangler.py} +56 -20
  140. machineconfig/scripts/python/{fire_jobs_args_helper.py → helpers_fire_command/fire_jobs_args_helper.py} +5 -1
  141. machineconfig/scripts/python/helpers_fire_command/fire_jobs_route_helper.py +121 -0
  142. machineconfig/scripts/python/helpers_fire_command/fire_jobs_streamlit_helper.py +0 -0
  143. machineconfig/scripts/python/helpers_msearch/__init__.py +5 -0
  144. machineconfig/scripts/{linux → python/helpers_msearch/scripts_linux}/fzfg +3 -3
  145. machineconfig/scripts/python/helpers_msearch/scripts_windows/fzfg.ps1 +59 -0
  146. machineconfig/scripts/python/helpers_navigator/__init__.py +20 -0
  147. machineconfig/scripts/python/helpers_navigator/command_builder.py +111 -0
  148. machineconfig/scripts/python/helpers_navigator/command_detail.py +44 -0
  149. machineconfig/scripts/python/helpers_navigator/command_tree.py +620 -0
  150. machineconfig/scripts/python/helpers_navigator/data_models.py +28 -0
  151. machineconfig/scripts/python/helpers_navigator/main_app.py +272 -0
  152. machineconfig/scripts/python/helpers_navigator/search_bar.py +15 -0
  153. machineconfig/scripts/python/helpers_network/__init__.py +0 -0
  154. machineconfig/scripts/python/helpers_network/address.py +132 -0
  155. machineconfig/scripts/python/{devops_add_identity.py → helpers_network/devops_add_identity.py} +0 -2
  156. machineconfig/scripts/python/helpers_network/devops_add_ssh_key.py +153 -0
  157. machineconfig/scripts/{linux → python/helpers_network}/mount_nfs +0 -1
  158. machineconfig/scripts/python/{mount_nfs.py → helpers_network/mount_nfs.py} +3 -3
  159. machineconfig/scripts/{linux → python/helpers_network}/mount_nw_drive +1 -2
  160. machineconfig/scripts/python/{mount_ssh.py → helpers_network/mount_ssh.py} +3 -3
  161. machineconfig/scripts/python/{onetimeshare.py → helpers_network/onetimeshare.py} +0 -1
  162. machineconfig/scripts/python/helpers_network/ssh_debug_linux.py +391 -0
  163. machineconfig/scripts/python/helpers_network/ssh_debug_windows.py +338 -0
  164. machineconfig/scripts/python/{wifi_conn.py → helpers_network/wifi_conn.py} +1 -53
  165. machineconfig/scripts/python/{wsl_windows_transfer.py → helpers_network/wsl_windows_transfer.py} +5 -4
  166. machineconfig/scripts/python/helpers_repos/action.py +209 -0
  167. machineconfig/scripts/python/helpers_repos/action_helper.py +150 -0
  168. machineconfig/scripts/python/{repos_helper_clone.py → helpers_repos/clone.py} +2 -3
  169. machineconfig/scripts/python/helpers_repos/cloud_repo_sync.py +218 -0
  170. machineconfig/scripts/python/{repos_helper.py → helpers_repos/entrypoint.py} +9 -17
  171. machineconfig/scripts/python/helpers_repos/grource.py +340 -0
  172. machineconfig/scripts/python/{repos_helper_record.py → helpers_repos/record.py} +4 -3
  173. machineconfig/scripts/python/helpers_repos/repo_analyzer_1.py +160 -0
  174. machineconfig/scripts/python/{count_lines.py → helpers_repos/repo_analyzer_2.py} +113 -192
  175. machineconfig/scripts/python/helpers_repos/sync.py +66 -0
  176. machineconfig/scripts/python/{repos_helper_update.py → helpers_repos/update.py} +3 -3
  177. machineconfig/scripts/python/helpers_sessions/__init__.py +0 -0
  178. machineconfig/scripts/python/helpers_sessions/sessions_multiprocess.py +65 -0
  179. machineconfig/scripts/python/helpers_utils/download.py +150 -0
  180. machineconfig/scripts/python/helpers_utils/path.py +185 -0
  181. machineconfig/scripts/python/interactive.py +64 -84
  182. machineconfig/scripts/python/mcfg_entry.py +58 -0
  183. machineconfig/scripts/python/msearch.py +71 -0
  184. machineconfig/scripts/python/sessions.py +119 -45
  185. machineconfig/scripts/python/terminal.py +133 -0
  186. machineconfig/scripts/python/utils.py +64 -0
  187. machineconfig/scripts/windows/mounts/Restore-ThunderbirdProfile.ps1 +92 -0
  188. machineconfig/scripts/windows/{mount_nfs.ps1 → mounts/mount_nfs.ps1} +1 -3
  189. machineconfig/scripts/windows/{mount_ssh.ps1 → mounts/mount_ssh.ps1} +1 -1
  190. machineconfig/scripts/windows/{share_smb.ps1 → mounts/share_smb.ps1} +0 -6
  191. machineconfig/scripts/windows/wrap_mcfg.ps1 +63 -0
  192. machineconfig/settings/broot/br.sh +0 -4
  193. machineconfig/settings/broot/conf.toml +1 -1
  194. machineconfig/settings/helix/config.toml +16 -0
  195. machineconfig/settings/helix/languages.toml +13 -4
  196. machineconfig/settings/helix/yazi-picker.sh +12 -0
  197. machineconfig/settings/lf/linux/exe/lfcd.sh +1 -0
  198. machineconfig/settings/lf/linux/exe/previewer.sh +9 -3
  199. machineconfig/settings/lf/linux/lfrc +10 -12
  200. machineconfig/settings/lf/windows/lfcd.ps1 +1 -1
  201. machineconfig/settings/lf/windows/lfrc +18 -38
  202. machineconfig/settings/lf/windows/mkfile.ps1 +1 -1
  203. machineconfig/settings/linters/.ruff.toml +1 -1
  204. machineconfig/settings/lvim/windows/archive/config_additional.lua +0 -6
  205. machineconfig/settings/marimo/marimo.toml +80 -0
  206. machineconfig/settings/marimo/snippets/globalize.py +34 -0
  207. machineconfig/settings/pistol/pistol.conf +1 -1
  208. machineconfig/settings/shells/bash/init.sh +82 -31
  209. machineconfig/settings/shells/ipy/profiles/default/startup/playext.py +1 -1
  210. machineconfig/settings/shells/nushell/config.nu +2 -35
  211. machineconfig/settings/shells/nushell/env.nu +45 -6
  212. machineconfig/settings/shells/nushell/init.nu +314 -0
  213. machineconfig/settings/shells/pwsh/init.ps1 +61 -43
  214. machineconfig/settings/shells/starship/starship.toml +16 -0
  215. machineconfig/settings/shells/wezterm/wezterm.lua +2 -0
  216. machineconfig/settings/shells/wt/settings.json +32 -17
  217. machineconfig/settings/shells/zsh/init.sh +89 -0
  218. machineconfig/settings/svim/linux/init.toml +0 -4
  219. machineconfig/settings/svim/windows/init.toml +0 -3
  220. machineconfig/settings/television/cable_unix/alias.toml +8 -0
  221. machineconfig/settings/television/cable_unix/aws-buckets.toml +14 -0
  222. machineconfig/settings/television/cable_unix/aws-instances.toml +13 -0
  223. machineconfig/settings/television/cable_unix/bash-history.toml +8 -0
  224. machineconfig/settings/television/cable_unix/channels.toml +19 -0
  225. machineconfig/settings/television/cable_unix/dirs.toml +13 -0
  226. machineconfig/settings/television/cable_unix/distrobox-list.toml +42 -0
  227. machineconfig/settings/television/cable_unix/docker-images.toml +13 -0
  228. machineconfig/settings/television/cable_unix/dotfiles.toml +11 -0
  229. machineconfig/settings/television/cable_unix/env.toml +17 -0
  230. machineconfig/settings/television/cable_unix/files.toml +11 -0
  231. machineconfig/settings/television/cable_unix/fish-history.toml +8 -0
  232. machineconfig/settings/television/cable_unix/git-branch.toml +11 -0
  233. machineconfig/settings/television/cable_unix/git-diff.toml +10 -0
  234. machineconfig/settings/television/cable_unix/git-log.toml +12 -0
  235. machineconfig/settings/television/cable_unix/git-reflog.toml +12 -0
  236. machineconfig/settings/television/cable_unix/git-repos.toml +16 -0
  237. machineconfig/settings/television/cable_unix/guix.toml +20 -0
  238. machineconfig/settings/television/cable_unix/just-recipes.toml +18 -0
  239. machineconfig/settings/television/cable_unix/k8s-deployments.toml +36 -0
  240. machineconfig/settings/television/cable_unix/k8s-pods.toml +50 -0
  241. machineconfig/settings/television/cable_unix/k8s-services.toml +36 -0
  242. machineconfig/settings/television/cable_unix/man-pages.toml +24 -0
  243. machineconfig/settings/television/cable_unix/nu-history.toml +7 -0
  244. machineconfig/settings/television/cable_unix/procs.toml +20 -0
  245. machineconfig/settings/television/cable_unix/text.toml +17 -0
  246. machineconfig/settings/television/cable_unix/tldr.toml +18 -0
  247. machineconfig/settings/television/cable_unix/zsh-history.toml +9 -0
  248. machineconfig/settings/television/cable_windows/alias.toml +7 -0
  249. machineconfig/settings/television/cable_windows/dirs.toml +13 -0
  250. machineconfig/settings/television/cable_windows/docker-images.toml +13 -0
  251. machineconfig/settings/television/cable_windows/dotfiles.toml +11 -0
  252. machineconfig/settings/television/cable_windows/env.toml +17 -0
  253. machineconfig/settings/television/cable_windows/files.toml +14 -0
  254. machineconfig/settings/television/cable_windows/git-branch.toml +11 -0
  255. machineconfig/settings/television/cable_windows/git-diff.toml +10 -0
  256. machineconfig/settings/television/cable_windows/git-log.toml +11 -0
  257. machineconfig/settings/television/cable_windows/git-reflog.toml +11 -0
  258. machineconfig/settings/television/cable_windows/git-repos.toml +15 -0
  259. machineconfig/settings/television/cable_windows/nu-history.toml +7 -0
  260. machineconfig/settings/television/cable_windows/pwsh-history.toml +6 -0
  261. machineconfig/settings/television/cable_windows/text.toml +17 -0
  262. machineconfig/settings/yazi/init.lua +61 -0
  263. machineconfig/settings/yazi/keymap_linux.toml +94 -0
  264. machineconfig/settings/yazi/keymap_windows.toml +78 -0
  265. machineconfig/settings/yazi/shell/yazi_cd.ps1 +33 -0
  266. machineconfig/settings/yazi/shell/yazi_cd.sh +8 -0
  267. machineconfig/settings/yazi/theme.toml +4 -0
  268. machineconfig/settings/yazi/yazi_linux.toml +84 -0
  269. machineconfig/settings/yazi/yazi_windows.toml +58 -0
  270. machineconfig/setup_linux/__init__.py +11 -0
  271. machineconfig/setup_linux/apps_desktop.sh +89 -0
  272. machineconfig/setup_linux/apps_gui.sh +64 -0
  273. machineconfig/setup_linux/ssh/openssh_all.sh +25 -0
  274. machineconfig/setup_linux/ssh/openssh_wsl.sh +38 -0
  275. machineconfig/setup_linux/uv.sh +15 -0
  276. machineconfig/setup_linux/web_shortcuts/interactive.sh +26 -6
  277. machineconfig/setup_linux/web_shortcuts/live_from_github.sh +31 -0
  278. machineconfig/setup_mac/__init__.py +16 -0
  279. machineconfig/setup_mac/apps_gui.sh +248 -0
  280. machineconfig/setup_mac/ssh/openssh_setup.sh +114 -0
  281. machineconfig/setup_mac/uv.sh +36 -0
  282. machineconfig/setup_windows/__init__.py +11 -0
  283. machineconfig/setup_windows/others/power_options.ps1 +7 -0
  284. machineconfig/setup_windows/ssh/add-sshkey.ps1 +29 -0
  285. machineconfig/setup_windows/ssh/add_identity.ps1 +11 -0
  286. machineconfig/setup_windows/ssh/openssh-server.ps1 +37 -0
  287. machineconfig/setup_windows/uv.ps1 +17 -0
  288. machineconfig/setup_windows/web_shortcuts/interactive.ps1 +27 -10
  289. machineconfig/setup_windows/web_shortcuts/live_from_github.ps1 +30 -0
  290. machineconfig/setup_windows/web_shortcuts/quick_init.ps1 +17 -0
  291. machineconfig/utils/accessories.py +7 -5
  292. machineconfig/utils/cloud/onedrive/README.md +139 -0
  293. machineconfig/utils/code.py +155 -105
  294. machineconfig/utils/files/art/fat_croco.txt +10 -0
  295. machineconfig/utils/files/art/halfwit_croco.txt +9 -0
  296. machineconfig/utils/files/art/happy_croco.txt +22 -0
  297. machineconfig/utils/files/art/water_croco.txt +11 -0
  298. machineconfig/utils/files/ascii_art.py +1 -1
  299. machineconfig/utils/files/dbms.py +257 -0
  300. machineconfig/utils/files/headers.py +11 -14
  301. machineconfig/utils/files/ouch/__init__.py +0 -0
  302. machineconfig/utils/files/ouch/decompress.py +45 -0
  303. machineconfig/utils/files/read.py +10 -18
  304. machineconfig/utils/installer_utils/github_release_bulk.py +156 -119
  305. machineconfig/utils/installer_utils/install_from_url.py +183 -0
  306. machineconfig/utils/installer_utils/installer_class.py +64 -181
  307. machineconfig/utils/installer_utils/installer_cli.py +175 -0
  308. machineconfig/utils/installer_utils/installer_helper.py +129 -0
  309. machineconfig/utils/installer_utils/{installer_abc.py → installer_locator_utils.py} +66 -97
  310. machineconfig/utils/{installer.py → installer_utils/installer_runner.py} +49 -82
  311. machineconfig/utils/io.py +77 -23
  312. machineconfig/utils/links.py +254 -162
  313. machineconfig/utils/meta.py +256 -0
  314. machineconfig/utils/notifications.py +1 -1
  315. machineconfig/utils/options.py +46 -18
  316. machineconfig/utils/options_tv.py +119 -0
  317. machineconfig/utils/path_extended.py +48 -101
  318. machineconfig/utils/path_helper.py +76 -23
  319. machineconfig/utils/procs.py +50 -70
  320. machineconfig/utils/scheduler.py +88 -124
  321. machineconfig/utils/scheduling.py +0 -3
  322. machineconfig/utils/schemas/fire_agents/fire_agents_input.py +1 -1
  323. machineconfig/utils/schemas/layouts/layout_types.py +1 -1
  324. machineconfig/utils/source_of_truth.py +3 -6
  325. machineconfig/utils/ssh.py +263 -274
  326. machineconfig/utils/ssh_utils/abc.py +5 -0
  327. machineconfig/utils/ssh_utils/copy_from_here.py +111 -0
  328. machineconfig/utils/ssh_utils/copy_to_here.py +302 -0
  329. machineconfig/utils/ssh_utils/utils.py +142 -0
  330. machineconfig/utils/ssh_utils/wsl.py +210 -0
  331. machineconfig/utils/terminal.py +3 -113
  332. machineconfig/utils/tst.py +20 -0
  333. machineconfig/utils/upgrade_packages.py +114 -28
  334. machineconfig/utils/ve.py +12 -4
  335. machineconfig-7.98.dist-info/METADATA +132 -0
  336. machineconfig-7.98.dist-info/RECORD +504 -0
  337. machineconfig-7.98.dist-info/entry_points.txt +13 -0
  338. machineconfig/cluster/sessions_managers/ffile.py +0 -4
  339. machineconfig/jobs/installer/linux_scripts/pgsql.sh +0 -49
  340. machineconfig/jobs/installer/linux_scripts/timescaledb.sh +0 -85
  341. machineconfig/jobs/linux/msc/cli_agents.sh +0 -16
  342. machineconfig/jobs/python/python_ve_symlink.py +0 -37
  343. machineconfig/jobs/python/vscode/api.py +0 -57
  344. machineconfig/jobs/python/vscode/sync_code.py +0 -73
  345. machineconfig/jobs/windows/archive/archive_pygraphviz.ps1 +0 -14
  346. machineconfig/jobs/windows/start_terminal.ps1 +0 -6
  347. machineconfig/jobs/windows/startup_file.cmd +0 -2
  348. machineconfig/profile/create.py +0 -303
  349. machineconfig/profile/shell.py +0 -176
  350. machineconfig/scripts/cloud/init.sh +0 -119
  351. machineconfig/scripts/linux/agents +0 -2
  352. machineconfig/scripts/linux/choose_wezterm_theme +0 -3
  353. machineconfig/scripts/linux/cloud_copy +0 -2
  354. machineconfig/scripts/linux/cloud_mount +0 -2
  355. machineconfig/scripts/linux/cloud_repo_sync +0 -2
  356. machineconfig/scripts/linux/cloud_sync +0 -2
  357. machineconfig/scripts/linux/croshell +0 -3
  358. machineconfig/scripts/linux/devops +0 -2
  359. machineconfig/scripts/linux/fire +0 -2
  360. machineconfig/scripts/linux/ftpx +0 -2
  361. machineconfig/scripts/linux/fzf2g +0 -21
  362. machineconfig/scripts/linux/fzfag +0 -17
  363. machineconfig/scripts/linux/fzffg +0 -25
  364. machineconfig/scripts/linux/fzfrga +0 -21
  365. machineconfig/scripts/linux/gh_models +0 -2
  366. machineconfig/scripts/linux/initai +0 -2
  367. machineconfig/scripts/linux/kill_process +0 -2
  368. machineconfig/scripts/linux/scheduler +0 -2
  369. machineconfig/scripts/linux/sessions +0 -2
  370. machineconfig/scripts/linux/share_smb +0 -1
  371. machineconfig/scripts/linux/skrg +0 -4
  372. machineconfig/scripts/linux/start_slidev +0 -2
  373. machineconfig/scripts/linux/start_terminals +0 -3
  374. machineconfig/scripts/linux/warp-cli.sh +0 -122
  375. machineconfig/scripts/linux/wifi_conn +0 -2
  376. machineconfig/scripts/linux/z_ls +0 -104
  377. machineconfig/scripts/python/ai/generate_files.py +0 -83
  378. machineconfig/scripts/python/ai/solutions/copilot/prompts/allLintersAndTypeCheckers.prompt.md +0 -5
  379. machineconfig/scripts/python/cloud_repo_sync.py +0 -190
  380. machineconfig/scripts/python/count_lines_frontend.py +0 -16
  381. machineconfig/scripts/python/devops_add_ssh_key.py +0 -120
  382. machineconfig/scripts/python/dotfile.py +0 -78
  383. machineconfig/scripts/python/fire_agents_help_launch.py +0 -120
  384. machineconfig/scripts/python/fire_agents_helper_types.py +0 -12
  385. machineconfig/scripts/python/fire_jobs_route_helper.py +0 -65
  386. machineconfig/scripts/python/get_zellij_cmd.py +0 -15
  387. machineconfig/scripts/python/gh_models.py +0 -104
  388. machineconfig/scripts/python/helpers/repo_sync_helpers.py +0 -116
  389. machineconfig/scripts/python/repos.py +0 -132
  390. machineconfig/scripts/python/repos_helper_action.py +0 -378
  391. machineconfig/scripts/python/snapshot.py +0 -25
  392. machineconfig/scripts/python/start_terminals.py +0 -121
  393. machineconfig/scripts/python/t4.py +0 -17
  394. machineconfig/scripts/windows/agents.ps1 +0 -1
  395. machineconfig/scripts/windows/choose_wezterm_theme.ps1 +0 -1
  396. machineconfig/scripts/windows/cloud_copy.ps1 +0 -1
  397. machineconfig/scripts/windows/cloud_mount.ps1 +0 -1
  398. machineconfig/scripts/windows/cloud_repo_sync.ps1 +0 -1
  399. machineconfig/scripts/windows/cloud_sync.ps1 +0 -1
  400. machineconfig/scripts/windows/croshell.ps1 +0 -1
  401. machineconfig/scripts/windows/devops.ps1 +0 -1
  402. machineconfig/scripts/windows/dotfile.ps1 +0 -1
  403. machineconfig/scripts/windows/fire.ps1 +0 -1
  404. machineconfig/scripts/windows/ftpx.ps1 +0 -1
  405. machineconfig/scripts/windows/fzfb.ps1 +0 -3
  406. machineconfig/scripts/windows/fzfg.ps1 +0 -2
  407. machineconfig/scripts/windows/fzfrga.bat +0 -20
  408. machineconfig/scripts/windows/gpt.ps1 +0 -1
  409. machineconfig/scripts/windows/grep.ps1 +0 -2
  410. machineconfig/scripts/windows/initai.ps1 +0 -1
  411. machineconfig/scripts/windows/kill_process.ps1 +0 -1
  412. machineconfig/scripts/windows/nano.ps1 +0 -3
  413. machineconfig/scripts/windows/pomodoro.ps1 +0 -1
  414. machineconfig/scripts/windows/reload_path.ps1 +0 -3
  415. machineconfig/scripts/windows/scheduler.ps1 +0 -1
  416. machineconfig/scripts/windows/sessions.ps1 +0 -1
  417. machineconfig/scripts/windows/snapshot.ps1 +0 -1
  418. machineconfig/scripts/windows/start_slidev.ps1 +0 -1
  419. machineconfig/scripts/windows/start_terminals.ps1 +0 -1
  420. machineconfig/scripts/windows/wifi_conn.ps1 +0 -2
  421. machineconfig/scripts/windows/wsl_rdp_windows_port_forwarding.ps1 +0 -46
  422. machineconfig/scripts/windows/wsl_ssh_windows_port_forwarding.ps1 +0 -76
  423. machineconfig/settings/lf/linux/exe/fzf_nano.sh +0 -16
  424. machineconfig/settings/lf/windows/fzf_edit.ps1 +0 -6
  425. machineconfig/settings/lf/windows/tst.ps1 +0 -1
  426. machineconfig/settings/yazi/yazi.toml +0 -4
  427. machineconfig/setup_linux/nix/cli_installation.sh +0 -157
  428. machineconfig/setup_linux/others/openssh-server_add_pub_key.sh +0 -57
  429. machineconfig/setup_linux/web_shortcuts/croshell.sh +0 -11
  430. machineconfig/setup_linux/web_shortcuts/ssh.sh +0 -52
  431. machineconfig/setup_windows/web_shortcuts/all.ps1 +0 -18
  432. machineconfig/setup_windows/web_shortcuts/ascii_art.ps1 +0 -36
  433. machineconfig/setup_windows/web_shortcuts/croshell.ps1 +0 -16
  434. machineconfig/setup_windows/web_shortcuts/ssh.ps1 +0 -11
  435. machineconfig/utils/ai/generate_file_checklist.py +0 -68
  436. machineconfig/utils/installer_utils/installer.py +0 -189
  437. machineconfig-5.15.dist-info/METADATA +0 -188
  438. machineconfig-5.15.dist-info/RECORD +0 -415
  439. machineconfig-5.15.dist-info/entry_points.txt +0 -18
  440. machineconfig/cluster/sessions_managers/{utils → helpers}/load_balancer_helper.py +0 -0
  441. machineconfig/scripts/linux/{share_nfs → other/share_nfs} +0 -0
  442. machineconfig/scripts/linux/{start_docker → other/start_docker} +0 -0
  443. machineconfig/scripts/linux/{switch_ip → other/switch_ip} +0 -0
  444. machineconfig/{jobs/python → scripts/python/ai/utils}/__init__.py +0 -0
  445. machineconfig/scripts/python/{helpers → helpers_agents}/__init__.py +0 -0
  446. machineconfig/{jobs/windows/msc/cli_agents.bat → scripts/python/helpers_agents/agentic_frameworks/__init__.py} +0 -0
  447. machineconfig/scripts/python/{fire_agents_help_search.py → helpers_agents/fire_agents_help_search.py} +0 -0
  448. machineconfig/scripts/python/{fire_agents_load_balancer.py → helpers_agents/fire_agents_load_balancer.py} +0 -0
  449. machineconfig/{jobs/windows/msc/cli_agents.ps1 → scripts/python/helpers_cloud/__init__.py} +0 -0
  450. machineconfig/scripts/python/{helpers → helpers_cloud}/cloud_helpers.py +1 -1
  451. /machineconfig/scripts/python/{helpers → helpers_cloud}/helpers5.py +0 -0
  452. /machineconfig/scripts/python/{fire_jobs_streamlit_helper.py → helpers_croshell/__init__.py} +0 -0
  453. /machineconfig/scripts/python/{pomodoro.py → helpers_croshell/pomodoro.py} +0 -0
  454. /machineconfig/scripts/python/{scheduler.py → helpers_croshell/scheduler.py} +0 -0
  455. /machineconfig/scripts/python/{viewer.py → helpers_croshell/viewer.py} +0 -0
  456. /machineconfig/scripts/python/{viewer_template.py → helpers_croshell/viewer_template.py} +0 -0
  457. /machineconfig/scripts/{windows/share_nfs.ps1 → python/helpers_devops/__init__.py} +0 -0
  458. /machineconfig/{settings/shells/pwsh/profile.ps1 → scripts/python/helpers_devops/themes/__init__.py} +0 -0
  459. /machineconfig/{settings/yazi/keymap.toml → scripts/python/helpers_devops/themes/choose_starship_theme.ps1} +0 -0
  460. /machineconfig/scripts/python/{cloud_manager.py → helpers_fire_command/cloud_manager.py} +0 -0
  461. /machineconfig/scripts/{linux → python/helpers_network}/mount_drive +0 -0
  462. /machineconfig/scripts/python/{mount_nw_drive.py → helpers_network/mount_nw_drive.py} +0 -0
  463. /machineconfig/scripts/{linux → python/helpers_network}/mount_smb +0 -0
  464. /machineconfig/scripts/windows/{mount_nw.ps1 → mounts/mount_nw.ps1} +0 -0
  465. /machineconfig/scripts/windows/{mount_smb.ps1 → mounts/mount_smb.ps1} +0 -0
  466. /machineconfig/scripts/windows/{share_cloud.cmd → mounts/share_cloud.cmd} +0 -0
  467. /machineconfig/scripts/windows/{unlock_bitlocker.ps1 → mounts/unlock_bitlocker.ps1} +0 -0
  468. /machineconfig/setup_linux/{web_shortcuts → others}/android.sh +0 -0
  469. /machineconfig/{jobs/windows/archive → setup_windows/ssh}/openssh-server_add_key.ps1 +0 -0
  470. /machineconfig/{jobs/windows/archive → setup_windows/ssh}/openssh-server_copy-ssh-id.ps1 +0 -0
  471. {machineconfig-5.15.dist-info → machineconfig-7.98.dist-info}/WHEEL +0 -0
  472. {machineconfig-5.15.dist-info → machineconfig-7.98.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,256 @@
1
+ """Metaprogramming utilities for analyzing and serializing Python functions."""
2
+
3
+ from collections.abc import Callable
4
+ from typing import Any
5
+
6
+
7
+ def get_import_module_string(py_file: str) -> str:
8
+ from machineconfig.scripts.python.helpers_fire_command.file_wrangler import get_import_module_code
9
+ from machineconfig.utils.accessories import get_repo_root
10
+ from pathlib import Path
11
+ repo_root = get_repo_root(Path(py_file))
12
+ import_line = get_import_module_code(py_file)
13
+ if repo_root is not None:
14
+ repo_root_add = f"""sys.path.append(r'{repo_root}')"""
15
+ else:
16
+ repo_root_add = ""
17
+ txt: str = f"""
18
+ try:
19
+ {import_line}
20
+ except (ImportError, ModuleNotFoundError) as ex:
21
+ print(fr"❌ Failed to import `{py_file}` as a module: {{ex}} ")
22
+ print(fr"⚠️ Attempting import with ad-hoc `$PATH` manipulation. DO NOT pickle any objects in this session as correct deserialization cannot be guaranteed.")
23
+ import sys
24
+ sys.path.append(r'{Path(py_file).parent}')
25
+ {repo_root_add}
26
+ from {Path(py_file).stem} import *
27
+ print(fr"✅ Successfully imported `{py_file}`")
28
+ """
29
+ return txt
30
+
31
+
32
+ def lambda_to_python_script(lmb: Callable[[], Any],
33
+ in_global: bool, import_module: bool) -> str:
34
+ """
35
+ caveats: always use keyword arguments in the lambda call for best results.
36
+ return statement not allowed in the wrapped function (otherwise it can be put in the global space)
37
+ type hint in kwargs has nothing that is not built in, e.g. Optional will not work as it requires an import.
38
+
39
+ Given a no-arg lambda like `lambda: func(a=var1, b=var2)`,
40
+ return a string containing the full function definition of `func`
41
+ but with the defaults for the parameters provided in the call replaced
42
+ by the *actual* values (repr) taken from the lambda's globals.
43
+
44
+ All imports are local to this function.
45
+
46
+ Args:
47
+ lmb: A lambda function with no arguments
48
+ in_global: If True, return kwargs as global variable assignments followed by dedented body.
49
+ If False, return the full function definition with updated defaults.
50
+ import_module: When True, prepend module import bootstrap code for the function's source file.
51
+ """
52
+ # local imports
53
+ import inspect as _inspect
54
+ import ast as _ast
55
+ import textwrap as _textwrap
56
+ import types as _types
57
+ from pathlib import Path as _Path
58
+
59
+ def _stringify_annotation(annotation: Any) -> Any:
60
+ if annotation is _inspect.Signature.empty or annotation is _inspect.Parameter.empty:
61
+ return annotation
62
+ if isinstance(annotation, str):
63
+ return annotation
64
+ try:
65
+ return _inspect.formatannotation(annotation)
66
+ except Exception:
67
+ return str(annotation)
68
+
69
+ # sanity checks
70
+ if not (callable(lmb) and isinstance(lmb, _types.LambdaType)):
71
+ raise TypeError("Expected a lambda function object")
72
+
73
+ src = _inspect.getsource(lmb)
74
+ src = _textwrap.dedent(src)
75
+ tree = _ast.parse(src)
76
+
77
+ # find first Lambda node
78
+ lambda_node = None
79
+ for n in _ast.walk(tree):
80
+ if isinstance(n, _ast.Lambda):
81
+ lambda_node = n
82
+ break
83
+ if lambda_node is None:
84
+ raise ValueError("Could not find a lambda expression in source")
85
+
86
+ body = lambda_node.body
87
+ if not isinstance(body, _ast.Call):
88
+ raise ValueError("Lambda body is not a call expression")
89
+
90
+ globals_dict = getattr(lmb, "__globals__", {})
91
+
92
+ # Also capture closure variables from the lambda
93
+ closure_dict: dict[str, Any] = {}
94
+ if lmb.__closure__:
95
+ code_obj = lmb.__code__
96
+ freevars = code_obj.co_freevars
97
+ for i, var_name in enumerate(freevars):
98
+ closure_dict[var_name] = lmb.__closure__[i].cell_contents
99
+
100
+ # Merge globals and closures (closures take precedence for shadowing)
101
+ eval_namespace = {**globals_dict, **closure_dict}
102
+
103
+ # resolve the function object being called
104
+ try:
105
+ func_ref_src = _ast.unparse(body.func)
106
+ except AttributeError:
107
+ func_ref_src = _ast.get_source_segment(src, body.func) or ""
108
+ try:
109
+ func_obj = eval(func_ref_src, eval_namespace)
110
+ except Exception as e:
111
+ raise RuntimeError(f"Could not resolve function reference '{func_ref_src}': {e}")
112
+
113
+ if not callable(func_obj):
114
+ raise TypeError("Resolved object is not callable")
115
+
116
+ func_name = getattr(func_obj, "__name__", "<unknown>")
117
+
118
+ import_prefix: str = ""
119
+ if import_module:
120
+ module_file = _inspect.getsourcefile(func_obj)
121
+ module_path_candidate: str = module_file if module_file is not None else _inspect.getfile(func_obj)
122
+ import_prefix = get_import_module_string(str(_Path(module_path_candidate)))
123
+
124
+ # Evaluate each keyword argument value in the lambda's globals to get real Python objects
125
+ call_kwargs: dict[str, Any] = {}
126
+ for kw in body.keywords:
127
+ if kw.arg is None:
128
+ # **kwargs in call — evaluate to dict and merge
129
+ try:
130
+ val = eval(compile(_ast.Expression(kw.value), "<lambda_eval>", "eval"), eval_namespace)
131
+ if isinstance(val, dict):
132
+ call_kwargs.update(val)
133
+ else:
134
+ raise ValueError("Keyword expansion did not evaluate to a dict")
135
+ except Exception as e:
136
+ raise RuntimeError(f"Failed to evaluate **kwargs expression: {e}")
137
+ else:
138
+ try:
139
+ val = eval(compile(_ast.Expression(kw.value), "<lambda_eval>", "eval"), eval_namespace)
140
+ call_kwargs[kw.arg] = val
141
+ except Exception as e:
142
+ raise RuntimeError(f"Failed to evaluate value for kw '{kw.arg}': {e}")
143
+
144
+ # Try to get original source and dedent it for body extraction
145
+ try:
146
+ orig_src = _inspect.getsource(func_obj)
147
+ ded = _textwrap.dedent(orig_src)
148
+ lines = ded.splitlines()
149
+ def_index = None
150
+ for i, ln in enumerate(lines):
151
+ if ln.lstrip().startswith(f"def {func_name}("):
152
+ def_index = i
153
+ break
154
+ if def_index is None:
155
+ body_lines = ded.splitlines()
156
+ else:
157
+ signature_end_index = None
158
+ for i in range(def_index, len(lines)):
159
+ line_no_comment = lines[i].split("#", 1)[0].rstrip()
160
+ if line_no_comment.endswith(":"):
161
+ signature_end_index = i
162
+ break
163
+ if signature_end_index is None:
164
+ body_lines = lines[def_index + 1 :]
165
+ else:
166
+ body_lines = lines[signature_end_index + 1 :]
167
+ # ensure we have a body, otherwise use pass
168
+ if not any(line.strip() for line in body_lines):
169
+ body_text = " pass\n"
170
+ else:
171
+ joined_body = "\n".join(body_lines)
172
+ if not joined_body.endswith("\n"):
173
+ joined_body = f"{joined_body}\n"
174
+ body_text = joined_body
175
+ except (OSError, IOError, TypeError):
176
+ body_text = " pass\n"
177
+
178
+ # Build a replaced signature using inspect.signature
179
+ sig = _inspect.signature(func_obj)
180
+ new_params: list[_inspect.Parameter] = []
181
+ for name, param in sig.parameters.items():
182
+ # If the call provided a value for this parameter, replace default
183
+ if name in call_kwargs:
184
+ new_default = call_kwargs[name]
185
+ else:
186
+ new_default = param.default
187
+
188
+ normalized_annotation = _stringify_annotation(param.annotation)
189
+
190
+ if new_default is _inspect.Parameter.empty:
191
+ new_param = _inspect.Parameter(name, param.kind, annotation=normalized_annotation)
192
+ else:
193
+ new_param = _inspect.Parameter(
194
+ name, param.kind, default=new_default, annotation=normalized_annotation
195
+ )
196
+ new_params.append(new_param)
197
+
198
+ return_annotation = _stringify_annotation(sig.return_annotation)
199
+ new_sig = _inspect.Signature(parameters=new_params, return_annotation=return_annotation)
200
+
201
+ # If in_global mode, return kwargs as global assignments + dedented body
202
+ if in_global:
203
+ global_assignments: list[str] = []
204
+ for name, param in sig.parameters.items():
205
+ # Get the value from call_kwargs if provided, else use original default
206
+ if name in call_kwargs:
207
+ value = call_kwargs[name]
208
+ elif param.default is not _inspect.Parameter.empty:
209
+ value = param.default
210
+ else:
211
+ # No value provided and no default - skip this parameter
212
+ continue
213
+
214
+ # Build type annotation string if available
215
+ if param.annotation is not _inspect.Parameter.empty:
216
+ annotation_literal = _stringify_annotation(param.annotation)
217
+ if isinstance(annotation_literal, str):
218
+ global_assignments.append(f"{name}: {repr(annotation_literal)} = {repr(value)}")
219
+ else:
220
+ global_assignments.append(f"{name} = {repr(value)}")
221
+ else:
222
+ global_assignments.append(f"{name} = {repr(value)}")
223
+
224
+ # Dedent the body text to remove function indentation
225
+ dedented_body = _textwrap.dedent(body_text).rstrip()
226
+
227
+ # Combine global assignments and body
228
+ if global_assignments:
229
+ result_parts: list[str] = ["\n".join(global_assignments), "", dedented_body]
230
+ result_text = "\n".join(result_parts)
231
+ else:
232
+ result_text = dedented_body
233
+ else:
234
+ header = f"def {func_name}{new_sig}:\n"
235
+ result_text = header + body_text
236
+
237
+ if in_global:
238
+ lines = result_text.splitlines()
239
+ if lines[-1].startswith("return "):
240
+ lines[-1] = lines[-1].replace("return ", "# return ", 1)
241
+ result_text = "\n".join(lines)
242
+
243
+ if "Optional" in result_text or "Any" in result_text or "Union" in result_text or "Literal" in result_text:
244
+ result_text = "from typing import Optional, Any, Union, Literal\n\n" + result_text
245
+ if import_prefix:
246
+ result_text = f"{import_prefix}{result_text}"
247
+ return result_text
248
+
249
+ if __name__ == "__main__":
250
+ from machineconfig.utils.code import print_code
251
+ import_code_robust = "<import_code_robust>"
252
+ res = lambda_to_python_script(
253
+ lambda: print_code(code=import_code_robust, lexer="python", desc="import as module code"),
254
+ in_global=True, import_module=False
255
+ )
256
+ print(res)
@@ -110,7 +110,7 @@ encryption = ssl
110
110
 
111
111
  def send_message(self, to: str, subject: str, body: str, txt_to_html: bool = True, attachments: Optional[list[Any]] = None):
112
112
  _ = attachments
113
- body += "\n\nThis is an automated email sent via crocodile.comms script."
113
+ body += "\n\nThis is an automated email sent via machineconfig.comms script."
114
114
  # msg = message.EmailMessage()
115
115
  msg = MIMEMultipart("alternative")
116
116
  msg["subject"] = subject
@@ -1,38 +1,66 @@
1
+
1
2
  from pathlib import Path
2
- from machineconfig.utils.installer_utils.installer_abc import check_tool_exists
3
3
  from rich.text import Text
4
4
  from rich.panel import Panel
5
5
  from rich.console import Console
6
6
  import subprocess
7
- from typing import Optional, Union, Iterable, overload, Literal
7
+ from typing import Optional, Union, Iterable, overload, Literal, cast
8
8
 
9
9
  @overload
10
- def choose_from_options[T](msg: str, options: Iterable[T], multi: Literal[False], custom_input: bool = False, header: str = "", tail: str = "", prompt: str = "", default: Optional[T] = None, fzf: bool = False) -> T: ...
10
+ def choose_from_options[T](options: Iterable[T], msg: str, multi: Literal[False], custom_input: bool = False, header: str = "", tail: str = "", prompt: str = "", default: Optional[T] = None, tv: bool = False) -> T: ...
11
11
  @overload
12
- def choose_from_options[T](msg: str, options: Iterable[T], multi: Literal[True], custom_input: bool = True, header: str = "", tail: str = "", prompt: str = "", default: Optional[T] = None, fzf: bool = False, ) -> list[T]: ...
13
- def choose_from_options[T](msg: str, options: Iterable[T], multi: bool, custom_input: bool = True, header: str = "", tail: str = "", prompt: str = "", default: Optional[T] = None, fzf: bool = False, ) -> Union[T, list[T]]:
12
+ def choose_from_options[T](options: Iterable[T], msg: str, multi: Literal[True], custom_input: bool = True, header: str = "", tail: str = "", prompt: str = "", default: Optional[T] = None, tv: bool = False, ) -> list[T]: ...
13
+ def choose_from_options[T](options: Iterable[T], msg: str, multi: bool, custom_input: bool = True, header: str = "", tail: str = "", prompt: str = "", default: Optional[T] = None, tv: bool = False, ) -> Union[T, list[T]]:
14
14
  # TODO: replace with https://github.com/tmbo/questionary
15
15
  # # also see https://github.com/charmbracelet/gum
16
16
  options_strings: list[str] = [str(x) for x in options]
17
17
  default_string = str(default) if default is not None else None
18
18
  console = Console()
19
- fzf_exists = check_tool_exists("fzf")
20
- # print("\n" * 10, f"{fzf=}, {fzf_exists=}", "\n" * 10)
21
- if fzf and fzf_exists:
22
- from pyfzf.pyfzf import FzfPrompt
23
- fzf_prompt = FzfPrompt()
24
- nl = "\n"
25
- choice_string_multi: list[str] = fzf_prompt.prompt(choices=options_strings, fzf_options=("--multi" if multi else "") + f' --prompt "{prompt.replace(nl, " ")}" ') # --border-label={msg.replace(nl, ' ')}")
26
- # --border=rounded doens't work on older versions of fzf installed at Ubuntu 20.04
19
+ from machineconfig.utils.installer_utils.installer_locator_utils import check_tool_exists
20
+ # from machineconfig.utils.installer_utils.installer_cli import check_tool_exists
21
+ # print("ch1")
22
+ if tv and check_tool_exists("tv"):
23
+ # from pyfzf.pyfzf import FzfPrompt
24
+ # fzf_prompt = FzfPrompt()
25
+ # nl = "\n"
26
+ # choice_string_multi: list[str] = fzf_prompt.prompt(choices=options_strings, fzf_options=("--multi" if multi else "") + f' --prompt "{prompt.replace(nl, " ")}" --ansi') # --border-label={msg.replace(nl, ' ')}")
27
+ # print("ch2")
28
+ from machineconfig.utils.accessories import randstr
29
+ options_txt_path = Path.home().joinpath("tmp_results/tmp_files/choices_" + randstr(6) + ".txt")
30
+ options_txt_path.parent.mkdir(parents=True, exist_ok=True)
31
+ options_txt_path.write_text("\n".join(options_strings), encoding="utf-8")
32
+
33
+ # Run `tv` interactively so the user can make selections. We redirect tv's
34
+ # stdout to a temporary output file so we can read the chosen lines after
35
+ # the interactive session completes. Do not capture_output or redirect
36
+ # stdin/stderr here so `tv` stays attached to the terminal.
37
+ tv_out_path = options_txt_path.with_name(options_txt_path.stem + "_out.txt")
38
+ tv_cmd = f"""cat {options_txt_path} | tv --ansi true --source-output "{{strip_ansi}}" > {tv_out_path}"""
39
+ res = subprocess.run(tv_cmd, shell=True)
40
+
41
+ # If tv returned a non-zero code and there is no output file, treat it as an error.
42
+ if res.returncode != 0 and not tv_out_path.exists():
43
+ raise RuntimeError(f"Got error running tv command: {tv_cmd}\nreturncode: {res.returncode}")
44
+
45
+ # Read selections (if any) from the output file created by tv.
46
+ out_text = tv_out_path.read_text(encoding="utf-8") if tv_out_path.exists() else ""
47
+ choice_string_multi = [x for x in out_text.splitlines() if x.strip() != ""]
48
+
49
+ # Cleanup temporary files
50
+ options_txt_path.unlink(missing_ok=True)
51
+ tv_out_path.unlink(missing_ok=True)
27
52
  if not multi:
28
53
  try:
29
54
  choice_one_string = choice_string_multi[0]
55
+ if isinstance(list(options)[0], str): return cast(T, choice_one_string)
30
56
  choice_idx = options_strings.index(choice_one_string)
31
57
  return list(options)[choice_idx]
32
58
  except IndexError as ie:
33
59
  print(f"❌ Error: {options=}, {choice_string_multi=}")
34
60
  print(f"🔍 Available choices: {choice_string_multi}")
35
61
  raise ie
62
+ if isinstance(list(options)[0], str):
63
+ return cast(list[T], choice_string_multi)
36
64
  choice_idx_s = [options_strings.index(x) for x in choice_string_multi]
37
65
  return [list(options)[x] for x in choice_idx_s]
38
66
  else:
@@ -55,7 +83,7 @@ def choose_from_options[T](msg: str, options: Iterable[T], multi: bool, custom_i
55
83
  if choice_string == "":
56
84
  if default_string is None:
57
85
  console.print(Panel("🧨 Default option not available!", title="Error", expand=False))
58
- return choose_from_options(msg=msg, options=options, header=header, tail=tail, prompt=prompt, default=default, fzf=fzf, multi=multi, custom_input=custom_input)
86
+ return choose_from_options(msg=msg, options=options, header=header, tail=tail, prompt=prompt, default=default, tv=tv, multi=multi, custom_input=custom_input)
59
87
  choice_idx = options_strings.index(default_string)
60
88
  assert default is not None, "🧨 Default option not available!"
61
89
  choice_one: T = default
@@ -73,7 +101,7 @@ def choose_from_options[T](msg: str, options: Iterable[T], multi: bool, custom_i
73
101
  _ = ie
74
102
  # raise ValueError(f"Unknown choice. {choice_string}") from ie
75
103
  console.print(Panel(f"❓ Unknown choice: '{choice_string}'", title="Error", expand=False))
76
- return choose_from_options(msg=msg, options=options, header=header, tail=tail, prompt=prompt, default=default, fzf=fzf, multi=multi, custom_input=custom_input)
104
+ return choose_from_options(msg=msg, options=options, header=header, tail=tail, prompt=prompt, default=default, tv=tv, multi=multi, custom_input=custom_input)
77
105
  except (TypeError, ValueError) as te: # int(choice_string) failed due to # either the number is invalid, or the input is custom.
78
106
  if choice_string in options_strings: # string input
79
107
  choice_idx = options_strings.index(choice_one) # type: ignore
@@ -84,7 +112,7 @@ def choose_from_options[T](msg: str, options: Iterable[T], multi: bool, custom_i
84
112
  _ = te
85
113
  # raise ValueError(f"Unknown choice. {choice_string}") from te
86
114
  console.print(Panel(f"❓ Unknown choice: '{choice_string}'", title="Error", expand=False))
87
- return choose_from_options(msg=msg, options=options, header=header, tail=tail, prompt=prompt, default=default, fzf=fzf, multi=multi, custom_input=custom_input)
115
+ return choose_from_options(msg=msg, options=options, header=header, tail=tail, prompt=prompt, default=default, tv=tv, multi=multi, custom_input=custom_input)
88
116
  console.print(Panel(f"✅ Selected option {choice_idx}: {choice_one}", title="Selected", expand=False))
89
117
  if multi:
90
118
  return [choice_one]
@@ -103,7 +131,7 @@ def choose_cloud_interactively() -> str:
103
131
  raise ValueError(f"Got {tmp} from rclone listremotes")
104
132
  if len(remotes) == 0:
105
133
  raise RuntimeError("You don't have remotes. Configure your rclone first to get cloud services access.")
106
- cloud: str = choose_from_options(msg="WHICH CLOUD?", multi=False, options=list(remotes), default=remotes[0], fzf=True)
134
+ cloud: str = choose_from_options(msg="WHICH CLOUD?", multi=False, options=list(remotes), default=remotes[0], tv=True)
107
135
  console.print(Panel(f"✅ SELECTED CLOUD | {cloud}", border_style="bold blue", expand=False))
108
136
  return cloud
109
137
 
@@ -121,4 +149,4 @@ def choose_ssh_host(multi: Literal[False]) -> str: ...
121
149
  @overload
122
150
  def choose_ssh_host(multi: Literal[True]) -> list[str]: ...
123
151
  def choose_ssh_host(multi: bool):
124
- return choose_from_options(msg="", options=get_ssh_hosts(), multi=multi, fzf=True)
152
+ return choose_from_options(msg="", options=get_ssh_hosts(), multi=multi, tv=True)
@@ -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)