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
@@ -1,73 +1,40 @@
1
- from typing import Optional, Any, Union, List
1
+ from typing import Callable, Optional, Any, cast, Union, Literal
2
2
  import os
3
- from dataclasses import dataclass
3
+ from pathlib import Path
4
+ import platform
5
+ from machineconfig.scripts.python.helpers_utils.path import MachineSpecs
6
+ from machineconfig.utils.code import get_uv_run_command
4
7
  import rich.console
5
- from machineconfig.utils.terminal import Response, MACHINE
6
- from machineconfig.utils.path_extended import PathExtended, PLike, OPLike
7
- from machineconfig.utils.accessories import pprint
8
- # from machineconfig.utils.ve import get_ve_activate_line
9
-
10
-
11
- def get_header(wdir: OPLike, toolbox: bool):
12
- if toolbox:
13
- toobox_code = """
14
- try:
15
- from crocodile.toolbox import *
16
- except ImportError:
17
- print("Crocodile not found, skipping import.")
18
- pass
19
- """
20
- else:
21
- toobox_code = "# No toolbox import."
22
- return f"""
23
- # >> Code prepended
24
- {toobox_code}
25
- {'''sys.path.insert(0, r'{wdir}') ''' if wdir is not None else "# No path insertion."}
26
- # >> End of header, start of script passed
27
- """
28
-
29
-
30
- @dataclass
31
- class Scout:
32
- source_full: PathExtended
33
- source_rel2home: PathExtended
34
- exists: bool
35
- is_dir: bool
36
- files: Optional[List[PathExtended]]
37
-
38
-
39
- def scout(source: PLike, z: bool = False, r: bool = False) -> Scout:
40
- source_full = PathExtended(source).expanduser().absolute()
41
- source_rel2home = source_full.collapseuser()
42
- exists = source_full.exists()
43
- is_dir = source_full.is_dir() if exists else False
44
- if z and exists:
45
- try:
46
- source_full = source_full.zip()
47
- except Exception as ex:
48
- raise Exception(f"Could not zip {source_full} due to {ex}") from ex # type: ignore # pylint: disable=W0719
49
- source_rel2home = source_full.zip()
50
- if r and exists and is_dir:
51
- files = [item.collapseuser() for item in source_full.search(folders=False, r=True)]
52
- else:
53
- files = None
54
- return Scout(source_full=source_full, source_rel2home=source_rel2home, exists=exists, is_dir=is_dir, files=files)
55
-
56
-
57
- class SSH: # inferior alternative: https://github.com/fabric/fabric
8
+ from machineconfig.utils.terminal import Response
9
+ from machineconfig.utils.accessories import pprint, randstr
10
+ from machineconfig.utils.meta import lambda_to_python_script
11
+ from machineconfig.utils.ssh_utils.abc import DEFAULT_PICKLE_SUBDIR
12
+
13
+
14
+ class SSH:
15
+ @staticmethod
16
+ def from_config_file(host: str) -> "SSH":
17
+ """Create SSH instance from SSH config file entry."""
18
+ return SSH(host=host, username=None, hostname=None, ssh_key_path=None, password=None, port=22, enable_compression=False)
19
+
58
20
  def __init__(
59
- self, host: Optional[str] = None, username: Optional[str] = None, hostname: Optional[str] = None, sshkey: Optional[str] = None, pwd: Optional[str] = None, port: int = 22, ve: Optional[str] = ".venv", compress: bool = False
60
- ): # https://stackoverflow.com/questions/51027192/execute-command-script-using-different-shell-in-ssh-paramiko
61
- self.pwd = pwd
62
- self.ve = ve
63
- self.compress = compress # Defaults: (1) use localhost if nothing provided.
21
+ self,
22
+ host: Optional[str],
23
+ username: Optional[str],
24
+ hostname: Optional[str],
25
+ ssh_key_path: Optional[str],
26
+ password: Optional[str],
27
+ port: int,
28
+ enable_compression: bool,
29
+ ):
30
+ self.password = password
31
+ self.enable_compression = enable_compression
64
32
 
65
33
  self.host: Optional[str] = None
66
34
  self.hostname: str
67
35
  self.username: str
68
36
  self.port: int = port
69
37
  self.proxycommand: Optional[str] = None
70
- import platform
71
38
  import paramiko # type: ignore
72
39
  import getpass
73
40
 
@@ -75,26 +42,28 @@ class SSH: # inferior alternative: https://github.com/fabric/fabric
75
42
  try:
76
43
  import paramiko.config as pconfig
77
44
 
78
- config = pconfig.SSHConfig.from_path(str(PathExtended.home().joinpath(".ssh/config")))
45
+ config = pconfig.SSHConfig.from_path(str(Path.home().joinpath(".ssh/config")))
79
46
  config_dict = config.lookup(host)
