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.

Files changed (120) hide show
  1. machineconfig/cluster/data_transfer.py +2 -1
  2. machineconfig/cluster/job_params.py +1 -1
  3. machineconfig/cluster/script_execution.py +1 -1
  4. machineconfig/jobs/__pycache__/__init__.cpython-311.pyc +0 -0
  5. machineconfig/jobs/linux/msc/lid.sh +2 -4
  6. machineconfig/jobs/linux/msc/network.sh +3 -6
  7. machineconfig/jobs/python/check_installations.py +6 -6
  8. machineconfig/jobs/python/checkout_version.py +4 -4
  9. machineconfig/jobs/python/python_cargo_build_share.py +2 -2
  10. machineconfig/jobs/python/python_ve_symlink.py +4 -4
  11. machineconfig/jobs/python/vscode/api.py +2 -2
  12. machineconfig/jobs/python/vscode/link_ve.py +4 -4
  13. machineconfig/jobs/python/vscode/select_interpreter.py +4 -4
  14. machineconfig/jobs/python/vscode/sync_code.py +6 -6
  15. machineconfig/jobs/python_custom_installers/archive/ngrok.py +4 -4
  16. machineconfig/jobs/python_custom_installers/dev/aider.py +4 -4
  17. machineconfig/jobs/python_custom_installers/dev/alacritty.py +4 -4
  18. machineconfig/jobs/python_custom_installers/dev/brave.py +4 -4
  19. machineconfig/jobs/python_custom_installers/dev/bypass_paywall.py +4 -4
  20. machineconfig/jobs/python_custom_installers/dev/code.py +4 -4
  21. machineconfig/jobs/python_custom_installers/dev/docker.py +4 -4
  22. machineconfig/jobs/python_custom_installers/dev/docker_desktop.py +4 -4
  23. machineconfig/jobs/python_custom_installers/dev/espanso.py +8 -8
  24. machineconfig/jobs/python_custom_installers/dev/goes.py +4 -4
  25. machineconfig/jobs/python_custom_installers/dev/lvim.py +4 -4
  26. machineconfig/jobs/python_custom_installers/dev/nerdfont.py +4 -4
  27. machineconfig/jobs/python_custom_installers/dev/redis.py +4 -4
  28. machineconfig/jobs/python_custom_installers/dev/warp-cli.py +4 -4
  29. machineconfig/jobs/python_custom_installers/dev/wezterm.py +4 -4
  30. machineconfig/jobs/python_custom_installers/gh.py +6 -6
  31. machineconfig/jobs/python_custom_installers/hx.py +28 -58
  32. machineconfig/jobs/python_custom_installers/scripts/linux/brave.sh +4 -8
  33. machineconfig/jobs/python_custom_installers/scripts/linux/docker.sh +5 -10
  34. machineconfig/jobs/python_custom_installers/scripts/linux/docker_start.sh +3 -6
  35. machineconfig/jobs/python_custom_installers/scripts/linux/edge.sh +3 -6
  36. machineconfig/jobs/python_custom_installers/scripts/linux/nerdfont.sh +5 -10
  37. machineconfig/jobs/python_custom_installers/scripts/linux/pgsql.sh +4 -8
  38. machineconfig/jobs/python_custom_installers/scripts/linux/redis.sh +5 -10
  39. machineconfig/jobs/python_custom_installers/scripts/linux/timescaledb.sh +6 -12
  40. machineconfig/jobs/python_custom_installers/scripts/linux/vscode.sh +9 -8
  41. machineconfig/jobs/python_custom_installers/scripts/linux/warp-cli.sh +5 -10
  42. machineconfig/jobs/python_custom_installers/scripts/linux/wezterm.sh +3 -6
  43. machineconfig/jobs/python_generic_installers/__pycache__/__init__.cpython-311.pyc +0 -0
  44. machineconfig/jobs/python_linux_installers/__pycache__/__init__.cpython-311.pyc +0 -0
  45. machineconfig/profile/shell.py +26 -47
  46. machineconfig/scripts/__pycache__/__init__.cpython-311.pyc +0 -0
  47. machineconfig/scripts/cloud/init.sh +9 -18
  48. machineconfig/scripts/linux/fire +5 -24
  49. machineconfig/scripts/linux/share_cloud.sh +6 -12
  50. machineconfig/scripts/python/__pycache__/__init__.cpython-311.pyc +0 -0
  51. machineconfig/scripts/python/__pycache__/cloud_copy.cpython-311.pyc +0 -0
  52. machineconfig/scripts/python/__pycache__/cloud_mount.cpython-311.pyc +0 -0
  53. machineconfig/scripts/python/__pycache__/cloud_repo_sync.cpython-311.pyc +0 -0
  54. machineconfig/scripts/python/__pycache__/cloud_sync.cpython-311.pyc +0 -0
  55. machineconfig/scripts/python/__pycache__/croshell.cpython-311.pyc +0 -0
  56. machineconfig/scripts/python/__pycache__/devops.cpython-311.pyc +0 -0
  57. machineconfig/scripts/python/__pycache__/devops_devapps_install.cpython-311.pyc +0 -0
  58. machineconfig/scripts/python/__pycache__/devops_update_repos.cpython-311.pyc +0 -0
  59. machineconfig/scripts/python/__pycache__/fire_jobs.cpython-311.pyc +0 -0
  60. machineconfig/scripts/python/__pycache__/get_zellij_cmd.cpython-311.pyc +0 -0
  61. machineconfig/scripts/python/__pycache__/repos.cpython-311.pyc +0 -0
  62. machineconfig/scripts/python/archive/im2text.py +30 -30
  63. machineconfig/scripts/python/archive/tmate_conn.py +10 -13
  64. machineconfig/scripts/python/archive/tmate_start.py +12 -16
  65. machineconfig/scripts/python/choose_wezterm_theme.py +9 -18
  66. machineconfig/scripts/python/cloud_copy.py +38 -93
  67. machineconfig/scripts/python/cloud_manager.py +61 -53
  68. machineconfig/scripts/python/cloud_mount.py +23 -34
  69. machineconfig/scripts/python/cloud_repo_sync.py +20 -69
  70. machineconfig/scripts/python/cloud_sync.py +35 -45
  71. machineconfig/scripts/python/croshell.py +48 -73
  72. machineconfig/scripts/python/devops.py +50 -104
  73. machineconfig/scripts/python/devops_add_identity.py +41 -101
  74. machineconfig/scripts/python/devops_add_ssh_key.py +33 -140
  75. machineconfig/scripts/python/devops_backup_retrieve.py +23 -112
  76. machineconfig/scripts/python/devops_devapps_install.py +0 -4
  77. machineconfig/scripts/python/devops_update_repos.py +1 -1
  78. machineconfig/scripts/python/fire_jobs.py +73 -25
  79. machineconfig/scripts/python/helpers/__pycache__/__init__.cpython-311.pyc +0 -0
  80. machineconfig/scripts/python/helpers/__pycache__/cloud_helpers.cpython-311.pyc +0 -0
  81. machineconfig/scripts/python/helpers/__pycache__/helpers2.cpython-311.pyc +0 -0
  82. machineconfig/scripts/python/helpers/__pycache__/helpers4.cpython-311.pyc +0 -0
  83. machineconfig/scripts/python/helpers/__pycache__/repo_sync_helpers.cpython-311.pyc +0 -0
  84. machineconfig/scripts/python/helpers/cloud_helpers.py +37 -34
  85. machineconfig/scripts/python/helpers/helpers2.py +17 -31
  86. machineconfig/scripts/python/helpers/repo_sync_helpers.py +19 -54
  87. machineconfig/scripts/python/pomodoro.py +1 -1
  88. machineconfig/scripts/python/repos.py +49 -34
  89. machineconfig/scripts/python/wifi_conn.py +5 -3
  90. machineconfig/scripts/windows/fire.ps1 +27 -15
  91. machineconfig/settings/__pycache__/__init__.cpython-311.pyc +0 -0
  92. machineconfig/settings/shells/ipy/profiles/default/__pycache__/__init__.cpython-311.pyc +0 -0
  93. machineconfig/settings/shells/ipy/profiles/default/startup/__pycache__/__init__.cpython-311.pyc +0 -0
  94. machineconfig/settings/shells/ipy/profiles/default/startup/__pycache__/playext.cpython-311.pyc +0 -0
  95. machineconfig/setup_linux/nix/cli_installation.sh +9 -18
  96. machineconfig/setup_linux/others/openssh-server_add_pub_key.sh +3 -6
  97. machineconfig/setup_linux/web_shortcuts/all.sh +5 -10
  98. machineconfig/setup_linux/web_shortcuts/ascii_art.sh +7 -14
  99. machineconfig/setup_linux/web_shortcuts/croshell.sh +6 -12
  100. machineconfig/setup_linux/web_shortcuts/interactive.sh +34 -68
  101. machineconfig/setup_linux/web_shortcuts/ssh.sh +8 -16
  102. machineconfig/setup_linux/web_shortcuts/update_system.sh +7 -14
  103. machineconfig/setup_windows/wt_and_pwsh/set_wt_settings.py +16 -12
  104. machineconfig/utils/ai/browser_user_wrapper.py +60 -45
  105. machineconfig/utils/ai/generate_file_checklist.py +4 -7
  106. machineconfig/utils/ai/url2md.py +13 -5
  107. machineconfig/utils/{utils_code.py → code.py} +4 -10
  108. machineconfig/utils/installer.py +4 -10
  109. machineconfig/utils/{utils_links.py → links.py} +9 -20
  110. machineconfig/utils/{utils_options.py → options.py} +10 -20
  111. machineconfig/utils/{utils_path.py → path.py} +28 -80
  112. machineconfig/utils/procs.py +26 -30
  113. machineconfig/utils/scheduling.py +11 -11
  114. machineconfig/utils/utils.py +12 -19
  115. machineconfig/utils/ve.py +5 -21
  116. machineconfig/utils/ve_utils/ve2.py +15 -2
  117. {machineconfig-1.94.dist-info → machineconfig-1.95.dist-info}/METADATA +4 -2
  118. {machineconfig-1.94.dist-info → machineconfig-1.95.dist-info}/RECORD +120 -118
  119. {machineconfig-1.94.dist-info → machineconfig-1.95.dist-info}/WHEEL +1 -1
  120. {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
- print(f"""
13
- ╔{'═' * 60}╗
14
- 📡 Tmate Session Launcher
15
- ╚{'═' * 60}╝
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("Credentials loaded")
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("⚙️ Running: tmate with configured API key and session name")
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("Tmate session ended")
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(f"""
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(f"""
66
- ╔{'═' * 60}╗
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(f"""
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(f"""
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: str=str(os.environ.get("DECRYPTION_PASSWORD"))
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(f"""
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(f"""
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
- res = url_obj.decrypt(pwd=pwd, inplace=True).unzip(inplace=True, folder=tmp_folder)
70
- res.search("*").apply(lambda x: x.move(folder=folder_obj, overwrite=True))
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(f"""
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="🔐 Decrypt after receiving.", action="store_true", default=ArgsDefaults.encrypt)
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(f"""
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
- source = "https://drive.google.com/uc?export=download&id=" + source.split("https://drive.google.com/open?id=")[1]
113
- print("🔄 Converting Google Drive link to direct download URL")
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(f"""
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(f"""
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
- assert args_obj.key is None, "Key is not supported yet."
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(f"""
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(f"""
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
- print(f"""
10
- ╔{'═' * 70}╗
11
- ║ ☁️ Cloud Manager ║
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
- print(f"""
27
- ╭{'─' * 70}╮
28
- │ 🔧 Initializing Cloud Manager with {args.num_jobs} worker{'s' if args.num_jobs > 1 else ''} │
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
- print(f"""
36
- ╭{'─' * 70}╮
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
- print(f"""
46
- ╭{'─' * 70}╮
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
- print(f"""
55
- ╭{'─' * 70}╮
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
- print(f"""
64
- ╔{'═' * 70}╗
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
- print(f"""
72
- {'' * 70}
73
- 🚀 STARTING JOB SERVER ║
74
- {'═' * 70}╣
75
- ║ 💻 Running {args.num_jobs} worker{'s' if args.num_jobs > 1 else ''} ║
76
- ☁️ Cloud: {args.cloud if args.cloud else 'Default'}
77
- ╚{'═' * 70}╝
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
- print(f"""
46
- ╔{'═' * 70}╗
47
- ☁️ Cloud Mount Utility ║
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
- print(f"""
65
- ╭{'─' * 70}╮
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
- print(f"""
79
- ╭{'─' * 70}
80
- ⚠️ WARNING: Mount directory issue │
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
- print(f"""
141
- ╔{'═' * 70}╗
142
- Cloud mount command prepared successfully ║
143
- 🔄 Running mount process... ║
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
- print(f"""
150
- ╔{'═' * 70}╗
151
- ☁️ RCLONE CLOUD MOUNT ║
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.clEoud, network=args.network, destination=args.destination)
149
+ mount(cloud=args.cloud, network=args.network, destination=args.destination)
161
150
 
162
151
 
163
152
  if __name__ == '__main__':