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.
- machineconfig/__init__.py +0 -28
- machineconfig/cluster/remote/cloud_manager.py +1 -1
- machineconfig/cluster/remote/distribute.py +0 -1
- machineconfig/cluster/remote/file_manager.py +0 -2
- machineconfig/cluster/remote/script_execution.py +0 -1
- machineconfig/cluster/sessions_managers/{utils → helpers}/enhanced_command_runner.py +4 -6
- machineconfig/cluster/sessions_managers/utils/load_balancer.py +1 -1
- machineconfig/cluster/sessions_managers/utils/maker.py +69 -0
- machineconfig/cluster/sessions_managers/wt_local.py +114 -289
- machineconfig/cluster/sessions_managers/wt_local_manager.py +70 -210
- machineconfig/cluster/sessions_managers/wt_remote.py +51 -43
- machineconfig/cluster/sessions_managers/wt_remote_manager.py +52 -198
- machineconfig/cluster/sessions_managers/wt_utils/layout_generator.py +6 -19
- machineconfig/cluster/sessions_managers/wt_utils/manager_persistence.py +52 -0
- machineconfig/cluster/sessions_managers/wt_utils/monitoring_helpers.py +50 -0
- machineconfig/cluster/sessions_managers/wt_utils/status_reporter.py +4 -2
- machineconfig/cluster/sessions_managers/wt_utils/status_reporting.py +76 -0
- machineconfig/cluster/sessions_managers/wt_utils/wt_helpers.py +199 -0
- machineconfig/cluster/sessions_managers/zellij_local.py +81 -375
- machineconfig/cluster/sessions_managers/zellij_local_manager.py +25 -170
- machineconfig/cluster/sessions_managers/zellij_remote.py +40 -41
- machineconfig/cluster/sessions_managers/zellij_remote_manager.py +16 -12
- machineconfig/cluster/sessions_managers/zellij_utils/example_usage.py +4 -8
- machineconfig/cluster/sessions_managers/zellij_utils/layout_generator.py +5 -20
- machineconfig/cluster/sessions_managers/zellij_utils/process_monitor.py +3 -9
- machineconfig/cluster/sessions_managers/zellij_utils/status_reporter.py +3 -1
- machineconfig/cluster/sessions_managers/zellij_utils/zellij_local_helper.py +298 -0
- machineconfig/cluster/sessions_managers/zellij_utils/zellij_local_helper_restart.py +77 -0
- machineconfig/cluster/sessions_managers/zellij_utils/zellij_local_helper_with_panes.py +228 -0
- machineconfig/cluster/sessions_managers/zellij_utils/zellij_local_manager_helper.py +165 -0
- machineconfig/jobs/{python → installer}/check_installations.py +2 -3
- machineconfig/jobs/installer/custom/boxes.py +61 -0
- machineconfig/jobs/installer/custom/hx.py +76 -19
- machineconfig/jobs/installer/custom/yazi.py +119 -0
- machineconfig/jobs/installer/custom_dev/alacritty.py +4 -4
- machineconfig/jobs/installer/custom_dev/brave.py +5 -9
- machineconfig/jobs/installer/custom_dev/cloudflare_warp_cli.py +23 -0
- machineconfig/jobs/installer/custom_dev/code.py +4 -1
- machineconfig/jobs/installer/custom_dev/dubdb_adbc.py +30 -0
- machineconfig/jobs/installer/custom_dev/nerdfont.py +1 -1
- machineconfig/jobs/installer/custom_dev/nerfont_windows_helper.py +33 -28
- machineconfig/jobs/installer/custom_dev/sysabc.py +139 -0
- machineconfig/jobs/installer/custom_dev/wezterm.py +2 -19
- machineconfig/jobs/installer/custom_dev/winget.py +10 -14
- machineconfig/jobs/installer/installer_data.json +1487 -229
- machineconfig/jobs/installer/linux_scripts/brave.sh +4 -14
- machineconfig/jobs/installer/linux_scripts/{warp-cli.sh → cloudflare_warp_cli.sh} +5 -17
- machineconfig/jobs/installer/linux_scripts/docker.sh +5 -17
- machineconfig/jobs/installer/linux_scripts/docker_start.sh +6 -14
- machineconfig/jobs/installer/linux_scripts/edge.sh +3 -11
- machineconfig/jobs/{linux/msc → installer/linux_scripts}/lid.sh +2 -8
- machineconfig/jobs/installer/linux_scripts/nerdfont.sh +5 -17
- machineconfig/jobs/{linux/msc → installer/linux_scripts}/network.sh +2 -8
- machineconfig/jobs/installer/linux_scripts/q.sh +10 -6
- machineconfig/jobs/installer/linux_scripts/redis.sh +6 -17
- machineconfig/jobs/installer/linux_scripts/vscode.sh +5 -17
- machineconfig/jobs/installer/linux_scripts/wezterm.sh +4 -12
- machineconfig/jobs/installer/package_groups.py +106 -177
- machineconfig/jobs/installer/powershell_scripts/install_fonts.ps1 +129 -34
- machineconfig/logger.py +0 -1
- machineconfig/profile/backup.toml +49 -0
- machineconfig/profile/bash_shell_profiles.md +11 -0
- machineconfig/profile/create_helper.py +62 -0
- machineconfig/profile/create_links.py +288 -0
- machineconfig/profile/create_links_export.py +100 -0
- machineconfig/profile/create_shell_profile.py +147 -0
- machineconfig/profile/mapper.toml +263 -0
- machineconfig/scripts/__init__.py +0 -4
- machineconfig/scripts/linux/{share_cloud.sh → other/share_cloud.sh} +14 -25
- machineconfig/scripts/linux/wrap_mcfg +46 -0
- machineconfig/scripts/nu/wrap_mcfg.nu +69 -0
- machineconfig/scripts/python/agents.py +123 -117
- machineconfig/scripts/python/ai/initai.py +3 -28
- machineconfig/scripts/python/ai/scripts/command_runner.ps1 +33 -0
- machineconfig/scripts/python/ai/scripts/command_runner.sh +9 -0
- machineconfig/scripts/python/ai/scripts/lint_and_type_check.ps1 +17 -18
- machineconfig/scripts/python/ai/scripts/lint_and_type_check.sh +17 -18
- machineconfig/scripts/python/ai/solutions/_shared.py +9 -1
- machineconfig/scripts/python/ai/solutions/copilot/{chatmodes/Thinking-Beast-Mode.chatmode.md → agents/Thinking-Beast-Mode.agent.md} +0 -1
- machineconfig/scripts/python/ai/solutions/copilot/{chatmodes/Ultimate-Transparent-Thinking-Beast-Mode.chatmode.md → agents/Ultimate-Transparent-Thinking-Beast-Mode.agent.md} +0 -1
- machineconfig/scripts/python/ai/solutions/copilot/{chatmodes/deepResearch.chatmode.md → agents/deepResearch.agent.md} +2 -2
- machineconfig/scripts/python/ai/solutions/copilot/github_copilot.py +5 -5
- machineconfig/scripts/python/ai/solutions/copilot/instructions/python/dev.instructions.md +5 -1
- machineconfig/scripts/python/ai/solutions/copilot/instructions/python/watch_exec.prompt.md +20 -0
- machineconfig/scripts/python/ai/solutions/copilot/prompts/pyright_fix.md +16 -0
- machineconfig/scripts/python/ai/solutions/generic.py +28 -5
- machineconfig/scripts/python/ai/utils/generate_files.py +348 -0
- machineconfig/scripts/python/ai/utils/vscode_tasks.py +37 -0
- machineconfig/scripts/python/cloud.py +29 -0
- machineconfig/scripts/python/croshell.py +137 -113
- machineconfig/scripts/python/devops.py +61 -101
- machineconfig/scripts/python/devops_navigator.py +6 -0
- machineconfig/scripts/python/env_manager/__init__.py +1 -0
- machineconfig/scripts/python/env_manager/env_manager_tui.py +204 -0
- machineconfig/scripts/python/env_manager/path_manager_backend.py +47 -0
- machineconfig/scripts/python/env_manager/path_manager_tui.py +228 -0
- machineconfig/scripts/python/fire_jobs.py +110 -150
- machineconfig/scripts/python/ftpx.py +51 -24
- machineconfig/scripts/python/helpers/ast_search.py +74 -0
- machineconfig/scripts/python/helpers/qr_code.py +166 -0
- machineconfig/scripts/python/helpers/repo_rag.py +325 -0
- machineconfig/scripts/python/helpers/run_py_script.py +79 -0
- machineconfig/scripts/python/helpers/symantic_search.py +25 -0
- machineconfig/scripts/python/helpers/tmp_py_scripts/a.py +26 -0
- machineconfig/scripts/python/helpers_agents/agentic_frameworks/fire_crush.json +14 -0
- machineconfig/scripts/python/helpers_agents/agentic_frameworks/fire_crush.py +39 -0
- machineconfig/scripts/python/helpers_agents/agentic_frameworks/fire_cursor_agents.py +22 -0
- machineconfig/scripts/python/helpers_agents/agentic_frameworks/fire_gemini.py +55 -0
- machineconfig/scripts/python/helpers_agents/agentic_frameworks/fire_qwen.py +30 -0
- machineconfig/scripts/python/helpers_agents/fire_agents_help_launch.py +126 -0
- machineconfig/scripts/python/helpers_agents/fire_agents_helper_types.py +41 -0
- machineconfig/scripts/python/helpers_agents/templates/prompt.txt +10 -0
- machineconfig/scripts/python/helpers_agents/templates/template.ps1 +14 -0
- machineconfig/scripts/python/helpers_agents/templates/template.sh +32 -0
- machineconfig/scripts/python/{cloud_copy.py → helpers_cloud/cloud_copy.py} +30 -23
- machineconfig/scripts/python/{cloud_mount.py → helpers_cloud/cloud_mount.py} +29 -35
- machineconfig/scripts/python/{cloud_sync.py → helpers_cloud/cloud_sync.py} +12 -18
- machineconfig/scripts/python/{helpers → helpers_cloud}/helpers2.py +1 -1
- machineconfig/scripts/python/helpers_croshell/crosh.py +39 -0
- machineconfig/scripts/python/{start_slidev.py → helpers_croshell/start_slidev.py} +8 -9
- machineconfig/scripts/python/helpers_devops/cli_config.py +105 -0
- machineconfig/scripts/python/helpers_devops/cli_config_dotfile.py +89 -0
- machineconfig/scripts/python/helpers_devops/cli_data.py +25 -0
- machineconfig/scripts/python/helpers_devops/cli_nw.py +214 -0
- machineconfig/scripts/python/helpers_devops/cli_repos.py +215 -0
- machineconfig/scripts/python/helpers_devops/cli_self.py +172 -0
- machineconfig/scripts/python/helpers_devops/cli_share_file.py +137 -0
- machineconfig/scripts/python/helpers_devops/cli_share_server.py +142 -0
- machineconfig/scripts/python/{share_terminal.py → helpers_devops/cli_share_terminal.py} +45 -35
- machineconfig/scripts/python/helpers_devops/cli_utils.py +96 -0
- machineconfig/scripts/python/{devops_backup_retrieve.py → helpers_devops/devops_backup_retrieve.py} +7 -10
- machineconfig/scripts/python/helpers_devops/devops_status.py +499 -0
- machineconfig/scripts/python/{devops_update_repos.py → helpers_devops/devops_update_repos.py} +68 -49
- machineconfig/scripts/python/helpers_devops/themes/choose_pwsh_theme.ps1 +81 -0
- machineconfig/scripts/python/helpers_devops/themes/choose_starship_theme.bash +3 -0
- machineconfig/scripts/python/{choose_wezterm_theme.py → helpers_devops/themes/choose_wezterm_theme.py} +3 -3
- machineconfig/scripts/python/helpers_fire_command/__init__.py +0 -0
- machineconfig/scripts/python/helpers_fire_command/f.py +0 -0
- machineconfig/scripts/python/{helpers/helpers4.py → helpers_fire_command/file_wrangler.py} +56 -20
- machineconfig/scripts/python/{fire_jobs_args_helper.py → helpers_fire_command/fire_jobs_args_helper.py} +5 -1
- machineconfig/scripts/python/helpers_fire_command/fire_jobs_route_helper.py +121 -0
- machineconfig/scripts/python/helpers_fire_command/fire_jobs_streamlit_helper.py +0 -0
- machineconfig/scripts/python/helpers_msearch/__init__.py +5 -0
- machineconfig/scripts/{linux → python/helpers_msearch/scripts_linux}/fzfg +3 -3
- machineconfig/scripts/python/helpers_msearch/scripts_windows/fzfg.ps1 +59 -0
- machineconfig/scripts/python/helpers_navigator/__init__.py +20 -0
- machineconfig/scripts/python/helpers_navigator/command_builder.py +111 -0
- machineconfig/scripts/python/helpers_navigator/command_detail.py +44 -0
- machineconfig/scripts/python/helpers_navigator/command_tree.py +620 -0
- machineconfig/scripts/python/helpers_navigator/data_models.py +28 -0
- machineconfig/scripts/python/helpers_navigator/main_app.py +272 -0
- machineconfig/scripts/python/helpers_navigator/search_bar.py +15 -0
- machineconfig/scripts/python/helpers_network/__init__.py +0 -0
- machineconfig/scripts/python/helpers_network/address.py +132 -0
- machineconfig/scripts/python/{devops_add_identity.py → helpers_network/devops_add_identity.py} +0 -2
- machineconfig/scripts/python/helpers_network/devops_add_ssh_key.py +153 -0
- machineconfig/scripts/{linux → python/helpers_network}/mount_nfs +0 -1
- machineconfig/scripts/python/{mount_nfs.py → helpers_network/mount_nfs.py} +3 -3
- machineconfig/scripts/{linux → python/helpers_network}/mount_nw_drive +1 -2
- machineconfig/scripts/python/{mount_ssh.py → helpers_network/mount_ssh.py} +3 -3
- machineconfig/scripts/python/{onetimeshare.py → helpers_network/onetimeshare.py} +0 -1
- machineconfig/scripts/python/helpers_network/ssh_debug_linux.py +391 -0
- machineconfig/scripts/python/helpers_network/ssh_debug_windows.py +338 -0
- machineconfig/scripts/python/{wifi_conn.py → helpers_network/wifi_conn.py} +1 -53
- machineconfig/scripts/python/{wsl_windows_transfer.py → helpers_network/wsl_windows_transfer.py} +5 -4
- machineconfig/scripts/python/helpers_repos/action.py +209 -0
- machineconfig/scripts/python/helpers_repos/action_helper.py +150 -0
- machineconfig/scripts/python/{repos_helper_clone.py → helpers_repos/clone.py} +2 -3
- machineconfig/scripts/python/helpers_repos/cloud_repo_sync.py +218 -0
- machineconfig/scripts/python/{repos_helper.py → helpers_repos/entrypoint.py} +9 -17
- machineconfig/scripts/python/helpers_repos/grource.py +340 -0
- machineconfig/scripts/python/{repos_helper_record.py → helpers_repos/record.py} +4 -3
- machineconfig/scripts/python/helpers_repos/repo_analyzer_1.py +160 -0
- machineconfig/scripts/python/{count_lines.py → helpers_repos/repo_analyzer_2.py} +113 -192
- machineconfig/scripts/python/helpers_repos/sync.py +66 -0
- machineconfig/scripts/python/{repos_helper_update.py → helpers_repos/update.py} +3 -3
- machineconfig/scripts/python/helpers_sessions/__init__.py +0 -0
- machineconfig/scripts/python/helpers_sessions/sessions_multiprocess.py +65 -0
- machineconfig/scripts/python/helpers_utils/download.py +150 -0
- machineconfig/scripts/python/helpers_utils/path.py +185 -0
- machineconfig/scripts/python/interactive.py +64 -84
- machineconfig/scripts/python/mcfg_entry.py +58 -0
- machineconfig/scripts/python/msearch.py +71 -0
- machineconfig/scripts/python/sessions.py +119 -45
- machineconfig/scripts/python/terminal.py +133 -0
- machineconfig/scripts/python/utils.py +64 -0
- machineconfig/scripts/windows/mounts/Restore-ThunderbirdProfile.ps1 +92 -0
- machineconfig/scripts/windows/{mount_nfs.ps1 → mounts/mount_nfs.ps1} +1 -3
- machineconfig/scripts/windows/{mount_ssh.ps1 → mounts/mount_ssh.ps1} +1 -1
- machineconfig/scripts/windows/{share_smb.ps1 → mounts/share_smb.ps1} +0 -6
- machineconfig/scripts/windows/wrap_mcfg.ps1 +63 -0
- machineconfig/settings/broot/br.sh +0 -4
- machineconfig/settings/broot/conf.toml +1 -1
- machineconfig/settings/helix/config.toml +16 -0
- machineconfig/settings/helix/languages.toml +13 -4
- machineconfig/settings/helix/yazi-picker.sh +12 -0
- machineconfig/settings/lf/linux/exe/lfcd.sh +1 -0
- machineconfig/settings/lf/linux/exe/previewer.sh +9 -3
- machineconfig/settings/lf/linux/lfrc +10 -12
- machineconfig/settings/lf/windows/lfcd.ps1 +1 -1
- machineconfig/settings/lf/windows/lfrc +18 -38
- machineconfig/settings/lf/windows/mkfile.ps1 +1 -1
- machineconfig/settings/linters/.ruff.toml +1 -1
- machineconfig/settings/lvim/windows/archive/config_additional.lua +0 -6
- machineconfig/settings/marimo/marimo.toml +80 -0
- machineconfig/settings/marimo/snippets/globalize.py +34 -0
- machineconfig/settings/pistol/pistol.conf +1 -1
- machineconfig/settings/shells/bash/init.sh +82 -31
- machineconfig/settings/shells/ipy/profiles/default/startup/playext.py +1 -1
- machineconfig/settings/shells/nushell/config.nu +2 -35
- machineconfig/settings/shells/nushell/env.nu +45 -6
- machineconfig/settings/shells/nushell/init.nu +314 -0
- machineconfig/settings/shells/pwsh/init.ps1 +61 -43
- machineconfig/settings/shells/starship/starship.toml +16 -0
- machineconfig/settings/shells/wezterm/wezterm.lua +2 -0
- machineconfig/settings/shells/wt/settings.json +32 -17
- machineconfig/settings/shells/zsh/init.sh +89 -0
- machineconfig/settings/svim/linux/init.toml +0 -4
- machineconfig/settings/svim/windows/init.toml +0 -3
- machineconfig/settings/television/cable_unix/alias.toml +8 -0
- machineconfig/settings/television/cable_unix/aws-buckets.toml +14 -0
- machineconfig/settings/television/cable_unix/aws-instances.toml +13 -0
- machineconfig/settings/television/cable_unix/bash-history.toml +8 -0
- machineconfig/settings/television/cable_unix/channels.toml +19 -0
- machineconfig/settings/television/cable_unix/dirs.toml +13 -0
- machineconfig/settings/television/cable_unix/distrobox-list.toml +42 -0
- machineconfig/settings/television/cable_unix/docker-images.toml +13 -0
- machineconfig/settings/television/cable_unix/dotfiles.toml +11 -0
- machineconfig/settings/television/cable_unix/env.toml +17 -0
- machineconfig/settings/television/cable_unix/files.toml +11 -0
- machineconfig/settings/television/cable_unix/fish-history.toml +8 -0
- machineconfig/settings/television/cable_unix/git-branch.toml +11 -0
- machineconfig/settings/television/cable_unix/git-diff.toml +10 -0
- machineconfig/settings/television/cable_unix/git-log.toml +12 -0
- machineconfig/settings/television/cable_unix/git-reflog.toml +12 -0
- machineconfig/settings/television/cable_unix/git-repos.toml +16 -0
- machineconfig/settings/television/cable_unix/guix.toml +20 -0
- machineconfig/settings/television/cable_unix/just-recipes.toml +18 -0
- machineconfig/settings/television/cable_unix/k8s-deployments.toml +36 -0
- machineconfig/settings/television/cable_unix/k8s-pods.toml +50 -0
- machineconfig/settings/television/cable_unix/k8s-services.toml +36 -0
- machineconfig/settings/television/cable_unix/man-pages.toml +24 -0
- machineconfig/settings/television/cable_unix/nu-history.toml +7 -0
- machineconfig/settings/television/cable_unix/procs.toml +20 -0
- machineconfig/settings/television/cable_unix/text.toml +17 -0
- machineconfig/settings/television/cable_unix/tldr.toml +18 -0
- machineconfig/settings/television/cable_unix/zsh-history.toml +9 -0
- machineconfig/settings/television/cable_windows/alias.toml +7 -0
- machineconfig/settings/television/cable_windows/dirs.toml +13 -0
- machineconfig/settings/television/cable_windows/docker-images.toml +13 -0
- machineconfig/settings/television/cable_windows/dotfiles.toml +11 -0
- machineconfig/settings/television/cable_windows/env.toml +17 -0
- machineconfig/settings/television/cable_windows/files.toml +14 -0
- machineconfig/settings/television/cable_windows/git-branch.toml +11 -0
- machineconfig/settings/television/cable_windows/git-diff.toml +10 -0
- machineconfig/settings/television/cable_windows/git-log.toml +11 -0
- machineconfig/settings/television/cable_windows/git-reflog.toml +11 -0
- machineconfig/settings/television/cable_windows/git-repos.toml +15 -0
- machineconfig/settings/television/cable_windows/nu-history.toml +7 -0
- machineconfig/settings/television/cable_windows/pwsh-history.toml +6 -0
- machineconfig/settings/television/cable_windows/text.toml +17 -0
- machineconfig/settings/yazi/init.lua +61 -0
- machineconfig/settings/yazi/keymap_linux.toml +94 -0
- machineconfig/settings/yazi/keymap_windows.toml +78 -0
- machineconfig/settings/yazi/shell/yazi_cd.ps1 +33 -0
- machineconfig/settings/yazi/shell/yazi_cd.sh +8 -0
- machineconfig/settings/yazi/theme.toml +4 -0
- machineconfig/settings/yazi/yazi_linux.toml +84 -0
- machineconfig/settings/yazi/yazi_windows.toml +58 -0
- machineconfig/setup_linux/__init__.py +11 -0
- machineconfig/setup_linux/apps_desktop.sh +89 -0
- machineconfig/setup_linux/apps_gui.sh +64 -0
- machineconfig/setup_linux/ssh/openssh_all.sh +25 -0
- machineconfig/setup_linux/ssh/openssh_wsl.sh +38 -0
- machineconfig/setup_linux/uv.sh +15 -0
- machineconfig/setup_linux/web_shortcuts/interactive.sh +26 -6
- machineconfig/setup_linux/web_shortcuts/live_from_github.sh +31 -0
- machineconfig/setup_mac/__init__.py +16 -0
- machineconfig/setup_mac/apps_gui.sh +248 -0
- machineconfig/setup_mac/ssh/openssh_setup.sh +114 -0
- machineconfig/setup_mac/uv.sh +36 -0
- machineconfig/setup_windows/__init__.py +11 -0
- machineconfig/setup_windows/others/power_options.ps1 +7 -0
- machineconfig/setup_windows/ssh/add-sshkey.ps1 +29 -0
- machineconfig/setup_windows/ssh/add_identity.ps1 +11 -0
- machineconfig/setup_windows/ssh/openssh-server.ps1 +37 -0
- machineconfig/setup_windows/uv.ps1 +17 -0
- machineconfig/setup_windows/web_shortcuts/interactive.ps1 +27 -10
- machineconfig/setup_windows/web_shortcuts/live_from_github.ps1 +30 -0
- machineconfig/setup_windows/web_shortcuts/quick_init.ps1 +17 -0
- machineconfig/utils/accessories.py +7 -5
- machineconfig/utils/cloud/onedrive/README.md +139 -0
- machineconfig/utils/code.py +155 -105
- machineconfig/utils/files/art/fat_croco.txt +10 -0
- machineconfig/utils/files/art/halfwit_croco.txt +9 -0
- machineconfig/utils/files/art/happy_croco.txt +22 -0
- machineconfig/utils/files/art/water_croco.txt +11 -0
- machineconfig/utils/files/ascii_art.py +1 -1
- machineconfig/utils/files/dbms.py +257 -0
- machineconfig/utils/files/headers.py +11 -14
- machineconfig/utils/files/ouch/__init__.py +0 -0
- machineconfig/utils/files/ouch/decompress.py +45 -0
- machineconfig/utils/files/read.py +10 -18
- machineconfig/utils/installer_utils/github_release_bulk.py +156 -119
- machineconfig/utils/installer_utils/install_from_url.py +183 -0
- machineconfig/utils/installer_utils/installer_class.py +64 -181
- machineconfig/utils/installer_utils/installer_cli.py +175 -0
- machineconfig/utils/installer_utils/installer_helper.py +129 -0
- machineconfig/utils/installer_utils/{installer_abc.py → installer_locator_utils.py} +66 -97
- machineconfig/utils/{installer.py → installer_utils/installer_runner.py} +49 -82
- machineconfig/utils/io.py +77 -23
- machineconfig/utils/links.py +254 -162
- machineconfig/utils/meta.py +256 -0
- machineconfig/utils/notifications.py +1 -1
- machineconfig/utils/options.py +46 -18
- machineconfig/utils/options_tv.py +119 -0
- machineconfig/utils/path_extended.py +48 -101
- machineconfig/utils/path_helper.py +76 -23
- machineconfig/utils/procs.py +50 -70
- machineconfig/utils/scheduler.py +88 -124
- machineconfig/utils/scheduling.py +0 -3
- machineconfig/utils/schemas/fire_agents/fire_agents_input.py +1 -1
- machineconfig/utils/schemas/layouts/layout_types.py +1 -1
- machineconfig/utils/source_of_truth.py +3 -6
- machineconfig/utils/ssh.py +263 -274
- machineconfig/utils/ssh_utils/abc.py +5 -0
- machineconfig/utils/ssh_utils/copy_from_here.py +111 -0
- machineconfig/utils/ssh_utils/copy_to_here.py +302 -0
- machineconfig/utils/ssh_utils/utils.py +142 -0
- machineconfig/utils/ssh_utils/wsl.py +210 -0
- machineconfig/utils/terminal.py +3 -113
- machineconfig/utils/tst.py +20 -0
- machineconfig/utils/upgrade_packages.py +114 -28
- machineconfig/utils/ve.py +12 -4
- machineconfig-7.98.dist-info/METADATA +132 -0
- machineconfig-7.98.dist-info/RECORD +504 -0
- machineconfig-7.98.dist-info/entry_points.txt +13 -0
- machineconfig/cluster/sessions_managers/ffile.py +0 -4
- machineconfig/jobs/installer/linux_scripts/pgsql.sh +0 -49
- machineconfig/jobs/installer/linux_scripts/timescaledb.sh +0 -85
- machineconfig/jobs/linux/msc/cli_agents.sh +0 -16
- machineconfig/jobs/python/python_ve_symlink.py +0 -37
- machineconfig/jobs/python/vscode/api.py +0 -57
- machineconfig/jobs/python/vscode/sync_code.py +0 -73
- machineconfig/jobs/windows/archive/archive_pygraphviz.ps1 +0 -14
- machineconfig/jobs/windows/start_terminal.ps1 +0 -6
- machineconfig/jobs/windows/startup_file.cmd +0 -2
- machineconfig/profile/create.py +0 -303
- machineconfig/profile/shell.py +0 -176
- machineconfig/scripts/cloud/init.sh +0 -119
- machineconfig/scripts/linux/agents +0 -2
- machineconfig/scripts/linux/choose_wezterm_theme +0 -3
- machineconfig/scripts/linux/cloud_copy +0 -2
- machineconfig/scripts/linux/cloud_mount +0 -2
- machineconfig/scripts/linux/cloud_repo_sync +0 -2
- machineconfig/scripts/linux/cloud_sync +0 -2
- machineconfig/scripts/linux/croshell +0 -3
- machineconfig/scripts/linux/devops +0 -2
- machineconfig/scripts/linux/fire +0 -2
- machineconfig/scripts/linux/ftpx +0 -2
- machineconfig/scripts/linux/fzf2g +0 -21
- machineconfig/scripts/linux/fzfag +0 -17
- machineconfig/scripts/linux/fzffg +0 -25
- machineconfig/scripts/linux/fzfrga +0 -21
- machineconfig/scripts/linux/gh_models +0 -2
- machineconfig/scripts/linux/initai +0 -2
- machineconfig/scripts/linux/kill_process +0 -2
- machineconfig/scripts/linux/scheduler +0 -2
- machineconfig/scripts/linux/sessions +0 -2
- machineconfig/scripts/linux/share_smb +0 -1
- machineconfig/scripts/linux/skrg +0 -4
- machineconfig/scripts/linux/start_slidev +0 -2
- machineconfig/scripts/linux/start_terminals +0 -3
- machineconfig/scripts/linux/warp-cli.sh +0 -122
- machineconfig/scripts/linux/wifi_conn +0 -2
- machineconfig/scripts/linux/z_ls +0 -104
- machineconfig/scripts/python/ai/generate_files.py +0 -83
- machineconfig/scripts/python/ai/solutions/copilot/prompts/allLintersAndTypeCheckers.prompt.md +0 -5
- machineconfig/scripts/python/cloud_repo_sync.py +0 -190
- machineconfig/scripts/python/count_lines_frontend.py +0 -16
- machineconfig/scripts/python/devops_add_ssh_key.py +0 -120
- machineconfig/scripts/python/dotfile.py +0 -78
- machineconfig/scripts/python/fire_agents_help_launch.py +0 -120
- machineconfig/scripts/python/fire_agents_helper_types.py +0 -12
- machineconfig/scripts/python/fire_jobs_route_helper.py +0 -65
- machineconfig/scripts/python/get_zellij_cmd.py +0 -15
- machineconfig/scripts/python/gh_models.py +0 -104
- machineconfig/scripts/python/helpers/repo_sync_helpers.py +0 -116
- machineconfig/scripts/python/repos.py +0 -132
- machineconfig/scripts/python/repos_helper_action.py +0 -378
- machineconfig/scripts/python/snapshot.py +0 -25
- machineconfig/scripts/python/start_terminals.py +0 -121
- machineconfig/scripts/python/t4.py +0 -17
- machineconfig/scripts/windows/agents.ps1 +0 -1
- machineconfig/scripts/windows/choose_wezterm_theme.ps1 +0 -1
- machineconfig/scripts/windows/cloud_copy.ps1 +0 -1
- machineconfig/scripts/windows/cloud_mount.ps1 +0 -1
- machineconfig/scripts/windows/cloud_repo_sync.ps1 +0 -1
- machineconfig/scripts/windows/cloud_sync.ps1 +0 -1
- machineconfig/scripts/windows/croshell.ps1 +0 -1
- machineconfig/scripts/windows/devops.ps1 +0 -1
- machineconfig/scripts/windows/dotfile.ps1 +0 -1
- machineconfig/scripts/windows/fire.ps1 +0 -1
- machineconfig/scripts/windows/ftpx.ps1 +0 -1
- machineconfig/scripts/windows/fzfb.ps1 +0 -3
- machineconfig/scripts/windows/fzfg.ps1 +0 -2
- machineconfig/scripts/windows/fzfrga.bat +0 -20
- machineconfig/scripts/windows/gpt.ps1 +0 -1
- machineconfig/scripts/windows/grep.ps1 +0 -2
- machineconfig/scripts/windows/initai.ps1 +0 -1
- machineconfig/scripts/windows/kill_process.ps1 +0 -1
- machineconfig/scripts/windows/nano.ps1 +0 -3
- machineconfig/scripts/windows/pomodoro.ps1 +0 -1
- machineconfig/scripts/windows/reload_path.ps1 +0 -3
- machineconfig/scripts/windows/scheduler.ps1 +0 -1
- machineconfig/scripts/windows/sessions.ps1 +0 -1
- machineconfig/scripts/windows/snapshot.ps1 +0 -1
- machineconfig/scripts/windows/start_slidev.ps1 +0 -1
- machineconfig/scripts/windows/start_terminals.ps1 +0 -1
- machineconfig/scripts/windows/wifi_conn.ps1 +0 -2
- machineconfig/scripts/windows/wsl_rdp_windows_port_forwarding.ps1 +0 -46
- machineconfig/scripts/windows/wsl_ssh_windows_port_forwarding.ps1 +0 -76
- machineconfig/settings/lf/linux/exe/fzf_nano.sh +0 -16
- machineconfig/settings/lf/windows/fzf_edit.ps1 +0 -6
- machineconfig/settings/lf/windows/tst.ps1 +0 -1
- machineconfig/settings/yazi/yazi.toml +0 -4
- machineconfig/setup_linux/nix/cli_installation.sh +0 -157
- machineconfig/setup_linux/others/openssh-server_add_pub_key.sh +0 -57
- machineconfig/setup_linux/web_shortcuts/croshell.sh +0 -11
- machineconfig/setup_linux/web_shortcuts/ssh.sh +0 -52
- machineconfig/setup_windows/web_shortcuts/all.ps1 +0 -18
- machineconfig/setup_windows/web_shortcuts/ascii_art.ps1 +0 -36
- machineconfig/setup_windows/web_shortcuts/croshell.ps1 +0 -16
- machineconfig/setup_windows/web_shortcuts/ssh.ps1 +0 -11
- machineconfig/utils/ai/generate_file_checklist.py +0 -68
- machineconfig/utils/installer_utils/installer.py +0 -189
- machineconfig-5.15.dist-info/METADATA +0 -188
- machineconfig-5.15.dist-info/RECORD +0 -415
- machineconfig-5.15.dist-info/entry_points.txt +0 -18
- machineconfig/cluster/sessions_managers/{utils → helpers}/load_balancer_helper.py +0 -0
- machineconfig/scripts/linux/{share_nfs → other/share_nfs} +0 -0
- machineconfig/scripts/linux/{start_docker → other/start_docker} +0 -0
- machineconfig/scripts/linux/{switch_ip → other/switch_ip} +0 -0
- machineconfig/{jobs/python → scripts/python/ai/utils}/__init__.py +0 -0
- machineconfig/scripts/python/{helpers → helpers_agents}/__init__.py +0 -0
- machineconfig/{jobs/windows/msc/cli_agents.bat → scripts/python/helpers_agents/agentic_frameworks/__init__.py} +0 -0
- machineconfig/scripts/python/{fire_agents_help_search.py → helpers_agents/fire_agents_help_search.py} +0 -0
- machineconfig/scripts/python/{fire_agents_load_balancer.py → helpers_agents/fire_agents_load_balancer.py} +0 -0
- machineconfig/{jobs/windows/msc/cli_agents.ps1 → scripts/python/helpers_cloud/__init__.py} +0 -0
- machineconfig/scripts/python/{helpers → helpers_cloud}/cloud_helpers.py +1 -1
- /machineconfig/scripts/python/{helpers → helpers_cloud}/helpers5.py +0 -0
- /machineconfig/scripts/python/{fire_jobs_streamlit_helper.py → helpers_croshell/__init__.py} +0 -0
- /machineconfig/scripts/python/{pomodoro.py → helpers_croshell/pomodoro.py} +0 -0
- /machineconfig/scripts/python/{scheduler.py → helpers_croshell/scheduler.py} +0 -0
- /machineconfig/scripts/python/{viewer.py → helpers_croshell/viewer.py} +0 -0
- /machineconfig/scripts/python/{viewer_template.py → helpers_croshell/viewer_template.py} +0 -0
- /machineconfig/scripts/{windows/share_nfs.ps1 → python/helpers_devops/__init__.py} +0 -0
- /machineconfig/{settings/shells/pwsh/profile.ps1 → scripts/python/helpers_devops/themes/__init__.py} +0 -0
- /machineconfig/{settings/yazi/keymap.toml → scripts/python/helpers_devops/themes/choose_starship_theme.ps1} +0 -0
- /machineconfig/scripts/python/{cloud_manager.py → helpers_fire_command/cloud_manager.py} +0 -0
- /machineconfig/scripts/{linux → python/helpers_network}/mount_drive +0 -0
- /machineconfig/scripts/python/{mount_nw_drive.py → helpers_network/mount_nw_drive.py} +0 -0
- /machineconfig/scripts/{linux → python/helpers_network}/mount_smb +0 -0
- /machineconfig/scripts/windows/{mount_nw.ps1 → mounts/mount_nw.ps1} +0 -0
- /machineconfig/scripts/windows/{mount_smb.ps1 → mounts/mount_smb.ps1} +0 -0
- /machineconfig/scripts/windows/{share_cloud.cmd → mounts/share_cloud.cmd} +0 -0
- /machineconfig/scripts/windows/{unlock_bitlocker.ps1 → mounts/unlock_bitlocker.ps1} +0 -0
- /machineconfig/setup_linux/{web_shortcuts → others}/android.sh +0 -0
- /machineconfig/{jobs/windows/archive → setup_windows/ssh}/openssh-server_add_key.ps1 +0 -0
- /machineconfig/{jobs/windows/archive → setup_windows/ssh}/openssh-server_copy-ssh-id.ps1 +0 -0
- {machineconfig-5.15.dist-info → machineconfig-7.98.dist-info}/WHEEL +0 -0
- {machineconfig-5.15.dist-info → machineconfig-7.98.dist-info}/top_level.txt +0 -0
machineconfig/utils/ssh.py
CHANGED
|
@@ -1,73 +1,40 @@
|
|
|
1
|
-
from typing import Optional, Any, Union,
|
|
1
|
+
from typing import Callable, Optional, Any, cast, Union, Literal
|
|
2
2
|
import os
|
|
3
|
-
from
|
|
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
|
|
6
|
-
from machineconfig.utils.
|
|
7
|
-
from machineconfig.utils.
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
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,
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
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(
|
|
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
|
-
|
|
85
|
-
if isinstance(
|
|
86
|
-
|
|
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
|
-
|
|
55
|
+
ssh_key_path = identity_file_value
|
|
89
56
|
self.proxycommand = config_dict.get("proxycommand", None)
|
|
90
|
-
if
|
|
91
|
-
|
|
92
|
-
if isinstance(
|
|
93
|
-
|
|
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
|
-
|
|
62
|
+
ssh_key_path = wildcard_identity_file
|
|
96
63
|
except (FileNotFoundError, KeyError):
|
|
97
|
-
assert "@" in host or ":" in 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.
|
|
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(
|
|
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
|
|
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(
|
|
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.
|
|
130
|
-
self.ssh.connect(
|
|
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(
|
|
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
|
-
|
|
162
|
-
self.
|
|
163
|
-
|
|
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
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
self.
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
def
|
|
195
|
-
self
|
|
196
|
-
|
|
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
|
-
|
|
199
|
-
self.run(code)
|
|
219
|
+
import urllib.request
|
|
200
220
|
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
return self.
|
|
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}" + (
|
|
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
|
-
|
|
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
|
|
217
|
-
print(f"""💻 [LOCAL EXECUTION] Running command on node: {self.
|
|
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
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
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
|
-
|
|
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
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
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
|
-
|
|
338
|
-
|
|
339
|
-
|
|
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
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
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)
|