80
47
  self.hostname = config_dict["hostname"]
81
48
  self.username = config_dict["user"]
82
49
  self.host = host
83
50
  self.port = int(config_dict.get("port", port))
84
- tmp = config_dict.get("identityfile", sshkey)
85
- if isinstance(tmp, list):
86
- sshkey = tmp[0]
51
+ identity_file_value = config_dict.get("identityfile", ssh_key_path)
52
+ if isinstance(identity_file_value, list):
53
+ ssh_key_path = identity_file_value[0]
87
54
  else:
88
- sshkey = tmp
55
+ ssh_key_path = identity_file_value
89
56
  self.proxycommand = config_dict.get("proxycommand", None)
90
- if sshkey is not None:
91
- tmp = config.lookup("*").get("identityfile", sshkey)
92
- if isinstance(tmp, list):
93
- sshkey = tmp[0]
57
+ if ssh_key_path is not None:
58
+ wildcard_identity_file = config.lookup("*").get("identityfile", ssh_key_path)
59
+ if isinstance(wildcard_identity_file, list):
60
+ ssh_key_path = wildcard_identity_file[0]
94
61
  else:
95
- sshkey = tmp
62
+ ssh_key_path = wildcard_identity_file
96
63
  except (FileNotFoundError, KeyError):
97
- assert "@" in host or ":" in host, f"Host must be in the form of `username@hostname:port` or `username@hostname` or `hostname:port`, but it is: {host}"
64
+ assert "@" in host or ":" in host, (
65
+ f"Host must be in the form of `username@hostname:port` or `username@hostname` or `hostname:port`, but it is: {host}"
66
+ )
98
67
  if "@" in host:
99
68
  self.username, self.hostname = host.split("@")
100
69
  else:
@@ -110,31 +79,52 @@ class SSH: # inferior alternative: https://github.com/fabric/fabric
110
79
  print(f"Provided values: host={host}, username={username}, hostname={hostname}")
111
80
  raise ValueError("Either host or username and hostname must be provided.")
112
81
 
113
- self.sshkey = str(PathExtended(sshkey).expanduser().absolute()) if sshkey is not None else None # no need to pass sshkey if it was configured properly already
82
+ self.ssh_key_path = str(Path(ssh_key_path).expanduser().absolute()) if ssh_key_path is not None else None
114
83
  self.ssh = paramiko.SSHClient()
115
84
  self.ssh.load_system_host_keys()
116
85
  self.ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
117
- pprint(dict(host=self.host, hostname=self.hostname, username=self.username, password="***", port=self.port, key_filename=self.sshkey, ve=self.ve), title="SSHing To")
86
+ pprint(
87
+ dict(host=self.host, hostname=self.hostname, username=self.username, password="***", port=self.port, key_filename=self.ssh_key_path),
88
+ title="SSHing To",
89
+ )
118
90
  sock = paramiko.ProxyCommand(self.proxycommand) if self.proxycommand is not None else None
119
91
  try:
120
- if pwd is None:
92
+ if password is None:
121
93
  allow_agent = True
122
94
  look_for_keys = True
123
95
  else:
124
96
  allow_agent = False
125
97
  look_for_keys = False
126
- self.ssh.connect(hostname=self.hostname, username=self.username, password=self.pwd, port=self.port, key_filename=self.sshkey, compress=self.compress, sock=sock, allow_agent=allow_agent, look_for_keys=look_for_keys) # type: ignore
98
+ self.ssh.connect(
99
+ hostname=self.hostname,
100
+ username=self.username,
101
+ password=self.password,
102
+ port=self.port,
103
+ key_filename=self.ssh_key_path,
104
+ compress=self.enable_compression,
105
+ sock=sock,
106
+ allow_agent=allow_agent,
107
+ look_for_keys=look_for_keys,
108
+ ) # type: ignore
127
109
  except Exception as _err:
128
110
  rich.console.Console().print_exception()
129
- self.pwd = getpass.getpass(f"Enter password for {self.username}@{self.hostname}: ")
130
- self.ssh.connect(hostname=self.hostname, username=self.username, password=self.pwd, port=self.port, key_filename=self.sshkey, compress=self.compress, sock=sock, allow_agent=False, look_for_keys=False) # type: ignore
111
+ self.password = getpass.getpass(f"Enter password for {self.username}@{self.hostname}: ")
112
+ self.ssh.connect(
113
+ hostname=self.hostname,
114
+ username=self.username,
115
+ password=self.password,
116
+ port=self.port,
117
+ key_filename=self.ssh_key_path,
118
+ compress=self.enable_compression,
119
+ sock=sock,
120
+ allow_agent=False,
121
+ look_for_keys=False,
122
+ ) # type: ignore
131
123
  try:
