machineconfig 1.94__py3-none-any.whl → 1.95__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/data_transfer.py +2 -1
- machineconfig/cluster/job_params.py +1 -1
- machineconfig/cluster/script_execution.py +1 -1
- machineconfig/jobs/__pycache__/__init__.cpython-311.pyc +0 -0
- machineconfig/jobs/linux/msc/lid.sh +2 -4
- machineconfig/jobs/linux/msc/network.sh +3 -6
- machineconfig/jobs/python/check_installations.py +6 -6
- machineconfig/jobs/python/checkout_version.py +4 -4
- machineconfig/jobs/python/python_cargo_build_share.py +2 -2
- machineconfig/jobs/python/python_ve_symlink.py +4 -4
- machineconfig/jobs/python/vscode/api.py +2 -2
- machineconfig/jobs/python/vscode/link_ve.py +4 -4
- machineconfig/jobs/python/vscode/select_interpreter.py +4 -4
- machineconfig/jobs/python/vscode/sync_code.py +6 -6
- machineconfig/jobs/python_custom_installers/archive/ngrok.py +4 -4
- machineconfig/jobs/python_custom_installers/dev/aider.py +4 -4
- machineconfig/jobs/python_custom_installers/dev/alacritty.py +4 -4
- machineconfig/jobs/python_custom_installers/dev/brave.py +4 -4
- machineconfig/jobs/python_custom_installers/dev/bypass_paywall.py +4 -4
- machineconfig/jobs/python_custom_installers/dev/code.py +4 -4
- machineconfig/jobs/python_custom_installers/dev/docker.py +4 -4
- machineconfig/jobs/python_custom_installers/dev/docker_desktop.py +4 -4
- machineconfig/jobs/python_custom_installers/dev/espanso.py +8 -8
- machineconfig/jobs/python_custom_installers/dev/goes.py +4 -4
- machineconfig/jobs/python_custom_installers/dev/lvim.py +4 -4
- machineconfig/jobs/python_custom_installers/dev/nerdfont.py +4 -4
- machineconfig/jobs/python_custom_installers/dev/redis.py +4 -4
- machineconfig/jobs/python_custom_installers/dev/warp-cli.py +4 -4
- machineconfig/jobs/python_custom_installers/dev/wezterm.py +4 -4
- machineconfig/jobs/python_custom_installers/gh.py +6 -6
- machineconfig/jobs/python_custom_installers/hx.py +28 -58
- machineconfig/jobs/python_custom_installers/scripts/linux/brave.sh +4 -8
- machineconfig/jobs/python_custom_installers/scripts/linux/docker.sh +5 -10
- machineconfig/jobs/python_custom_installers/scripts/linux/docker_start.sh +3 -6
- machineconfig/jobs/python_custom_installers/scripts/linux/edge.sh +3 -6
- machineconfig/jobs/python_custom_installers/scripts/linux/nerdfont.sh +5 -10
- machineconfig/jobs/python_custom_installers/scripts/linux/pgsql.sh +4 -8
- machineconfig/jobs/python_custom_installers/scripts/linux/redis.sh +5 -10
- machineconfig/jobs/python_custom_installers/scripts/linux/timescaledb.sh +6 -12
- machineconfig/jobs/python_custom_installers/scripts/linux/vscode.sh +9 -8
- machineconfig/jobs/python_custom_installers/scripts/linux/warp-cli.sh +5 -10
- machineconfig/jobs/python_custom_installers/scripts/linux/wezterm.sh +3 -6
- machineconfig/jobs/python_generic_installers/__pycache__/__init__.cpython-311.pyc +0 -0
- machineconfig/jobs/python_linux_installers/__pycache__/__init__.cpython-311.pyc +0 -0
- machineconfig/profile/shell.py +26 -47
- machineconfig/scripts/__pycache__/__init__.cpython-311.pyc +0 -0
- machineconfig/scripts/cloud/init.sh +9 -18
- machineconfig/scripts/linux/fire +5 -24
- machineconfig/scripts/linux/share_cloud.sh +6 -12
- machineconfig/scripts/python/__pycache__/__init__.cpython-311.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_repo_sync.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_devapps_install.cpython-311.pyc +0 -0
- machineconfig/scripts/python/__pycache__/devops_update_repos.cpython-311.pyc +0 -0
- machineconfig/scripts/python/__pycache__/fire_jobs.cpython-311.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 +30 -30
- machineconfig/scripts/python/archive/tmate_conn.py +10 -13
- machineconfig/scripts/python/archive/tmate_start.py +12 -16
- machineconfig/scripts/python/choose_wezterm_theme.py +9 -18
- machineconfig/scripts/python/cloud_copy.py +38 -93
- machineconfig/scripts/python/cloud_manager.py +61 -53
- machineconfig/scripts/python/cloud_mount.py +23 -34
- machineconfig/scripts/python/cloud_repo_sync.py +20 -69
- machineconfig/scripts/python/cloud_sync.py +35 -45
- machineconfig/scripts/python/croshell.py +48 -73
- machineconfig/scripts/python/devops.py +50 -104
- machineconfig/scripts/python/devops_add_identity.py +41 -101
- machineconfig/scripts/python/devops_add_ssh_key.py +33 -140
- machineconfig/scripts/python/devops_backup_retrieve.py +23 -112
- machineconfig/scripts/python/devops_devapps_install.py +0 -4
- machineconfig/scripts/python/devops_update_repos.py +1 -1
- machineconfig/scripts/python/fire_jobs.py +73 -25
- machineconfig/scripts/python/helpers/__pycache__/__init__.cpython-311.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__/repo_sync_helpers.cpython-311.pyc +0 -0
- machineconfig/scripts/python/helpers/cloud_helpers.py +37 -34
- machineconfig/scripts/python/helpers/helpers2.py +17 -31
- machineconfig/scripts/python/helpers/repo_sync_helpers.py +19 -54
- machineconfig/scripts/python/pomodoro.py +1 -1
- machineconfig/scripts/python/repos.py +49 -34
- machineconfig/scripts/python/wifi_conn.py +5 -3
- machineconfig/scripts/windows/fire.ps1 +27 -15
- machineconfig/settings/__pycache__/__init__.cpython-311.pyc +0 -0
- 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/setup_linux/nix/cli_installation.sh +9 -18
- machineconfig/setup_linux/others/openssh-server_add_pub_key.sh +3 -6
- machineconfig/setup_linux/web_shortcuts/all.sh +5 -10
- machineconfig/setup_linux/web_shortcuts/ascii_art.sh +7 -14
- machineconfig/setup_linux/web_shortcuts/croshell.sh +6 -12
- machineconfig/setup_linux/web_shortcuts/interactive.sh +34 -68
- machineconfig/setup_linux/web_shortcuts/ssh.sh +8 -16
- machineconfig/setup_linux/web_shortcuts/update_system.sh +7 -14
- machineconfig/setup_windows/wt_and_pwsh/set_wt_settings.py +16 -12
- machineconfig/utils/ai/browser_user_wrapper.py +60 -45
- machineconfig/utils/ai/generate_file_checklist.py +4 -7
- machineconfig/utils/ai/url2md.py +13 -5
- machineconfig/utils/{utils_code.py → code.py} +4 -10
- machineconfig/utils/installer.py +4 -10
- machineconfig/utils/{utils_links.py → links.py} +9 -20
- machineconfig/utils/{utils_options.py → options.py} +10 -20
- machineconfig/utils/{utils_path.py → path.py} +28 -80
- machineconfig/utils/procs.py +26 -30
- machineconfig/utils/scheduling.py +11 -11
- machineconfig/utils/utils.py +12 -19
- machineconfig/utils/ve.py +5 -21
- machineconfig/utils/ve_utils/ve2.py +15 -2
- {machineconfig-1.94.dist-info → machineconfig-1.95.dist-info}/METADATA +4 -2
- {machineconfig-1.94.dist-info → machineconfig-1.95.dist-info}/RECORD +120 -118
- {machineconfig-1.94.dist-info → machineconfig-1.95.dist-info}/WHEEL +1 -1
- {machineconfig-1.94.dist-info → machineconfig-1.95.dist-info}/top_level.txt +0 -0
|
@@ -6,19 +6,19 @@ from pathlib import Path
|
|
|
6
6
|
import random
|
|
7
7
|
import string
|
|
8
8
|
import os
|
|
9
|
+
from rich.console import Console
|
|
10
|
+
from rich.panel import Panel
|
|
9
11
|
|
|
10
12
|
|
|
11
13
|
def main():
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
""
|
|
17
|
-
|
|
18
|
-
print("🔐 Loading credentials...")
|
|
14
|
+
console = Console()
|
|
15
|
+
|
|
16
|
+
console.print(Panel("📡 Tmate Session Launcher", title="[bold blue]Welcome[/bold blue]", subtitle="Manage your tmate sessions effortlessly"))
|
|
17
|
+
|
|
18
|
+
console.print("[bold yellow]Loading credentials...[/bold yellow]")
|
|
19
19
|
creds = configparser.ConfigParser()
|
|
20
20
|
creds.read(Path.home().joinpath('dotfiles/creds/tmate/creds.ini'))
|
|
21
|
-
print("
|
|
21
|
+
console.print("[green]Credentials loaded[/green]")
|
|
22
22
|
|
|
23
23
|
parser = argparse.ArgumentParser(description='Tmate launcher')
|
|
24
24
|
random_sess = random.choices(list(string.digits + string.ascii_letters), k=20)
|
|
@@ -27,21 +27,17 @@ def main():
|
|
|
27
27
|
|
|
28
28
|
args = parser.parse_args()
|
|
29
29
|
|
|
30
|
-
print(f"🔍 Looking up session configuration: {args.sess_name}")
|
|
30
|
+
console.print(f"🔍 Looking up session configuration: {args.sess_name}")
|
|
31
31
|
sess_name = creds['sessions_names'][args.sess_name]
|
|
32
32
|
api_key = creds['keys']['api_key']
|
|
33
33
|
|
|
34
|
-
print(f"""
|
|
35
|
-
╭{'─' * 60}╮
|
|
36
|
-
│ 🚀 Starting tmate session: {sess_name}
|
|
37
|
-
╰{'─' * 60}╯
|
|
38
|
-
""")
|
|
34
|
+
console.print(Panel(f"🚀 Starting tmate session: {sess_name}", title="[bold green]Session Info[/bold green]"))
|
|
39
35
|
|
|
40
36
|
res = f"tmate -a ~/.ssh/authorized_keys -k {api_key} -n {sess_name} -F"
|
|
41
|
-
print("
|
|
37
|
+
console.print("[bold cyan]Running:[/bold cyan] tmate with configured API key and session name")
|
|
42
38
|
os.system(res)
|
|
43
39
|
|
|
44
|
-
print("
|
|
40
|
+
console.print("[green]Tmate session ended[/green]")
|
|
45
41
|
|
|
46
42
|
|
|
47
43
|
if __name__ == '__main__':
|
|
@@ -5,6 +5,11 @@ Choose a theme for Wezterm
|
|
|
5
5
|
from machineconfig.utils.utils import choose_one_option, P
|
|
6
6
|
from typing import Any
|
|
7
7
|
import time
|
|
8
|
+
from rich.panel import Panel
|
|
9
|
+
from rich.console import Console
|
|
10
|
+
import curses
|
|
11
|
+
|
|
12
|
+
console = Console()
|
|
8
13
|
|
|
9
14
|
|
|
10
15
|
schemes_list = [
|
|
@@ -38,11 +43,7 @@ schemes_list = [
|
|
|
38
43
|
|
|
39
44
|
|
|
40
45
|
def main2():
|
|
41
|
-
print(
|
|
42
|
-
╔{'═' * 60}╗
|
|
43
|
-
║ 🎨 WezTerm Theme Selector
|
|
44
|
-
╚{'═' * 60}╝
|
|
45
|
-
""")
|
|
46
|
+
console.print(Panel("🎨 WezTerm Theme Selector", title_align="left", border_style="green"))
|
|
46
47
|
option = choose_one_option(options=schemes_list, header="Choose a theme for Wezterm", fzf=True)
|
|
47
48
|
set_theme(option)
|
|
48
49
|
print(f"✅ Theme set to: {option}")
|
|
@@ -62,24 +63,14 @@ def set_theme(theme: str):
|
|
|
62
63
|
|
|
63
64
|
|
|
64
65
|
def main():
|
|
65
|
-
print(
|
|
66
|
-
|
|
67
|
-
║ 🎨 WezTerm Theme Selector - Interactive Mode
|
|
68
|
-
╚{'═' * 60}╝
|
|
69
|
-
|
|
66
|
+
console.print(Panel("🎨 WezTerm Theme Selector - Interactive Mode", title_align="left", border_style="blue"))
|
|
67
|
+
print("""
|
|
70
68
|
📝 Use arrow keys to navigate, Enter to select a theme
|
|
71
69
|
""")
|
|
72
|
-
import curses # not availble on windows: https://docs.python.org/3/howto/curses.html
|
|
73
|
-
# from curses import wrapper
|
|
74
70
|
curses.wrapper(accessory)
|
|
75
|
-
print(
|
|
76
|
-
╔{'═' * 60}╗
|
|
77
|
-
║ ✅ Theme selection completed
|
|
78
|
-
╚{'═' * 60}╝
|
|
79
|
-
""")
|
|
71
|
+
console.print(Panel("✅ Theme selection completed", title_align="left", border_style="green"))
|
|
80
72
|
|
|
81
73
|
def accessory(stdscr: Any):
|
|
82
|
-
import curses
|
|
83
74
|
options = schemes_list
|
|
84
75
|
current_option = 0
|
|
85
76
|
page_size = stdscr.getmaxyx()[0] - 1 # curses.LINES - 1 # Number of lines in the terminal, -1 for status line
|
|
@@ -6,31 +6,28 @@ from crocodile.file_management import P
|
|
|
6
6
|
from crocodile.core import Struct
|
|
7
7
|
from crocodile.meta import RepeatUntilNoException
|
|
8
8
|
import getpass
|
|
9
|
-
from machineconfig.scripts.python.helpers.cloud_helpers import Args
|
|
10
9
|
import argparse
|
|
11
10
|
import os
|
|
12
|
-
# from dataclasses import dataclass
|
|
13
|
-
# from pydantic import BaseModel
|
|
14
11
|
from typing import Optional
|
|
15
12
|
|
|
16
13
|
from machineconfig.scripts.python.helpers.helpers2 import parse_cloud_source_target
|
|
17
|
-
from machineconfig.scripts.python.helpers.cloud_helpers import ArgsDefaults
|
|
14
|
+
from machineconfig.scripts.python.helpers.cloud_helpers import ArgsDefaults, Args
|
|
15
|
+
from rich.console import Console
|
|
16
|
+
from rich.panel import Panel
|
|
17
|
+
from rich.progress import Progress
|
|
18
18
|
|
|
19
|
+
console = Console()
|
|
19
20
|
|
|
20
21
|
@RepeatUntilNoException(retry=3, sleep=1)
|
|
21
22
|
def get_securely_shared_file(url: Optional[str] = None, folder: Optional[str] = None) -> None:
|
|
22
|
-
print(
|
|
23
|
-
╔{'═' * 70}╗
|
|
24
|
-
║ 🚀 Secure File Downloader ║
|
|
25
|
-
╚{'═' * 70}╝
|
|
26
|
-
""")
|
|
23
|
+
console.print(Panel("🚀 Secure File Downloader", title="[bold blue]Downloader[/bold blue]", border_style="blue"))
|
|
27
24
|
|
|
28
25
|
folder_obj = P.cwd() if folder is None else P(folder)
|
|
29
26
|
print(f"📂 Target folder: {folder_obj}")
|
|
30
27
|
|
|
31
28
|
if os.environ.get("DECRYPTION_PASSWORD") is not None:
|
|
32
29
|
print("🔑 Using password from environment variables")
|
|
33
|
-
pwd
|
|
30
|
+
pwd = str(os.environ.get("DECRYPTION_PASSWORD"))
|
|
34
31
|
else:
|
|
35
32
|
pwd = getpass.getpass(prompt="🔑 Enter decryption password: ")
|
|
36
33
|
|
|
@@ -42,40 +39,28 @@ def get_securely_shared_file(url: Optional[str] = None, folder: Optional[str] =
|
|
|
42
39
|
else:
|
|
43
40
|
url = input("🔗 Enter share URL: ")
|
|
44
41
|
|
|
45
|
-
print(
|
|
46
|
-
╭{'─' * 70}╮
|
|
47
|
-
│ 📡 Downloading from URL... │
|
|
48
|
-
╰{'─' * 70}╯
|
|
49
|
-
""")
|
|
50
|
-
from rich.progress import Progress
|
|
42
|
+
console.print(Panel("📡 Downloading from URL...", title="[bold blue]Download[/bold blue]", border_style="blue"))
|
|
51
43
|
with Progress(transient=True) as progress:
|
|
52
44
|
_task = progress.add_task("Downloading... ", total=None)
|
|
53
45
|
url_obj = P(url).download(folder=folder_obj)
|
|
54
46
|
|
|
55
|
-
print(f"""
|
|
56
|
-
╭{'─' * 70}╮
|
|
57
|
-
│ 📥 Downloaded file: {url_obj}
|
|
58
|
-
╰{'─' * 70}╯
|
|
59
|
-
""")
|
|
47
|
+
console.print(Panel(f"📥 Downloaded file: {url_obj}", title="[bold green]Success[/bold green]", border_style="green"))
|
|
60
48
|
|
|
61
|
-
print(
|
|
62
|
-
╭{'─' * 70}╮
|
|
63
|
-
│ 🔐 Decrypting and extracting... │
|
|
64
|
-
╰{'─' * 70}╯
|
|
65
|
-
""")
|
|
49
|
+
console.print(Panel("🔐 Decrypting and extracting...", title="[bold blue]Processing[/bold blue]", border_style="blue"))
|
|
66
50
|
with Progress(transient=True) as progress:
|
|
67
51
|
_task = progress.add_task("Decrypting... ", total=None)
|
|
68
52
|
tmp_folder = P.tmpdir(prefix="tmp_unzip")
|
|
69
|
-
|
|
70
|
-
|
|
53
|
+
try:
|
|
54
|
+
res = url_obj.decrypt(pwd=pwd, inplace=True).unzip(inplace=True, folder=tmp_folder)
|
|
55
|
+
res.search("*").apply(lambda x: x.move(folder=folder_obj, overwrite=True))
|
|
56
|
+
finally:
|
|
57
|
+
# Clean up temporary folder
|
|
58
|
+
if tmp_folder.exists():
|
|
59
|
+
tmp_folder.delete()
|
|
71
60
|
|
|
72
61
|
|
|
73
62
|
def arg_parser() -> None:
|
|
74
|
-
print(
|
|
75
|
-
╔{'═' * 70}╗
|
|
76
|
-
║ ☁️ Cloud Copy Utility ║
|
|
77
|
-
╚{'═' * 70}╝
|
|
78
|
-
""")
|
|
63
|
+
console.print(Panel("☁️ Cloud Copy Utility", title="[bold blue]Cloud Copy[/bold blue]", border_style="blue", width=152))
|
|
79
64
|
|
|
80
65
|
parser = argparse.ArgumentParser(description='🚀 Cloud CLI. It wraps rclone with sane defaults for optimum type time.')
|
|
81
66
|
|
|
@@ -90,7 +75,7 @@ def arg_parser() -> None:
|
|
|
90
75
|
|
|
91
76
|
parser.add_argument("--key", "-k", help="🔑 Key for encryption", type=str, default=ArgsDefaults.key)
|
|
92
77
|
parser.add_argument("--pwd", "-p", help="🔒 Password for encryption", type=str, default=ArgsDefaults.pwd)
|
|
93
|
-
parser.add_argument("--encrypt", "-e", help="🔐
|
|
78
|
+
parser.add_argument("--encrypt", "-e", help="🔐 Encrypt before sending.", action="store_true", default=ArgsDefaults.encrypt)
|
|
94
79
|
parser.add_argument("--zip", "-z", help="📦 unzip after receiving.", action="store_true", default=ArgsDefaults.zip_)
|
|
95
80
|
parser.add_argument("--os_specific", "-o", help="💻 choose path specific for this OS.", action="store_true", default=ArgsDefaults.os_specific)
|
|
96
81
|
|
|
@@ -103,98 +88,58 @@ def arg_parser() -> None:
|
|
|
103
88
|
args_obj = Args(**args_dict)
|
|
104
89
|
|
|
105
90
|
if args_obj.config == "ss" and (source.startswith("http") or source.startswith("bit.ly")):
|
|
106
|
-
print(
|
|
107
|
-
╭{'─' * 70}╮
|
|
108
|
-
│ 🔒 Detected secure share link │
|
|
109
|
-
╰{'─' * 70}╯
|
|
110
|
-
""")
|
|
91
|
+
console.print(Panel("🔒 Detected secure share link", title="[bold yellow]Warning[/bold yellow]", border_style="yellow"))
|
|
111
92
|
if source.startswith("https://drive.google.com/open?id="):
|
|
112
|
-
|
|
113
|
-
|
|
93
|
+
file_id = source.split("https://drive.google.com/open?id=")[1]
|
|
94
|
+
if file_id: # Ensure we actually extracted an ID
|
|
95
|
+
source = f"https://drive.google.com/uc?export=download&id={file_id}"
|
|
96
|
+
print("🔄 Converting Google Drive link to direct download URL")
|
|
97
|
+
else:
|
|
98
|
+
console.print(Panel("❌ Invalid Google Drive link format", title="[bold red]Error[/bold red]", border_style="red"))
|
|
99
|
+
raise ValueError("Invalid Google Drive link format")
|
|
114
100
|
return get_securely_shared_file(url=source, folder=target)
|
|
115
101
|
|
|
116
102
|
if args_obj.rel2home is True and args_obj.root is None:
|
|
117
103
|
args_obj.root = "myhome"
|
|
118
104
|
print("🏠 Using 'myhome' as root directory")
|
|
119
105
|
|
|
120
|
-
print(
|
|
121
|
-
╭{'─' * 70}╮
|
|
122
|
-
│ 🔍 Parsing source and target paths... │
|
|
123
|
-
╰{'─' * 70}╯
|
|
124
|
-
""")
|
|
106
|
+
console.print(Panel("🔍 Parsing source and target paths...", title="[bold blue]Info[/bold blue]", border_style="blue"))
|
|
125
107
|
cloud, source, target = parse_cloud_source_target(args=args_obj, source=source, target=target)
|
|
126
108
|
|
|
127
|
-
print(
|
|
128
|
-
╭{'─' * 70}╮
|
|
129
|
-
│ ⚙️ Configuration: │
|
|
130
|
-
╰{'─' * 70}╯
|
|
131
|
-
""")
|
|
109
|
+
console.print(Panel("⚙️ Configuration:", title="[bold blue]Config[/bold blue]", border_style="blue"))
|
|
132
110
|
Struct(args_obj.__dict__).print(as_config=True, title="CLI config")
|
|
133
111
|
|
|
134
|
-
|
|
112
|
+
if args_obj.key is not None:
|
|
113
|
+
console.print(Panel("❌ Key-based encryption is not supported yet", title="[bold red]Error[/bold red]", border_style="red"))
|
|
114
|
+
raise ValueError("Key-based encryption is not supported yet.")
|
|
135
115
|
|
|
136
116
|
if cloud in source:
|
|
137
|
-
print(f"""
|
|
138
|
-
╔{'═' * 70}╗
|
|
139
|
-
║ 📥 DOWNLOADING FROM CLOUD ║
|
|
140
|
-
╠{'═' * 70}╣
|
|
141
|
-
║ ☁️ Cloud: {cloud}
|
|
142
|
-
║ 📂 Source: {source.replace(cloud + ":", "")}
|
|
143
|
-
║ 🎯 Target: {target}
|
|
144
|
-
╚{'═' * 70}╝
|
|
145
|
-
""")
|
|
117
|
+
console.print(Panel(f"📥 DOWNLOADING FROM CLOUD\n☁️ Cloud: {cloud}\n📂 Source: {source.replace(cloud + ':', '')}\n🎯 Target: {target}", title="[bold blue]Download[/bold blue]", border_style="blue", width=152))
|
|
146
118
|
|
|
147
119
|
P(target).from_cloud(cloud=cloud, remotepath=source.replace(cloud + ":", ""),
|
|
148
120
|
unzip=args_obj.zip, decrypt=args_obj.encrypt, pwd=args_obj.pwd,
|
|
149
121
|
overwrite=args_obj.overwrite,
|
|
150
122
|
rel2home=args_obj.rel2home, os_specific=args_obj.os_specific, root=args_obj.root, strict=False,
|
|
151
123
|
)
|
|
152
|
-
print(
|
|
153
|
-
╔{'═' * 70}╗
|
|
154
|
-
║ ✅ Download completed successfully ║
|
|
155
|
-
╚{'═' * 70}╝
|
|
156
|
-
""")
|
|
124
|
+
console.print(Panel("✅ Download completed successfully", title="[bold green]Success[/bold green]", border_style="green", width=152))
|
|
157
125
|
|
|
158
126
|
elif cloud in target:
|
|
159
|
-
print(f"""
|
|
160
|
-
╔{'═' * 70}╗
|
|
161
|
-
║ 📤 UPLOADING TO CLOUD ║
|
|
162
|
-
╠{'═' * 70}╣
|
|
163
|
-
║ ☁️ Cloud: {cloud}
|
|
164
|
-
║ 📂 Source: {source}
|
|
165
|
-
║ 🎯 Target: {target.replace(cloud + ":", "")}
|
|
166
|
-
╚{'═' * 70}╝
|
|
167
|
-
""")
|
|
127
|
+
console.print(Panel(f"📤 UPLOADING TO CLOUD\n☁️ Cloud: {cloud}\n📂 Source: {source}\n🎯 Target: {target.replace(cloud + ':', '')}", title="[bold blue]Upload[/bold blue]", border_style="blue", width=152))
|
|
168
128
|
|
|
169
129
|
res = P(source).to_cloud(cloud=cloud, remotepath=target.replace(cloud + ":", ""),
|
|
170
130
|
zip=args_obj.zip, encrypt=args_obj.encrypt, pwd=args_obj.pwd,
|
|
171
131
|
rel2home=args_obj.rel2home, root=args_obj.root, os_specific=args_obj.os_specific, strict=False,
|
|
172
132
|
share=args_obj.share)
|
|
173
|
-
print(
|
|
174
|
-
╔{'═' * 70}╗
|
|
175
|
-
║ ✅ Upload completed successfully ║
|
|
176
|
-
╚{'═' * 70}╝
|
|
177
|
-
""")
|
|
133
|
+
console.print(Panel("✅ Upload completed successfully", title="[bold green]Success[/bold green]", border_style="green", width=152))
|
|
178
134
|
|
|
179
135
|
if args_obj.share:
|
|
180
136
|
fname = f".share_url_{cloud}"
|
|
181
137
|
if P(source).is_dir(): share_url_path = P(source).joinpath(fname)
|
|
182
138
|
else: share_url_path = P(source).with_suffix(fname)
|
|
183
139
|
share_url_path.write_text(res.as_url_str())
|
|
184
|
-
print(f"""
|
|
185
|
-
╔{'═' * 70}╗
|
|
186
|
-
║ 🔗 SHARE URL GENERATED ║
|
|
187
|
-
╠{'═' * 70}╣
|
|
188
|
-
║ 📝 URL file: {share_url_path}
|
|
189
|
-
║ 🌍 {res.as_url_str()}
|
|
190
|
-
╚{'═' * 70}╝
|
|
191
|
-
""")
|
|
140
|
+
console.print(Panel(f"🔗 SHARE URL GENERATED\n📝 URL file: {share_url_path}\n🌍 {res.as_url_str()}", title="[bold blue]Share[/bold blue]", border_style="blue", width=152))
|
|
192
141
|
else:
|
|
193
|
-
print(f"""
|
|
194
|
-
╔{'═' * 70}╗
|
|
195
|
-
║ ❌ ERROR: Cloud '{cloud}' not found in source or target ║
|
|
196
|
-
╚{'═' * 70}╝
|
|
197
|
-
""")
|
|
142
|
+
console.print(Panel(f"❌ ERROR: Cloud '{cloud}' not found in source or target", title="[bold red]Error[/bold red]", border_style="red", width=152))
|
|
198
143
|
raise ValueError(f"Cloud `{cloud}` not found in source or target.")
|
|
199
144
|
|
|
200
145
|
|
|
@@ -1,17 +1,48 @@
|
|
|
1
1
|
"""Run cloud manager.
|
|
2
2
|
"""
|
|
3
3
|
|
|
4
|
-
from machineconfig.cluster.loader_runner import CloudManager
|
|
4
|
+
# from machineconfig.cluster.loader_runner import CloudManager
|
|
5
|
+
from crocodile.file_management import P # Add import for P
|
|
6
|
+
from rich.console import Console # Add import for Console
|
|
7
|
+
from rich.panel import Panel # Add import for Panel
|
|
5
8
|
import argparse
|
|
6
9
|
|
|
7
10
|
|
|
11
|
+
console = Console()
|
|
12
|
+
|
|
13
|
+
BOX_WIDTH = 150 # width for box drawing
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
def print_section_title(title: str):
|
|
17
|
+
"""Prints a section title formatted nicely with a border and padding."""
|
|
18
|
+
console = Console()
|
|
19
|
+
console.print(Panel(title, title_align="left", expand=False))
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
class CloudManager:
|
|
23
|
+
"""Manages cloud operations like syncing, comparing, and listing files."""
|
|
24
|
+
|
|
25
|
+
def compare_local_and_cloud(self, sub_path: P):
|
|
26
|
+
"""Compares local and cloud files and prints a summary."""
|
|
27
|
+
local_files, cloud_files = self._get_local_and_cloud_files(sub_path)
|
|
28
|
+
title1 = f"Comparing Local and Cloud: {sub_path.name}"
|
|
29
|
+
run_line = f"Local files: {len(local_files)}"
|
|
30
|
+
cloud_line = f"Cloud files: {len(cloud_files)}"
|
|
31
|
+
console = Console()
|
|
32
|
+
console.print(Panel(f"{title1}\n{run_line}\n{cloud_line}", title_align="left", expand=False))
|
|
33
|
+
|
|
34
|
+
def list_cloud_files(self, sub_path: P):
|
|
35
|
+
"""Lists files in the cloud directory."""
|
|
36
|
+
cloud_files = self._get_cloud_files(sub_path)
|
|
37
|
+
title = f"Cloud Files in {sub_path.name}: {len(cloud_files)}"
|
|
38
|
+
console = Console()
|
|
39
|
+
console.print(Panel(title, title_align="left", expand=False))
|
|
40
|
+
|
|
41
|
+
|
|
8
42
|
def main():
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
╚{'═' * 70}╝
|
|
13
|
-
""")
|
|
14
|
-
|
|
43
|
+
console = Console() # Add console initialization
|
|
44
|
+
console.print(Panel("☁️ Cloud Manager", title_align="left", expand=False))
|
|
45
|
+
|
|
15
46
|
parser = argparse.ArgumentParser()
|
|
16
47
|
parser.add_argument("-c", "--cloud", help="Rclone Config Name", action="store", type=str, default=None)
|
|
17
48
|
parser.add_argument("-s", "--serve", help="Start job server", action="store_true", default=False)
|
|
@@ -23,66 +54,43 @@ def main():
|
|
|
23
54
|
parser.add_argument("-j", "--num_jobs", help="Number of jobs the server will run in parallel.", action="store", type=int, default=1)
|
|
24
55
|
args = parser.parse_args()
|
|
25
56
|
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
╰{'─' * 70}╯
|
|
30
|
-
""")
|
|
31
|
-
|
|
57
|
+
init_line = f"🔧 Initializing Cloud Manager with {args.num_jobs} worker{'s' if args.num_jobs > 1 else ''}"
|
|
58
|
+
console.print(Panel(init_line, title_align="left", expand=False))
|
|
59
|
+
|
|
32
60
|
cm = CloudManager(max_jobs=args.num_jobs, cloud=args.cloud, reset_local=args.reset_local)
|
|
33
|
-
|
|
61
|
+
|
|
34
62
|
if args.release_lock:
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
│ 🔓 Releasing lock... │
|
|
38
|
-
╰{'─' * 70}╯
|
|
39
|
-
""")
|
|
63
|
+
line = "🔓 Releasing lock..."
|
|
64
|
+
console.print(Panel(line, title_align="left", expand=False))
|
|
40
65
|
cm.claim_lock()
|
|
41
66
|
cm.release_lock()
|
|
42
67
|
print("✅ Lock successfully released")
|
|
43
|
-
|
|
68
|
+
|
|
44
69
|
if args.queue_failed_jobs:
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
│ 🔄 Requeuing failed jobs... │
|
|
48
|
-
╰{'─' * 70}╯
|
|
49
|
-
""")
|
|
70
|
+
line = "🔄 Requeuing failed jobs..."
|
|
71
|
+
console.print(Panel(line, title_align="left", expand=False))
|
|
50
72
|
cm.clean_failed_jobs_mess()
|
|
51
73
|
print("✅ Failed jobs moved to queue")
|
|
52
|
-
|
|
74
|
+
|
|
53
75
|
if args.rerun_jobs:
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
│ 🔁 Rerunning jobs... │
|
|
57
|
-
╰{'─' * 70}╯
|
|
58
|
-
""")
|
|
76
|
+
line = "🔁 Rerunning jobs..."
|
|
77
|
+
console.print(Panel(line, title_align="left", expand=False))
|
|
59
78
|
cm.rerun_jobs()
|
|
60
79
|
print("✅ Jobs restarted successfully")
|
|
61
|
-
|
|
80
|
+
|
|
62
81
|
if args.monitor_cloud:
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
║ 👁️ STARTING CLOUD MONITOR ║
|
|
66
|
-
╚{'═' * 70}╝
|
|
67
|
-
""")
|
|
82
|
+
title = "👁️ STARTING CLOUD MONITOR"
|
|
83
|
+
console.print(Panel(title, title_align="left", expand=False))
|
|
68
84
|
cm.run_monitor()
|
|
69
|
-
|
|
85
|
+
|
|
70
86
|
if args.serve:
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
""")
|
|
79
|
-
cm.serve()
|
|
80
|
-
|
|
81
|
-
print(f"""
|
|
82
|
-
╔{'═' * 70}╗
|
|
83
|
-
║ ✅ Cloud Manager finished successfully ║
|
|
84
|
-
╚{'═' * 70}╝
|
|
85
|
-
""")
|
|
87
|
+
title1 = "🚀 STARTING JOB SERVER"
|
|
88
|
+
run_line = f"💻 Running {args.num_jobs} worker{'s' if args.num_jobs > 1 else ''}"
|
|
89
|
+
cloud_line = f"☁️ Cloud: {args.cloud if args.cloud else 'Default'}"
|
|
90
|
+
console.print(Panel(f"{title1}\n{run_line}\n{cloud_line}", title_align="left", expand=False))
|
|
91
|
+
|
|
92
|
+
title = "✅ Cloud Manager finished successfully"
|
|
93
|
+
console.print(Panel(title, title_align="left", expand=False))
|
|
86
94
|
import sys
|
|
87
95
|
sys.exit(0)
|
|
88
96
|
|
|
@@ -8,6 +8,10 @@ from crocodile.file_management import P, Read
|
|
|
8
8
|
import platform
|
|
9
9
|
import argparse
|
|
10
10
|
from typing import Optional
|
|
11
|
+
from rich.console import Console
|
|
12
|
+
from rich.panel import Panel
|
|
13
|
+
|
|
14
|
+
console = Console()
|
|
11
15
|
|
|
12
16
|
|
|
13
17
|
DEFAULT_MOUNT = "~/data/rclone"
|
|
@@ -42,11 +46,9 @@ mprocs "echo 'see {DEFAULT_MOUNT}/{cloud} for the mounted cloud'; rclone about {
|
|
|
42
46
|
|
|
43
47
|
|
|
44
48
|
def mount(cloud: Optional[str], network: Optional[str], destination: Optional[str]) -> None:
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
╚{'═' * 70}╝
|
|
49
|
-
""")
|
|
49
|
+
# draw header box dynamically
|
|
50
|
+
title = "☁️ Cloud Mount Utility"
|
|
51
|
+
console.print(Panel(title, title_align="left", border_style="blue"))
|
|
50
52
|
|
|
51
53
|
config = get_rclone_config()
|
|
52
54
|
if cloud is None:
|
|
@@ -61,11 +63,8 @@ def mount(cloud: Optional[str], network: Optional[str], destination: Optional[st
|
|
|
61
63
|
else:
|
|
62
64
|
mount_loc = P(destination)
|
|
63
65
|
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
│ 📂 Mount location: {mount_loc} │
|
|
67
|
-
╰{'─' * 70}╯
|
|
68
|
-
""")
|
|
66
|
+
mount_info = f"📂 Mount location: {mount_loc}"
|
|
67
|
+
console.print(Panel(mount_info, border_style="blue"))
|
|
69
68
|
|
|
70
69
|
if platform.system() == "Windows":
|
|
71
70
|
print("🪟 Creating mount directory on Windows...")
|
|
@@ -75,12 +74,9 @@ def mount(cloud: Optional[str], network: Optional[str], destination: Optional[st
|
|
|
75
74
|
try: mount_loc.create()
|
|
76
75
|
except (FileExistsError, OSError) as err:
|
|
77
76
|
# We need a umount command here.
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
│ {err}
|
|
82
|
-
╰{'─' * 70}╯
|
|
83
|
-
""")
|
|
77
|
+
warning_line = "⚠️ WARNING: Mount directory issue"
|
|
78
|
+
err_line = f"{err}"
|
|
79
|
+
console.print(Panel(f"{warning_line}\n{err_line}", title="Warning", border_style="yellow"))
|
|
84
80
|
pass
|
|
85
81
|
else: raise ValueError("unsupported platform")
|
|
86
82
|
|
|
@@ -90,12 +86,7 @@ def mount(cloud: Optional[str], network: Optional[str], destination: Optional[st
|
|
|
90
86
|
else: raise ValueError("network mount only supported on windows")
|
|
91
87
|
|
|
92
88
|
mount_cmd = f"rclone mount {cloud}: {mount_loc} --vfs-cache-mode full --file-perms=0777"
|
|
93
|
-
print(f"""
|
|
94
|
-
╭{'─' * 70}╮
|
|
95
|
-
│ 🚀 Preparing mount command: │
|
|
96
|
-
│ {mount_cmd}
|
|
97
|
-
╰{'─' * 70}╯
|
|
98
|
-
""")
|
|
89
|
+
console.print(Panel(f"🚀 Preparing mount command:\n{mount_cmd}", border_style="blue"))
|
|
99
90
|
|
|
100
91
|
# txt = get_mprocs_mount_txt(cloud, mount_cmd)
|
|
101
92
|
if platform.system() == "Windows":
|
|
@@ -126,6 +117,8 @@ sleep 0.1; zellij action resize decrease up
|
|
|
126
117
|
sleep 0.1; zellij action resize decrease up
|
|
127
118
|
sleep 0.1; zellij action resize decrease up
|
|
128
119
|
sleep 0.1; zellij action resize decrease up
|
|
120
|
+
sleep 0.1; zellij action resize decrease up
|
|
121
|
+
sleep 0.1; zellij action resize decrease up
|
|
129
122
|
zellij run --direction right --name about -- rclone about {cloud}:
|
|
130
123
|
zellij action move-focus up
|
|
131
124
|
# zellij action write-chars "cd $HOME/data/rclone/{cloud}; sleep 0.1; ls"
|
|
@@ -137,27 +130,23 @@ zellij action move-focus up
|
|
|
137
130
|
else: raise ValueError("unsupported platform")
|
|
138
131
|
# print(f"running command: \n{txt}")
|
|
139
132
|
PROGRAM_PATH.write_text(txt)
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
╚{'═' * 70}╝
|
|
145
|
-
""")
|
|
133
|
+
# draw success box dynamically
|
|
134
|
+
title1 = "✅ Cloud mount command prepared successfully"
|
|
135
|
+
title2 = "🔄 Running mount process..."
|
|
136
|
+
console.print(Panel(f"{title1}\n{title2}", title="Success", border_style="green"))
|
|
146
137
|
|
|
147
138
|
|
|
148
139
|
def main():
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
╚{'═' * 70}╝
|
|
153
|
-
""")
|
|
140
|
+
# draw main title box dynamically
|
|
141
|
+
main_title = "☁️ RCLONE CLOUD MOUNT"
|
|
142
|
+
console.print(Panel(main_title, title_align="left", border_style="blue"))
|
|
154
143
|
|
|
155
144
|
parser = argparse.ArgumentParser(description='mount cloud')
|
|
156
145
|
parser.add_argument('cloud', nargs='?', type=str, default=None, help='cloud to mount')
|
|
157
146
|
parser.add_argument('destination', nargs='?', type=str, default=None, help='destination to mount')
|
|
158
147
|
parser.add_argument('--network', type=str, default=None, help='mount network drive')
|
|
159
148
|
args = parser.parse_args()
|
|
160
|
-
mount(cloud=args.
|
|
149
|
+
mount(cloud=args.cloud, network=args.network, destination=args.destination)
|
|
161
150
|
|
|
162
151
|
|
|
163
152
|
if __name__ == '__main__':
|