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.

@@ -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 = argparse.ArgumentParser(description="Secure Repo CLI.")
177
- # parser.add_argument("cmd", help="command to run", choices=["pull", "push"])
178
- parser.add_argument("path", nargs="?", type=str, help="Repository path, defaults to cwd.", default=None)
179
- # parser.add_argument("--share", help="Repository path, defaults to cwd.", action="store_true", default=False)
180
- parser.add_argument("--cloud", "-c", help="rclone cloud profile name.", default=None)
181
- parser.add_argument("--message", "-m", help="Commit Message", default=f"new message {randstr()}")
182
- # parser.add_argument("--skip_confirmation", "-s", help="Skip confirmation.", action="store_true", default=False)
183
- # parser.add_argument("--key", "-k", help="Key for encryption", default=None)
184
- parser.add_argument("--pwd", "-p", help="Password for encryption", default=None)
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 # Added import for rich.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.path_reduced import PathExtended
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 enum import Enum
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
- class Options(Enum):
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
- parser = argparse.ArgumentParser()
36
- new_line = "\n\n"
37
- parser.add_argument("-w", "--which", help=f"""which option to run\nChoose one of those:\n{new_line.join([f"{item.name}: {item.value}" for item in list(Options)])}""", type=str, default=None) # , choices=[op.value for op in Options]
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[str] = None):
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 = [op.value for op in 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 = Options[which].value
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 == Options.update.value:
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 == Options.cli_install.value:
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 == Options.sym_new.value:
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 == Options.sym_path_shell.value:
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 == Options.ssh_add_pubkey.value:
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 == Options.ssh_use_pair.value:
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 == Options.ssh_add_id.value: # so that you can SSH directly withuot pointing to identity 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 == Options.ssh_setup.value:
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 == Options.ssh_setup_wsl.value:
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 == Options.backup.value:
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 == Options.retreive.value:
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 == Options.scheduler.value:
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 main(which: Optional[WHICH_CAT | str]) -> None:
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 get_args, FireJobArgs, extract_kwargs
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
- args = get_args()
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
- args = get_args()
339
- route(args)
392
+ pass
@@ -1,6 +1,6 @@
1
1
  from dataclasses import dataclass
2
- from typing import Optional
3
- import argparse
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 argparse
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
- parser = argparse.ArgumentParser(description="FTP client")
23
-
24
- parser.add_argument("source", help="source path (machine:path)")
25
- parser.add_argument("target", help="target path (machine:path)")
26
-
27
- # FLAGS
28
- parser.add_argument("--recursive", "-r", help="Send recursively.", action="store_true") # default is False
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 = args.source.split(":")
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 args.target == ES:
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
- target = PathExtended(args.target).expanduser().absolute()
50
- source = target.collapseuser().as_posix()
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
- source = ":".join(args.source.split(":")[1:])
53
- if args.target == ES:
54
- target = None
54
+ resolved_source = ":".join(source.split(":")[1:])
55
+ if target == ES:
56
+ resolved_target = None
55
57
  else:
56
- target = PathExtended(args.target).expanduser().absolute().as_posix()
58
+ resolved_target = PathExtended(target).expanduser().absolute().as_posix()
57
59
 
58
- elif ":" in args.target and (args.target[1] != ":" if len(args.target) > 1 else True): # avoid the case of "C:/":
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 = args.target.split(":")
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 args.source == ES:
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
- source = args.source
72
- target = None
73
+ resolved_source = source
74
+ resolved_target = None
73
75
  else:
74
- target = ":".join(args.target.split(":")[1:])
75
- if args.source == ES:
76
- source = None
76
+ resolved_target = ":".join(target.split(":")[1:])
77
+ if source == ES:
78
+ resolved_source = None
77
79
  else:
78
- source = PathExtended(args.source).expanduser().absolute()
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(source), "target": str(target), "machine": machine}, "CLI Resolution")
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 args.cloud:
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 {source} :^", desc="Uploading from remote to the cloud.").print()
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 :^ {target}").print()
121
- received_file = PathExtended(target) # type: ignore
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 source is not None, """
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: {source}
130
- │ Target: {target}
131
- │ Options: {"ZIP compression" if args.zipFirst else "No compression"}, {"Recursive" if args.recursive else "Non-recursive"}
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=source, target=target, z=args.zipFirst, r=args.recursive)
135
+ received_file = ssh.copy_to_here(source=resolved_source, target=resolved_target, z=zipFirst, r=recursive)
134
136
  else:
135
- assert source is not None, """
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: {source}
141
- │ Target: {target}
142
- │ Options: {"ZIP compression" if args.zipFirst else "No compression"}, {"Recursive" if args.recursive else "Non-recursive"}
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=source, target=target, z=args.zipFirst, r=args.recursive)
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
- main()
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 argparse
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
- parser = argparse.ArgumentParser(description="REPO MANAGER")
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(args.directory).expanduser().absolute()
107
+ repos_root = PathExtended(directory).expanduser().absolute()
113
108
 