132
124
  self.sftp: Optional[paramiko.SFTPClient] = self.ssh.open_sftp()
133
125
  except Exception as err:
134
126
  self.sftp = None
135
- print(f"""⚠️ WARNING: Failed to open SFTP connection to {hostname}.
136
- Error Details: {err}\nData transfer may be affected!""")
137
-
127
+ print(f"""⚠️ WARNING: Failed to open SFTP connection to {self.hostname}. Error Details: {err}\nData transfer may be affected!""")
138
128
  from rich.progress import Progress, SpinnerColumn, TextColumn, BarColumn, FileSizeColumn, TransferSpeedColumn
139
129
 
140
130
  class RichProgressWrapper:
@@ -144,7 +134,9 @@ class SSH: # inferior alternative: https://github.com/fabric/fabric
144
134
  self.task: Optional[Any] = None
145
135
 
146
136
  def __enter__(self) -> "RichProgressWrapper":
147
- self.progress = Progress(SpinnerColumn(), TextColumn("[bold blue]{task.description}"), BarColumn(), FileSizeColumn(), TransferSpeedColumn())
137
+ self.progress = Progress(
138
+ SpinnerColumn(), TextColumn("[bold blue]{task.description}"), BarColumn(), FileSizeColumn(), TransferSpeedColumn()
139
+ )
148
140
  self.progress.start()
149
141
  self.task = self.progress.add_task("Transferring...", total=0)
150
142
  return self
@@ -156,216 +148,213 @@ class SSH: # inferior alternative: https://github.com/fabric/fabric
156
148
  def view_bar(self, transferred: int, total: int) -> None:
157
149
  if self.progress and self.task is not None:
158
150
  self.progress.update(self.task, completed=transferred, total=total)
159
-
160
151
  self.tqdm_wrap = RichProgressWrapper
161
- self._local_distro: Optional[str] = None
162
- self._remote_distro: Optional[str] = None
163
- self._remote_machine: Optional[MACHINE] = None
152
+ from machineconfig.scripts.python.helpers_utils.path import get_machine_specs
153
+ self.local_specs: MachineSpecs = get_machine_specs()
154
+ resp = self.run_shell_cmd_on_remote(
155
+ command="""~/.local/bin/utils get-machine-specs """,
156
+ verbose_output=False,
157
+ description="Getting remote machine specs",
158
+ strict_stderr=False,
159
+ strict_return_code=False,
160
+ )
161
+ json_str = resp.op
162
+ import ast
163
+ self.remote_specs: MachineSpecs = cast(MachineSpecs, ast.literal_eval(json_str))
164
164
  self.terminal_responses: list[Response] = []
165
- self.platform = platform
166
165
 
