machineconfig 1.95__py3-none-any.whl → 1.96__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of machineconfig might be problematic. Click here for more details.
- machineconfig/cluster/cloud_manager.py +445 -343
- machineconfig/cluster/data_transfer.py +63 -57
- machineconfig/cluster/distribute.py +284 -280
- machineconfig/cluster/file_manager.py +234 -237
- machineconfig/cluster/job_params.py +133 -133
- machineconfig/cluster/loader_runner.py +183 -149
- machineconfig/cluster/remote_machine.py +269 -252
- machineconfig/cluster/script_execution.py +215 -209
- machineconfig/cluster/script_notify_upon_completion.py +50 -43
- machineconfig/cluster/self_ssh.py +52 -54
- machineconfig/cluster/sessions_managers/__init__.py +0 -0
- machineconfig/cluster/sessions_managers/archive/__init__.py +0 -0
- machineconfig/{jobs/python → cluster/sessions_managers/archive}/create_zellij_template.py +5 -3
- machineconfig/cluster/sessions_managers/archive/session_managers.py +184 -0
- machineconfig/cluster/sessions_managers/demo_rich_zellij.py +0 -0
- machineconfig/cluster/sessions_managers/enhanced_command_runner.py +160 -0
- machineconfig/cluster/sessions_managers/wt_local.py +494 -0
- machineconfig/cluster/sessions_managers/wt_local_manager.py +577 -0
- machineconfig/cluster/sessions_managers/wt_remote.py +288 -0
- machineconfig/cluster/sessions_managers/wt_remote_manager.py +483 -0
- machineconfig/cluster/sessions_managers/wt_utils/layout_generator.py +196 -0
- machineconfig/cluster/sessions_managers/wt_utils/process_monitor.py +418 -0
- machineconfig/cluster/sessions_managers/wt_utils/remote_executor.py +175 -0
- machineconfig/cluster/sessions_managers/wt_utils/session_manager.py +300 -0
- machineconfig/cluster/sessions_managers/wt_utils/status_reporter.py +228 -0
- machineconfig/cluster/sessions_managers/zellij_local.py +418 -0
- machineconfig/cluster/sessions_managers/zellij_local_manager.py +533 -0
- machineconfig/cluster/sessions_managers/zellij_remote.py +229 -0
- machineconfig/cluster/sessions_managers/zellij_remote_manager.py +188 -0
- machineconfig/cluster/sessions_managers/zellij_utils/example_usage.py +64 -0
- machineconfig/cluster/sessions_managers/zellij_utils/layout_generator.py +126 -0
- machineconfig/cluster/sessions_managers/zellij_utils/process_monitor.py +334 -0
- machineconfig/cluster/sessions_managers/zellij_utils/remote_executor.py +68 -0
- machineconfig/cluster/sessions_managers/zellij_utils/session_manager.py +119 -0
- machineconfig/cluster/sessions_managers/zellij_utils/status_reporter.py +85 -0
- machineconfig/cluster/templates/cli_click.py +0 -1
- machineconfig/cluster/templates/cli_gooey.py +102 -104
- machineconfig/cluster/templates/run_cloud.py +51 -51
- machineconfig/cluster/templates/run_cluster.py +103 -59
- machineconfig/cluster/templates/run_remote.py +57 -58
- machineconfig/cluster/templates/utils.py +69 -36
- machineconfig/jobs/__pycache__/__init__.cpython-311.pyc +0 -0
- machineconfig/jobs/python/__pycache__/__init__.cpython-311.pyc +0 -0
- machineconfig/jobs/python/check_installations.py +258 -190
- machineconfig/jobs/python/create_bootable_media.py +7 -3
- machineconfig/jobs/python/python_cargo_build_share.py +50 -50
- machineconfig/jobs/python/python_ve_symlink.py +6 -6
- machineconfig/jobs/python/vscode/__pycache__/select_interpreter.cpython-311.pyc +0 -0
- machineconfig/jobs/python/vscode/api.py +1 -1
- machineconfig/jobs/python/vscode/link_ve.py +2 -2
- machineconfig/jobs/python/vscode/select_interpreter.py +9 -5
- machineconfig/jobs/python/vscode/sync_code.py +8 -5
- machineconfig/jobs/python_custom_installers/__pycache__/__init__.cpython-311.pyc +0 -0
- machineconfig/jobs/python_custom_installers/archive/ngrok.py +1 -1
- machineconfig/jobs/python_custom_installers/dev/alacritty.py +3 -2
- machineconfig/jobs/python_custom_installers/dev/brave.py +7 -3
- machineconfig/jobs/python_custom_installers/dev/bypass_paywall.py +3 -4
- machineconfig/jobs/python_custom_installers/dev/code.py +3 -1
- machineconfig/jobs/python_custom_installers/dev/cursor.py +66 -5
- machineconfig/jobs/python_custom_installers/dev/docker_desktop.py +0 -1
- machineconfig/jobs/python_custom_installers/dev/espanso.py +13 -9
- machineconfig/jobs/python_custom_installers/dev/goes.py +2 -8
- machineconfig/jobs/python_custom_installers/dev/lvim.py +3 -2
- machineconfig/jobs/python_custom_installers/dev/nerdfont.py +1 -1
- machineconfig/jobs/python_custom_installers/dev/redis.py +7 -3
- machineconfig/jobs/python_custom_installers/dev/wezterm.py +8 -4
- machineconfig/jobs/python_custom_installers/dev/winget.py +194 -0
- machineconfig/jobs/python_custom_installers/{dev/docker.py → docker.py} +8 -3
- machineconfig/jobs/python_custom_installers/gh.py +4 -3
- machineconfig/jobs/python_custom_installers/hx.py +9 -8
- machineconfig/jobs/python_custom_installers/scripts/linux/vscode.sh +97 -30
- machineconfig/jobs/python_custom_installers/{dev/warp-cli.py → warp-cli.py} +1 -1
- machineconfig/jobs/python_generic_installers/__pycache__/__init__.cpython-311.pyc +0 -0
- machineconfig/jobs/python_generic_installers/config.json +133 -9
- machineconfig/jobs/python_generic_installers/dev/config.json +208 -37
- machineconfig/jobs/python_generic_installers/update.py +3 -0
- machineconfig/jobs/python_linux_installers/__pycache__/__init__.cpython-311.pyc +0 -0
- machineconfig/jobs/python_linux_installers/config.json +42 -6
- machineconfig/jobs/python_linux_installers/dev/config.json +79 -11
- machineconfig/jobs/python_windows_installers/config.json +6 -0
- machineconfig/profile/__pycache__/__init__.cpython-311.pyc +0 -0
- machineconfig/profile/__pycache__/create.cpython-311.pyc +0 -0
- machineconfig/profile/__pycache__/shell.cpython-311.pyc +0 -0
- machineconfig/profile/create.py +5 -5
- machineconfig/profile/create_hardlinks.py +5 -5
- machineconfig/profile/shell.py +44 -17
- machineconfig/scripts/__pycache__/__init__.cpython-311.pyc +0 -0
- machineconfig/scripts/__pycache__/__init__.cpython-313.pyc +0 -0
- machineconfig/scripts/linux/fire_agents +27 -0
- machineconfig/scripts/linux/wifi_conn +24 -0
- machineconfig/scripts/python/__pycache__/__init__.cpython-311.pyc +0 -0
- machineconfig/scripts/python/__pycache__/__init__.cpython-313.pyc +0 -0
- machineconfig/scripts/python/__pycache__/cloud_copy.cpython-311.pyc +0 -0
- machineconfig/scripts/python/__pycache__/cloud_mount.cpython-311.pyc +0 -0
- machineconfig/scripts/python/__pycache__/cloud_sync.cpython-311.pyc +0 -0
- machineconfig/scripts/python/__pycache__/croshell.cpython-311.pyc +0 -0
- machineconfig/scripts/python/__pycache__/devops.cpython-311.pyc +0 -0
- machineconfig/scripts/python/__pycache__/devops_backup_retrieve.cpython-311.pyc +0 -0
- machineconfig/scripts/python/__pycache__/devops_devapps_install.cpython-311.pyc +0 -0
- machineconfig/scripts/python/__pycache__/devops_update_repos.cpython-311.pyc +0 -0
- machineconfig/scripts/python/__pycache__/fire_agents.cpython-311.pyc +0 -0
- machineconfig/scripts/python/__pycache__/fire_jobs.cpython-311.pyc +0 -0
- machineconfig/scripts/python/__pycache__/fire_jobs.cpython-313.pyc +0 -0
- machineconfig/scripts/python/__pycache__/get_zellij_cmd.cpython-311.pyc +0 -0
- machineconfig/scripts/python/__pycache__/repos.cpython-311.pyc +0 -0
- machineconfig/scripts/python/archive/im2text.py +1 -3
- machineconfig/scripts/python/choose_wezterm_theme.py +3 -3
- machineconfig/scripts/python/cloud_copy.py +10 -10
- machineconfig/scripts/python/cloud_manager.py +77 -99
- machineconfig/scripts/python/cloud_mount.py +13 -12
- machineconfig/scripts/python/cloud_repo_sync.py +14 -11
- machineconfig/scripts/python/croshell.py +24 -21
- machineconfig/scripts/python/devops.py +12 -17
- machineconfig/scripts/python/devops_add_identity.py +32 -10
- machineconfig/scripts/python/devops_add_ssh_key.py +10 -10
- machineconfig/scripts/python/devops_backup_retrieve.py +9 -8
- machineconfig/scripts/python/devops_devapps_install.py +6 -6
- machineconfig/scripts/python/devops_update_repos.py +4 -3
- machineconfig/scripts/python/dotfile.py +10 -7
- machineconfig/scripts/python/fire_agents.py +69 -0
- machineconfig/scripts/python/fire_jobs.py +56 -65
- machineconfig/scripts/python/ftpx.py +8 -8
- machineconfig/scripts/python/get_zellij_cmd.py +3 -3
- machineconfig/scripts/python/gh_models.py +6 -4
- machineconfig/scripts/python/helpers/__pycache__/__init__.cpython-311.pyc +0 -0
- machineconfig/scripts/python/helpers/__pycache__/__init__.cpython-313.pyc +0 -0
- machineconfig/scripts/python/helpers/__pycache__/cloud_helpers.cpython-311.pyc +0 -0
- machineconfig/scripts/python/helpers/__pycache__/helpers2.cpython-311.pyc +0 -0
- machineconfig/scripts/python/helpers/__pycache__/helpers4.cpython-311.pyc +0 -0
- machineconfig/scripts/python/helpers/__pycache__/helpers4.cpython-313.pyc +0 -0
- machineconfig/scripts/python/helpers/__pycache__/repo_sync_helpers.cpython-311.pyc +0 -0
- machineconfig/scripts/python/helpers/cloud_helpers.py +12 -12
- machineconfig/scripts/python/helpers/helpers2.py +9 -8
- machineconfig/scripts/python/helpers/helpers4.py +23 -35
- machineconfig/scripts/python/helpers/repo_sync_helpers.py +17 -16
- machineconfig/scripts/python/mount_nfs.py +8 -11
- machineconfig/scripts/python/mount_nw_drive.py +4 -4
- machineconfig/scripts/python/mount_ssh.py +2 -2
- machineconfig/scripts/python/onetimeshare.py +56 -57
- machineconfig/scripts/python/pomodoro.py +55 -55
- machineconfig/scripts/python/repos.py +26 -18
- machineconfig/scripts/python/scheduler.py +70 -53
- machineconfig/scripts/python/snapshot.py +21 -24
- machineconfig/scripts/python/start_slidev.py +6 -5
- machineconfig/scripts/python/start_terminals.py +3 -1
- machineconfig/scripts/python/viewer.py +5 -4
- machineconfig/scripts/python/viewer_template.py +138 -140
- machineconfig/scripts/python/wifi_conn.py +412 -60
- machineconfig/scripts/python/wsl_windows_transfer.py +18 -3
- machineconfig/settings/linters/.pylintrc +6 -7
- machineconfig/settings/lvim/windows/config.lua +0 -0
- machineconfig/settings/shells/bash/init.sh +6 -0
- machineconfig/settings/shells/ipy/profiles/default/startup/playext.py +7 -6
- machineconfig/settings/shells/pwsh/init.ps1 +6 -6
- machineconfig/settings/shells/wt/settings.json +51 -266
- machineconfig/setup_linux/web_shortcuts/interactive.sh +5 -2
- machineconfig/setup_windows/wt_and_pwsh/set_pwsh_theme.py +3 -6
- machineconfig/setup_windows/wt_and_pwsh/set_wt_settings.py +11 -9
- machineconfig/utils/ai/url2md.py +2 -2
- machineconfig/utils/cloud/onedrive/setup_oauth.py +59 -0
- machineconfig/utils/cloud/onedrive/transaction.py +796 -0
- machineconfig/utils/code.py +22 -13
- machineconfig/utils/installer.py +78 -35
- machineconfig/utils/installer_utils/installer_abc.py +7 -6
- machineconfig/utils/installer_utils/installer_class.py +44 -25
- machineconfig/utils/io_save.py +107 -0
- machineconfig/utils/links.py +19 -15
- machineconfig/utils/options.py +4 -8
- machineconfig/utils/path.py +91 -78
- machineconfig/utils/path_reduced.py +608 -0
- machineconfig/utils/procs.py +110 -45
- machineconfig/utils/scheduling.py +312 -222
- machineconfig/utils/utils.py +7 -7
- machineconfig/utils/utils2.py +42 -0
- machineconfig/utils/utils5.py +84 -0
- machineconfig/utils/ve.py +49 -87
- {machineconfig-1.95.dist-info → machineconfig-1.96.dist-info}/METADATA +2 -2
- machineconfig-1.96.dist-info/RECORD +437 -0
- machineconfig/cluster/session_managers.py +0 -183
- machineconfig/cluster/templates/f.py +0 -4
- machineconfig/jobs/python/__pycache__/check_installations.cpython-311.pyc +0 -0
- machineconfig/jobs/python/__pycache__/checkout_version.cpython-311.pyc +0 -0
- machineconfig/jobs/python/__pycache__/python_ve_symlink.cpython-311.pyc +0 -0
- machineconfig/jobs/python/checkout_version.py +0 -123
- machineconfig/jobs/python/vscode/__pycache__/api.cpython-311.pyc +0 -0
- machineconfig/jobs/python/vscode/__pycache__/link_ve.cpython-311.pyc +0 -0
- machineconfig/jobs/python_custom_installers/__pycache__/hx.cpython-311.pyc +0 -0
- machineconfig/jobs/python_windows_installers/__pycache__/__init__.cpython-311.pyc +0 -0
- machineconfig/scripts/python/.mypy_cache/.gitignore +0 -2
- machineconfig/scripts/python/.mypy_cache/3.11/@plugins_snapshot.json +0 -1
- machineconfig/scripts/python/.mypy_cache/3.11/__future__.data.json +0 -1
- machineconfig/scripts/python/.mypy_cache/3.11/__future__.meta.json +0 -1
- machineconfig/scripts/python/.mypy_cache/3.11/_ast.data.json +0 -1
- machineconfig/scripts/python/.mypy_cache/3.11/_ast.meta.json +0 -1
- machineconfig/scripts/python/.mypy_cache/3.11/_bz2.data.json +0 -1
- machineconfig/scripts/python/.mypy_cache/3.11/_bz2.meta.json +0 -1
- machineconfig/scripts/python/.mypy_cache/3.11/_codecs.data.json +0 -1
- machineconfig/scripts/python/.mypy_cache/3.11/_codecs.meta.json +0 -1
- machineconfig/scripts/python/.mypy_cache/3.11/_collections_abc.data.json +0 -1
- machineconfig/scripts/python/.mypy_cache/3.11/_collections_abc.meta.json +0 -1
- machineconfig/scripts/python/.mypy_cache/3.11/_compression.data.json +0 -1
- machineconfig/scripts/python/.mypy_cache/3.11/_compression.meta.json +0 -1
- machineconfig/scripts/python/.mypy_cache/3.11/_decimal.data.json +0 -1
- machineconfig/scripts/python/.mypy_cache/3.11/_decimal.meta.json +0 -1
- machineconfig/scripts/python/.mypy_cache/3.11/_frozen_importlib.data.json +0 -1
- machineconfig/scripts/python/.mypy_cache/3.11/_frozen_importlib.meta.json +0 -1
- machineconfig/scripts/python/.mypy_cache/3.11/_frozen_importlib_external.data.json +0 -1
- machineconfig/scripts/python/.mypy_cache/3.11/_frozen_importlib_external.meta.json +0 -1
- machineconfig/scripts/python/.mypy_cache/3.11/_io.data.json +0 -1
- machineconfig/scripts/python/.mypy_cache/3.11/_io.meta.json +0 -1
- machineconfig/scripts/python/.mypy_cache/3.11/_locale.data.json +0 -1
- machineconfig/scripts/python/.mypy_cache/3.11/_locale.meta.json +0 -1
- machineconfig/scripts/python/.mypy_cache/3.11/_stat.data.json +0 -1
- machineconfig/scripts/python/.mypy_cache/3.11/_stat.meta.json +0 -1
- machineconfig/scripts/python/.mypy_cache/3.11/_struct.data.json +0 -1
- machineconfig/scripts/python/.mypy_cache/3.11/_struct.meta.json +0 -1
- machineconfig/scripts/python/.mypy_cache/3.11/_thread.data.json +0 -1
- machineconfig/scripts/python/.mypy_cache/3.11/_thread.meta.json +0 -1
- machineconfig/scripts/python/.mypy_cache/3.11/_typeshed/__init__.data.json +0 -1
- machineconfig/scripts/python/.mypy_cache/3.11/_typeshed/__init__.meta.json +0 -1
- machineconfig/scripts/python/.mypy_cache/3.11/_typeshed/importlib.data.json +0 -1
- machineconfig/scripts/python/.mypy_cache/3.11/_typeshed/importlib.meta.json +0 -1
- machineconfig/scripts/python/.mypy_cache/3.11/_warnings.data.json +0 -1
- machineconfig/scripts/python/.mypy_cache/3.11/_warnings.meta.json +0 -1
- machineconfig/scripts/python/.mypy_cache/3.11/_weakref.data.json +0 -1
- machineconfig/scripts/python/.mypy_cache/3.11/_weakref.meta.json +0 -1
- machineconfig/scripts/python/.mypy_cache/3.11/_weakrefset.data.json +0 -1
- machineconfig/scripts/python/.mypy_cache/3.11/_weakrefset.meta.json +0 -1
- machineconfig/scripts/python/.mypy_cache/3.11/abc.data.json +0 -1
- machineconfig/scripts/python/.mypy_cache/3.11/abc.meta.json +0 -1
- machineconfig/scripts/python/.mypy_cache/3.11/argparse.data.json +0 -1
- machineconfig/scripts/python/.mypy_cache/3.11/argparse.meta.json +0 -1
- machineconfig/scripts/python/.mypy_cache/3.11/ast.data.json +0 -1
- machineconfig/scripts/python/.mypy_cache/3.11/ast.meta.json +0 -1
- machineconfig/scripts/python/.mypy_cache/3.11/binascii.data.json +0 -1
- machineconfig/scripts/python/.mypy_cache/3.11/binascii.meta.json +0 -1
- machineconfig/scripts/python/.mypy_cache/3.11/builtins.data.json +0 -1
- machineconfig/scripts/python/.mypy_cache/3.11/builtins.meta.json +0 -1
- machineconfig/scripts/python/.mypy_cache/3.11/bz2.data.json +0 -1
- machineconfig/scripts/python/.mypy_cache/3.11/bz2.meta.json +0 -1
- machineconfig/scripts/python/.mypy_cache/3.11/calendar.data.json +0 -1
- machineconfig/scripts/python/.mypy_cache/3.11/calendar.meta.json +0 -1
- machineconfig/scripts/python/.mypy_cache/3.11/codecs.data.json +0 -1
- machineconfig/scripts/python/.mypy_cache/3.11/codecs.meta.json +0 -1
- machineconfig/scripts/python/.mypy_cache/3.11/collections/__init__.data.json +0 -1
- machineconfig/scripts/python/.mypy_cache/3.11/collections/__init__.meta.json +0 -1
- machineconfig/scripts/python/.mypy_cache/3.11/collections/abc.data.json +0 -1
- machineconfig/scripts/python/.mypy_cache/3.11/collections/abc.meta.json +0 -1
- machineconfig/scripts/python/.mypy_cache/3.11/configparser.data.json +0 -1
- machineconfig/scripts/python/.mypy_cache/3.11/configparser.meta.json +0 -1
- machineconfig/scripts/python/.mypy_cache/3.11/contextlib.data.json +0 -1
- machineconfig/scripts/python/.mypy_cache/3.11/contextlib.meta.json +0 -1
- machineconfig/scripts/python/.mypy_cache/3.11/dataclasses.data.json +0 -1
- machineconfig/scripts/python/.mypy_cache/3.11/dataclasses.meta.json +0 -1
- machineconfig/scripts/python/.mypy_cache/3.11/datetime.data.json +0 -1
- machineconfig/scripts/python/.mypy_cache/3.11/datetime.meta.json +0 -1
- machineconfig/scripts/python/.mypy_cache/3.11/decimal.data.json +0 -1
- machineconfig/scripts/python/.mypy_cache/3.11/decimal.meta.json +0 -1
- machineconfig/scripts/python/.mypy_cache/3.11/dis.data.json +0 -1
- machineconfig/scripts/python/.mypy_cache/3.11/dis.meta.json +0 -1
- machineconfig/scripts/python/.mypy_cache/3.11/email/__init__.data.json +0 -1
- machineconfig/scripts/python/.mypy_cache/3.11/email/__init__.meta.json +0 -1
- machineconfig/scripts/python/.mypy_cache/3.11/email/_policybase.data.json +0 -1
- machineconfig/scripts/python/.mypy_cache/3.11/email/_policybase.meta.json +0 -1
- machineconfig/scripts/python/.mypy_cache/3.11/email/charset.data.json +0 -1
- machineconfig/scripts/python/.mypy_cache/3.11/email/charset.meta.json +0 -1
- machineconfig/scripts/python/.mypy_cache/3.11/email/contentmanager.data.json +0 -1
- machineconfig/scripts/python/.mypy_cache/3.11/email/contentmanager.meta.json +0 -1
- machineconfig/scripts/python/.mypy_cache/3.11/email/errors.data.json +0 -1
- machineconfig/scripts/python/.mypy_cache/3.11/email/errors.meta.json +0 -1
- machineconfig/scripts/python/.mypy_cache/3.11/email/header.data.json +0 -1
- machineconfig/scripts/python/.mypy_cache/3.11/email/header.meta.json +0 -1
- machineconfig/scripts/python/.mypy_cache/3.11/email/message.data.json +0 -1
- machineconfig/scripts/python/.mypy_cache/3.11/email/message.meta.json +0 -1
- machineconfig/scripts/python/.mypy_cache/3.11/email/policy.data.json +0 -1
- machineconfig/scripts/python/.mypy_cache/3.11/email/policy.meta.json +0 -1
- machineconfig/scripts/python/.mypy_cache/3.11/enum.data.json +0 -1
- machineconfig/scripts/python/.mypy_cache/3.11/enum.meta.json +0 -1
- machineconfig/scripts/python/.mypy_cache/3.11/fnmatch.data.json +0 -1
- machineconfig/scripts/python/.mypy_cache/3.11/fnmatch.meta.json +0 -1
- machineconfig/scripts/python/.mypy_cache/3.11/functools.data.json +0 -1
- machineconfig/scripts/python/.mypy_cache/3.11/functools.meta.json +0 -1
- machineconfig/scripts/python/.mypy_cache/3.11/gc.data.json +0 -1
- machineconfig/scripts/python/.mypy_cache/3.11/gc.meta.json +0 -1
- machineconfig/scripts/python/.mypy_cache/3.11/genericpath.data.json +0 -1
- machineconfig/scripts/python/.mypy_cache/3.11/genericpath.meta.json +0 -1
- machineconfig/scripts/python/.mypy_cache/3.11/getpass.data.json +0 -1
- machineconfig/scripts/python/.mypy_cache/3.11/getpass.meta.json +0 -1
- machineconfig/scripts/python/.mypy_cache/3.11/git/__init__.data.json +0 -1
- machineconfig/scripts/python/.mypy_cache/3.11/git/__init__.meta.json +0 -1
- machineconfig/scripts/python/.mypy_cache/3.11/git/cmd.data.json +0 -1
- machineconfig/scripts/python/.mypy_cache/3.11/git/cmd.meta.json +0 -1
- machineconfig/scripts/python/.mypy_cache/3.11/git/compat.data.json +0 -1
- machineconfig/scripts/python/.mypy_cache/3.11/git/compat.meta.json +0 -1
- machineconfig/scripts/python/.mypy_cache/3.11/git/config.data.json +0 -1
- machineconfig/scripts/python/.mypy_cache/3.11/git/config.meta.json +0 -1
- machineconfig/scripts/python/.mypy_cache/3.11/git/db.data.json +0 -1
- machineconfig/scripts/python/.mypy_cache/3.11/git/db.meta.json +0 -1
- machineconfig/scripts/python/.mypy_cache/3.11/git/diff.data.json +0 -1
- machineconfig/scripts/python/.mypy_cache/3.11/git/diff.meta.json +0 -1
- machineconfig/scripts/python/.mypy_cache/3.11/git/exc.data.json +0 -1
- machineconfig/scripts/python/.mypy_cache/3.11/git/exc.meta.json +0 -1
- machineconfig/scripts/python/.mypy_cache/3.11/git/index/__init__.data.json +0 -1
- machineconfig/scripts/python/.mypy_cache/3.11/git/index/__init__.meta.json +0 -1
- machineconfig/scripts/python/.mypy_cache/3.11/git/index/base.data.json +0 -1
- machineconfig/scripts/python/.mypy_cache/3.11/git/index/base.meta.json +0 -1
- machineconfig/scripts/python/.mypy_cache/3.11/git/index/fun.data.json +0 -1
- machineconfig/scripts/python/.mypy_cache/3.11/git/index/fun.meta.json +0 -1
- machineconfig/scripts/python/.mypy_cache/3.11/git/index/typ.data.json +0 -1
- machineconfig/scripts/python/.mypy_cache/3.11/git/index/typ.meta.json +0 -1
- machineconfig/scripts/python/.mypy_cache/3.11/git/index/util.data.json +0 -1
- machineconfig/scripts/python/.mypy_cache/3.11/git/index/util.meta.json +0 -1
- machineconfig/scripts/python/.mypy_cache/3.11/git/objects/__init__.data.json +0 -1
- machineconfig/scripts/python/.mypy_cache/3.11/git/objects/__init__.meta.json +0 -1
- machineconfig/scripts/python/.mypy_cache/3.11/git/objects/base.data.json +0 -1
- machineconfig/scripts/python/.mypy_cache/3.11/git/objects/base.meta.json +0 -1
- machineconfig/scripts/python/.mypy_cache/3.11/git/objects/blob.data.json +0 -1
- machineconfig/scripts/python/.mypy_cache/3.11/git/objects/blob.meta.json +0 -1
- machineconfig/scripts/python/.mypy_cache/3.11/git/objects/commit.data.json +0 -1
- machineconfig/scripts/python/.mypy_cache/3.11/git/objects/commit.meta.json +0 -1
- machineconfig/scripts/python/.mypy_cache/3.11/git/objects/fun.data.json +0 -1
- machineconfig/scripts/python/.mypy_cache/3.11/git/objects/fun.meta.json +0 -1
- machineconfig/scripts/python/.mypy_cache/3.11/git/objects/submodule/__init__.data.json +0 -1
- machineconfig/scripts/python/.mypy_cache/3.11/git/objects/submodule/__init__.meta.json +0 -1
- machineconfig/scripts/python/.mypy_cache/3.11/git/objects/submodule/base.data.json +0 -1
- machineconfig/scripts/python/.mypy_cache/3.11/git/objects/submodule/base.meta.json +0 -1
- machineconfig/scripts/python/.mypy_cache/3.11/git/objects/submodule/root.data.json +0 -1
- machineconfig/scripts/python/.mypy_cache/3.11/git/objects/submodule/root.meta.json +0 -1
- machineconfig/scripts/python/.mypy_cache/3.11/git/objects/submodule/util.data.json +0 -1
- machineconfig/scripts/python/.mypy_cache/3.11/git/objects/submodule/util.meta.json +0 -1
- machineconfig/scripts/python/.mypy_cache/3.11/git/objects/tag.data.json +0 -1
- machineconfig/scripts/python/.mypy_cache/3.11/git/objects/tag.meta.json +0 -1
- machineconfig/scripts/python/.mypy_cache/3.11/git/objects/tree.data.json +0 -1
- machineconfig/scripts/python/.mypy_cache/3.11/git/objects/tree.meta.json +0 -1
- machineconfig/scripts/python/.mypy_cache/3.11/git/objects/util.data.json +0 -1
- machineconfig/scripts/python/.mypy_cache/3.11/git/objects/util.meta.json +0 -1
- machineconfig/scripts/python/.mypy_cache/3.11/git/refs/__init__.data.json +0 -1
- machineconfig/scripts/python/.mypy_cache/3.11/git/refs/__init__.meta.json +0 -1
- machineconfig/scripts/python/.mypy_cache/3.11/git/refs/head.data.json +0 -1
- machineconfig/scripts/python/.mypy_cache/3.11/git/refs/head.meta.json +0 -1
- machineconfig/scripts/python/.mypy_cache/3.11/git/refs/log.data.json +0 -1
- machineconfig/scripts/python/.mypy_cache/3.11/git/refs/log.meta.json +0 -1
- machineconfig/scripts/python/.mypy_cache/3.11/git/refs/reference.data.json +0 -1
- machineconfig/scripts/python/.mypy_cache/3.11/git/refs/reference.meta.json +0 -1
- machineconfig/scripts/python/.mypy_cache/3.11/git/refs/remote.data.json +0 -1
- machineconfig/scripts/python/.mypy_cache/3.11/git/refs/remote.meta.json +0 -1
- machineconfig/scripts/python/.mypy_cache/3.11/git/refs/symbolic.data.json +0 -1
- machineconfig/scripts/python/.mypy_cache/3.11/git/refs/symbolic.meta.json +0 -1
- machineconfig/scripts/python/.mypy_cache/3.11/git/refs/tag.data.json +0 -1
- machineconfig/scripts/python/.mypy_cache/3.11/git/refs/tag.meta.json +0 -1
- machineconfig/scripts/python/.mypy_cache/3.11/git/remote.data.json +0 -1
- machineconfig/scripts/python/.mypy_cache/3.11/git/remote.meta.json +0 -1
- machineconfig/scripts/python/.mypy_cache/3.11/git/repo/__init__.data.json +0 -1
- machineconfig/scripts/python/.mypy_cache/3.11/git/repo/__init__.meta.json +0 -1
- machineconfig/scripts/python/.mypy_cache/3.11/git/repo/base.data.json +0 -1
- machineconfig/scripts/python/.mypy_cache/3.11/git/repo/base.meta.json +0 -1
- machineconfig/scripts/python/.mypy_cache/3.11/git/repo/fun.data.json +0 -1
- machineconfig/scripts/python/.mypy_cache/3.11/git/repo/fun.meta.json +0 -1
- machineconfig/scripts/python/.mypy_cache/3.11/git/types.data.json +0 -1
- machineconfig/scripts/python/.mypy_cache/3.11/git/types.meta.json +0 -1
- machineconfig/scripts/python/.mypy_cache/3.11/git/util.data.json +0 -1
- machineconfig/scripts/python/.mypy_cache/3.11/git/util.meta.json +0 -1
- machineconfig/scripts/python/.mypy_cache/3.11/glob.data.json +0 -1
- machineconfig/scripts/python/.mypy_cache/3.11/glob.meta.json +0 -1
- machineconfig/scripts/python/.mypy_cache/3.11/gzip.data.json +0 -1
- machineconfig/scripts/python/.mypy_cache/3.11/gzip.meta.json +0 -1
- machineconfig/scripts/python/.mypy_cache/3.11/importlib/__init__.data.json +0 -1
- machineconfig/scripts/python/.mypy_cache/3.11/importlib/__init__.meta.json +0 -1
- machineconfig/scripts/python/.mypy_cache/3.11/importlib/_abc.data.json +0 -1
- machineconfig/scripts/python/.mypy_cache/3.11/importlib/_abc.meta.json +0 -1
- machineconfig/scripts/python/.mypy_cache/3.11/importlib/_bootstrap.data.json +0 -1
- machineconfig/scripts/python/.mypy_cache/3.11/importlib/_bootstrap.meta.json +0 -1
- machineconfig/scripts/python/.mypy_cache/3.11/importlib/_bootstrap_external.data.json +0 -1
- machineconfig/scripts/python/.mypy_cache/3.11/importlib/_bootstrap_external.meta.json +0 -1
- machineconfig/scripts/python/.mypy_cache/3.11/importlib/abc.data.json +0 -1
- machineconfig/scripts/python/.mypy_cache/3.11/importlib/abc.meta.json +0 -1
- machineconfig/scripts/python/.mypy_cache/3.11/importlib/machinery.data.json +0 -1
- machineconfig/scripts/python/.mypy_cache/3.11/importlib/machinery.meta.json +0 -1
- machineconfig/scripts/python/.mypy_cache/3.11/importlib/metadata/__init__.data.json +0 -1
- machineconfig/scripts/python/.mypy_cache/3.11/importlib/metadata/__init__.meta.json +0 -1
- machineconfig/scripts/python/.mypy_cache/3.11/importlib/metadata/_meta.data.json +0 -1
- machineconfig/scripts/python/.mypy_cache/3.11/importlib/metadata/_meta.meta.json +0 -1
- machineconfig/scripts/python/.mypy_cache/3.11/importlib/readers.data.json +0 -1
- machineconfig/scripts/python/.mypy_cache/3.11/importlib/readers.meta.json +0 -1
- machineconfig/scripts/python/.mypy_cache/3.11/importlib/resources/__init__.data.json +0 -1
- machineconfig/scripts/python/.mypy_cache/3.11/importlib/resources/__init__.meta.json +0 -1
- machineconfig/scripts/python/.mypy_cache/3.11/importlib/resources/_common.data.json +0 -1
- machineconfig/scripts/python/.mypy_cache/3.11/importlib/resources/_common.meta.json +0 -1
- machineconfig/scripts/python/.mypy_cache/3.11/importlib/resources/abc.data.json +0 -1
- machineconfig/scripts/python/.mypy_cache/3.11/importlib/resources/abc.meta.json +0 -1
- machineconfig/scripts/python/.mypy_cache/3.11/inspect.data.json +0 -1
- machineconfig/scripts/python/.mypy_cache/3.11/inspect.meta.json +0 -1
- machineconfig/scripts/python/.mypy_cache/3.11/io.data.json +0 -1
- machineconfig/scripts/python/.mypy_cache/3.11/io.meta.json +0 -1
- machineconfig/scripts/python/.mypy_cache/3.11/itertools.data.json +0 -1
- machineconfig/scripts/python/.mypy_cache/3.11/itertools.meta.json +0 -1
- machineconfig/scripts/python/.mypy_cache/3.11/locale.data.json +0 -1
- machineconfig/scripts/python/.mypy_cache/3.11/locale.meta.json +0 -1
- machineconfig/scripts/python/.mypy_cache/3.11/logging/__init__.data.json +0 -1
- machineconfig/scripts/python/.mypy_cache/3.11/logging/__init__.meta.json +0 -1
- machineconfig/scripts/python/.mypy_cache/3.11/mimetypes.data.json +0 -1
- machineconfig/scripts/python/.mypy_cache/3.11/mimetypes.meta.json +0 -1
- machineconfig/scripts/python/.mypy_cache/3.11/mmap.data.json +0 -1
- machineconfig/scripts/python/.mypy_cache/3.11/mmap.meta.json +0 -1
- machineconfig/scripts/python/.mypy_cache/3.11/numbers.data.json +0 -1
- machineconfig/scripts/python/.mypy_cache/3.11/numbers.meta.json +0 -1
- machineconfig/scripts/python/.mypy_cache/3.11/opcode.data.json +0 -1
- machineconfig/scripts/python/.mypy_cache/3.11/opcode.meta.json +0 -1
- machineconfig/scripts/python/.mypy_cache/3.11/os/__init__.data.json +0 -1
- machineconfig/scripts/python/.mypy_cache/3.11/os/__init__.meta.json +0 -1
- machineconfig/scripts/python/.mypy_cache/3.11/os/path.data.json +0 -1
- machineconfig/scripts/python/.mypy_cache/3.11/os/path.meta.json +0 -1
- machineconfig/scripts/python/.mypy_cache/3.11/pathlib.data.json +0 -1
- machineconfig/scripts/python/.mypy_cache/3.11/pathlib.meta.json +0 -1
- machineconfig/scripts/python/.mypy_cache/3.11/platform.data.json +0 -1
- machineconfig/scripts/python/.mypy_cache/3.11/platform.meta.json +0 -1
- machineconfig/scripts/python/.mypy_cache/3.11/posixpath.data.json +0 -1
- machineconfig/scripts/python/.mypy_cache/3.11/posixpath.meta.json +0 -1
- machineconfig/scripts/python/.mypy_cache/3.11/re.data.json +0 -1
- machineconfig/scripts/python/.mypy_cache/3.11/re.meta.json +0 -1
- machineconfig/scripts/python/.mypy_cache/3.11/resource.data.json +0 -1
- machineconfig/scripts/python/.mypy_cache/3.11/resource.meta.json +0 -1
- machineconfig/scripts/python/.mypy_cache/3.11/shlex.data.json +0 -1
- machineconfig/scripts/python/.mypy_cache/3.11/shlex.meta.json +0 -1
- machineconfig/scripts/python/.mypy_cache/3.11/shutil.data.json +0 -1
- machineconfig/scripts/python/.mypy_cache/3.11/shutil.meta.json +0 -1
- machineconfig/scripts/python/.mypy_cache/3.11/signal.data.json +0 -1
- machineconfig/scripts/python/.mypy_cache/3.11/signal.meta.json +0 -1
- machineconfig/scripts/python/.mypy_cache/3.11/src/__init__.data.json +0 -1
- machineconfig/scripts/python/.mypy_cache/3.11/src/__init__.meta.json +0 -1
- machineconfig/scripts/python/.mypy_cache/3.11/src/machineconfig/__init__.data.json +0 -1
- machineconfig/scripts/python/.mypy_cache/3.11/src/machineconfig/__init__.meta.json +0 -1
- machineconfig/scripts/python/.mypy_cache/3.11/src/machineconfig/scripts/__init__.data.json +0 -1
- machineconfig/scripts/python/.mypy_cache/3.11/src/machineconfig/scripts/__init__.meta.json +0 -1
- machineconfig/scripts/python/.mypy_cache/3.11/src/machineconfig/scripts/python/__init__.data.json +0 -1
- machineconfig/scripts/python/.mypy_cache/3.11/src/machineconfig/scripts/python/__init__.meta.json +0 -1
- machineconfig/scripts/python/.mypy_cache/3.11/sre_compile.data.json +0 -1
- machineconfig/scripts/python/.mypy_cache/3.11/sre_compile.meta.json +0 -1
- machineconfig/scripts/python/.mypy_cache/3.11/sre_constants.data.json +0 -1
- machineconfig/scripts/python/.mypy_cache/3.11/sre_constants.meta.json +0 -1
- machineconfig/scripts/python/.mypy_cache/3.11/sre_parse.data.json +0 -1
- machineconfig/scripts/python/.mypy_cache/3.11/sre_parse.meta.json +0 -1
- machineconfig/scripts/python/.mypy_cache/3.11/stat.data.json +0 -1
- machineconfig/scripts/python/.mypy_cache/3.11/stat.meta.json +0 -1
- machineconfig/scripts/python/.mypy_cache/3.11/string.data.json +0 -1
- machineconfig/scripts/python/.mypy_cache/3.11/string.meta.json +0 -1
- machineconfig/scripts/python/.mypy_cache/3.11/struct.data.json +0 -1
- machineconfig/scripts/python/.mypy_cache/3.11/struct.meta.json +0 -1
- machineconfig/scripts/python/.mypy_cache/3.11/subprocess.data.json +0 -1
- machineconfig/scripts/python/.mypy_cache/3.11/subprocess.meta.json +0 -1
- machineconfig/scripts/python/.mypy_cache/3.11/sys/__init__.data.json +0 -1
- machineconfig/scripts/python/.mypy_cache/3.11/sys/__init__.meta.json +0 -1
- machineconfig/scripts/python/.mypy_cache/3.11/tarfile.data.json +0 -1
- machineconfig/scripts/python/.mypy_cache/3.11/tarfile.meta.json +0 -1
- machineconfig/scripts/python/.mypy_cache/3.11/tempfile.data.json +0 -1
- machineconfig/scripts/python/.mypy_cache/3.11/tempfile.meta.json +0 -1
- machineconfig/scripts/python/.mypy_cache/3.11/textwrap.data.json +0 -1
- machineconfig/scripts/python/.mypy_cache/3.11/textwrap.meta.json +0 -1
- machineconfig/scripts/python/.mypy_cache/3.11/threading.data.json +0 -1
- machineconfig/scripts/python/.mypy_cache/3.11/threading.meta.json +0 -1
- machineconfig/scripts/python/.mypy_cache/3.11/time.data.json +0 -1
- machineconfig/scripts/python/.mypy_cache/3.11/time.meta.json +0 -1
- machineconfig/scripts/python/.mypy_cache/3.11/types.data.json +0 -1
- machineconfig/scripts/python/.mypy_cache/3.11/types.meta.json +0 -1
- machineconfig/scripts/python/.mypy_cache/3.11/typing.data.json +0 -1
- machineconfig/scripts/python/.mypy_cache/3.11/typing.meta.json +0 -1
- machineconfig/scripts/python/.mypy_cache/3.11/typing_extensions.data.json +0 -1
- machineconfig/scripts/python/.mypy_cache/3.11/typing_extensions.meta.json +0 -1
- machineconfig/scripts/python/.mypy_cache/3.11/urllib/__init__.data.json +0 -1
- machineconfig/scripts/python/.mypy_cache/3.11/urllib/__init__.meta.json +0 -1
- machineconfig/scripts/python/.mypy_cache/3.11/urllib/parse.data.json +0 -1
- machineconfig/scripts/python/.mypy_cache/3.11/urllib/parse.meta.json +0 -1
- machineconfig/scripts/python/.mypy_cache/3.11/uuid.data.json +0 -1
- machineconfig/scripts/python/.mypy_cache/3.11/uuid.meta.json +0 -1
- machineconfig/scripts/python/.mypy_cache/3.11/warnings.data.json +0 -1
- machineconfig/scripts/python/.mypy_cache/3.11/warnings.meta.json +0 -1
- machineconfig/scripts/python/.mypy_cache/3.11/weakref.data.json +0 -1
- machineconfig/scripts/python/.mypy_cache/3.11/weakref.meta.json +0 -1
- machineconfig/scripts/python/.mypy_cache/3.11/zipfile/__init__.data.json +0 -1
- machineconfig/scripts/python/.mypy_cache/3.11/zipfile/__init__.meta.json +0 -1
- machineconfig/scripts/python/.mypy_cache/3.11/zlib.data.json +0 -1
- machineconfig/scripts/python/.mypy_cache/3.11/zlib.meta.json +0 -1
- machineconfig/scripts/python/.mypy_cache/CACHEDIR.TAG +0 -3
- machineconfig/scripts/python/__pycache__/cloud_repo_sync.cpython-311.pyc +0 -0
- machineconfig/scripts/python/__pycache__/gh_models.cpython-311.pyc +0 -0
- machineconfig/scripts/python/__pycache__/url2md.cpython-311.pyc +0 -0
- machineconfig/scripts/python/__pycache__/viewer.cpython-311.pyc +0 -0
- machineconfig/scripts/python/__pycache__/vscode_api.cpython-311.pyc +0 -0
- machineconfig/settings/__pycache__/__init__.cpython-311.pyc +0 -0
- machineconfig/settings/linters/.ruff_cache/.gitignore +0 -2
- machineconfig/settings/linters/.ruff_cache/CACHEDIR.TAG +0 -1
- machineconfig/settings/shells/ipy/profiles/default/__pycache__/__init__.cpython-311.pyc +0 -0
- machineconfig/settings/shells/ipy/profiles/default/startup/__pycache__/__init__.cpython-311.pyc +0 -0
- machineconfig/settings/shells/ipy/profiles/default/startup/__pycache__/playext.cpython-311.pyc +0 -0
- machineconfig/utils/ve_utils/ve1.py +0 -111
- machineconfig/utils/ve_utils/ve2.py +0 -155
- machineconfig-1.95.dist-info/RECORD +0 -712
- {machineconfig-1.95.dist-info → machineconfig-1.96.dist-info}/WHEEL +0 -0
- {machineconfig-1.95.dist-info → machineconfig-1.96.dist-info}/top_level.txt +0 -0
|
@@ -0,0 +1,483 @@
|
|
|
1
|
+
from datetime import datetime
|
|
2
|
+
import json
|
|
3
|
+
import uuid
|
|
4
|
+
import logging
|
|
5
|
+
from pathlib import Path
|
|
6
|
+
from typing import Optional, Any
|
|
7
|
+
from machineconfig.utils.utils5 import Scheduler
|
|
8
|
+
from machineconfig.cluster.sessions_managers.wt_local import run_command_in_wt_tab
|
|
9
|
+
from machineconfig.cluster.sessions_managers.wt_remote import WTRemoteLayoutGenerator
|
|
10
|
+
|
|
11
|
+
TMP_SERIALIZATION_DIR = Path.home().joinpath("tmp_results", "session_manager", "wt", "remote_manager")
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
class WTSessionManager:
|
|
15
|
+
def __init__(self, machine2wt_tabs: dict[str, dict[str, tuple[str, str]]], session_name_prefix: str = "WTJobMgr"):
|
|
16
|
+
self.session_name_prefix = session_name_prefix
|
|
17
|
+
self.machine2wt_tabs = machine2wt_tabs # Store the original config
|
|
18
|
+
self.managers: list[WTRemoteLayoutGenerator] = []
|
|
19
|
+
for machine, tab_config in machine2wt_tabs.items():
|
|
20
|
+
an_m = WTRemoteLayoutGenerator(remote_name=machine, session_name_prefix=self.session_name_prefix)
|
|
21
|
+
an_m.create_wt_layout(tab_config=tab_config)
|
|
22
|
+
self.managers.append(an_m)
|
|
23
|
+
|
|
24
|
+
def ssh_to_all_machines(self) -> str:
|
|
25
|
+
hostname2wt_session = {}
|
|
26
|
+
for an_m in self.managers:
|
|
27
|
+
hostname = an_m.remote_name
|
|
28
|
+
session_name = an_m.session_name
|
|
29
|
+
hostname2wt_session[hostname] = session_name
|
|
30
|
+
cmds = ""
|
|
31
|
+
for hostname, session_name in hostname2wt_session.items():
|
|
32
|
+
# ssh hpc-node024 -t "wt -w WTJobMgrd074muex"
|
|
33
|
+
ssh_cmd = f"ssh {hostname} -t 'wt -w {session_name}'"
|
|
34
|
+
a_cmd = run_command_in_wt_tab(command=ssh_cmd, tab_name=hostname, cwd=None)
|
|
35
|
+
cmds += a_cmd + "\n"
|
|
36
|
+
return cmds
|
|
37
|
+
|
|
38
|
+
def kill_all_sessions(self) -> None:
|
|
39
|
+
for an_m in self.managers:
|
|
40
|
+
WTRemoteLayoutGenerator.run_remote_command(
|
|
41
|
+
remote_name=an_m.remote_name,
|
|
42
|
+
command="powershell -Command \"Get-Process -Name 'WindowsTerminal' -ErrorAction SilentlyContinue | Stop-Process -Force\""
|
|
43
|
+
)
|
|
44
|
+
|
|
45
|
+
def run_monitoring_routine(self, wait_ms: int = 60000) -> None:
|
|
46
|
+
def routine(scheduler: Scheduler):
|
|
47
|
+
if scheduler.cycle % 2 == 0:
|
|
48
|
+
statuses = []
|
|
49
|
+
for _idx, an_m in enumerate(self.managers):
|
|
50
|
+
a_status = an_m.check_all_commands_status()
|
|
51
|
+
statuses.append(a_status)
|
|
52
|
+
keys = []
|
|
53
|
+
for item in statuses:
|
|
54
|
+
keys.extend(item.keys())
|
|
55
|
+
values = []
|
|
56
|
+
for item in statuses:
|
|
57
|
+
values.extend(item.values())
|
|
58
|
+
# Create list of dictionaries instead of DataFrame
|
|
59
|
+
status_data = []
|
|
60
|
+
for i, key in enumerate(keys):
|
|
61
|
+
if i < len(values):
|
|
62
|
+
status_data.append({"tabName": key, "status": values[i]})
|
|
63
|
+
|
|
64
|
+
# Check if all stopped
|
|
65
|
+
running_count = sum(1 for item in status_data if item.get("status", {}).get("running", False))
|
|
66
|
+
if running_count == 0: # they all stopped
|
|
67
|
+
scheduler.max_cycles = scheduler.cycle # stop the scheduler from calling this routine again
|
|
68
|
+
|
|
69
|
+
# Print status
|
|
70
|
+
for item in status_data:
|
|
71
|
+
print(f"Tab: {item['tabName']}, Status: {item['status']}")
|
|
72
|
+
else:
|
|
73
|
+
statuses = []
|
|
74
|
+
for _idx, an_m in enumerate(self.managers):
|
|
75
|
+
a_status = an_m.check_wt_session_status()
|
|
76
|
+
statuses.append(a_status)
|
|
77
|
+
|
|
78
|
+
# Print statuses
|
|
79
|
+
for i, status in enumerate(statuses):
|
|
80
|
+
print(f"Manager {i}: {status}")
|
|
81
|
+
sched = Scheduler(routine=routine, wait_ms=wait_ms)
|
|
82
|
+
sched.run()
|
|
83
|
+
|
|
84
|
+
def save(self, session_id: Optional[str] = None) -> str:
|
|
85
|
+
if session_id is None:
|
|
86
|
+
session_id = str(uuid.uuid4())[:8]
|
|
87
|
+
|
|
88
|
+
# Create session directory
|
|
89
|
+
session_dir = TMP_SERIALIZATION_DIR / session_id
|
|
90
|
+
session_dir.mkdir(parents=True, exist_ok=True)
|
|
91
|
+
|
|
92
|
+
# Save the machine2wt_tabs configuration
|
|
93
|
+
config_file = session_dir / "machine2wt_tabs.json"
|
|
94
|
+
with open(config_file, 'w', encoding='utf-8') as f:
|
|
95
|
+
json.dump(self.machine2wt_tabs, f, indent=2, ensure_ascii=False)
|
|
96
|
+
|
|
97
|
+
# Save session metadata
|
|
98
|
+
metadata = {
|
|
99
|
+
"session_name_prefix": self.session_name_prefix,
|
|
100
|
+
"created_at": str(datetime.now()),
|
|
101
|
+
"num_managers": len(self.managers),
|
|
102
|
+
"machines": list(self.machine2wt_tabs.keys()),
|
|
103
|
+
"manager_type": "WTSessionManager"
|
|
104
|
+
}
|
|
105
|
+
metadata_file = session_dir / "metadata.json"
|
|
106
|
+
with open(metadata_file, 'w', encoding='utf-8') as f:
|
|
107
|
+
json.dump(metadata, f, indent=2, ensure_ascii=False)
|
|
108
|
+
|
|
109
|
+
# Save each WTRemoteLayoutGenerator
|
|
110
|
+
managers_dir = session_dir / "managers"
|
|
111
|
+
managers_dir.mkdir(exist_ok=True)
|
|
112
|
+
|
|
113
|
+
for i, manager in enumerate(self.managers):
|
|
114
|
+
manager_file = managers_dir / f"manager_{i}_{manager.remote_name}.json"
|
|
115
|
+
manager.to_json(str(manager_file))
|
|
116
|
+
|
|
117
|
+
logging.info(f"✅ Saved WTSessionManager session to: {session_dir}")
|
|
118
|
+
return session_id
|
|
119
|
+
|
|
120
|
+
@classmethod
|
|
121
|
+
def load(cls, session_id: str) -> 'WTSessionManager':
|
|
122
|
+
session_dir = TMP_SERIALIZATION_DIR / session_id
|
|
123
|
+
|
|
124
|
+
if not session_dir.exists():
|
|
125
|
+
raise FileNotFoundError(f"Session directory not found: {session_dir}")
|
|
126
|
+
config_file = session_dir / "machine2wt_tabs.json"
|
|
127
|
+
if not config_file.exists():
|
|
128
|
+
raise FileNotFoundError(f"Configuration file not found: {config_file}")
|
|
129
|
+
with open(config_file, 'r', encoding='utf-8') as f:
|
|
130
|
+
machine2wt_tabs = json.load(f)
|
|
131
|
+
|
|
132
|
+
# Load metadata
|
|
133
|
+
metadata_file = session_dir / "metadata.json"
|
|
134
|
+
session_name_prefix = "WTJobMgr" # default fallback
|
|
135
|
+
if metadata_file.exists():
|
|
136
|
+
with open(metadata_file, 'r', encoding='utf-8') as f:
|
|
137
|
+
metadata = json.load(f)
|
|
138
|
+
session_name_prefix = metadata.get("session_name_prefix", "WTJobMgr")
|
|
139
|
+
# Create new instance (this will create new managers)
|
|
140
|
+
instance = cls(machine2wt_tabs=machine2wt_tabs, session_name_prefix=session_name_prefix)
|
|
141
|
+
# Load saved managers to restore their states
|
|
142
|
+
managers_dir = session_dir / "managers"
|
|
143
|
+
if managers_dir.exists():
|
|
144
|
+
# Clear the auto-created managers and load the saved ones
|
|
145
|
+
instance.managers = []
|
|
146
|
+
# Get all manager files and sort them
|
|
147
|
+
manager_files = sorted(managers_dir.glob("manager_*.json"))
|
|
148
|
+
for manager_file in manager_files:
|
|
149
|
+
try:
|
|
150
|
+
loaded_manager = WTRemoteLayoutGenerator.from_json(str(manager_file))
|
|
151
|
+
instance.managers.append(loaded_manager)
|
|
152
|
+
except Exception as e:
|
|
153
|
+
logging.warning(f"Failed to load manager from {manager_file}: {e}")
|
|
154
|
+
logging.info(f"✅ Loaded WTSessionManager session from: {session_dir}")
|
|
155
|
+
return instance
|
|
156
|
+
|
|
157
|
+
@staticmethod
|
|
158
|
+
def list_saved_sessions() -> list[str]:
|
|
159
|
+
if not TMP_SERIALIZATION_DIR.exists():
|
|
160
|
+
return []
|
|
161
|
+
|
|
162
|
+
sessions = []
|
|
163
|
+
for item in TMP_SERIALIZATION_DIR.iterdir():
|
|
164
|
+
if item.is_dir() and (item / "metadata.json").exists():
|
|
165
|
+
sessions.append(item.name)
|
|
166
|
+
|
|
167
|
+
return sorted(sessions)
|
|
168
|
+
|
|
169
|
+
@staticmethod
|
|
170
|
+
def delete_session(session_id: str) -> bool:
|
|
171
|
+
session_dir = TMP_SERIALIZATION_DIR / session_id
|
|
172
|
+
|
|
173
|
+
if not session_dir.exists():
|
|
174
|
+
logging.warning(f"Session directory not found: {session_dir}")
|
|
175
|
+
return False
|
|
176
|
+
|
|
177
|
+
try:
|
|
178
|
+
import shutil
|
|
179
|
+
shutil.rmtree(session_dir)
|
|
180
|
+
logging.info(f"✅ Deleted session: {session_id}")
|
|
181
|
+
return True
|
|
182
|
+
except Exception as e:
|
|
183
|
+
logging.error(f"Failed to delete session {session_id}: {e}")
|
|
184
|
+
return False
|
|
185
|
+
|
|
186
|
+
def start_all_sessions(self) -> dict[str, Any]:
|
|
187
|
+
"""Start all Windows Terminal sessions on their respective remote machines."""
|
|
188
|
+
results = {}
|
|
189
|
+
for manager in self.managers:
|
|
190
|
+
try:
|
|
191
|
+
session_name = manager.session_name
|
|
192
|
+
remote_name = manager.remote_name
|
|
193
|
+
|
|
194
|
+
# Start the Windows Terminal session on the remote machine
|
|
195
|
+
start_result = manager.start_wt_session()
|
|
196
|
+
|
|
197
|
+
results[f"{remote_name}:{session_name}"] = start_result
|
|
198
|
+
|
|
199
|
+
if start_result.get("success"):
|
|
200
|
+
logging.info(f"✅ Started session '{session_name}' on {remote_name}")
|
|
201
|
+
else:
|
|
202
|
+
logging.error(f"❌ Failed to start session '{session_name}' on {remote_name}: {start_result.get('error')}")
|
|
203
|
+
|
|
204
|
+
except Exception as e:
|
|
205
|
+
results[f"{manager.remote_name}:{manager.session_name}"] = {
|
|
206
|
+
"success": False,
|
|
207
|
+
"error": str(e)
|
|
208
|
+
}
|
|
209
|
+
logging.error(f"❌ Exception starting session on {manager.remote_name}: {e}")
|
|
210
|
+
|
|
211
|
+
return results
|
|
212
|
+
|
|
213
|
+
def check_all_sessions_status(self) -> dict[str, dict[str, Any]]:
|
|
214
|
+
"""Check the status of all remote sessions and their commands."""
|
|
215
|
+
status_report = {}
|
|
216
|
+
|
|
217
|
+
for manager in self.managers:
|
|
218
|
+
session_key = f"{manager.remote_name}:{manager.session_name}"
|
|
219
|
+
|
|
220
|
+
try:
|
|
221
|
+
# Get Windows Terminal session status
|
|
222
|
+
wt_status = manager.check_wt_session_status()
|
|
223
|
+
|
|
224
|
+
# Get commands status for this session
|
|
225
|
+
commands_status = manager.check_all_commands_status()
|
|
226
|
+
|
|
227
|
+
# Calculate summary for this session
|
|
228
|
+
running_count = sum(1 for status in commands_status.values() if status.get("running", False))
|
|
229
|
+
total_count = len(commands_status)
|
|
230
|
+
|
|
231
|
+
status_report[session_key] = {
|
|
232
|
+
"remote_name": manager.remote_name,
|
|
233
|
+
"session_name": manager.session_name,
|
|
234
|
+
"wt_status": wt_status,
|
|
235
|
+
"commands_status": commands_status,
|
|
236
|
+
"summary": {
|
|
237
|
+
"total_commands": total_count,
|
|
238
|
+
"running_commands": running_count,
|
|
239
|
+
"stopped_commands": total_count - running_count,
|
|
240
|
+
"session_healthy": wt_status.get("wt_running", False)
|
|
241
|
+
}
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
except Exception as e:
|
|
245
|
+
status_report[session_key] = {
|
|
246
|
+
"remote_name": manager.remote_name,
|
|
247
|
+
"session_name": manager.session_name,
|
|
248
|
+
"error": str(e),
|
|
249
|
+
"summary": {
|
|
250
|
+
"total_commands": 0,
|
|
251
|
+
"running_commands": 0,
|
|
252
|
+
"stopped_commands": 0,
|
|
253
|
+
"session_healthy": False
|
|
254
|
+
}
|
|
255
|
+
}
|
|
256
|
+
logging.error(f"Error checking status for {session_key}: {e}")
|
|
257
|
+
|
|
258
|
+
return status_report
|
|
259
|
+
|
|
260
|
+
def get_global_summary(self) -> dict[str, Any]:
|
|
261
|
+
"""Get a global summary across all remote sessions."""
|
|
262
|
+
all_status = self.check_all_sessions_status()
|
|
263
|
+
|
|
264
|
+
total_sessions = len(all_status)
|
|
265
|
+
healthy_sessions = sum(1 for status in all_status.values()
|
|
266
|
+
if status["summary"]["session_healthy"])
|
|
267
|
+
total_commands = sum(status["summary"]["total_commands"]
|
|
268
|
+
for status in all_status.values())
|
|
269
|
+
total_running = sum(status["summary"]["running_commands"]
|
|
270
|
+
for status in all_status.values())
|
|
271
|
+
|
|
272
|
+
return {
|
|
273
|
+
"total_sessions": total_sessions,
|
|
274
|
+
"healthy_sessions": healthy_sessions,
|
|
275
|
+
"unhealthy_sessions": total_sessions - healthy_sessions,
|
|
276
|
+
"total_commands": total_commands,
|
|
277
|
+
"running_commands": total_running,
|
|
278
|
+
"stopped_commands": total_commands - total_running,
|
|
279
|
+
"all_sessions_healthy": healthy_sessions == total_sessions,
|
|
280
|
+
"all_commands_running": total_running == total_commands,
|
|
281
|
+
"remote_machines": list(set(status["remote_name"] for status in all_status.values()))
|
|
282
|
+
}
|
|
283
|
+
|
|
284
|
+
def print_status_report(self) -> None:
|
|
285
|
+
"""Print a comprehensive status report for all remote sessions."""
|
|
286
|
+
all_status = self.check_all_sessions_status()
|
|
287
|
+
global_summary = self.get_global_summary()
|
|
288
|
+
|
|
289
|
+
print("=" * 80)
|
|
290
|
+
print("🖥️ WINDOWS TERMINAL REMOTE MANAGER STATUS REPORT")
|
|
291
|
+
print("=" * 80)
|
|
292
|
+
|
|
293
|
+
# Global summary
|
|
294
|
+
print("🌐 GLOBAL SUMMARY:")
|
|
295
|
+
print(f" Total sessions: {global_summary['total_sessions']}")
|
|
296
|
+
print(f" Healthy sessions: {global_summary['healthy_sessions']}")
|
|
297
|
+
print(f" Total commands: {global_summary['total_commands']}")
|
|
298
|
+
print(f" Running commands: {global_summary['running_commands']}")
|
|
299
|
+
print(f" Remote machines: {len(global_summary['remote_machines'])}")
|
|
300
|
+
print(f" All healthy: {'✅' if global_summary['all_sessions_healthy'] else '❌'}")
|
|
301
|
+
print()
|
|
302
|
+
|
|
303
|
+
# Per-session details
|
|
304
|
+
for _, status in all_status.items():
|
|
305
|
+
remote_name = status["remote_name"]
|
|
306
|
+
session_name = status["session_name"]
|
|
307
|
+
|
|
308
|
+
print(f"🖥️ REMOTE: {remote_name} | SESSION: {session_name}")
|
|
309
|
+
print("-" * 60)
|
|
310
|
+
|
|
311
|
+
if "error" in status:
|
|
312
|
+
print(f"❌ Error: {status['error']}")
|
|
313
|
+
print()
|
|
314
|
+
continue
|
|
315
|
+
|
|
316
|
+
wt_status = status["wt_status"]
|
|
317
|
+
commands_status = status["commands_status"]
|
|
318
|
+
summary = status["summary"]
|
|
319
|
+
|
|
320
|
+
# Windows Terminal session health
|
|
321
|
+
if wt_status.get("wt_running", False):
|
|
322
|
+
if wt_status.get("session_exists", False):
|
|
323
|
+
session_windows = wt_status.get("session_windows", [])
|
|
324
|
+
all_windows = wt_status.get("all_windows", [])
|
|
325
|
+
print(f"✅ Windows Terminal is running on {remote_name}")
|
|
326
|
+
print(f" Session windows: {len(session_windows)}")
|
|
327
|
+
print(f" Total WT windows: {len(all_windows)}")
|
|
328
|
+
else:
|
|
329
|
+
print(f"⚠️ Windows Terminal is running but no session windows found on {remote_name}")
|
|
330
|
+
else:
|
|
331
|
+
print(f"❌ Windows Terminal issue on {remote_name}: {wt_status.get('error', 'Unknown error')}")
|
|
332
|
+
|
|
333
|
+
# Commands in this session
|
|
334
|
+
print(f" Commands ({summary['running_commands']}/{summary['total_commands']} running):")
|
|
335
|
+
for tab_name, cmd_status in commands_status.items():
|
|
336
|
+
status_icon = "✅" if cmd_status.get("running", False) else "❌"
|
|
337
|
+
cmd_text = cmd_status.get("command", "Unknown")[:50]
|
|
338
|
+
if len(cmd_status.get("command", "")) > 50:
|
|
339
|
+
cmd_text += "..."
|
|
340
|
+
print(f" {status_icon} {tab_name}: {cmd_text}")
|
|
341
|
+
|
|
342
|
+
if cmd_status.get("processes"):
|
|
343
|
+
for proc in cmd_status["processes"][:2]: # Show first 2 processes
|
|
344
|
+
print(f" └─ PID {proc.get('pid', 'Unknown')}: {proc.get('name', 'Unknown')}")
|
|
345
|
+
print()
|
|
346
|
+
|
|
347
|
+
print("=" * 80)
|
|
348
|
+
|
|
349
|
+
def get_remote_overview(self) -> dict[str, Any]:
|
|
350
|
+
"""Get overview of all remote machines and their Windows Terminal status."""
|
|
351
|
+
overview = {}
|
|
352
|
+
|
|
353
|
+
for manager in self.managers:
|
|
354
|
+
try:
|
|
355
|
+
remote_name = manager.remote_name
|
|
356
|
+
|
|
357
|
+
# Get remote Windows info
|
|
358
|
+
windows_info = manager.get_remote_windows_info()
|
|
359
|
+
|
|
360
|
+
# Get Windows Terminal processes
|
|
361
|
+
wt_processes = manager.list_wt_processes()
|
|
362
|
+
|
|
363
|
+
# Get Windows Terminal version
|
|
364
|
+
wt_version = manager.get_wt_version()
|
|
365
|
+
|
|
366
|
+
overview[remote_name] = {
|
|
367
|
+
"windows_info": windows_info,
|
|
368
|
+
"wt_processes": wt_processes,
|
|
369
|
+
"wt_version": wt_version,
|
|
370
|
+
"session_name": manager.session_name,
|
|
371
|
+
"tab_count": len(manager.tab_config)
|
|
372
|
+
}
|
|
373
|
+
|
|
374
|
+
except Exception as e:
|
|
375
|
+
overview[manager.remote_name] = {
|
|
376
|
+
"error": str(e),
|
|
377
|
+
"session_name": manager.session_name
|
|
378
|
+
}
|
|
379
|
+
|
|
380
|
+
return overview
|
|
381
|
+
|
|
382
|
+
def print_remote_overview(self) -> None:
|
|
383
|
+
"""Print overview of all remote machines."""
|
|
384
|
+
overview = self.get_remote_overview()
|
|
385
|
+
|
|
386
|
+
print("=" * 80)
|
|
387
|
+
print("🌐 REMOTE MACHINES OVERVIEW")
|
|
388
|
+
print("=" * 80)
|
|
389
|
+
|
|
390
|
+
for remote_name, info in overview.items():
|
|
391
|
+
print(f"🖥️ REMOTE: {remote_name}")
|
|
392
|
+
print("-" * 40)
|
|
393
|
+
|
|
394
|
+
if "error" in info:
|
|
395
|
+
print(f"❌ Error: {info['error']}")
|
|
396
|
+
print()
|
|
397
|
+
continue
|
|
398
|
+
|
|
399
|
+
# Windows Terminal availability
|
|
400
|
+
windows_info = info.get("windows_info", {})
|
|
401
|
+
wt_available = windows_info.get("wt_available", False)
|
|
402
|
+
print(f"Windows Terminal: {'✅ Available' if wt_available else '❌ Not Available'}")
|
|
403
|
+
|
|
404
|
+
# Version info
|
|
405
|
+
wt_version = info.get("wt_version", {})
|
|
406
|
+
if wt_version.get("success"):
|
|
407
|
+
print(f"Version: {wt_version.get('version', 'Unknown')}")
|
|
408
|
+
|
|
409
|
+
# Current processes
|
|
410
|
+
wt_processes = info.get("wt_processes", {})
|
|
411
|
+
if wt_processes.get("success"):
|
|
412
|
+
processes_output = wt_processes.get("processes", "")
|
|
413
|
+
if processes_output.strip():
|
|
414
|
+
print(f"Active processes: Found")
|
|
415
|
+
else:
|
|
416
|
+
print(f"Active processes: None")
|
|
417
|
+
|
|
418
|
+
# Session info
|
|
419
|
+
session_name = info.get("session_name", "Unknown")
|
|
420
|
+
tab_count = info.get("tab_count", 0)
|
|
421
|
+
print(f"Managed session: {session_name} ({tab_count} tabs)")
|
|
422
|
+
|
|
423
|
+
print()
|
|
424
|
+
|
|
425
|
+
print("=" * 80)
|
|
426
|
+
|
|
427
|
+
|
|
428
|
+
if __name__ == "__main__":
|
|
429
|
+
# Example usage
|
|
430
|
+
sample_machines = {
|
|
431
|
+
"server1": {
|
|
432
|
+
"🤖Bot1": ("~/code/project", "python bot1.py"),
|
|
433
|
+
"📊Monitor": ("~", "Get-Process | Sort-Object CPU -Descending | Select-Object -First 10"),
|
|
434
|
+
},
|
|
435
|
+
"server2": {
|
|
436
|
+
"🤖Bot2": ("~/code/project", "python bot2.py"),
|
|
437
|
+
"📝Logs": ("C:/logs", "Get-Content app.log -Wait"),
|
|
438
|
+
}
|
|
439
|
+
}
|
|
440
|
+
|
|
441
|
+
try:
|
|
442
|
+
# Create the remote manager
|
|
443
|
+
manager = WTSessionManager(sample_machines, session_name_prefix="RemoteJobs")
|
|
444
|
+
print(f"✅ Remote manager created with {len(manager.managers)} remote sessions")
|
|
445
|
+
|
|
446
|
+
# Show SSH commands
|
|
447
|
+
print("\n📎 SSH commands to connect to all machines:")
|
|
448
|
+
ssh_commands = manager.ssh_to_all_machines()
|
|
449
|
+
print(ssh_commands)
|
|
450
|
+
|
|
451
|
+
# Show current status
|
|
452
|
+
print("\n🔍 Current status:")
|
|
453
|
+
manager.print_status_report()
|
|
454
|
+
|
|
455
|
+
# Show remote overview
|
|
456
|
+
print("\n🌐 Remote machines overview:")
|
|
457
|
+
manager.print_remote_overview()
|
|
458
|
+
|
|
459
|
+
# Demonstrate save/load
|
|
460
|
+
print("\n💾 Demonstrating save/load...")
|
|
461
|
+
session_id = manager.save()
|
|
462
|
+
print(f"✅ Saved session: {session_id}")
|
|
463
|
+
|
|
464
|
+
# List saved sessions
|
|
465
|
+
saved_sessions = WTSessionManager.list_saved_sessions()
|
|
466
|
+
print(f"📋 Saved sessions: {saved_sessions}")
|
|
467
|
+
|
|
468
|
+
# Load and verify
|
|
469
|
+
loaded_manager = WTSessionManager.load(session_id)
|
|
470
|
+
print(f"✅ Loaded session with {len(loaded_manager.managers)} remote sessions")
|
|
471
|
+
|
|
472
|
+
# Show how to start sessions
|
|
473
|
+
print("\n▶️ To start all sessions, run:")
|
|
474
|
+
print("manager.start_all_sessions()")
|
|
475
|
+
|
|
476
|
+
# Show how to start monitoring (commented out to prevent infinite loop in demo)
|
|
477
|
+
print("\n⏰ To start monitoring, run:")
|
|
478
|
+
print("manager.run_monitoring_routine(wait_ms=60000) # 60 seconds")
|
|
479
|
+
|
|
480
|
+
except Exception as e:
|
|
481
|
+
print(f"❌ Error: {e}")
|
|
482
|
+
import traceback
|
|
483
|
+
traceback.print_exc()
|
|
@@ -0,0 +1,196 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
"""
|
|
3
|
+
Windows Terminal layout generation utilities for creating wt command strings.
|
|
4
|
+
Based on Windows Terminal documentation: https://learn.microsoft.com/en-us/windows/terminal/command-line-arguments
|
|
5
|
+
"""
|
|
6
|
+
import shlex
|
|
7
|
+
import random
|
|
8
|
+
import string
|
|
9
|
+
from typing import Dict, List, Tuple
|
|
10
|
+
from pathlib import Path
|
|
11
|
+
import logging
|
|
12
|
+
|
|
13
|
+
logger = logging.getLogger(__name__)
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
class WTLayoutGenerator:
|
|
17
|
+
"""Handles generation of Windows Terminal command strings for multi-tab layouts."""
|
|
18
|
+
|
|
19
|
+
@staticmethod
|
|
20
|
+
def generate_random_suffix(length: int = 8) -> str:
|
|
21
|
+
"""Generate a random string suffix for unique window names."""
|
|
22
|
+
return ''.join(random.choices(string.ascii_lowercase + string.digits, k=length))
|
|
23
|
+
|
|
24
|
+
@staticmethod
|
|
25
|
+
def parse_command(command: str) -> Tuple[str, List[str]]:
|
|
26
|
+
"""Parse a command string into command and arguments."""
|
|
27
|
+
try:
|
|
28
|
+
parts = shlex.split(command)
|
|
29
|
+
if not parts:
|
|
30
|
+
raise ValueError("Empty command provided")
|
|
31
|
+
return parts[0], parts[1:] if len(parts) > 1 else []
|
|
32
|
+
except ValueError as e:
|
|
33
|
+
logger.error(f"Error parsing command '{command}': {e}")
|
|
34
|
+
parts = command.split()
|
|
35
|
+
return parts[0] if parts else "", parts[1:] if len(parts) > 1 else []
|
|
36
|
+
|
|
37
|
+
@staticmethod
|
|
38
|
+
def escape_for_wt(text: str) -> str:
|
|
39
|
+
"""Escape text for use in Windows Terminal commands."""
|
|
40
|
+
# Windows Terminal uses PowerShell-style escaping
|
|
41
|
+
# Escape special characters that might cause issues
|
|
42
|
+
text = text.replace('"', '""') # Escape quotes for PowerShell
|
|
43
|
+
if ' ' in text or ';' in text or '&' in text or '|' in text:
|
|
44
|
+
return f'"{text}"'
|
|
45
|
+
return text
|
|
46
|
+
|
|
47
|
+
@staticmethod
|
|
48
|
+
def create_tab_command(tab_name: str, cwd: str, command: str, is_first_tab: bool = False) -> str:
|
|
49
|
+
"""Create a Windows Terminal tab command string."""
|
|
50
|
+
cmd, args = WTLayoutGenerator.parse_command(command)
|
|
51
|
+
|
|
52
|
+
# Convert paths to Windows format if needed
|
|
53
|
+
if cwd.startswith('~/'):
|
|
54
|
+
cwd = cwd.replace('~/', f"{Path.home()}/")
|
|
55
|
+
elif cwd == '~':
|
|
56
|
+
cwd = str(Path.home())
|
|
57
|
+
|
|
58
|
+
# Build the wt command parts
|
|
59
|
+
tab_parts = []
|
|
60
|
+
|
|
61
|
+
if not is_first_tab:
|
|
62
|
+
tab_parts.append("new-tab")
|
|
63
|
+
|
|
64
|
+
# Add profile if specified (could be extended to support different shells)
|
|
65
|
+
# tab_parts.extend(["-p", "\"Command Prompt\""]) # or "PowerShell", "WSL", etc.
|
|
66
|
+
|
|
67
|
+
# Add starting directory
|
|
68
|
+
tab_parts.extend(["-d", WTLayoutGenerator.escape_for_wt(cwd)])
|
|
69
|
+
|
|
70
|
+
# Add tab title
|
|
71
|
+
tab_parts.extend(["--title", WTLayoutGenerator.escape_for_wt(tab_name)])
|
|
72
|
+
|
|
73
|
+
# Add the command to execute
|
|
74
|
+
full_command = command if not args else f"{cmd} {' '.join(args)}"
|
|
75
|
+
tab_parts.append(WTLayoutGenerator.escape_for_wt(full_command))
|
|
76
|
+
|
|
77
|
+
return " ".join(tab_parts)
|
|
78
|
+
|
|
79
|
+
@staticmethod
|
|
80
|
+
def validate_tab_config(tab_config: Dict[str, Tuple[str, str]]) -> None:
|
|
81
|
+
"""Validate tab configuration format and content."""
|
|
82
|
+
if not tab_config:
|
|
83
|
+
raise ValueError("Tab configuration cannot be empty")
|
|
84
|
+
for tab_name, (cwd, command) in tab_config.items():
|
|
85
|
+
if not tab_name.strip():
|
|
86
|
+
raise ValueError(f"Invalid tab name: {tab_name}")
|
|
87
|
+
if not command.strip():
|
|
88
|
+
raise ValueError(f"Invalid command for tab '{tab_name}': {command}")
|
|
89
|
+
if not cwd.strip():
|
|
90
|
+
raise ValueError(f"Invalid cwd for tab '{tab_name}': {cwd}")
|
|
91
|
+
|
|
92
|
+
def generate_wt_command(self, tab_config: Dict[str, Tuple[str, str]],
|
|
93
|
+
window_name: str | None = None,
|
|
94
|
+
maximized: bool = False,
|
|
95
|
+
focus: bool = True) -> str:
|
|
96
|
+
"""Generate complete Windows Terminal command string."""
|
|
97
|
+
self.validate_tab_config(tab_config)
|
|
98
|
+
|
|
99
|
+
# Start building the wt command
|
|
100
|
+
wt_parts = ["wt"]
|
|
101
|
+
|
|
102
|
+
# Add window options
|
|
103
|
+
if maximized:
|
|
104
|
+
wt_parts.append("--maximized")
|
|
105
|
+
|
|
106
|
+
if focus:
|
|
107
|
+
wt_parts.append("--focus")
|
|
108
|
+
|
|
109
|
+
if window_name:
|
|
110
|
+
wt_parts.extend(["-w", WTLayoutGenerator.escape_for_wt(window_name)])
|
|
111
|
+
|
|
112
|
+
# Add tabs
|
|
113
|
+
tab_commands = []
|
|
114
|
+
for i, (tab_name, (cwd, command)) in enumerate(tab_config.items()):
|
|
115
|
+
is_first = i == 0
|
|
116
|
+
tab_cmd = self.create_tab_command(tab_name, cwd, command, is_first)
|
|
117
|
+
tab_commands.append(tab_cmd)
|
|
118
|
+
|
|
119
|
+
# Join all parts with semicolons (Windows Terminal command separator)
|
|
120
|
+
if tab_commands:
|
|
121
|
+
if len(tab_commands) == 1:
|
|
122
|
+
# Single tab - just add to the main command
|
|
123
|
+
wt_parts.extend(tab_commands[0].split())
|
|
124
|
+
else:
|
|
125
|
+
# Multiple tabs - join with semicolons
|
|
126
|
+
wt_parts.append(tab_commands[0]) # First tab
|
|
127
|
+
for tab_cmd in tab_commands[1:]:
|
|
128
|
+
wt_parts.extend([";", tab_cmd])
|
|
129
|
+
|
|
130
|
+
return " ".join(wt_parts)
|
|
131
|
+
|
|
132
|
+
def create_wt_script(self, tab_config: Dict[str, Tuple[str, str]],
|
|
133
|
+
output_dir: Path, session_name: str,
|
|
134
|
+
window_name: str | None = None) -> str:
|
|
135
|
+
"""Create a Windows Terminal script file and return its absolute path."""
|
|
136
|
+
self.validate_tab_config(tab_config)
|
|
137
|
+
|
|
138
|
+
# Generate unique suffix for this script
|
|
139
|
+
random_suffix = self.generate_random_suffix()
|
|
140
|
+
wt_command = self.generate_wt_command(tab_config, window_name or session_name)
|
|
141
|
+
|
|
142
|
+
try:
|
|
143
|
+
# Create output directory if it doesn't exist
|
|
144
|
+
output_dir.mkdir(parents=True, exist_ok=True)
|
|
145
|
+
|
|
146
|
+
# Create both .bat and .ps1 versions for flexibility
|
|
147
|
+
bat_file = output_dir / f"wt_layout_{session_name}_{random_suffix}.bat"
|
|
148
|
+
ps1_file = output_dir / f"wt_layout_{session_name}_{random_suffix}.ps1"
|
|
149
|
+
|
|
150
|
+
# Create batch file
|
|
151
|
+
with open(bat_file, 'w', encoding='utf-8') as f:
|
|
152
|
+
f.write(f"@echo off\n")
|
|
153
|
+
f.write(f"REM Windows Terminal layout for {session_name}\n")
|
|
154
|
+
f.write(f"{wt_command}\n")
|
|
155
|
+
|
|
156
|
+
# Create PowerShell file (better for complex commands)
|
|
157
|
+
with open(ps1_file, 'w', encoding='utf-8') as f:
|
|
158
|
+
f.write(f"# Windows Terminal layout for {session_name}\n")
|
|
159
|
+
f.write(f"# Generated on {random_suffix}\n")
|
|
160
|
+
f.write(f"{wt_command}\n")
|
|
161
|
+
|
|
162
|
+
logger.info(f"Windows Terminal script files created: {bat_file.absolute()}")
|
|
163
|
+
return str(bat_file.absolute())
|
|
164
|
+
|
|
165
|
+
except OSError as e:
|
|
166
|
+
logger.error(f"Failed to create script file: {e}")
|
|
167
|
+
raise
|
|
168
|
+
|
|
169
|
+
def generate_split_pane_command(self, tab_config: Dict[str, Tuple[str, str]],
|
|
170
|
+
window_name: str | None = None) -> str:
|
|
171
|
+
"""Generate Windows Terminal command with split panes instead of separate tabs."""
|
|
172
|
+
self.validate_tab_config(tab_config)
|
|
173
|
+
|
|
174
|
+
wt_parts = ["wt"]
|
|
175
|
+
|
|
176
|
+
if window_name:
|
|
177
|
+
wt_parts.extend(["-w", WTLayoutGenerator.escape_for_wt(window_name)])
|
|
178
|
+
|
|
179
|
+
# First pane (main tab)
|
|
180
|
+
first_tab = list(tab_config.items())[0]
|
|
181
|
+
tab_name, (cwd, command) = first_tab
|
|
182
|
+
|
|
183
|
+
# Start with first tab
|
|
184
|
+
wt_parts.extend(["-d", WTLayoutGenerator.escape_for_wt(cwd)])
|
|
185
|
+
wt_parts.extend(["--title", WTLayoutGenerator.escape_for_wt(tab_name)])
|
|
186
|
+
wt_parts.append(WTLayoutGenerator.escape_for_wt(command))
|
|
187
|
+
|
|
188
|
+
# Add split panes for remaining tabs
|
|
189
|
+
for tab_name, (cwd, command) in list(tab_config.items())[1:]:
|
|
190
|
+
wt_parts.append(";")
|
|
191
|
+
wt_parts.append("split-pane")
|
|
192
|
+
wt_parts.extend(["-d", WTLayoutGenerator.escape_for_wt(cwd)])
|
|
193
|
+
wt_parts.extend(["--title", WTLayoutGenerator.escape_for_wt(tab_name)])
|
|
194
|
+
wt_parts.append(WTLayoutGenerator.escape_for_wt(command))
|
|
195
|
+
|
|
196
|
+
return " ".join(wt_parts)
|