114
- auto_sync = not args.no_sync # Enable auto sync by default, disable with --no-sync
109
+ auto_sync = not no_sync # Enable auto sync by default, disable with --no-sync
115
110
 
116
- if args.record:
111
+ if record:
117
112
  save_path = record_repos(repos_root=repos_root)
118
- if args.cloud is not None:
119
- PathExtended(save_path).to_cloud(rel2home=True, cloud=args.cloud)
113
+ if cloud is not None:
114
+ PathExtended(save_path).to_cloud(rel2home=True, cloud=cloud)
120
115
 
121
- elif args.clone or args.checkout or args.checkout_to_branch:
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 args.cloud is None:
128
- cloud: str = read_ini(DEFAULTS_PATH)["general"]["rclone_config_name"]
129
- print(f"⚠️ Using default cloud: {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
- cloud = args.cloud
132
- assert cloud is not None, f"Path {repos_root} does not exist and cloud was not passed. You can't clone without one of them."
133
- repos_root.from_cloud(cloud=cloud, rel2home=True)
134
- assert (repos_root.exists() and repos_root.name == "repos.json") or args.cloud is not None, f"Path {repos_root} does not exist and cloud was not passed. You can't clone without one of them."
135
- clone_repos(spec_path=repos_root, preferred_remote=None, checkout_branch_flag=args.checkout_to_branch, checkout_commit_flag=args.checkout)
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 args.all or args.commit or args.pull or args.push:
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 args.pull or args.all:
144
- path_success = git_action(path=a_path, action=GitAction.pull, r=args.recursive, auto_sync=auto_sync) and path_success
145
- if args.commit or args.all:
146
- path_success = git_action(a_path, action=GitAction.commit, r=args.recursive, auto_sync=auto_sync) and path_success
147
- if args.push or args.all:
148
- path_success = git_action(a_path, action=GitAction.push, r=args.recursive, auto_sync=auto_sync) and path_success
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
- main()
159
+ main_from_parser()
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: machineconfig
3
- Version: 3.8
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=wXrCgZyPldFZAbK4cUsTHID7XIujz-eXdzgc0w6nkfE,10023
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=8ywivKgbg-2iaeAqrVWx4bKu6jM05pClGB5vCKghoMA,9638
172
- machineconfig/scripts/python/devops.py,sha256=VJWrRniX2suOi_E4x-6KU4x97TwbfvgXrNm47gjiXfg,6223
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=QBwBF9EC6kFj-93kNC1YS8N3P4g-eT9yCu0i0OrjYrY,9653
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=Ny0AdZE_ZX-Nq9wAY3T1gfa8Y_aOIR-I21q_Ulk7EcM,16713
184
- machineconfig/scripts/python/fire_jobs_args_helper.py,sha256=TfCKSExGZhYrZ6JmXIHsd0wpNSWcKeLeRh9gFR3FG-M,4330
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=VyvfdSa6ee0bMMG24HtBk7ooYeYSZuDUOJ7IkgJkdaU,9920
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=yaoUKJNq_xnXk8-2unH4OvoP5gw7sYR9ha2ajm76SBE,7451
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.8.dist-info/METADATA,sha256=eMF7Wf25jy644UorB76cz5tokYUdYvgwHmo4Q2RMS9M,6963
429
- machineconfig-3.8.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
430
- machineconfig-3.8.dist-info/entry_points.txt,sha256=gFSet9HBtk9WbSZcZ8Scv1k3CKibx_mKjySBGZ2tqbU,1023
431
- machineconfig-3.8.dist-info/top_level.txt,sha256=porRtB8qms8fOIUJgK-tO83_FeH6Bpe12oUVC670teA,14
432
- machineconfig-3.8.dist-info/RECORD,,
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:main
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:main
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:main
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()