167
- def get_remote_machine(self) -> MACHINE:
168
- if self._remote_machine is None:
169
- if self.run("$env:OS", verbose=False, desc="Testing Remote OS Type").op == "Windows_NT" or self.run("echo %OS%", verbose=False, desc="Testing Remote OS Type Again").op == "Windows_NT":
170
- self._remote_machine = "Windows"
171
- else:
172
- self._remote_machine = "Linux"
173
- return self._remote_machine # echo %OS% TODO: uname on linux
174
-
175
- def get_local_distro(self) -> str:
176
- if self._local_distro is None:
177
- command = """uv run --with distro python -c "import distro; print(distro.name(pretty=True))" """
178
- import subprocess
179
-
180
- res = subprocess.run(command, shell=True, capture_output=True, text=True).stdout.strip()
181
- self._local_distro = res
182
- return res
183
- return self._local_distro
184
-
185
- def get_remote_distro(self):
186
- if self._remote_distro is None:
187
- res = self.run("""~/.local/bin/uv run --with distro python -c "import distro; print(distro.name(pretty=True))" """)
188
- self._remote_distro = res.op_if_successfull_or_default() or ""
189
- return self._remote_distro
190
-
191
- def restart_computer(self):
192
- self.run("Restart-Computer -Force" if self.get_remote_machine() == "Windows" else "sudo reboot")
193
-
194
- def send_ssh_key(self):
195
- self.copy_from_here("~/.ssh/id_rsa.pub")
196
- assert self.get_remote_machine() == "Windows"
166
+ from rich import inspect
167
+
168
+ # local_info = dict(distro=self.local_specs.get("distro"), system=self.local_specs.get("system"), home_dir=self.local_specs.get("home_dir"))
169
+ # remote_info = dict(distro=self.remote_specs.get("distro"), system=self.remote_specs.get("system"), home_dir=self.remote_specs.get("home_dir"))
170
+
171
+ console = rich.console.Console()
172
+
173
+ from io import StringIO
174
+
175
+ local_buffer = StringIO()
176
+ remote_buffer = StringIO()
177
+ local_console = rich.console.Console(file=local_buffer, width=40)
178
+ remote_console = rich.console.Console(file=remote_buffer, width=40)
179
+ inspect(
180
+ type("LocalInfo", (object,), dict(self.local_specs))(), value=False, title="SSHing From", docs=False, dunder=False, sort=False, console=local_console
181
+ )
182
+ inspect(
183
+ type("RemoteInfo", (object,), dict(self.remote_specs))(), value=False, title="SSHing To", docs=False, dunder=False, sort=False, console=remote_console
184
+ )
185
+ local_lines = local_buffer.getvalue().split("\n")
186
+ remote_lines = remote_buffer.getvalue().split("\n")
187
+ max_lines = max(len(local_lines), len(remote_lines))
188
+ for i in range(max_lines):
189
+ left = local_lines[i] if i < len(local_lines) else ""
190
+ right = remote_lines[i] if i < len(remote_lines) else ""
191
+ console.print(f"{left:<50} {right}")
192
+
193
+ def __enter__(self) -> "SSH":
194
+ return self
195
+
196
+ def __exit__(self, exc_type: Any, exc_val: Any, exc_tb: Any) -> None:
197
+ self.close()
198
+
199
+ def close(self) -> None:
200
+ if self.sftp is not None:
201
+ self.sftp.close()
202
+ self.sftp = None
203
+ self.ssh.close()
204
+
205
+ def restart_computer(self) -> Response:
206
+ return self.run_shell_cmd_on_remote(
207
+ command="Restart-Computer -Force" if self.remote_specs["system"] == "Windows" else "sudo reboot",
208
+ verbose_output=True,
209
+ description="",
210
+ strict_stderr=False,
211
+ strict_return_code=False,
212
+ )
213
+
214
+ def send_ssh_key(self) -> Response:
215
+ self.copy_from_here(source_path="~/.ssh/id_rsa.pub", target_rel2home=None, compress_with_zip=False, recursive=False, overwrite_existing=False)
216
+ if self.remote_specs["system"] != "Windows":
217
+ raise RuntimeError("send_ssh_key is only supported for Windows remote machines")
197
218
  code_url = "https://raw.githubusercontent.com/thisismygitrepo/machineconfig/refs/heads/main/src/machineconfig/setup_windows/openssh-server_add-sshkey.ps1"
198
- code = PathExtended(code_url).download().read_text(encoding="utf-8")
199
- self.run(code)
219
+ import urllib.request
200
220
 
201
- def copy_env_var(self, name: str):
202
- assert self.get_remote_machine() == "Linux"
203
- return self.run(f"{name} = {os.environ[name]}; export {name}")
221
+ with urllib.request.urlopen(code_url) as response:
222
+ code = response.read().decode("utf-8")
223
+ return self.run_shell_cmd_on_remote(command=code, verbose_output=True, description="", strict_stderr=False, strict_return_code=False)
204
224
 
205
225
  def get_remote_repr(self, add_machine: bool = False) -> str:
206
- return f"{self.username}@{self.hostname}:{self.port}" + (f" [{self.get_remote_machine()}][{self.get_remote_distro()}]" if add_machine else "")
207
-
226
+ return f"{self.username}@{self.hostname}:{self.port}" + (
227
+ f" [{self.remote_specs['system']}][{self.remote_specs['distro']}]" if add_machine else ""
228
+ )
208
229
  def get_local_repr(self, add_machine: bool = False) -> str:
209
230
  import getpass
231
+ return f"{getpass.getuser()}@{platform.node()}" + (f" [{platform.system()}][{self.local_specs['distro']}]" if add_machine else "")
232
+
233
+ def get_ssh_conn_str(self, command: str) -> str:
234
+ return (
235
+ "ssh "
236
+ + (f" -i {self.ssh_key_path}" if self.ssh_key_path else "")
237
+ + self.get_remote_repr(add_machine=False).replace(":", " -p ")
238
+ + (f" -t {command} " if command != "" else " ")
239
+ )
210
240
 
211
- return f"{getpass.getuser()}@{self.platform.node()}" + (f" [{self.platform.system()}][{self.get_local_distro()}]" if add_machine else "")
212
-
213
- def __repr__(self):
241
+ def __repr__(self) -> str:
214
242
  return f"local {self.get_local_repr(add_machine=True)} >>> SSH TO >>> remote {self.get_remote_repr(add_machine=True)}"
215
243
 
