machineconfig 3.8__py3-none-any.whl → 3.82__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/scripts/python/cloud_repo_sync.py +11 -17
- machineconfig/scripts/python/croshell.py +2 -3
- machineconfig/scripts/python/devops.py +21 -38
- machineconfig/scripts/python/devops_devapps_install.py +11 -4
- machineconfig/scripts/python/fire_jobs.py +59 -6
- machineconfig/scripts/python/fire_jobs_args_helper.py +2 -38
- machineconfig/scripts/python/ftpx.py +55 -48
- machineconfig/scripts/python/repos.py +43 -44
- {machineconfig-3.8.dist-info → machineconfig-3.82.dist-info}/METADATA +2 -1
- {machineconfig-3.8.dist-info → machineconfig-3.82.dist-info}/RECORD +13 -17
- {machineconfig-3.8.dist-info → machineconfig-3.82.dist-info}/entry_points.txt +4 -3
- machineconfig/cluster/templates/cli_click.py +0 -102
- machineconfig/scripts/python/archive/im2text.py +0 -34
- machineconfig/scripts/python/archive/tmate_conn.py +0 -41
- machineconfig/scripts/python/archive/tmate_start.py +0 -44
- {machineconfig-3.8.dist-info → machineconfig-3.82.dist-info}/WHEEL +0 -0
- {machineconfig-3.8.dist-info → machineconfig-3.82.dist-info}/top_level.txt +0 -0
|
@@ -5,14 +5,12 @@ import git
|
|
|
5
5
|
from machineconfig.utils.io import read_ini
|
|
6
6
|
from machineconfig.utils.path_extended import PathExtended as PathExtended
|
|
7
7
|
from machineconfig.utils.terminal import Terminal
|
|
8
|
-
from machineconfig.utils.accessories import randstr
|
|
9
8
|
|
|
10
9
|
from machineconfig.scripts.python.helpers.repo_sync_helpers import fetch_dotfiles
|
|
11
10
|
from machineconfig.utils.source_of_truth import CONFIG_PATH, DEFAULTS_PATH
|
|
12
11
|
from machineconfig.utils.options import choose_from_options
|
|
13
12
|
from machineconfig.utils.code import get_shell_file_executing_python_script, write_shell_script_to_file
|
|
14
13
|
import platform
|
|
15
|
-
import argparse
|
|
16
14
|
from typing import Optional, Literal
|
|
17
15
|
from rich.console import Console
|
|
18
16
|
from rich.panel import Panel
|
|
@@ -171,21 +169,17 @@ git commit -am "finished merging"
|
|
|
171
169
|
|
|
172
170
|
|
|
173
171
|
def args_parser():
|
|
174
|
-
console.print(Panel("🔄 Repository Synchronization Utility", title_align="left", border_style="blue"))
|
|
175
|
-
|
|
176
|
-
parser =
|
|
177
|
-
# parser.add_argument("
|
|
178
|
-
parser.add_argument("
|
|
179
|
-
# parser.add_argument("--
|
|
180
|
-
parser.add_argument("--
|
|
181
|
-
|
|
182
|
-
#
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
# parser.add_argument("--no_push", "-u", help="push to reomte.", action="store_true") # default is False
|
|
186
|
-
parser.add_argument("--action", "-a", help="Action to take if merge fails.", choices=["ask", "pushLocalMerge", "overwriteLocal", "InspectRepos", "RemoveLocalRclone"], default="ask")
|
|
187
|
-
args = parser.parse_args()
|
|
188
|
-
main(cloud=args.cloud, path=args.path, message=args.message, action=args.action)
|
|
172
|
+
# console.print(Panel("🔄 Repository Synchronization Utility", title_align="left", border_style="blue"))
|
|
173
|
+
# parser = argparse.ArgumentParser(description="Secure Repo CLI.")
|
|
174
|
+
# parser.add_argument("path", nargs="?", type=str, help="Repository path, defaults to cwd.", default=None)
|
|
175
|
+
# parser.add_argument("--cloud", "-c", help="rclone cloud profile name.", default=None)
|
|
176
|
+
# parser.add_argument("--message", "-m", help="Commit Message", default=f"new message {randstr()}")
|
|
177
|
+
# parser.add_argument("--pwd", "-p", help="Password for encryption", default=None)
|
|
178
|
+
# parser.add_argument("--action", "-a", help="Action to take if merge fails.", choices=["ask", "pushLocalMerge", "overwriteLocal", "InspectRepos", "RemoveLocalRclone"], default="ask")
|
|
179
|
+
# args = parser.parse_args()
|
|
180
|
+
# main(cloud=args.cloud, path=args.path, message=args.message, action=args.action)
|
|
181
|
+
import typer
|
|
182
|
+
typer.run(main)
|
|
189
183
|
|
|
190
184
|
|
|
191
185
|
if __name__ == "__main__":
|
|
@@ -13,8 +13,7 @@ from machineconfig.utils.ve import get_ve_activate_line
|
|
|
13
13
|
from typing import Optional
|
|
14
14
|
from rich.console import Console
|
|
15
15
|
from rich.panel import Panel
|
|
16
|
-
from rich.text import Text
|
|
17
|
-
# from machineconfig.utils.utils2 import pprint
|
|
16
|
+
from rich.text import Text
|
|
18
17
|
|
|
19
18
|
console = Console()
|
|
20
19
|
|
|
@@ -24,7 +23,7 @@ def add_print_header_pycode(path: str, title: str):
|
|
|
24
23
|
try:
|
|
25
24
|
from crocodile.file_management import P as PathExtended
|
|
26
25
|
except ImportError:
|
|
27
|
-
from machineconfig.utils.
|
|
26
|
+
from machineconfig.utils.path_extended import PathExtended
|
|
28
27
|
pycode = PathExtended(r'{path}').read_text(encoding="utf-8")
|
|
29
28
|
pycode = pycode.split("except Exception: print(pycode)")[2]
|
|
30
29
|
|
|
@@ -3,8 +3,7 @@
|
|
|
3
3
|
from machineconfig.utils.options import choose_from_options
|
|
4
4
|
|
|
5
5
|
from platform import system
|
|
6
|
-
from
|
|
7
|
-
from typing import Optional
|
|
6
|
+
from typing import Optional, Literal, TypeAlias
|
|
8
7
|
from rich.console import Console
|
|
9
8
|
from rich.panel import Panel
|
|
10
9
|
|
|
@@ -13,36 +12,20 @@ console = Console()
|
|
|
13
12
|
BOX_WIDTH = 150 # width for box drawing
|
|
14
13
|
|
|
15
14
|
|
|
16
|
-
|
|
17
|
-
update = "🔄 UPDATE essential repos"
|
|
18
|
-
cli_install = "⚙️ DEVAPPS install"
|
|
19
|
-
sym_path_shell = "🔗 SYMLINKS, SHELL PROFILE, FONT, TERMINAL SETTINGS."
|
|
20
|
-
sym_new = "🆕 SYMLINKS new"
|
|
21
|
-
ssh_add_pubkey = "🔑 SSH add pub key to this machine"
|
|
22
|
-
ssh_add_id = "🗝️ SSH add identity (private key) to this machine"
|
|
23
|
-
ssh_use_pair = "🔐 SSH use key pair to connect two machines"
|
|
24
|
-
ssh_setup = "📡 SSH setup"
|
|
25
|
-
ssh_setup_wsl = "🐧 SSH setup wsl"
|
|
26
|
-
backup = "💾 BACKUP"
|
|
27
|
-
retreive = "📥 RETRIEVE"
|
|
28
|
-
scheduler = "⏰ SCHEDULER"
|
|
15
|
+
Options: TypeAlias = Literal["🔄 UPDATE essential repos", "⚙️ DEVAPPS install", "🔗 SYMLINKS, SHELL PROFILE, FONT, TERMINAL SETTINGS.", "🆕 SYMLINKS new", "🔑 SSH add pub key to this machine", "🗝️ SSH add identity (private key) to this machine", "🔐 SSH use key pair to connect two machines", "📡 SSH setup", "🐧 SSH setup wsl", "💾 BACKUP", "📥 RETRIEVE", "⏰ SCHEDULER"]
|
|
29
16
|
|
|
17
|
+
options_list = list(Options.__args__)
|
|
30
18
|
|
|
31
|
-
def args_parser():
|
|
32
|
-
console.print(Panel("🛠️ DevOps Tool Suite", title_align="left", border_style="blue", width=BOX_WIDTH))
|
|
33
|
-
import argparse
|
|
34
19
|
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
args = parser.parse_args()
|
|
39
|
-
main(which=args.which)
|
|
20
|
+
def args_parser():
|
|
21
|
+
import typer
|
|
22
|
+
typer.run(main)
|
|
40
23
|
|
|
41
24
|
|
|
42
|
-
def main(which: Optional[
|
|
25
|
+
def main(which: Optional[Options] = None):
|
|
43
26
|
# PathExtended(_program_PATH).delete(sure=True, verbose=False)
|
|
44
27
|
console.print(Panel("🚀 Initializing DevOps operation...", width=BOX_WIDTH, border_style="blue"))
|
|
45
|
-
options =
|
|
28
|
+
options = options_list
|
|
46
29
|
if which is None:
|
|
47
30
|
try:
|
|
48
31
|
choice_key = choose_from_options(msg="", options=options, header="🛠️ DEVOPS", default=options[0], multi=False)
|
|
@@ -50,51 +33,51 @@ def main(which: Optional[str] = None):
|
|
|
50
33
|
console.print(Panel("❌ Operation cancelled by user", title_align="left", border_style="red", width=BOX_WIDTH))
|
|
51
34
|
return
|
|
52
35
|
else:
|
|
53
|
-
choice_key =
|
|
36
|
+
choice_key = which
|
|
54
37
|
|
|
55
38
|
console.print(Panel(f"🔧 SELECTED OPERATION\n{choice_key}", title_align="left", border_style="green", width=BOX_WIDTH))
|
|
56
39
|
|
|
57
|
-
if choice_key ==
|
|
40
|
+
if choice_key == "🔄 UPDATE essential repos":
|
|
58
41
|
console.print(Panel("🔄 Updating essential repositories...", width=BOX_WIDTH, border_style="blue"))
|
|
59
42
|
import machineconfig.scripts.python.devops_update_repos as helper
|
|
60
43
|
|
|
61
44
|
helper.main()
|
|
62
|
-
elif choice_key ==
|
|
45
|
+
elif choice_key == "⚙️ DEVAPPS install":
|
|
63
46
|
console.print(Panel("⚙️ Installing development applications...", width=BOX_WIDTH, border_style="blue"))
|
|
64
47
|
import machineconfig.scripts.python.devops_devapps_install as helper
|
|
65
48
|
|
|
66
49
|
helper.main(which=None)
|
|
67
50
|
|
|
68
|
-
elif choice_key ==
|
|
51
|
+
elif choice_key == "🆕 SYMLINKS new":
|
|
69
52
|
console.print(Panel("🔄 Creating new symlinks...", width=BOX_WIDTH, border_style="blue"))
|
|
70
53
|
import machineconfig.jobs.python.python_ve_symlink as helper
|
|
71
54
|
|
|
72
55
|
helper.main()
|
|
73
56
|
|
|
74
|
-
elif choice_key ==
|
|
57
|
+
elif choice_key == "🔗 SYMLINKS, SHELL PROFILE, FONT, TERMINAL SETTINGS.":
|
|
75
58
|
console.print(Panel("🔗 Setting up symlinks, PATH, and shell profile...", width=BOX_WIDTH, border_style="blue"))
|
|
76
59
|
import machineconfig.profile.create as helper
|
|
77
60
|
|
|
78
61
|
helper.main()
|
|
79
62
|
"echo '✅ done with symlinks'"
|
|
80
63
|
|
|
81
|
-
elif choice_key ==
|
|
64
|
+
elif choice_key == "🔑 SSH add pub key to this machine":
|
|
82
65
|
console.print(Panel("🔑 Adding public SSH key to this machine...", width=BOX_WIDTH, border_style="blue"))
|
|
83
66
|
import machineconfig.scripts.python.devops_add_ssh_key as helper
|
|
84
67
|
|
|
85
68
|
helper.main()
|
|
86
69
|
|
|
87
|
-
elif choice_key ==
|
|
70
|
+
elif choice_key == "🔐 SSH use key pair to connect two machines":
|
|
88
71
|
console.print(Panel("❌ ERROR: Not Implemented\nSSH key pair connection feature is not yet implemented", title_align="left", border_style="red", width=BOX_WIDTH))
|
|
89
72
|
raise NotImplementedError
|
|
90
73
|
|
|
91
|
-
elif choice_key ==
|
|
74
|
+
elif choice_key == "🗝️ SSH add identity (private key) to this machine": # so that you can SSH directly withuot pointing to identity key.
|
|
92
75
|
console.print(Panel("🗝️ Adding SSH identity (private key) to this machine...", width=BOX_WIDTH, border_style="blue"))
|
|
93
76
|
import machineconfig.scripts.python.devops_add_identity as helper
|
|
94
77
|
|
|
95
78
|
helper.main()
|
|
96
79
|
|
|
97
|
-
elif choice_key ==
|
|
80
|
+
elif choice_key == "📡 SSH setup":
|
|
98
81
|
console.print(Panel("📡 Setting up SSH...", width=BOX_WIDTH, border_style="blue"))
|
|
99
82
|
_program_windows = """Invoke-WebRequest https://raw.githubusercontent.com/thisismygitrepo/machineconfig/main/src/machineconfig/setup_windows/openssh_all.ps1 | Invoke-Expression # https://github.com/thisismygitrepo.keys"""
|
|
100
83
|
_program_linux = """curl https://raw.githubusercontent.com/thisismygitrepo/machineconfig/main/src/machineconfig/setup_linux/openssh_all.sh | sudo bash # https://github.com/thisismygitrepo.keys"""
|
|
@@ -103,23 +86,23 @@ def main(which: Optional[str] = None):
|
|
|
103
86
|
|
|
104
87
|
subprocess.run(_program_linux if system() == "Linux" else _program_windows, shell=True, check=True)
|
|
105
88
|
|
|
106
|
-
elif choice_key ==
|
|
89
|
+
elif choice_key == "🐧 SSH setup wsl":
|
|
107
90
|
console.print(Panel("🐧 Setting up SSH for WSL...", width=BOX_WIDTH, border_style="blue"))
|
|
108
91
|
"""curl https://raw.githubusercontent.com/thisismygitrepo/machineconfig/main/src/machineconfig/setup_linux/openssh_wsl.sh | sudo bash"""
|
|
109
92
|
|
|
110
|
-
elif choice_key ==
|
|
93
|
+
elif choice_key == "💾 BACKUP":
|
|
111
94
|
console.print(Panel("💾 Creating backup...", width=BOX_WIDTH, border_style="blue"))
|
|
112
95
|
from machineconfig.scripts.python.devops_backup_retrieve import main_backup_retrieve
|
|
113
96
|
|
|
114
97
|
main_backup_retrieve(direction="BACKUP")
|
|
115
98
|
|
|
116
|
-
elif choice_key ==
|
|
99
|
+
elif choice_key == "📥 RETRIEVE":
|
|
117
100
|
console.print(Panel("📥 Retrieving backup...", width=BOX_WIDTH, border_style="blue"))
|
|
118
101
|
from machineconfig.scripts.python.devops_backup_retrieve import main_backup_retrieve
|
|
119
102
|
|
|
120
103
|
main_backup_retrieve(direction="RETRIEVE")
|
|
121
104
|
|
|
122
|
-
elif choice_key ==
|
|
105
|
+
elif choice_key == "⏰ SCHEDULER":
|
|
123
106
|
console.print(Panel("⏰ Setting up scheduler...", width=BOX_WIDTH, border_style="blue"))
|
|
124
107
|
# from machineconfig.scripts.python.scheduler import main as helper
|
|
125
108
|
# helper()
|
|
@@ -1,18 +1,25 @@
|
|
|
1
1
|
"""Devops Devapps Install"""
|
|
2
2
|
|
|
3
3
|
# import subprocess
|
|
4
|
+
import typer
|
|
4
5
|
from rich.progress import Progress, SpinnerColumn, TextColumn
|
|
5
6
|
from machineconfig.utils.source_of_truth import LIBRARY_ROOT
|
|
6
7
|
from machineconfig.utils.options import choose_from_options
|
|
7
8
|
from machineconfig.utils.installer import get_installers, install_all
|
|
8
9
|
from platform import system
|
|
9
|
-
from typing import Any, Optional, Literal, TypeAlias, get_args
|
|
10
|
-
|
|
10
|
+
from typing import Any, Optional, Literal, TypeAlias, get_args, Annotated
|
|
11
11
|
|
|
12
12
|
WHICH_CAT: TypeAlias = Literal["AllEssentials", "EssentialsAndOthers", "SystemInstallers", "PrecheckedCloudInstaller"]
|
|
13
13
|
|
|
14
14
|
|
|
15
|
-
def
|
|
15
|
+
def main_with_parser():
|
|
16
|
+
import typer
|
|
17
|
+
app = typer.Typer()
|
|
18
|
+
app.command()(main)
|
|
19
|
+
app()
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
def main(which: Annotated[Optional[str], typer.Argument(help=f"Choose a category or program to install, {list(get_args(WHICH_CAT))} or <program_name>")]) -> None:
|
|
16
23
|
if which is not None and which in get_args(WHICH_CAT): # install by category
|
|
17
24
|
return get_programs_by_category(program_name=which) # type: ignore
|
|
18
25
|
|
|
@@ -123,7 +130,7 @@ def get_programs_by_category(program_name: WHICH_CAT):
|
|
|
123
130
|
if sub_program.startswith("#winget"):
|
|
124
131
|
sub_program = sub_program[1:]
|
|
125
132
|
program += "\n" + sub_program
|
|
126
|
-
|
|
133
|
+
# case "CHOOSE": raise NotImplementedError("CHOOSE is not implemented yet.")
|
|
127
134
|
# case "OtherDevApps":
|
|
128
135
|
# installers = get_installers(dev=True, system=system())
|
|
129
136
|
# options__: list[str] = [x.get_description() for x in tqdm(installers, desc="Checking installed programs")]
|
|
@@ -17,11 +17,12 @@ from machineconfig.utils.path_helper import match_file_name, sanitize_path
|
|
|
17
17
|
|
|
18
18
|
from machineconfig.utils.path_extended import PathExtended as PathExtended
|
|
19
19
|
from machineconfig.utils.accessories import get_repo_root, randstr
|
|
20
|
-
from machineconfig.scripts.python.fire_jobs_args_helper import
|
|
20
|
+
from machineconfig.scripts.python.fire_jobs_args_helper import FireJobArgs, extract_kwargs
|
|
21
21
|
import platform
|
|
22
|
-
from typing import Optional
|
|
22
|
+
from typing import Optional, Annotated
|
|
23
23
|
from pathlib import Path
|
|
24
24
|
import tomllib
|
|
25
|
+
import typer
|
|
25
26
|
# import os
|
|
26
27
|
|
|
27
28
|
|
|
@@ -328,12 +329,64 @@ python -m machineconfig.cluster.templates.cli_click --file {choice_file} """
|
|
|
328
329
|
subprocess.run(command, shell=True, check=True)
|
|
329
330
|
|
|
330
331
|
|
|
331
|
-
def main(
|
|
332
|
-
|
|
332
|
+
def main(
|
|
333
|
+
path: Annotated[str, typer.Argument(help="The directory containing the jobs")] = ".",
|
|
334
|
+
function: Annotated[Optional[str], typer.Argument(help="Function to run")] = None,
|
|
335
|
+
ve: Annotated[str, typer.Option("--ve", "-v", help="Virtual environment name")] = "",
|
|
336
|
+
cmd: Annotated[bool, typer.Option("--cmd", "-B", help="Create a cmd fire command to launch the job asynchronously")] = False,
|
|
337
|
+
interactive: Annotated[bool, typer.Option("--interactive", "-i", help="Whether to run the job interactively using IPython")] = False,
|
|
338
|
+
debug: Annotated[bool, typer.Option("--debug", "-d", help="Enable debug mode")] = False,
|
|
339
|
+
choose_function: Annotated[bool, typer.Option("--choose_function", "-c", help="Choose function interactively")] = False,
|
|
340
|
+
loop: Annotated[bool, typer.Option("--loop", "-l", help="Infinite recursion (runs again after completion/interruption)")] = False,
|
|
341
|
+
jupyter: Annotated[bool, typer.Option("--jupyter", "-j", help="Open in a jupyter notebook")] = False,
|
|
342
|
+
submit_to_cloud: Annotated[bool, typer.Option("--submit_to_cloud", "-C", help="Submit to cloud compute")] = False,
|
|
343
|
+
remote: Annotated[bool, typer.Option("--remote", "-r", help="Launch on a remote machine")] = False,
|
|
344
|
+
module: Annotated[bool, typer.Option("--module", "-m", help="Launch the main file")] = False,
|
|
345
|
+
streamlit: Annotated[bool, typer.Option("--streamlit", "-S", help="Run as streamlit app")] = False,
|
|
346
|
+
environment: Annotated[str, typer.Option("--environment", "-E", help="Choose ip, localhost, hostname or arbitrary url")] = "",
|
|
347
|
+
holdDirectory: Annotated[bool, typer.Option("--holdDirectory", "-D", help="Hold current directory and avoid cd'ing to the script directory")] = False,
|
|
348
|
+
PathExport: Annotated[bool, typer.Option("--PathExport", "-P", help="Augment the PYTHONPATH with repo root")] = False,
|
|
349
|
+
git_pull: Annotated[bool, typer.Option("--git_pull", "-g", help="Start by pulling the git repo")] = False,
|
|
350
|
+
optimized: Annotated[bool, typer.Option("--optimized", "-O", help="Run the optimized version of the function")] = False,
|
|
351
|
+
Nprocess: Annotated[int, typer.Option("--Nprocess", "-p", help="Number of processes to use")] = 1,
|
|
352
|
+
zellij_tab: Annotated[Optional[str], typer.Option("--zellij_tab", "-z", help="Open in a new zellij tab")] = None,
|
|
353
|
+
watch: Annotated[bool, typer.Option("--watch", "-w", help="Watch the file for changes")] = False,
|
|
354
|
+
kw: Annotated[Optional[list[str]], typer.Option("--kw", help="Keyword arguments to pass to the function in the form of k1 v1 k2 v2 ... (meaning k1=v1, k2=v2, etc)")] = None,
|
|
355
|
+
layout: Annotated[bool, typer.Option("--layout", "-L", help="Use layout configuration (Zellij Or WindowsTerminal)")] = False,
|
|
356
|
+
) -> None:
|
|
357
|
+
"""Main function to process fire jobs arguments."""
|
|
358
|
+
args = FireJobArgs(
|
|
359
|
+
path=path,
|
|
360
|
+
function=function,
|
|
361
|
+
ve=ve,
|
|
362
|
+
cmd=cmd,
|
|
363
|
+
interactive=interactive,
|
|
364
|
+
debug=debug,
|
|
365
|
+
choose_function=choose_function,
|
|
366
|
+
loop=loop,
|
|
367
|
+
jupyter=jupyter,
|
|
368
|
+
submit_to_cloud=submit_to_cloud,
|
|
369
|
+
remote=remote,
|
|
370
|
+
module=module,
|
|
371
|
+
streamlit=streamlit,
|
|
372
|
+
environment=environment,
|
|
373
|
+
holdDirectory=holdDirectory,
|
|
374
|
+
PathExport=PathExport,
|
|
375
|
+
git_pull=git_pull,
|
|
376
|
+
optimized=optimized,
|
|
377
|
+
Nprocess=Nprocess,
|
|
378
|
+
zellij_tab=zellij_tab,
|
|
379
|
+
watch=watch,
|
|
380
|
+
kw=kw,
|
|
381
|
+
layout=layout,
|
|
382
|
+
)
|
|
333
383
|
route(args)
|
|
334
384
|
|
|
335
385
|
|
|
386
|
+
def main_from_parser():
|
|
387
|
+
typer.run(main)
|
|
388
|
+
|
|
389
|
+
|
|
336
390
|
if __name__ == "__main__":
|
|
337
391
|
# options, func_args = parse_pyfile(file_path="C:/Users/aalsaf01/code/machineconfig/myresources/crocodile/core.py")
|
|
338
|
-
|
|
339
|
-
route(args)
|
|
392
|
+
pass
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
from dataclasses import dataclass
|
|
2
|
-
from typing import Optional
|
|
3
|
-
import
|
|
2
|
+
from typing import Optional, Annotated
|
|
3
|
+
import typer
|
|
4
4
|
|
|
5
5
|
|
|
6
6
|
@dataclass
|
|
@@ -32,42 +32,6 @@ class FireJobArgs:
|
|
|
32
32
|
layout: bool = False
|
|
33
33
|
|
|
34
34
|
|
|
35
|
-
def get_args() -> FireJobArgs:
|
|
36
|
-
parser = argparse.ArgumentParser()
|
|
37
|
-
parser.add_argument("path", nargs="?", type=str, help="The directory containing the jobs", default=".")
|
|
38
|
-
parser.add_argument("function", nargs="?", type=str, help="Fuction to run", default=None)
|
|
39
|
-
parser.add_argument("--ve", "-v", type=str, help="virtual enviroment name", default="")
|
|
40
|
-
parser.add_argument("--cmd", "-B", action="store_true", help="Create a cmd fire command to launch the the job asynchronously.")
|
|
41
|
-
parser.add_argument("--interactive", "-i", action="store_true", help="Whether to run the job interactively using IPython")
|
|
42
|
-
parser.add_argument("--debug", "-d", action="store_true", help="debug")
|
|
43
|
-
parser.add_argument("--choose_function", "-c", action="store_true", help="debug")
|
|
44
|
-
parser.add_argument("--loop", "-l", action="store_true", help="infinite recusion (runs again after completion/interruption)")
|
|
45
|
-
parser.add_argument("--jupyter", "-j", action="store_true", help="open in a jupyter notebook")
|
|
46
|
-
parser.add_argument("--submit_to_cloud", "-C", action="store_true", help="submit to cloud compute")
|
|
47
|
-
parser.add_argument("--remote", "-r", action="store_true", help="launch on a remote machine")
|
|
48
|
-
parser.add_argument("--module", "-m", action="store_true", help="launch the main file")
|
|
49
|
-
parser.add_argument("--streamlit", "-S", action="store_true", help="run as streamlit app")
|
|
50
|
-
parser.add_argument("--environment", "-E", type=str, help="Choose ip, localhost, hostname or arbitrary url", default="")
|
|
51
|
-
parser.add_argument("--holdDirectory", "-D", action="store_true", help="hold current directory and avoid cd'ing to the script directory")
|
|
52
|
-
parser.add_argument("--PathExport", "-P", action="store_true", help="augment the PYTHONPATH with repo root.")
|
|
53
|
-
parser.add_argument("--git_pull", "-g", action="store_true", help="Start by pulling the git repo")
|
|
54
|
-
parser.add_argument("--optimized", "-O", action="store_true", help="Run the optimized version of the function")
|
|
55
|
-
parser.add_argument("--Nprocess", "-p", type=int, help="Number of processes to use", default=1)
|
|
56
|
-
parser.add_argument("--zellij_tab", "-z", type=str, dest="zellij_tab", help="open in a new zellij tab")
|
|
57
|
-
parser.add_argument("--watch", "-w", action="store_true", help="watch the file for changes")
|
|
58
|
-
parser.add_argument("--kw", nargs="*", default=None, help="keyword arguments to pass to the function in the form of k1 v1 k2 v2 ... (meaning k1=v1, k2=v2, etc)")
|
|
59
|
-
parser.add_argument("--layout", "-L", action="store_true", help="use layout configuration (Zellij Or WindowsTerminal)")
|
|
60
|
-
|
|
61
|
-
try:
|
|
62
|
-
args_raw = parser.parse_args()
|
|
63
|
-
except Exception as ex:
|
|
64
|
-
print(f"❌ Failed to parse arguments: {ex}")
|
|
65
|
-
parser.print_help()
|
|
66
|
-
raise ex
|
|
67
|
-
args = FireJobArgs(**vars(args_raw))
|
|
68
|
-
return args
|
|
69
|
-
|
|
70
|
-
|
|
71
35
|
def extract_kwargs(args: FireJobArgs) -> dict[str, object]:
|
|
72
36
|
str2obj = {"True": True, "False": False, "None": None}
|
|
73
37
|
if args.kw is not None:
|
|
@@ -6,39 +6,40 @@ Currently, the only way to work around this is to predifine the host in ~/.ssh/c
|
|
|
6
6
|
|
|
7
7
|
"""
|
|
8
8
|
|
|
9
|
-
import
|
|
9
|
+
import typer
|
|
10
|
+
from typing_extensions import Annotated
|
|
10
11
|
from machineconfig.utils.ssh import SSH
|
|
11
12
|
from machineconfig.utils.path_extended import PathExtended as PathExtended
|
|
12
13
|
from machineconfig.scripts.python.helpers.helpers2 import ES
|
|
13
14
|
from machineconfig.utils.accessories import pprint
|
|
14
15
|
|
|
15
16
|
|
|
16
|
-
def main(
|
|
17
|
+
def main(
|
|
18
|
+
source: Annotated[str, typer.Argument(help="Source path (machine:path)")],
|
|
19
|
+
target: Annotated[str, typer.Argument(help="Target path (machine:path)")],
|
|
20
|
+
recursive: Annotated[bool, typer.Option("--recursive", "-r", help="Send recursively.")] = False,
|
|
21
|
+
zipFirst: Annotated[bool, typer.Option("--zipFirst", "-z", help="Zip before sending.")] = False,
|
|
22
|
+
cloud: Annotated[bool, typer.Option("--cloud", "-c", help="Transfer through the cloud.")] = False,
|
|
23
|
+
) -> None:
|
|
17
24
|
print("""
|
|
18
25
|
┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
19
26
|
┃ 🚀 FTP File Transfer
|
|
20
27
|
┃ 📋 Starting transfer process...
|
|
21
28
|
┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━""")
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
parser.add_argument("--zipFirst", "-z", help="Zip before sending.", action="store_true") # default is False
|
|
30
|
-
parser.add_argument("--cloud", "-c", help="Transfer through the cloud.", action="store_true") # default is False
|
|
31
|
-
|
|
32
|
-
args = parser.parse_args()
|
|
33
|
-
|
|
34
|
-
if ":" in args.source and (args.source[1] != ":" if len(args.source) > 1 else True): # avoid the case of "C:/":
|
|
29
|
+
|
|
30
|
+
# Initialize variables
|
|
31
|
+
resolved_source: str | None = None
|
|
32
|
+
resolved_target: str | None = None
|
|
33
|
+
machine: str = ""
|
|
34
|
+
|
|
35
|
+
if ":" in source and (source[1] != ":" if len(source) > 1 else True): # avoid the case of "C:/":
|
|
35
36
|
source_is_remote = True
|
|
36
37
|
|
|
37
38
|
# calculating source:
|
|
38
|
-
source_parts =
|
|
39
|
+
source_parts = source.split(":")
|
|
39
40
|
machine = source_parts[0]
|
|
40
41
|
if len(source_parts) > 1 and source_parts[1] == ES: # the source path is to be inferred from target.
|
|
41
|
-
if
|
|
42
|
+
if target == ES:
|
|
42
43
|
raise ValueError(f"""
|
|
43
44
|
┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
44
45
|
┃ ❌ Configuration Error
|
|
@@ -46,21 +47,22 @@ def main():
|
|
|
46
47
|
┃ This creates a cyclical inference dependency
|
|
47
48
|
┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━""")
|
|
48
49
|
else:
|
|
49
|
-
|
|
50
|
-
|
|
50
|
+
target_path_obj = PathExtended(target).expanduser().absolute()
|
|
51
|
+
resolved_source = target_path_obj.collapseuser().as_posix()
|
|
52
|
+
resolved_target = target
|
|
51
53
|
else:
|
|
52
|
-
|
|
53
|
-
if
|
|
54
|
-
|
|
54
|
+
resolved_source = ":".join(source.split(":")[1:])
|
|
55
|
+
if target == ES:
|
|
56
|
+
resolved_target = None
|
|
55
57
|
else:
|
|
56
|
-
|
|
58
|
+
resolved_target = PathExtended(target).expanduser().absolute().as_posix()
|
|
57
59
|
|
|
58
|
-
elif ":" in
|
|
60
|
+
elif ":" in target and (target[1] != ":" if len(target) > 1 else True): # avoid the case of "C:/":
|
|
59
61
|
source_is_remote = False
|
|
60
|
-
target_parts =
|
|
62
|
+
target_parts = target.split(":")
|
|
61
63
|
machine = target_parts[0]
|
|
62
64
|
if len(target_parts) > 1 and target_parts[1] == ES:
|
|
63
|
-
if
|
|
65
|
+
if source == ES:
|
|
64
66
|
raise ValueError(f"""
|
|
65
67
|
┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
66
68
|
┃ ❌ Configuration Error
|
|
@@ -68,14 +70,14 @@ def main():
|
|
|
68
70
|
┃ This creates a cyclical inference dependency
|
|
69
71
|
┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━""")
|
|
70
72
|
else:
|
|
71
|
-
|
|
72
|
-
|
|
73
|
+
resolved_source = source
|
|
74
|
+
resolved_target = None
|
|
73
75
|
else:
|
|
74
|
-
|
|
75
|
-
if
|
|
76
|
-
|
|
76
|
+
resolved_target = ":".join(target.split(":")[1:])
|
|
77
|
+
if source == ES:
|
|
78
|
+
resolved_source = None
|
|
77
79
|
else:
|
|
78
|
-
|
|
80
|
+
resolved_source = PathExtended(source).expanduser().absolute().as_posix()
|
|
79
81
|
|
|
80
82
|
else:
|
|
81
83
|
raise ValueError("""
|
|
@@ -85,7 +87,7 @@ def main():
|
|
|
85
87
|
┃ Format should be: machine:path
|
|
86
88
|
┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━""")
|
|
87
89
|
|
|
88
|
-
pprint({"source": str(
|
|
90
|
+
pprint({"source": str(resolved_source), "target": str(resolved_target), "machine": machine}, "CLI Resolution")
|
|
89
91
|
|
|
90
92
|
from paramiko.ssh_exception import AuthenticationException # type: ignore
|
|
91
93
|
|
|
@@ -105,43 +107,43 @@ def main():
|
|
|
105
107
|
pwd = getpass.getpass()
|
|
106
108
|
ssh = SSH(rf"{machine}", pwd=pwd)
|
|
107
109
|
|
|
108
|
-
if
|
|
110
|
+
if cloud:
|
|
109
111
|
print("""
|
|
110
112
|
┌────────────────────────────────────────────────────────────────
|
|
111
113
|
│ ☁️ Cloud Transfer Mode
|
|
112
114
|
│ Uploading from remote to cloud...
|
|
113
115
|
└────────────────────────────────────────────────────────────────""")
|
|
114
|
-
ssh.run(f"cloud_copy {
|
|
116
|
+
ssh.run(f"cloud_copy {resolved_source} :^", desc="Uploading from remote to the cloud.").print()
|
|
115
117
|
print("""
|
|
116
118
|
┌────────────────────────────────────────────────────────────────
|
|
117
119
|
│ ⬇️ Cloud Transfer Mode
|
|
118
120
|
│ Downloading from cloud to local...
|
|
119
121
|
└────────────────────────────────────────────────────────────────""")
|
|
120
|
-
ssh.run_locally(f"cloud_copy :^ {
|
|
121
|
-
received_file = PathExtended(
|
|
122
|
+
ssh.run_locally(f"cloud_copy :^ {resolved_target}").print()
|
|
123
|
+
received_file = PathExtended(resolved_target) # type: ignore
|
|
122
124
|
else:
|
|
123
125
|
if source_is_remote:
|
|
124
|
-
assert
|
|
126
|
+
assert resolved_source is not None, """
|
|
125
127
|
❌ Path Error: Source must be a remote path (machine:path)"""
|
|
126
128
|
print(f"""
|
|
127
129
|
┌────────────────────────────────────────────────────────────────
|
|
128
130
|
│ 📥 Transfer Mode: Remote → Local
|
|
129
|
-
│ Source: {
|
|
130
|
-
│ Target: {
|
|
131
|
-
│ Options: {"ZIP compression" if
|
|
131
|
+
│ Source: {resolved_source}
|
|
132
|
+
│ Target: {resolved_target}
|
|
133
|
+
│ Options: {"ZIP compression" if zipFirst else "No compression"}, {"Recursive" if recursive else "Non-recursive"}
|
|
132
134
|
└────────────────────────────────────────────────────────────────""")
|
|
133
|
-
received_file = ssh.copy_to_here(source=
|
|
135
|
+
received_file = ssh.copy_to_here(source=resolved_source, target=resolved_target, z=zipFirst, r=recursive)
|
|
134
136
|
else:
|
|
135
|
-
assert
|
|
137
|
+
assert resolved_source is not None, """
|
|
136
138
|
❌ Path Error: Target must be a remote path (machine:path)"""
|
|
137
139
|
print(f"""
|
|
138
140
|
┌────────────────────────────────────────────────────────────────
|
|
139
141
|
│ 📤 Transfer Mode: Local → Remote
|
|
140
|
-
│ Source: {
|
|
141
|
-
│ Target: {
|
|
142
|
-
│ Options: {"ZIP compression" if
|
|
142
|
+
│ Source: {resolved_source}
|
|
143
|
+
│ Target: {resolved_target}
|
|
144
|
+
│ Options: {"ZIP compression" if zipFirst else "No compression"}, {"Recursive" if recursive else "Non-recursive"}
|
|
143
145
|
└────────────────────────────────────────────────────────────────""")
|
|
144
|
-
received_file = ssh.copy_from_here(source=
|
|
146
|
+
received_file = ssh.copy_from_here(source=resolved_source, target=resolved_target, z=zipFirst, r=recursive)
|
|
145
147
|
|
|
146
148
|
if source_is_remote and isinstance(received_file, PathExtended):
|
|
147
149
|
print(f"""
|
|
@@ -157,5 +159,10 @@ def main():
|
|
|
157
159
|
┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━""")
|
|
158
160
|
|
|
159
161
|
|
|
162
|
+
def main_from_parser() -> None:
|
|
163
|
+
"""Entry point function that uses typer to parse arguments and call main."""
|
|
164
|
+
typer.run(main)
|
|
165
|
+
|
|
166
|
+
|
|
160
167
|
if __name__ == "__main__":
|
|
161
|
-
|
|
168
|
+
main_from_parser()
|
|
@@ -13,9 +13,9 @@ from machineconfig.scripts.python.repos_helper_update import update_repository
|
|
|
13
13
|
from machineconfig.scripts.python.repos_helper_record import main as record_repos
|
|
14
14
|
from machineconfig.scripts.python.repos_helper_clone import clone_repos
|
|
15
15
|
|
|
16
|
-
import
|
|
16
|
+
import typer
|
|
17
17
|
from enum import Enum
|
|
18
|
-
from typing import Optional
|
|
18
|
+
from typing import Annotated, Optional
|
|
19
19
|
|
|
20
20
|
from rich import print as pprint
|
|
21
21
|
|
|
@@ -83,69 +83,64 @@ def git_action(path: PathExtended, action: GitAction, mess: Optional[str] = None
|
|
|
83
83
|
return True
|
|
84
84
|
|
|
85
85
|
|
|
86
|
-
def main(
|
|
86
|
+
def main(
|
|
87
|
+
directory: Annotated[str, typer.Argument(help="📁 Folder containing repos to record or a specs JSON file to follow.")] = "",
|
|
88
|
+
push: Annotated[bool, typer.Option("--push", help="🚀 Push changes.")] = False,
|
|
89
|
+
pull: Annotated[bool, typer.Option("--pull", help="⬇️ Pull changes.")] = False,
|
|
90
|
+
commit: Annotated[bool, typer.Option("--commit", help="💾 Commit changes.")] = False,
|
|
91
|
+
all: Annotated[bool, typer.Option("--all", help="🔄 Pull, commit, and push changes.")] = False,
|
|
92
|
+
record: Annotated[bool, typer.Option("--record", help="📝 Record repositories.")] = False,
|
|
93
|
+
clone: Annotated[bool, typer.Option("--clone", help="📥 Clone repositories from record.")] = False,
|
|
94
|
+
checkout: Annotated[bool, typer.Option("--checkout", help="🔀 Check out to versions provided in a JSON file.")] = False,
|
|
95
|
+
checkout_to_branch: Annotated[bool, typer.Option("--checkout-to-branch", help="🔀 Check out to the main branch.")] = False,
|
|
96
|
+
recursive: Annotated[bool, typer.Option("--recursive", "-r", help="🔍 Recursive flag.")] = False,
|
|
97
|
+
no_sync: Annotated[bool, typer.Option("--no-sync", help="🚫 Disable automatic uv sync after pulls.")] = False,
|
|
98
|
+
cloud: Annotated[Optional[str], typer.Option("--cloud", "-c", help="☁️ Cloud storage option.")] = None,
|
|
99
|
+
) -> None:
|
|
87
100
|
print("\n" + "=" * 50)
|
|
88
101
|
print("📂 Welcome to the Repository Manager")
|
|
89
102
|
print("=" * 50 + "\n")
|
|
90
103
|
|
|
91
|
-
|
|
92
|
-
# POSITIONAL
|
|
93
|
-
parser.add_argument("directory", help="📁 Folder containing repos to record or a specs JSON file to follow.", default="")
|
|
94
|
-
# FLAGS
|
|
95
|
-
parser.add_argument("--push", help="🚀 Push changes.", action="store_true")
|
|
96
|
-
parser.add_argument("--pull", help="⬇️ Pull changes.", action="store_true")
|
|
97
|
-
parser.add_argument("--commit", help="💾 Commit changes.", action="store_true")
|
|
98
|
-
parser.add_argument("--all", help="🔄 Pull, commit, and push changes.", action="store_true")
|
|
99
|
-
parser.add_argument("--record", help="📝 Record repositories.", action="store_true")
|
|
100
|
-
parser.add_argument("--clone", help="📥 Clone repositories from record.", action="store_true")
|
|
101
|
-
parser.add_argument("--checkout", help="🔀 Check out to versions provided in a JSON file.", action="store_true")
|
|
102
|
-
parser.add_argument("--checkout_to_branch", help="🔀 Check out to the main branch.", action="store_true")
|
|
103
|
-
parser.add_argument("--recursive", "-r", help="🔍 Recursive flag.", action="store_true")
|
|
104
|
-
parser.add_argument("--no-sync", help="🚫 Disable automatic uv sync after pulls.", action="store_true")
|
|
105
|
-
# OPTIONAL
|
|
106
|
-
parser.add_argument("--cloud", "-c", help="☁️ Cloud storage option.", default=None)
|
|
107
|
-
args = parser.parse_args()
|
|
108
|
-
|
|
109
|
-
if args.directory == "":
|
|
104
|
+
if directory == "":
|
|
110
105
|
repos_root = PathExtended.home().joinpath("code") # it is a positional argument, can never be empty.
|
|
111
106
|
else:
|
|
112
|
-
repos_root = PathExtended(
|
|
107
|
+
repos_root = PathExtended(directory).expanduser().absolute()
|
|
113
108
|
|
|
114
|
-
auto_sync = not
|
|
109
|
+
auto_sync = not no_sync # Enable auto sync by default, disable with --no-sync
|
|
115
110
|
|
|
116
|
-
if
|
|
111
|
+
if record:
|
|
117
112
|
save_path = record_repos(repos_root=repos_root)
|
|
118
|
-
if
|
|
119
|
-
PathExtended(save_path).to_cloud(rel2home=True, cloud=
|
|
113
|
+
if cloud is not None:
|
|
114
|
+
PathExtended(save_path).to_cloud(rel2home=True, cloud=cloud)
|
|
120
115
|
|
|
121
|
-
elif
|
|
116
|
+
elif clone or checkout or checkout_to_branch:
|
|
122
117
|
print("\n📥 Cloning or checking out repositories...")
|
|
123
118
|
print(">>>>>>>>> Cloning Repos")
|
|
124
119
|
if not repos_root.exists() or repos_root.name != "repos.json":
|
|
125
120
|
repos_root = PathExtended(CONFIG_PATH).joinpath("repos").joinpath(repos_root.rel2home()).joinpath("repos.json")
|
|
126
121
|
if not repos_root.exists():
|
|
127
|
-
if
|
|
128
|
-
|
|
129
|
-
print(f"⚠️ Using default cloud: {
|
|
122
|
+
if cloud is None:
|
|
123
|
+
cloud_name: str = read_ini(DEFAULTS_PATH)["general"]["rclone_config_name"]
|
|
124
|
+
print(f"⚠️ Using default cloud: {cloud_name}")
|
|
130
125
|
else:
|
|
131
|
-
|
|
132
|
-
assert
|
|
133
|
-
repos_root.from_cloud(cloud=
|
|
134
|
-
assert (repos_root.exists() and repos_root.name == "repos.json") or
|
|
135
|
-
clone_repos(spec_path=repos_root, preferred_remote=None, checkout_branch_flag=
|
|
126
|
+
cloud_name = cloud
|
|
127
|
+
assert cloud_name is not None, f"Path {repos_root} does not exist and cloud was not passed. You can't clone without one of them."
|
|
128
|
+
repos_root.from_cloud(cloud=cloud_name, rel2home=True)
|
|
129
|
+
assert (repos_root.exists() and repos_root.name == "repos.json") or cloud is not None, f"Path {repos_root} does not exist and cloud was not passed. You can't clone without one of them."
|
|
130
|
+
clone_repos(spec_path=repos_root, preferred_remote=None, checkout_branch_flag=checkout_to_branch, checkout_commit_flag=checkout)
|
|
136
131
|
|
|
137
|
-
elif
|
|
132
|
+
elif all or commit or pull or push:
|
|
138
133
|
print(f"\n🔄 Performing Git actions on repositories @ `{repos_root}`...")
|
|
139
134
|
overall_success = True
|
|
140
135
|
for a_path in repos_root.search("*"):
|
|
141
136
|
print(f"{('Handling ' + str(a_path)).center(80, '-')}")
|
|
142
137
|
path_success = True
|
|
143
|
-
if
|
|
144
|
-
path_success = git_action(path=a_path, action=GitAction.pull, r=
|
|
145
|
-
if
|
|
146
|
-
path_success = git_action(a_path, action=GitAction.commit, r=
|
|
147
|
-
if
|
|
148
|
-
path_success = git_action(a_path, action=GitAction.push, r=
|
|
138
|
+
if pull or all:
|
|
139
|
+
path_success = git_action(path=a_path, action=GitAction.pull, r=recursive, auto_sync=auto_sync) and path_success
|
|
140
|
+
if commit or all:
|
|
141
|
+
path_success = git_action(a_path, action=GitAction.commit, r=recursive, auto_sync=auto_sync) and path_success
|
|
142
|
+
if push or all:
|
|
143
|
+
path_success = git_action(a_path, action=GitAction.push, r=recursive, auto_sync=auto_sync) and path_success
|
|
149
144
|
overall_success = overall_success and path_success
|
|
150
145
|
|
|
151
146
|
if overall_success:
|
|
@@ -156,5 +151,9 @@ def main():
|
|
|
156
151
|
print("❌ No action specified. Try passing --push, --pull, --commit, or --all.")
|
|
157
152
|
|
|
158
153
|
|
|
154
|
+
def main_from_parser() -> None:
|
|
155
|
+
typer.run(main)
|
|
156
|
+
|
|
157
|
+
|
|
159
158
|
if __name__ == "__main__":
|
|
160
|
-
|
|
159
|
+
main_from_parser()
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: machineconfig
|
|
3
|
-
Version: 3.
|
|
3
|
+
Version: 3.82
|
|
4
4
|
Summary: Dotfiles management package
|
|
5
5
|
Author-email: Alex Al-Saffar <programmer@usa.com>
|
|
6
6
|
License: Apache 2.0
|
|
@@ -24,6 +24,7 @@ Requires-Dist: gitpython>=3.1.44
|
|
|
24
24
|
Requires-Dist: pyfzf>=0.3.1
|
|
25
25
|
Requires-Dist: rclone-python>=0.1.23
|
|
26
26
|
Requires-Dist: pyjson5>=1.6.9
|
|
27
|
+
Requires-Dist: typer-slim>=0.19.2
|
|
27
28
|
Provides-Extra: windows
|
|
28
29
|
Requires-Dist: pywin32; extra == "windows"
|
|
29
30
|
Provides-Extra: docs
|
|
@@ -33,7 +33,6 @@ machineconfig/cluster/sessions_managers/zellij_utils/remote_executor.py,sha256=I
|
|
|
33
33
|
machineconfig/cluster/sessions_managers/zellij_utils/session_manager.py,sha256=7JLq8HY-NWbJfzHfxaok_o1KrIwzMCK_PUnsdZYfzuA,4929
|
|
34
34
|
machineconfig/cluster/sessions_managers/zellij_utils/status_reporter.py,sha256=AtpIoko_ghhOXENGAfgiS2jA4IYBFRMjEbyIy_P6HIM,3758
|
|
35
35
|
machineconfig/cluster/templates/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
36
|
-
machineconfig/cluster/templates/cli_click.py,sha256=7v6w-dj1whBd9ydKeOAQFuD5kF7_6ivyPAqNl8BEvc0,5084
|
|
37
36
|
machineconfig/cluster/templates/cli_gooey.py,sha256=KUiZDuqmHDkGS7NqwBTzZUbxysgasq-M0DWmwd44vOE,5534
|
|
38
37
|
machineconfig/cluster/templates/cli_trogon.py,sha256=PFWGy8SFYIhT9r3ZV4oIEYfImsQwzAHH_04stPuV5bY,647
|
|
39
38
|
machineconfig/cluster/templates/run_cloud.py,sha256=0o4-v5yFEqvlHzoKDXljRCR5ikx_r5w4oYE5OCtVIK8,2378
|
|
@@ -166,25 +165,25 @@ machineconfig/scripts/python/choose_wezterm_theme.py,sha256=Hlu_EOQhLM6wYdAdY25j
|
|
|
166
165
|
machineconfig/scripts/python/cloud_copy.py,sha256=d3gBSPBCtNCRDANpzUoCJBM3kHBarwizyZo8dkL_BXQ,8553
|
|
167
166
|
machineconfig/scripts/python/cloud_manager.py,sha256=MAVOKqXGxnlMaQGEv6k-q_PrgN0at6J8qQDhPiH2lI8,3488
|
|
168
167
|
machineconfig/scripts/python/cloud_mount.py,sha256=PLTPC9aH6v5g9lTJ8jFBBxz8ZGAuWo4sRU4FXfd1koA,6816
|
|
169
|
-
machineconfig/scripts/python/cloud_repo_sync.py,sha256=
|
|
168
|
+
machineconfig/scripts/python/cloud_repo_sync.py,sha256=GBhdUu9BJwhLYmhxxtvqJGLy7xKdQcnH9kkL4jcbzEE,9502
|
|
170
169
|
machineconfig/scripts/python/cloud_sync.py,sha256=RfgrEPGg_LrIaY3hfLDHsK8blrZvyPsoN66X0Z3WeCw,3859
|
|
171
|
-
machineconfig/scripts/python/croshell.py,sha256=
|
|
172
|
-
machineconfig/scripts/python/devops.py,sha256=
|
|
170
|
+
machineconfig/scripts/python/croshell.py,sha256=tDQaG4yxs_53Mvr9Fzc-HLuG-XVIBgcR3RRfJ4mxJhY,9561
|
|
171
|
+
machineconfig/scripts/python/devops.py,sha256=ws9AzqD-poLndODMFTe5bii3JNsPMsi0BuJJ11ZbPSw,5658
|
|
173
172
|
machineconfig/scripts/python/devops_add_identity.py,sha256=JfN3ZrYMCgmt4ks_VCfnV9BIIHAsOYO3E0W0wZ15FR8,3791
|
|
174
173
|
machineconfig/scripts/python/devops_add_ssh_key.py,sha256=KaoX83KltBsmutfKhSfZjd7nP_R1hJ2OLAWRhbswO7o,6889
|
|
175
174
|
machineconfig/scripts/python/devops_backup_retrieve.py,sha256=jZe5Vki7E2GCMG8hvqUZeOONFC4cNzISoGzq_dMG4GA,5601
|
|
176
|
-
machineconfig/scripts/python/devops_devapps_install.py,sha256=
|
|
175
|
+
machineconfig/scripts/python/devops_devapps_install.py,sha256=Q2suPkfwwdtIN3mjxH6tGZLYC7tZVxdxrGW7d9phiPA,9972
|
|
177
176
|
machineconfig/scripts/python/devops_update_repos.py,sha256=c5qBc9cuTGDEqDHufkjDT4d_vvJsswv3tlqk9MAulYk,8063
|
|
178
177
|
machineconfig/scripts/python/dotfile.py,sha256=1a4THWmfGXiJHjWGFf1Qbp6vrMEGIkonIofOcUVic90,2260
|
|
179
178
|
machineconfig/scripts/python/fire_agents.py,sha256=_k1CcPaAp3B7h72tSczFDbLsqTg6FmPDgxxU-GjRHWA,9179
|
|
180
179
|
machineconfig/scripts/python/fire_agents_help_launch.py,sha256=sTdjNz2pDinDMMjUAMN7OqH-KAUeHh6Aihr_zUvtM6k,6128
|
|
181
180
|
machineconfig/scripts/python/fire_agents_help_search.py,sha256=qIfSS_su2YJ1Gb0_lu4cbjlJlYMBw0v52NTGiSrGjk8,2991
|
|
182
181
|
machineconfig/scripts/python/fire_agents_load_balancer.py,sha256=QPiCbQq9j5REHStPdYqQcGNkz_rp5CjotqOpMY3v5TM,2099
|
|
183
|
-
machineconfig/scripts/python/fire_jobs.py,sha256=
|
|
184
|
-
machineconfig/scripts/python/fire_jobs_args_helper.py,sha256=
|
|
182
|
+
machineconfig/scripts/python/fire_jobs.py,sha256=W7JDckAWrpHlB3WHpULpZP3M22ORxvLO-6lcnRloHX8,20119
|
|
183
|
+
machineconfig/scripts/python/fire_jobs_args_helper.py,sha256=CeXmx0FJZlUSsQHcUmvHM2dQBmKcTNtTkha5PHaQQhc,1505
|
|
185
184
|
machineconfig/scripts/python/fire_jobs_layout_helper.py,sha256=Hj77uKgmNKSEBtnW0oCdRBwdKEuhzPxX1p81mRTBibo,3314
|
|
186
185
|
machineconfig/scripts/python/fire_jobs_streamlit_helper.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
187
|
-
machineconfig/scripts/python/ftpx.py,sha256=
|
|
186
|
+
machineconfig/scripts/python/ftpx.py,sha256=vqwhfkg3jVaAdjlWvrcPms2pUD7_c370jn2W6o5XArM,10269
|
|
188
187
|
machineconfig/scripts/python/get_zellij_cmd.py,sha256=e35-18hoXM9N3PFbvbizfkNY_-63iMicieWE3TbGcCQ,576
|
|
189
188
|
machineconfig/scripts/python/gh_models.py,sha256=3BLfW25mBRiPO5VKtVm-nMlKLv-PaZDw7mObajq6F6M,5538
|
|
190
189
|
machineconfig/scripts/python/mount_nfs.py,sha256=c8pWXimDWdgCkSskcnPgT-8ESPosil6Cvy2hGSaIBJE,3359
|
|
@@ -192,7 +191,7 @@ machineconfig/scripts/python/mount_nw_drive.py,sha256=iru6AtnTyvyuk6WxlK5R4lDkul
|
|
|
192
191
|
machineconfig/scripts/python/mount_ssh.py,sha256=rGY2pgtlnWMi0Rrge1aCdjtfbULrj2cyaStDoX-y2w4,2236
|
|
193
192
|
machineconfig/scripts/python/onetimeshare.py,sha256=bmGsNnskym5OWfIhpOfZG5jq3m89FS0a6dF5Sb8LaZM,2539
|
|
194
193
|
machineconfig/scripts/python/pomodoro.py,sha256=SPkfeoZGv8rylGiOyzQ7UK3aXZ3G2FIOuGkSuBUggOI,2019
|
|
195
|
-
machineconfig/scripts/python/repos.py,sha256=
|
|
194
|
+
machineconfig/scripts/python/repos.py,sha256=gU1gmYmiGTGDlZyIj3b1bC78yV5XZSXEkDD95WRqUnM,7376
|
|
196
195
|
machineconfig/scripts/python/repos_helper_clone.py,sha256=xW5YZEoNt3k7h9NIULhUhOnh53-B63eiXF2FjOl1IKQ,5535
|
|
197
196
|
machineconfig/scripts/python/repos_helper_record.py,sha256=YEEQORfEiLddOIIgePo5eEkyQUFruFg3kc8npMvRL-o,10927
|
|
198
197
|
machineconfig/scripts/python/repos_helper_update.py,sha256=AYyKIB7eQ48yoYmFjydIhRI1lV39TBv_S4_LCa-oKuQ,11042
|
|
@@ -230,9 +229,6 @@ machineconfig/scripts/python/ai/solutions/gemini/settings.json,sha256=hv0POw6ySh
|
|
|
230
229
|
machineconfig/scripts/python/ai/solutions/kilocode/privacy.md,sha256=oKOXnfFOdUuMlKwVf5MqeqCc24hZcjKE_e1MEXpijJI,117
|
|
231
230
|
machineconfig/scripts/python/ai/solutions/opencode/opencode.json,sha256=nahHKRw1dNzkUCS_vCX_fy2TisRtfg8DXH-D4N1iUVU,99
|
|
232
231
|
machineconfig/scripts/python/ai/solutions/opencode/opencode.py,sha256=AbpHGcgLb-kRsJGnwFEktk7uzpZOCcBY74-YBdrKVGs,1
|
|
233
|
-
machineconfig/scripts/python/archive/im2text.py,sha256=WLyic89vxi_pqQMzo-MOrGf39JEZjCdvDrXYUMVvZNY,1163
|
|
234
|
-
machineconfig/scripts/python/archive/tmate_conn.py,sha256=BiZQmYabl4K4-mbOpcb_R1JzYfEwxuAnk5FOciqGHFo,1231
|
|
235
|
-
machineconfig/scripts/python/archive/tmate_start.py,sha256=Hp7xv32u-fRuCG_f-Cy6qg0VemoaPOP-Pxs_gsFYcyg,1518
|
|
236
232
|
machineconfig/scripts/python/helpers/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
237
233
|
machineconfig/scripts/python/helpers/cloud_helpers.py,sha256=GA-bxXouUmknk9fyQAsPT-Xl3RG9-yBed71a2tu9Pig,4914
|
|
238
234
|
machineconfig/scripts/python/helpers/helpers2.py,sha256=ZdqeF1MLlaBRwoqsQAqnHi4b8rW0byFCBnbyCrPKkoA,7336
|
|
@@ -425,8 +421,8 @@ machineconfig/utils/schemas/fire_agents/fire_agents_input.py,sha256=CCs5ebomW1ac
|
|
|
425
421
|
machineconfig/utils/schemas/installer/installer_types.py,sha256=iAzcALc9z_FAQE9iuGHfX6Z0B1_n3Gt6eC0d6heYik0,599
|
|
426
422
|
machineconfig/utils/schemas/layouts/layout_types.py,sha256=OmiOX9xtakPz4l6IobWnpFHpbn95fitEE9q0YL1WxjQ,617
|
|
427
423
|
machineconfig/utils/schemas/repos/repos_types.py,sha256=ECVr-3IVIo8yjmYmVXX2mnDDN1SLSwvQIhx4KDDQHBQ,405
|
|
428
|
-
machineconfig-3.
|
|
429
|
-
machineconfig-3.
|
|
430
|
-
machineconfig-3.
|
|
431
|
-
machineconfig-3.
|
|
432
|
-
machineconfig-3.
|
|
424
|
+
machineconfig-3.82.dist-info/METADATA,sha256=lBIY_Ul0cOylp78PYNbNbIlXyzPRfyYGrWbBtFsrGiI,6998
|
|
425
|
+
machineconfig-3.82.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
|
426
|
+
machineconfig-3.82.dist-info/entry_points.txt,sha256=RwV4BmImYKp4GrXGqb_YDEI25O2_5mhsbvjUD6a0hps,1138
|
|
427
|
+
machineconfig-3.82.dist-info/top_level.txt,sha256=porRtB8qms8fOIUJgK-tO83_FeH6Bpe12oUVC670teA,14
|
|
428
|
+
machineconfig-3.82.dist-info/RECORD,,
|
|
@@ -6,13 +6,14 @@ cloud_repo_sync = machineconfig.scripts.python.cloud_repo_sync:args_parser
|
|
|
6
6
|
cloud_sync = machineconfig.scripts.python.cloud_sync:args_parser
|
|
7
7
|
croshell = machineconfig.scripts.python.croshell:build_parser
|
|
8
8
|
devops = machineconfig.scripts.python.devops:args_parser
|
|
9
|
-
fire = machineconfig.scripts.python.fire_jobs:
|
|
9
|
+
fire = machineconfig.scripts.python.fire_jobs:main_from_parser
|
|
10
10
|
fire_agents = machineconfig.scripts.python.fire_agents:main
|
|
11
|
-
ftpx = machineconfig.scripts.python.ftpx:
|
|
11
|
+
ftpx = machineconfig.scripts.python.ftpx:main_from_parser
|
|
12
12
|
initai = machineconfig.scripts.python.ai.initai:main
|
|
13
|
+
install = machineconfig.scripts.python.devops_devapps_install:main_with_parser
|
|
13
14
|
kill_process = machineconfig.utils.procs:main
|
|
14
15
|
mount_nfs = machineconfig.scripts.python.mount_nfs:main
|
|
15
16
|
mount_nw_drive = machineconfig.scripts.python.mount_nw_drive:main
|
|
16
|
-
repos = machineconfig.scripts.python.repos:
|
|
17
|
+
repos = machineconfig.scripts.python.repos:main_from_parser
|
|
17
18
|
start_slidev = machineconfig.scripts.python.start_slidev:main
|
|
18
19
|
wifi_conn = machineconfig.scripts.python.wifi_conn:main
|
|
@@ -1,102 +0,0 @@
|
|
|
1
|
-
# """Trogon
|
|
2
|
-
# """
|
|
3
|
-
|
|
4
|
-
# #
|
|
5
|
-
# # from machineconfig.cluster.distribute import Cluster, WorkloadParams
|
|
6
|
-
# from machineconfig.cluster.remote_machine import RemoteMachineConfig, RemoteMachine, CloudManager
|
|
7
|
-
# from machineconfig.cluster.templates.run_cloud import to_email_default, email_config_name_default, default_cloud
|
|
8
|
-
# import click
|
|
9
|
-
# # from trogon import tui
|
|
10
|
-
# from typing import Any, Optional
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
# @click.command()
|
|
14
|
-
# @click.option('--file', prompt="Py File: ", help="The file to run.", default="")
|
|
15
|
-
# @click.option('--function', prompt="Function: ", help="The function to run.", default=None)
|
|
16
|
-
# @click.pass_context
|
|
17
|
-
# def main2(ctx: Any, file: str, function: Optional[str] = None):
|
|
18
|
-
# ctx.obj = {'file': file, 'function': function}
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
# # @tui()
|
|
22
|
-
# # @click.group("gg")
|
|
23
|
-
# @click.command()
|
|
24
|
-
# @click.option('--file', prompt="Py File: ", help="The file to run.", default="")
|
|
25
|
-
# @click.option('--function', prompt="Function: ", help="The function to run.", default=None)
|
|
26
|
-
# @click.option('--description', prompt="Description of the job: ", default=f"Description of running func on remotes", help="Write something that describes what this job is about.")
|
|
27
|
-
# @click.option('--update_repo', prompt="Update repo: ", default=False, help="Update the repo on the remote machine.")
|
|
28
|
-
# @click.option('--update_essential_repos', prompt="Update essential repos: ", default=True, help="Update essential repos on the remote machine.")
|
|
29
|
-
# @click.option('--cloud_name', prompt="Cloud name: ", default=default_cloud, help="The name of the cloud to use.")
|
|
30
|
-
# @click.option('--notify_upon_completion', prompt="Notify upon completion: ", default=False, help="Send an email upon completion.")
|
|
31
|
-
# @click.option('--to_email', prompt="To email: ", default=to_email_default, help="The email to send to.")
|
|
32
|
-
# @click.option('--email_config_name', prompt="Email config name: ", default=email_config_name_default, help="The name of the email config to use.")
|
|
33
|
-
# @click.option('--kill_on_completion', prompt="Kill on completion: ", default=False)
|
|
34
|
-
# @click.option('--ipython', prompt="Use ipython: ", default=False)
|
|
35
|
-
# @click.option('--interactive', prompt="Interactive: ", default=False)
|
|
36
|
-
# @click.option('--pdb', prompt="Use pdb: ", default=False)
|
|
37
|
-
# @click.option('--pudb', prompt="Use pudb: ", default=False)
|
|
38
|
-
# @click.option('--wrap_in_try_except', prompt="Wrap in try except: ", default=False)
|
|
39
|
-
# @click.option('--lock_resources', prompt="Lock resources: ", default=False)
|
|
40
|
-
# @click.option('--max_simulataneous_jobs', prompt="Max simultaneous jobs: ", default=2)
|
|
41
|
-
# @click.option('--split', prompt="Split: ", default=1)
|
|
42
|
-
# @click.option('--reset_cloud', prompt="Reset cloud: ", default=False)
|
|
43
|
-
# @click.option('--reset_local', prompt="Reset local: ", default=False)
|
|
44
|
-
# # @click.pass_context
|
|
45
|
-
# def main(
|
|
46
|
-
# file: str, function: Optional[str],
|
|
47
|
-
# description: str, update_repo: bool, update_essential_repos: bool, cloud_name: str,
|
|
48
|
-
# notify_upon_completion: bool, to_email: str, email_config_name: str, kill_on_completion: bool, ipython: bool, interactive: bool,
|
|
49
|
-
# pdb: bool, pudb: bool, wrap_in_try_except: bool, lock_resources: bool, max_simulataneous_jobs: bool,
|
|
50
|
-
# split: int, reset_cloud: bool, reset_local: bool,
|
|
51
|
-
# ) -> Any:
|
|
52
|
-
|
|
53
|
-
# # function = ctx.obj['function']
|
|
54
|
-
# # description = ctx.obj['file']
|
|
55
|
-
# from machineconfig.cluster.self_ssh import SelfSSH
|
|
56
|
-
# config = RemoteMachineConfig(
|
|
57
|
-
# # connection
|
|
58
|
-
# ssh_obj=SelfSSH(),
|
|
59
|
-
# # ssh_params=None,
|
|
60
|
-
# description=description,
|
|
61
|
-
# # job_id=, base_dir="",
|
|
62
|
-
# # data
|
|
63
|
-
# copy_repo=False, # copy_repo,
|
|
64
|
-
# update_repo=update_repo,
|
|
65
|
-
# install_repo=True, # install_repo,
|
|
66
|
-
# update_essential_repos=update_essential_repos,
|
|
67
|
-
# data=[],
|
|
68
|
-
# transfer_method="cloud", # "transfer_method,
|
|
69
|
-
# cloud_name=cloud_name,
|
|
70
|
-
# # remote machine behaviour
|
|
71
|
-
# # open_console=open_console,
|
|
72
|
-
# notify_upon_completion=notify_upon_completion,
|
|
73
|
-
# to_email=to_email,
|
|
74
|
-
# email_config_name=email_config_name,
|
|
75
|
-
# kill_on_completion=kill_on_completion,
|
|
76
|
-
# workload_params=None,
|
|
77
|
-
# launch_method="cloud_manager",
|
|
78
|
-
# # execution behaviour
|
|
79
|
-
# ipython=ipython,
|
|
80
|
-
# interactive=interactive,
|
|
81
|
-
# pdb=pdb,
|
|
82
|
-
# pudb=pudb,
|
|
83
|
-
# wrap_in_try_except=wrap_in_try_except,
|
|
84
|
-
# # resources
|
|
85
|
-
# lock_resources=lock_resources,
|
|
86
|
-
# max_simulataneous_jobs=max_simulataneous_jobs,
|
|
87
|
-
# parallelize=False, # parallelize,
|
|
88
|
-
# )
|
|
89
|
-
|
|
90
|
-
# if function is not None:
|
|
91
|
-
# module: dict[str, Any] = Read.py(file)
|
|
92
|
-
# func = module[function]
|
|
93
|
-
# else: func = file
|
|
94
|
-
# m = RemoteMachine(func=func, func_kwargs=None, config=config)
|
|
95
|
-
# res = m.submit_to_cloud(split=split, cm=CloudManager(max_jobs=0, reset_local=reset_local), reset_cloud=reset_cloud)
|
|
96
|
-
# return res
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
# if __name__ == '__main__':
|
|
100
|
-
# # conf = get_options(standalone_mode=False) # type: ignore # pylint: disable=no-value-for-parameter
|
|
101
|
-
# # main2() # type: ignore
|
|
102
|
-
# main() # type: ignore
|
|
@@ -1,34 +0,0 @@
|
|
|
1
|
-
# """Convert image to text.
|
|
2
|
-
# """
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
# # import sys
|
|
6
|
-
# from rich.console import Console
|
|
7
|
-
# from rich.panel import Panel
|
|
8
|
-
# import pytesseract
|
|
9
|
-
# from PIL import Image
|
|
10
|
-
|
|
11
|
-
# console = Console()
|
|
12
|
-
|
|
13
|
-
# console.print(Panel("📸 Image to Text Converter", title="Status", expand=False))
|
|
14
|
-
|
|
15
|
-
# print("📷 Capturing image from webcam...")
|
|
16
|
-
# img_path = capture_from_webcam(show=False, wait=False, save=True)
|
|
17
|
-
# print(f"✅ Image captured and saved to: {img_path}")
|
|
18
|
-
|
|
19
|
-
# # img_rgb = cv2.cvtColor(img_cv, cv2.COLOR_BGR2RGB)
|
|
20
|
-
# # import cv2
|
|
21
|
-
# # img_cv = cv2.imread(r'C:\Users\alex\Downloads\name.jpg')
|
|
22
|
-
|
|
23
|
-
# # sys.path.insert(0, PathExtended.home().joinpath("AppData/Local/Tesseract-OCR").str)
|
|
24
|
-
# # import pytesseract
|
|
25
|
-
# # print(pytesseract.image_to_string(img_cv))
|
|
26
|
-
|
|
27
|
-
# print("\n🔍 Processing image with Tesseract OCR...")
|
|
28
|
-
# q = Terminal().run(f"cd ~/AppData/Local/Tesseract-OCR; pytesseract '{img_path}'", shell="pwsh").capture().op
|
|
29
|
-
|
|
30
|
-
# try:
|
|
31
|
-
# text = pytesseract.image_to_string(Image.open(img_path))
|
|
32
|
-
# console.print(Panel(text, title="📄 Extracted Text Result:", title_align="left", expand=False))
|
|
33
|
-
# except FileNotFoundError:
|
|
34
|
-
# print(f"Error: Image file not found at {img_path}")
|
|
@@ -1,41 +0,0 @@
|
|
|
1
|
-
import argparse
|
|
2
|
-
import configparser
|
|
3
|
-
from pathlib import Path
|
|
4
|
-
import random
|
|
5
|
-
import string
|
|
6
|
-
import os
|
|
7
|
-
from rich.console import Console
|
|
8
|
-
from rich.panel import Panel
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
console = Console()
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
def get_conn_string(sess_name: str) -> str:
|
|
15
|
-
creds = configparser.ConfigParser()
|
|
16
|
-
creds.read(Path.home().joinpath("dotfiles/creds/tmate/creds.ini"))
|
|
17
|
-
sess_name = creds["sessions_names"][sess_name]
|
|
18
|
-
user_name = creds["keys"]["username"]
|
|
19
|
-
return f"{user_name}/{sess_name}@sgp1.tmate.io"
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
def main():
|
|
23
|
-
console.print(Panel("🔌 Tmate Connection Manager", title="[bold]Welcome[/bold]"))
|
|
24
|
-
|
|
25
|
-
parser = argparse.ArgumentParser(description="Tmate launcher")
|
|
26
|
-
parser.add_argument("sess_name", help="session name", default=random.choices(list(string.digits + string.ascii_letters), k=20))
|
|
27
|
-
args = parser.parse_args()
|
|
28
|
-
|
|
29
|
-
console.print(f"🔍 Looking up session: {args.sess_name}")
|
|
30
|
-
conn_string = get_conn_string(args.sess_name)
|
|
31
|
-
|
|
32
|
-
console.print(Panel(f"SSH Connection String: ssh {conn_string}", title="[bold green]SSH Connection[/bold green]"))
|
|
33
|
-
|
|
34
|
-
console.print("🚀 Connecting to tmate session...")
|
|
35
|
-
os.system(f"ssh {conn_string}")
|
|
36
|
-
|
|
37
|
-
console.print("✅ Connection closed")
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
if __name__ == "__main__":
|
|
41
|
-
main()
|
|
@@ -1,44 +0,0 @@
|
|
|
1
|
-
"""Tmate"""
|
|
2
|
-
|
|
3
|
-
import argparse
|
|
4
|
-
import configparser
|
|
5
|
-
from pathlib import Path
|
|
6
|
-
import random
|
|
7
|
-
import string
|
|
8
|
-
import os
|
|
9
|
-
from rich.console import Console
|
|
10
|
-
from rich.panel import Panel
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
def main():
|
|
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
|
-
creds = configparser.ConfigParser()
|
|
20
|
-
creds.read(Path.home().joinpath("dotfiles/creds/tmate/creds.ini"))
|
|
21
|
-
console.print("[green]Credentials loaded[/green]")
|
|
22
|
-
|
|
23
|
-
parser = argparse.ArgumentParser(description="Tmate launcher")
|
|
24
|
-
random_sess = random.choices(list(string.digits + string.ascii_letters), k=20)
|
|
25
|
-
_ = random_sess
|
|
26
|
-
parser.add_argument("sess_name", help="session name (new only with random string will be chosen if not passed)", default=None)
|
|
27
|
-
|
|
28
|
-
args = parser.parse_args()
|
|
29
|
-
|
|
30
|
-
console.print(f"🔍 Looking up session configuration: {args.sess_name}")
|
|
31
|
-
sess_name = creds["sessions_names"][args.sess_name]
|
|
32
|
-
api_key = creds["keys"]["api_key"]
|
|
33
|
-
|
|
34
|
-
console.print(Panel(f"🚀 Starting tmate session: {sess_name}", title="[bold green]Session Info[/bold green]"))
|
|
35
|
-
|
|
36
|
-
res = f"tmate -a ~/.ssh/authorized_keys -k {api_key} -n {sess_name} -F"
|
|
37
|
-
console.print("[bold cyan]Running:[/bold cyan] tmate with configured API key and session name")
|
|
38
|
-
os.system(res)
|
|
39
|
-
|
|
40
|
-
console.print("[green]Tmate session ended[/green]")
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
if __name__ == "__main__":
|
|
44
|
-
main()
|
|
File without changes
|
|
File without changes
|