216
- def run_locally(self, command: str):
217
- print(f"""💻 [LOCAL EXECUTION] Running command on node: {self.platform.node()} Command: {command}""")
244
+ def run_shell_cmd_on_local(self, command: str) -> Response:
245
+ print(f"""💻 [LOCAL EXECUTION] Running command on node: {self.local_specs["system"]} Command: {command}""")
218
246
  res = Response(cmd=command)
219
247
  res.output.returncode = os.system(command)
220
248
  return res
221
249
 
222
- def get_ssh_conn_str(self, cmd: str = ""):
223
- return "ssh " + (f" -i {self.sshkey}" if self.sshkey else "") + self.get_remote_repr().replace(":", " -p ") + (f" -t {cmd} " if cmd != "" else " ")
224
-
225
- def run(self, cmd: str, verbose: bool = True, desc: str = "", strict_err: bool = False, strict_returncode: bool = False) -> Response:
226
- raw = self.ssh.exec_command(cmd)
227
- res = Response(stdin=raw[0], stdout=raw[1], stderr=raw[2], cmd=cmd, desc=desc) # type: ignore
228
- if not verbose:
229
- res.capture().print_if_unsuccessful(desc=desc, strict_err=strict_err, strict_returncode=strict_returncode, assert_success=False)
230
- else:
250
+ def run_shell_cmd_on_remote(self, command: str, verbose_output: bool, description: str, strict_stderr: bool, strict_return_code: bool) -> Response:
251
+ raw = self.ssh.exec_command(command)
252
+ res = Response(stdin=raw[0], stdout=raw[1], stderr=raw[2], cmd=command, desc=description) # type: ignore
253
+ if verbose_output:
231
254
  res.print()
232
- self.terminal_responses.append(res)
255
+ else:
256
+ res.capture().print_if_unsuccessful(
257
+ desc=description, strict_err=strict_stderr, strict_returncode=strict_return_code, assert_success=False
258
+ )
259
+ # self.terminal_responses.append(res)
233
260
  return res
234
261
 
235
- def run_py(self, cmd: str, desc: str = "", return_obj: bool = False, verbose: bool = True, strict_err: bool = False, strict_returncode: bool = False) -> Union[Any, Response]:
236
- assert '"' not in cmd, 'Avoid using `"` in your command. I dont know how to handle this when passing is as command to python in pwsh command.'
237
- if not return_obj:
238
- return self.run(
239
- cmd=f"""uv run --no-dev --project $HOME/code/machineconfig -c "{get_header(wdir=None, toolbox=True)}{cmd}\n""" + '"',
240
- desc=desc or f"run_py on {self.get_remote_repr()}",
241
- verbose=verbose,
242
- strict_err=strict_err,
243
- strict_returncode=strict_returncode,
244
- )
245
- assert "obj=" in cmd, "The command sent to run_py must have `obj=` statement if return_obj is set to True"
246
- source_file = self.run_py(f"""{cmd}\npath = Save.pickle(obj=obj, path=P.tmpfile(suffix='.pkl'))\nprint(path)""", desc=desc, verbose=verbose, strict_err=True, strict_returncode=True).op.split("\n")[-1]
247
- res = self.copy_to_here(source=source_file, target=PathExtended.tmpfile(suffix=".pkl"))
248
- import pickle
249
-
250
- return pickle.loads(res.read_bytes())
251
-
252
- def copy_from_here(self, source: PLike, target: OPLike = None, z: bool = False, r: bool = False, overwrite: bool = False, init: bool = True) -> Union[PathExtended, list[PathExtended]]:
253
- if init:
254
- print(f"{'⬆️' * 5} [SFTP UPLOAD] FROM `{source}` TO `{target}`") # TODO: using return_obj do all tests required in one go.
255
- source_obj = PathExtended(source).expanduser().absolute()
256
- if not source_obj.exists():
257
- raise RuntimeError(f"Meta.SSH Error: source `{source_obj}` does not exist!")
258
- if target is None:
259
- target = PathExtended(source_obj).expanduser().absolute().collapseuser(strict=True)
260
- assert target.is_relative_to("~"), "If target is not specified, source must be relative to home."
261
- if z:
262
- target += ".zip"
263
- if not z and source_obj.is_dir():
264
- if r is False:
265
- raise RuntimeError(f"Meta.SSH Error: source `{source_obj}` is a directory! either set `r=True` for recursive sending or raise `z=True` flag to zip it first.")
266
- source_list: list[PathExtended] = source_obj.search("*", folders=False, files=True, r=True)
267
- remote_root = (
268
- self.run_py(
269
- f"path=P(r'{PathExtended(target).as_posix()}').expanduser()\n{'path.delete(sure=True)' if overwrite else ''}\nprint(path.create())",
270
- desc=f"Creating Target directory `{PathExtended(target).as_posix()}` @ {self.get_remote_repr()}",
271
- verbose=False,
272
- ).op
273
- or ""
274
- )
275
- for idx, item in enumerate(source_list):
276
- print(f" {idx + 1:03d}. {item}")
277
- for item in source_list:
278
- a__target = PathExtended(remote_root).joinpath(item.relative_to(source_obj))
279
- self.copy_from_here(source=item, target=a__target)
280
- return list(source_list)
281
- if z:
282
- print("🗜️ ZIPPING ...")
283
- source_obj = PathExtended(source_obj).expanduser().zip(content=True) # .append(f"_{randstr()}", inplace=True) # eventually, unzip will raise content flag, so this name doesn't matter.
284
- remotepath = (
285
- self.run_py(
286
- f"path=P(r'{PathExtended(target).as_posix()}').expanduser()\n{'path.delete(sure=True)' if overwrite else ''}\nprint(path.parent.create())",
287
- desc=f"Creating Target directory `{PathExtended(target).parent.as_posix()}` @ {self.get_remote_repr()}",
288
- verbose=False,
289
- ).op
290
- or ""
291
- )
292
- remotepath = PathExtended(remotepath.split("\n")[-1]).joinpath(PathExtended(target).name)
293
- print(f"""📤 [SFTP UPLOAD] Sending file: {repr(PathExtended(source_obj))} ==> Remote Path: {remotepath.as_posix()}""")
294
- with self.tqdm_wrap(ascii=True, unit="b", unit_scale=True) as pbar:
295
- self.sftp.put(localpath=PathExtended(source_obj).expanduser(), remotepath=remotepath.as_posix(), callback=pbar.view_bar) # type: ignore # pylint: disable=E1129
296
- if z:
297
- _resp = self.run_py(f"""P(r'{remotepath.as_posix()}').expanduser().unzip(content=False, inplace=True, overwrite={overwrite})""", desc=f"UNZIPPING {remotepath.as_posix()}", verbose=False, strict_err=True, strict_returncode=True)
298
- source_obj.delete(sure=True)
299
- print("\n")
300
- return source_obj
301
-
302
- def copy_to_here(self, source: PLike, target: OPLike = None, z: bool = False, r: bool = False, init: bool = True) -> PathExtended:
303
- if init:
304
- print(f"{'⬇️' * 5} SFTP DOWNLOADING FROM `{source}` TO `{target}`")
305
- if not z and self.run_py(f"print(P(r'{source}').expanduser().absolute().is_dir())", desc=f"Check if source `{source}` is a dir", verbose=False, strict_returncode=True, strict_err=True).op.split("\n")[-1] == "True":
306
- if r is False:
307
- raise RuntimeError(f"source `{source}` is a directory! either set r=True for recursive sending or raise zip_first flag.")
308
- source_list = self.run_py(f"obj=P(r'{source}').search(folders=False, r=True).collapseuser(strict=False)", desc="Searching for files in source", return_obj=True, verbose=False)
309
- assert isinstance(source_list, List), f"Could not resolve source path {source} due to error"
310
- for file in source_list:
311
- self.copy_to_here(source=file.as_posix(), target=PathExtended(target).joinpath(PathExtended(file).relative_to(source)) if target else None, r=False)
312
- if z:
313
- tmp: Response = self.run_py(f"print(P(r'{source}').expanduser().zip(inplace=False, verbose=False))", desc=f"Zipping source file {source}", verbose=False)
314
- tmp2 = tmp.op2path(strict_returncode=True, strict_err=True)
315
- if not isinstance(tmp2, PathExtended):
316
- raise RuntimeError(f"Could not zip {source} due to {tmp.err}")
317
- else:
318
- source = tmp2
319
- if target is None:
320
- tmpx = self.run_py(f"print(P(r'{PathExtended(source).as_posix()}').collapseuser(strict=False).as_posix())", desc="Finding default target via relative source path", strict_returncode=True, strict_err=True, verbose=False).op2path()
321
- if isinstance(tmpx, PathExtended):
322
- target = tmpx
323
- else:
324
- raise RuntimeError(f"Could not resolve target path {target} due to error")
325
- assert target.is_relative_to("~"), f"If target is not specified, source must be relative to home.\n{target=}"
326
- target_obj = PathExtended(target).expanduser().absolute()
327
- target_obj.parent.mkdir(parents=True, exist_ok=True)
328
- if z and ".zip" not in target_obj.suffix:
329
- target_obj += ".zip"
330
- if "~" in str(source):
331
- tmp3 = self.run_py(f"print(P(r'{source}').expanduser())", desc="# Resolving source path address by expanding user", strict_returncode=True, strict_err=True, verbose=False).op2path()
332
- if isinstance(tmp3, PathExtended):
333
- source = tmp3
334
- else:
335
- raise RuntimeError(f"Could not resolve source path {source} due to")
262
+ def _run_py_prep(self, python_code: str, uv_with: Optional[list[str]], uv_project_dir: Optional[str], on: Literal["local", "remote"]) -> str:
263
+ py_path = Path.home().joinpath(f"{DEFAULT_PICKLE_SUBDIR}/runpy_{randstr()}.py")
264
+ py_path.parent.mkdir(parents=True, exist_ok=True)
265
+ py_path.write_text(python_code, encoding="utf-8")
266
+ self.copy_from_here(source_path=str(py_path), target_rel2home=None, compress_with_zip=False, recursive=False, overwrite_existing=False)
267
+ if uv_with is not None and len(uv_with) > 0:
268
+ with_clause = " --with " + '"' + ",".join(uv_with) + '"'
336
269
  else:
337
- source = PathExtended(source)
338
- print(f"""📥 [DOWNLOAD] Receiving: {source} ==> Local Path: {target_obj}""")
339
- with self.tqdm_wrap(ascii=True, unit="b", unit_scale=True) as pbar: # type: ignore # pylint: disable=E1129
340
- assert self.sftp is not None, f"Could not establish SFTP connection to {self.hostname}."
341
- self.sftp.get(remotepath=source.as_posix(), localpath=str(target_obj), callback=pbar.view_bar) # type: ignore
342
- if z:
343
- target_obj = target_obj.unzip(inplace=True, content=True)
344
- self.run_py(f"P(r'{source.as_posix()}').delete(sure=True)", desc="Cleaning temp zip files @ remote.", strict_returncode=True, strict_err=True, verbose=False)
345
- print("\n")
346
- return target_obj
347
-
348
- def receieve(self, source: PLike, target: OPLike = None, z: bool = False, r: bool = False) -> PathExtended:
349
- scout = self.run_py(cmd=f"obj=scout(r'{source}', z={z}, r={r})", desc=f"Scouting source `{source}` path on remote", return_obj=True, verbose=False)
350
- assert isinstance(scout, Scout)
351
- if not z and scout.is_dir and scout.files is not None:
352
- if r:
353
- tmp: list[PathExtended] = [self.receieve(source=file.as_posix(), target=PathExtended(target).joinpath(PathExtended(file).relative_to(source)) if target else None, r=False) for file in scout.files]
354
- return tmp[0]
355
- else:
356
- print("Source is a directory! either set `r=True` for recursive sending or raise `zip_first=True` flag.")
357
- if target:
358
- target = PathExtended(target).expanduser().absolute()
270
+ with_clause = ""
271
+ if uv_project_dir is not None:
272
+ with_clause += f" --project {uv_project_dir}"
359
273
  else:
360
- target = scout.source_rel2home.expanduser().absolute()
361
- target.parent.mkdir(parents=True, exist_ok=True)
362
- if z and ".zip" not in target.suffix:
363
- target += ".zip"
364
- source = scout.source_full
365
- with self.tqdm_wrap(ascii=True, unit="b", unit_scale=True) as pbar:
366
- self.sftp.get(remotepath=source.as_posix(), localpath=target.as_posix(), callback=pbar.view_bar) # type: ignore # pylint: disable=E1129
367
- if z:
368
- target = target.unzip(inplace=True, content=True)
369
- self.run_py(f"P(r'{source.as_posix()}').delete(sure=True)", desc="Cleaning temp zip files @ remote.", strict_returncode=True, strict_err=True)
370
- print("\n")
371
- return target
274
+ with_clause += ""
275
+ match on:
276
+ case "local":
277
+ uv_run_cmd = get_uv_run_command(platform=self.local_specs["system"])
278
+ case "remote":
279
+ uv_run_cmd = get_uv_run_command(platform=self.remote_specs["system"])
280
+ case _:
281
+ raise ValueError(f"Invalid value for 'on': {on}. Must be 'local' or 'remote'")
282
+ uv_cmd = f"""{uv_run_cmd} {with_clause} python {py_path.relative_to(Path.home())}"""
283
+ return uv_cmd
284
+
285
+ def run_py_remotely(
286
+ self,
287
+ python_code: str,
288
+ uv_with: Optional[list[str]],
289
+ uv_project_dir: Optional[str],
290
+ description: str,
291
+ verbose_output: bool,
292
+ strict_stderr: bool,
293
+ strict_return_code: bool,
294
+ ) -> Response:
295
+ uv_cmd = self._run_py_prep(python_code=python_code, uv_with=uv_with, uv_project_dir=uv_project_dir, on="remote")
296
+ return self.run_shell_cmd_on_remote(
297
+ command=uv_cmd,
298
+ verbose_output=verbose_output,
299
+ description=description or f"run_py on {self.get_remote_repr(add_machine=False)}",
300
+ strict_stderr=strict_stderr,
301
+ strict_return_code=strict_return_code,
302
+ )
303
+
304
+ def run_lambda_function(self, func: Callable[..., Any], import_module: bool, uv_with: Optional[list[str]], uv_project_dir: Optional[str]):
305
+ command = lambda_to_python_script(func,
306
+ in_global=True, import_module=import_module)
307
+ # turns ou that the code below for some reason runs but zellij doesn't start, looks like things are assigned to different user.
308
+ # return self.run_py(python_code=command, uv_with=uv_with, uv_project_dir=uv_project_dir,
309
+ # description=f"run_py_func {func.__name__} on {self.get_remote_repr(add_machine=False)}",
310
+ # verbose_output=True, strict_stderr=True, strict_return_code=True)
311
+ uv_cmd = self._run_py_prep(python_code=command, uv_with=uv_with, uv_project_dir=uv_project_dir, on="remote")
312
+ if self.remote_specs["system"] == "Linux":
313
+ uv_cmd_modified = f'bash -l -c "{uv_cmd}"'
314
+ else:
315
+ uv_cmd_modified = uv_cmd
316
+ # This works even withou the modified uv cmd:
317
+ # from machineconfig.utils.code import run_shell_script
318
+ # assert self.host is not None, "SSH host must be specified to run remote commands"
319
+ # process = run_shell_script(f"ssh {self.host} -n '. ~/.profile; . ~/.bashrc; {uv_cmd}'")
320
+ # return process
321
+ return self.run_shell_cmd_on_remote(
322
+ command=uv_cmd_modified,
323
+ verbose_output=True,
324
+ description=f"run_py_func {func.__name__} on {self.get_remote_repr(add_machine=False)}",
325
+ strict_stderr=True,
326
+ strict_return_code=True,
327
+ )
328
+
329
+ def simple_sftp_get(self, remote_path: str, local_path: Path) -> None:
330
+ """Simple SFTP get without any recursion or path expansion - for internal use only."""
331
+ if self.sftp is None:
332
+ raise RuntimeError(f"SFTP connection not available for {self.hostname}")
333
+ local_path.parent.mkdir(parents=True, exist_ok=True)
334
+ self.sftp.get(remotepath=remote_path, localpath=str(local_path))
335
+
336
+ def create_parent_dir_and_check_if_exists(self, path_rel2home: str, overwrite_existing: bool) -> None:
337
+ from machineconfig.utils.ssh_utils.utils import create_dir_and_check_if_exists
338
+ return create_dir_and_check_if_exists(self, path_rel2home=path_rel2home, overwrite_existing=overwrite_existing)
339
+
340
+ def check_remote_is_dir(self, source_path: Union[str, Path]) -> bool:
341
+ from machineconfig.utils.ssh_utils.utils import check_remote_is_dir
342
+ return check_remote_is_dir(self, source_path=source_path)
343
+
344
+ def expand_remote_path(self, source_path: Union[str, Path]) -> str:
345
+ from machineconfig.utils.ssh_utils.utils import expand_remote_path
346
+ return expand_remote_path(self, source_path=source_path)
347
+
348
+ def copy_from_here(self, source_path: str, target_rel2home: Optional[str], compress_with_zip: bool, recursive: bool, overwrite_existing: bool) -> None:
349
+ from machineconfig.utils.ssh_utils.copy_from_here import copy_from_here
350
+ return copy_from_here(self, source_path=source_path, target_rel2home=target_rel2home, compress_with_zip=compress_with_zip, recursive=recursive, overwrite_existing=overwrite_existing)
351
+
352
+ def copy_to_here(self, source: Union[str, Path], target: Optional[Union[str, Path]], compress_with_zip: bool, recursive: bool, internal_call: bool = False) -> None:
353
+ from machineconfig.utils.ssh_utils.copy_to_here import copy_to_here
354
+ return copy_to_here(self, source=source, target=target, compress_with_zip=compress_with_zip, recursive=recursive, internal_call=internal_call)
355
+
356
+
357
+
358
+
359
+ if __name__ == "__main__":
360
+ ssh = SSH(host="p51s", username=None, hostname=None, ssh_key_path=None, password=None, port=22, enable_compression=False)
@@ -0,0 +1,5 @@
1
+
2
+
3
+ MACHINECONFIG_VERSION = "machineconfig>=7.98"
4
+ DEFAULT_PICKLE_SUBDIR = "tmp_results/tmp_scripts/ssh"
5
+