machineconfig 1.7__py3-none-any.whl → 1.8__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of machineconfig might be problematic. Click here for more details.

Files changed (63) hide show
  1. machineconfig/__init__.py +2 -2
  2. machineconfig/jobs/python/check_installations.py +37 -31
  3. machineconfig/jobs/python/create_bootable_media.py +4 -4
  4. machineconfig/jobs/python/create_zellij_template.py +3 -2
  5. machineconfig/jobs/python/python_cargo_build_share.py +14 -9
  6. machineconfig/jobs/python/python_ve_symlink.py +6 -6
  7. machineconfig/jobs/{python_linux_installers/dev → script_installer}/azure_data_studio.py +6 -5
  8. machineconfig/jobs/{python_windows_installers/dev → script_installer}/bypass_paywall.py +5 -4
  9. machineconfig/jobs/script_installer/code.py +34 -0
  10. machineconfig/jobs/{python_linux_installers/dev → script_installer}/docker_desktop.py +2 -2
  11. machineconfig/jobs/script_installer/ngrok.py +29 -0
  12. machineconfig/jobs/script_installer/skim.py +21 -0
  13. machineconfig/jobs/script_installer/wezterm.py +34 -0
  14. machineconfig/profile/create.py +8 -6
  15. machineconfig/profile/shell.py +15 -13
  16. machineconfig/scripts/python/cloud_copy.py +14 -13
  17. machineconfig/scripts/python/cloud_mount.py +27 -11
  18. machineconfig/scripts/python/cloud_repo_sync.py +32 -14
  19. machineconfig/scripts/python/cloud_sync.py +9 -9
  20. machineconfig/scripts/python/croshell.py +3 -3
  21. machineconfig/scripts/python/devops.py +22 -6
  22. machineconfig/scripts/python/devops_add_identity.py +7 -6
  23. machineconfig/scripts/python/devops_add_ssh_key.py +10 -9
  24. machineconfig/scripts/python/devops_backup_retrieve.py +5 -5
  25. machineconfig/scripts/python/devops_devapps_install.py +13 -14
  26. machineconfig/scripts/python/devops_update_repos.py +5 -4
  27. machineconfig/scripts/python/dotfile.py +8 -4
  28. machineconfig/scripts/python/fire_jobs.py +95 -24
  29. machineconfig/scripts/python/ftpx.py +1 -1
  30. machineconfig/scripts/python/mount_nfs.py +13 -10
  31. machineconfig/scripts/python/mount_nw_drive.py +4 -3
  32. machineconfig/scripts/python/mount_ssh.py +8 -5
  33. machineconfig/scripts/python/repos.py +21 -20
  34. machineconfig/scripts/python/snapshot.py +2 -2
  35. machineconfig/scripts/python/start_slidev.py +104 -0
  36. machineconfig/setup_windows/wt_and_pwsh/set_pwsh_theme.py +20 -34
  37. machineconfig/setup_windows/wt_and_pwsh/set_wt_settings.py +11 -12
  38. machineconfig/utils/installer.py +96 -204
  39. machineconfig/utils/scheduling.py +1 -1
  40. machineconfig/utils/utils.py +102 -51
  41. machineconfig/utils/ve.py +96 -13
  42. {machineconfig-1.7.dist-info → machineconfig-1.8.dist-info}/METADATA +8 -8
  43. machineconfig-1.8.dist-info/RECORD +70 -0
  44. machineconfig/jobs/python_generic_installers/archive/gopass.py +0 -18
  45. machineconfig/jobs/python_generic_installers/archive/nvim.py +0 -20
  46. machineconfig/jobs/python_generic_installers/archive/opencommit.py +0 -25
  47. machineconfig/jobs/python_generic_installers/archive/strongbox.py +0 -33
  48. machineconfig/jobs/python_generic_installers/dev/__init__.py +0 -0
  49. machineconfig/jobs/python_linux_installers/archive/__init__.py +0 -0
  50. machineconfig/jobs/python_linux_installers/archive/bandwhich.py +0 -14
  51. machineconfig/jobs/python_linux_installers/archive/ranger.py +0 -19
  52. machineconfig/jobs/python_linux_installers/dev/bytehound.py +0 -20
  53. machineconfig/jobs/python_linux_installers/dev/nnn.py +0 -22
  54. machineconfig/jobs/python_windows_installers/archive/ntop.py +0 -21
  55. machineconfig/jobs/python_windows_installers/dev/obs_background_removal_plugin.py +0 -22
  56. machineconfig/scripts/python/choose_ohmybash_theme.py +0 -31
  57. machineconfig/scripts/python/choose_ohmyposh_theme.py +0 -57
  58. machineconfig/utils/pandas_type.py +0 -37
  59. machineconfig/utils/to_exe.py +0 -7
  60. machineconfig-1.7.dist-info/RECORD +0 -81
  61. /machineconfig/jobs/{python_generic_installers/archive → script_installer}/__init__.py +0 -0
  62. {machineconfig-1.7.dist-info → machineconfig-1.8.dist-info}/WHEEL +0 -0
  63. {machineconfig-1.7.dist-info → machineconfig-1.8.dist-info}/top_level.txt +0 -0
@@ -14,12 +14,13 @@ from typing import Optional
14
14
 
15
15
 
16
16
  @RepeatUntilNoException()
17
- def get_shared_file(url: Optional[str] = None, folder: Optional[str] = None):
17
+ def get_securely_shared_file(url: Optional[str] = None, folder: Optional[str] = None):
18
+ folder_obj = P.cwd() if folder is None else P(folder)
18
19
 
19
20
  if os.environ.get("DECRYPTION_PASSWORD") is not None:
20
- pwd = os.environ.get("DECRYPTION_PASSWORD")
21
+ pwd: str = str(os.environ.get("DECRYPTION_PASSWORD"))
21
22
  else:
22
- pwd = getpass.getpass("Enter decryption password: ")
23
+ pwd = getpass.getpass(prompt="Enter decryption password: ")
23
24
 
24
25
  if url is None:
25
26
  if os.environ.get("SHARE_URL") is not None:
@@ -31,10 +32,12 @@ def get_shared_file(url: Optional[str] = None, folder: Optional[str] = None):
31
32
  from rich.progress import Progress
32
33
  with Progress(transient=True) as progress:
33
34
  _task = progress.add_task("Downloading ... ", total=None)
34
- url_obj = P(url).download(folder=folder)
35
+ url_obj = P(url).download(folder=folder_obj)
35
36
  with Progress(transient=True) as progress:
36
37
  _task = progress.add_task("Decrypting ... ", total=None)
37
- res = url_obj.decrypt(pwd=pwd, inplace=True).unzip(inplace=True, merge=True)
38
+ tmp_folder = P.tmpdir(prefix="tmp_unzip")
39
+ res = url_obj.decrypt(pwd=pwd, inplace=True).unzip(inplace=True, folder=tmp_folder)
40
+ res.search("*").apply(lambda x: x.move(folder=folder_obj, overwrite=True))
38
41
  print(f"Decrypted to {res}")
39
42
 
40
43
 
@@ -44,19 +47,16 @@ def arg_parser() -> None:
44
47
  # positional argument
45
48
  parser.add_argument("source", help="file/folder path to be taken from here.")
46
49
  parser.add_argument("target", help="file/folder path to be be sent to here.")
47
- # FLAGS
48
- # parser.add_argument("--recursive", "-r", help="Send recursively.", action="store_true") # default is False
49
- parser.add_argument("--encrypt", "-e", help="Decrypt after receiving.", action="store_true", default=ArgsDefaults.encrypt)
50
- parser.add_argument("--zip", "-z", help="unzip after receiving.", action="store_true", default=ArgsDefaults.zip_)
50
+
51
51
  parser.add_argument("--overwrite", "-w", help="Overwrite existing file.", action="store_true", default=ArgsDefaults.overwrite)
52
52
  parser.add_argument("--share", "-s", help="Share file / directory", action="store_true", default=ArgsDefaults.share)
53
- # optional argument
54
53
  parser.add_argument("--rel2home", "-r", help="Relative to `myhome` folder", action="store_true", default=ArgsDefaults.rel2home)
55
54
  parser.add_argument("--root", "-R", help="Remote root. None is the default, unless rel2home is raied, making the default `myhome`.", default=ArgsDefaults.root)
56
- parser.add_argument("--os_specific", "-o", help="OS specific path (relevant only when relative flag is raised as well.", action="store_true", default=ArgsDefaults.os_specific)
57
55
 
58
56
  parser.add_argument("--key", "-k", help="Key for encryption", type=str, default=ArgsDefaults.key)
59
57
  parser.add_argument("--pwd", "-p", help="Password for encryption", type=str, default=ArgsDefaults.pwd)
58
+ parser.add_argument("--encrypt", "-e", help="Decrypt after receiving.", action="store_true", default=ArgsDefaults.encrypt)
59
+ parser.add_argument("--zip", "-z", help="unzip after receiving.", action="store_true", default=ArgsDefaults.zip_)
60
60
 
61
61
  parser.add_argument("--config", "-c", help="path to cloud.json file.", default=None)
62
62
 
@@ -67,7 +67,7 @@ def arg_parser() -> None:
67
67
  args_obj = Args(**args_dict)
68
68
  Struct(args_obj.__dict__).print(as_config=True, title=f"CLI config")
69
69
 
70
- if args_obj.config == "ss" and (source.startswith("http") or source.startswith("bit.ly")): return get_shared_file(url=source, folder=target)
70
+ if args_obj.config == "ss" and (source.startswith("http") or source.startswith("bit.ly")): return get_securely_shared_file(url=source, folder=target)
71
71
  if args_obj.rel2home is True and args_obj.root is None: args_obj.root = "myhome"
72
72
 
73
73
  cloud, source, target = parse_cloud_source_target(args=args_obj, source=source, target=target)
@@ -84,7 +84,8 @@ def arg_parser() -> None:
84
84
  zip=args_obj.zip, encrypt=args_obj.encrypt, pwd=args_obj.pwd,
85
85
  rel2home=args_obj.rel2home, root=args_obj.root, os_specific=args_obj.os_specific, strict=False,
86
86
  share=args_obj.share)
87
- if args_obj.share: print(res.as_url_str())
87
+ if args_obj.share:
88
+ print(res.as_url_str())
88
89
  else: raise ValueError(f"Cloud `{cloud}` not found in source or target.")
89
90
 
90
91
 
@@ -2,8 +2,10 @@
2
2
  """Cloud mount script
3
3
  """
4
4
 
5
- import crocodile.toolbox as tb
6
- from machineconfig.utils.utils import PROGRAM_PATH, display_options
5
+
6
+ from machineconfig.utils.utils import PROGRAM_PATH, choose_one_option
7
+ from crocodile.file_management import P, Read
8
+
7
9
  import platform
8
10
  import argparse
9
11
  from typing import Optional
@@ -13,17 +15,17 @@ DEFAULT_MOUNT = "~/data/rclone"
13
15
 
14
16
 
15
17
  def get_rclone_config():
16
- if platform.system() == "Windows": config = tb.Read.ini(tb.P.home().joinpath("AppData/Roaming/rclone/rclone.conf"))
17
- elif platform.system() == "Linux": config = tb.Read.ini(tb.P.home().joinpath(".config/rclone/rclone.conf"))
18
+ if platform.system() == "Windows": config = Read.ini(P.home().joinpath("AppData/Roaming/rclone/rclone.conf"))
19
+ elif platform.system() == "Linux": config = Read.ini(P.home().joinpath(".config/rclone/rclone.conf"))
18
20
  else: raise ValueError("unsupported platform")
19
21
  return config
20
22
 
21
23
 
22
24
  def get_mprocs_mount_txt(cloud: str, rclone_cmd: str, cloud_brand: str): # cloud_brand = config[cloud]["type"]
23
- # config = tb.Read.ini(tb.P.home().joinpath(".config/rclone/rclone.conf"))
25
+ # config = Read.ini(P.home().joinpath(".config/rclone/rclone.conf"))
24
26
  header = f"{' ' + cloud + ' | ' + cloud_brand + ' '}".center(50, "=")
25
27
  if platform.system() == "Windows":
26
- sub_text_path = tb.P.tmpfile(suffix=".ps1").write_text(f"""
28
+ sub_text_path = P.tmpfile(suffix=".ps1").write_text(f"""
27
29
  echo "{header}"
28
30
  iex 'rclone about {cloud}:'
29
31
  echo 'See {DEFAULT_MOUNT}/{cloud} for the mounted cloud'
@@ -40,19 +42,23 @@ mprocs "echo 'see {DEFAULT_MOUNT}/{cloud} for the mounted cloud'; rclone about {
40
42
  return txt
41
43
 
42
44
 
43
- def mount(cloud: Optional[str] = None, network: Optional[str] = None) -> None:
45
+ def mount(cloud: Optional[str], network: Optional[str], destination: Optional[str]) -> None:
44
46
 
45
47
  config = get_rclone_config()
46
48
  if cloud is None:
47
- res = display_options(msg="which cloud", options=config.sections(), header="CLOUD MOUNT", default=None)
49
+ res = choose_one_option(msg="which cloud", options=config.sections(), header="CLOUD MOUNT", default=None)
48
50
  if type(res) is str: cloud = res
49
51
  else: raise ValueError("no cloud selected")
50
- # assert isinstance(cloud, str)
52
+
53
+
51
54
  if network is None:
52
- mount_loc = tb.P(DEFAULT_MOUNT).expanduser().joinpath(cloud)
55
+ if destination is None: mount_loc = P(DEFAULT_MOUNT).expanduser().joinpath(cloud)
56
+ else: mount_loc = P(destination)
57
+
53
58
  if platform.system() == "Windows": mount_loc.parent.create()
54
59
  elif platform.system() == "Linux": mount_loc.create()
55
60
  else: raise ValueError("unsupported platform")
61
+
56
62
  elif network and platform.system() == "Windows": mount_loc = "X: --network-mode"
57
63
  else: raise ValueError("network mount only supported on windows")
58
64
 
@@ -63,6 +69,15 @@ def mount(cloud: Optional[str] = None, network: Optional[str] = None) -> None:
63
69
  wt --window 0 --profile "Windows PowerShell" --startingDirectory "$HOME/data/rclone" `; split-pane --horizontal --profile "Command Prompt" --size 0.2 powershell -Command "{mount_cmd}" `; split-pane --vertical --profile "Windows PowerShell" --size 0.2 powershell -NoExit -Command "rclone about {cloud}:" `; move-focus up
64
70
  """
65
71
  elif platform.system() == "Linux": txt = f"""
72
+
73
+ ZJ_SESSIONS=$(zellij list-sessions)
74
+
75
+ if [[ "${{ZJ_SESSIONS}}" != *"(current)"* ]]; then
76
+ echo "Not inside a zellij session ..."
77
+ echo '{mount_cmd}'
78
+ exit 1
79
+ fi
80
+
66
81
  zellij run --direction down --name rclone -- {mount_cmd}
67
82
  sleep 1; zellij action resize decrease down
68
83
  sleep 0.2; zellij action resize decrease up
@@ -90,9 +105,10 @@ zellij action move-focus up
90
105
  def main():
91
106
  parser = argparse.ArgumentParser(description='mount cloud')
92
107
  parser.add_argument('cloud', nargs='?', type=str, default=None, help='cloud to mount')
108
+ parser.add_argument('destination', nargs='?', type=str, default=None, help='destination to mount')
93
109
  parser.add_argument('--network', type=str, default=None, help='mount network drive')
94
110
  args = parser.parse_args()
95
- mount(cloud=args.cloud, network=args.network)
111
+ mount(cloud=args.cloud, network=args.network, destination=args.destination)
96
112
 
97
113
 
98
114
  if __name__ == '__main__':
@@ -1,8 +1,11 @@
1
1
 
2
2
  """utils"""
3
3
 
4
- import crocodile.toolbox as tb
4
+
5
5
  from machineconfig.utils.utils import CONFIG_PATH, DEFAULTS_PATH, write_shell_script, get_shell_file_executing_python_script
6
+ from crocodile.file_management import P, Read, install_n_import
7
+ from crocodile.core import randstr
8
+ from crocodile.meta import Terminal
6
9
  import argparse
7
10
  import platform
8
11
  from typing import Optional
@@ -10,10 +13,23 @@ from typing import Optional
10
13
  # import subprocess
11
14
 
12
15
 
13
- def get_wt_cmd(wd1: tb.P, wd2: tb.P) -> str: return f"""wt --window 0 new-tab --profile pwsh --title "gitdiff" --tabColor `#3b04d1 --startingDirectory {wd1} ` --colorScheme "Solarized Dark" `; split-pane --horizontal --profile pwsh --startingDirectory {wd2} --size 0.5 --colorScheme "Tango Dark" -- pwsh -Interactive"""
14
-
16
+ def get_wt_cmd(wd1: P, wd2: P) -> str:
17
+ lines = [
18
+ f"""wt --window 0 new-tab --profile pwsh --title "gitdiff" --tabColor `#3b04d1 --startingDirectory {wd1} ` --colorScheme "Solarized Dark" """,
19
+ f"""split-pane --horizontal --profile pwsh --startingDirectory {wd2} --size 0.5 --colorScheme "Tango Dark" -- pwsh -Interactive """
20
+ ]
21
+ return " `; ".join(lines)
15
22
 
16
- def get_zellij_cmd(wd1: tb.P, wd2: tb.P) -> str: return f""" zellij action new-tab --name gitdiff; zellij action new-pane --direction down --name local --cwd ./data; zellij action write-chars "cd '{wd1}'; git status"; zellij action move-focus up; zellij action close-pane; zellij action new-pane --direction down --name remote --cwd code; zellij action write-chars "cd '{wd2}'; git status" """
23
+ def get_zellij_cmd(wd1: P, wd2: P) -> str:
24
+ lines = [f""" zellij action new-tab --name gitdiff""",
25
+ f"""zellij action new-pane --direction down --name local --cwd ./data """,
26
+ f"""zellij action write-chars "cd '{wd1}'; git status" """,
27
+ f"""zellij action move-focus up; zellij action close-pane """,
28
+ f"""zellij action new-pane --direction down --name remote --cwd code """,
29
+ f"""zellij action write-chars "cd '{wd2}' """,
30
+ f"""git status" """
31
+ ]
32
+ return "; ".join(lines)
17
33
 
18
34
 
19
35
  def args_parser():
@@ -25,7 +41,7 @@ def args_parser():
25
41
  # parser.add_argument("--share", help="Repository path, defaults to cwd.", action="store_true", default=False)
26
42
 
27
43
  parser.add_argument("--cloud", "-c", help="rclone cloud profile name.", default=None)
28
- parser.add_argument("--message", "-m", help="Commit Message", default=f"new message {tb.randstr()}")
44
+ parser.add_argument("--message", "-m", help="Commit Message", default=f"new message {randstr()}")
29
45
  parser.add_argument("--skip_confirmation", "-s", help="Skip confirmation.", action="store_true", default=False)
30
46
  # parser.add_argument("--key", "-k", help="Key for encryption", default=None)
31
47
  parser.add_argument("--pwd", "-p", help="Password for encryption", default=None)
@@ -41,15 +57,17 @@ def args_parser():
41
57
 
42
58
  def main(cloud: Optional[str] = None, path: Optional[str] = None, message: Optional[str] = None, skip_confirmation: bool = False, pwd: Optional[str] = None, push: bool = True):
43
59
  if cloud is None:
44
- try: cloud_resolved = tb.Read.ini(DEFAULTS_PATH)['general']['rclone_config_name']
60
+ try:
61
+ cloud_resolved = Read.ini(DEFAULTS_PATH)['general']['rclone_config_name']
62
+ print(f"⚠️ Using default cloud: `{cloud_resolved}` from {DEFAULTS_PATH} ⚠️")
45
63
  except FileNotFoundError:
46
64
  print(f"No cloud profile found @ {DEFAULTS_PATH}, please set one up or provide one via the --cloud flag.")
47
65
  return ""
48
66
  else: cloud_resolved = cloud
49
- # repo_root = tb.P(args.repo).expanduser().absolute()
50
- repo_root = tb.P.cwd() if path is None else tb.P(path).expanduser().absolute()
51
- repo_obj = tb.install_n_import("git", "gitpython").Repo(repo_root, search_parent_directories=True)
52
- repo_root = tb.P(repo_obj.working_dir) # cwd might have been in a sub directory of repo_root, so its better to redefine it.
67
+ # repo_root = P(args.repo).expanduser().absolute()
68
+ repo_root = P.cwd() if path is None else P(path).expanduser().absolute()
69
+ repo_obj = install_n_import("git", "gitpython").Repo(repo_root, search_parent_directories=True)
70
+ repo_root = P(repo_obj.working_dir) # cwd might have been in a sub directory of repo_root, so its better to redefine it.
53
71
  CONFIG_PATH.joinpath("remote").create()
54
72
  repo_sync_root = CONFIG_PATH.joinpath("remote", repo_root.rel2home()) # .delete(sure=True)
55
73
  try:
@@ -60,7 +78,7 @@ def main(cloud: Optional[str] = None, path: Optional[str] = None, message: Optio
60
78
  print("Remote does not exist, creating it and exiting ... ")
61
79
  repo_root.to_cloud(cloud=cloud_resolved, zip=True, encrypt=True, rel2home=True, pwd=pwd, os_specific=False)
62
80
  return ""
63
- repo_sync_obj = tb.install_n_import("git", "gitpython").Repo(repo_sync_root)
81
+ repo_sync_obj = install_n_import("git", "gitpython").Repo(repo_sync_root)
64
82
  if repo_sync_obj.is_dirty():
65
83
  print("=" * 50, '\n', f"WRANING: the remote `{repo_sync_root}` is dirty, please commit or stash changes before proceeding.", '\n', "=" * 50)
66
84
 
@@ -84,7 +102,7 @@ git pull originEnc master
84
102
 
85
103
  """
86
104
  suffix = '.ps1' if platform.system() == 'Windows' else '.sh'
87
- res = tb.Terminal().run(f". {tb.P.tmpfile(suffix=suffix).write_text(script)}", shell="powershell").capture().print()
105
+ res = Terminal().run(f". {P.tmpfile(suffix=suffix).write_text(script)}", shell="powershell").capture().print()
88
106
 
89
107
  if res.is_successful(strict_err=True, strict_returcode=True):
90
108
  print("\n", "Pull succeeded, removing originEnc, the local copy of remote & pushing merged repo_root to remote ... ")
@@ -122,8 +140,8 @@ func(remote_repo=r'{repo_sync_root.str}', local_repo=r'{repo_root.str}', cloud=r
122
140
 
123
141
 
124
142
  def delete_remote_repo_copy_and_push_local(remote_repo: str, local_repo: str, cloud: str):
125
- repo_sync_root = tb.P(remote_repo).expanduser().absolute()
126
- repo_root_path = tb.P(local_repo).expanduser().absolute()
143
+ repo_sync_root = P(remote_repo).expanduser().absolute()
144
+ repo_root_path = P(local_repo).expanduser().absolute()
127
145
  repo_sync_root.delete(sure=True)
128
146
  from git.remote import Remote
129
147
  from git.repo import Repo
@@ -39,8 +39,6 @@ from pydantic import ConfigDict
39
39
 
40
40
  @dataclass(config=ConfigDict(extra="forbid", frozen=True))
41
41
  class Args():
42
- # source: str
43
- # target: str
44
42
  cloud: Optional[str] = None
45
43
 
46
44
  zip: bool = ArgsDefaults.zip_
@@ -81,12 +79,14 @@ def get_secure_share_cloud_config(interactive: bool = True) -> Args:
81
79
  cloud = default_cloud
82
80
  else:
83
81
  try:
84
- default_cloud = Read.ini(DEFAULTS_PATH)['general']['rclone_config_name']
82
+ default_cloud__ = Read.ini(DEFAULTS_PATH)['general']['rclone_config_name']
85
83
  except Exception:
86
- default_cloud = 'No default cloud found.'
87
- if default_cloud == 'No default cloud found.' or interactive:
88
- cloud = input(f"Enter cloud name (default {default_cloud}): ") or default_cloud
89
- else: cloud = default_cloud
84
+ default_cloud__ = 'No default cloud found.'
85
+ if default_cloud__ == 'No default cloud found.' or interactive:
86
+ # assert default_cloud is not None
87
+ cloud = input(f"Enter cloud name (default {default_cloud__}): ") or default_cloud__
88
+ else:
89
+ cloud = default_cloud__
90
90
 
91
91
  default_password_path = P.home().joinpath("dotfiles/creds/passwords/quick_password")
92
92
  if default_password_path.exists():
@@ -99,7 +99,7 @@ def get_secure_share_cloud_config(interactive: bool = True) -> Args:
99
99
  res = Args(cloud=cloud,
100
100
  pwd=pwd, encrypt=True,
101
101
  zip=True, overwrite=True, share=True,
102
- rel2home=True, root="myhome", os_specific=False,)
102
+ rel2home=True, root="myshare", os_specific=False,)
103
103
  Struct(res.__dict__).print(as_config=True, title=f"⚠️ Using SecureShare cloud config")
104
104
  return res
105
105
 
@@ -215,7 +215,7 @@ def args_parser():
215
215
  parser.add_argument("--transfers", "-t", help="Number of threads in syncing.", default=10) # default is False
216
216
  parser.add_argument("--root", "-R", help="Remote root.", default="myhome") # default is False
217
217
 
218
- # parser.add_argument("--key", "-k", help="Key for encryption", default=None)
218
+ parser.add_argument("--key", "-k", help="Key for encryption", default=None)
219
219
  parser.add_argument("--pwd", "-P", help="Password for encryption", default=None)
220
220
  parser.add_argument("--encrypt", "-e", help="Decrypt after receiving.", action="store_true") # default is False
221
221
  parser.add_argument("--zip", "-z", help="unzip after receiving.", action="store_true") # default is False
@@ -34,7 +34,7 @@ def get_read_data_pycode(path: str):
34
34
  p = P(r\'{path}\').absolute()
35
35
  try:
36
36
  dat = p.readit()
37
- if type(dat) == tb.Struct: dat.print(as_config=True, title=p.name)
37
+ if type(dat) == Struct: dat.print(as_config=True, title=p.name)
38
38
  else: print(f"Succcesfully read the file {{p.name}}")
39
39
  except Exception as e:
40
40
  print(e)
@@ -67,7 +67,7 @@ def build_parser():
67
67
  parser.add_argument("--fzf", "-F", help="search with fuzzy finder for python scripts and run them", action="store_true", default=False)
68
68
 
69
69
  # OPTIONAL KEYWORD
70
- parser.add_argument("--venv", "-v", help="virtual enviroment to use, defaults to activated ve, if existed, else ve.", default=None)
70
+ parser.add_argument("--ve", "-v", help="virtual enviroment to use, defaults to activated ve, if existed, else ve.", default=None)
71
71
  parser.add_argument("--profile", "-P", help="ipython profile to use, defaults to default profile.", default=None)
72
72
  parser.add_argument("--read", "-r", dest="read", help="read a binary file.", default="")
73
73
  parser.add_argument("--file", "-f", dest="file", help="python file path to interpret", default="")
@@ -131,7 +131,7 @@ print_logo(logo="crocodile")
131
131
  pyfile.write_text(total_program, encoding='utf-8')
132
132
  if profile is None: profile = "default"
133
133
 
134
- ve = get_ve_profile(P(file)) if args.venv is None else str(args.ve)
134
+ ve = get_ve_profile(P(file)) if args.ve is None else str(args.ve)
135
135
 
136
136
  final_program = f"""
137
137
  # deactivate
@@ -1,11 +1,11 @@
1
1
 
2
+
3
+
2
4
  """devops
3
5
  """
4
-
5
- from platform import system
6
- # import subprocess
7
- # import crocodile.toolbox as tb
6
+ from crocodile.file_management import P
8
7
  from machineconfig.utils.utils import display_options, PROGRAM_PATH, write_shell_script
8
+ from platform import system
9
9
  from enum import Enum
10
10
  from typing import Optional
11
11
 
@@ -48,8 +48,24 @@ def main(which: Optional[str] = None):
48
48
  program = helper.main()
49
49
 
50
50
  elif choice_key == Options.ve.value:
51
- from machineconfig.utils.ve import get_ve_install_script
52
- program = get_ve_install_script()
51
+ program = ""
52
+ reply: bool = False
53
+ if P.cwd().joinpath(".ve.ini").exists():
54
+ reply = input("Detected .ve.ini file. Do you want to use it to build ve? (y/[n]): ") == "y"
55
+ if reply:
56
+ from machineconfig.utils.ve import get_ve_install_script_from_specs
57
+ program_win = get_ve_install_script_from_specs(repo_root=P.cwd().str, system="Windows")
58
+ program_lin = get_ve_install_script_from_specs(repo_root=P.cwd().str, system="Linux")
59
+ install_reply = input("Proceed with installation? (y/[n]): ") == "y"
60
+ if not install_reply: program = ""
61
+ else:
62
+ if system() == "Windows": program = program_win
63
+ elif system() == "Linux": program = program_lin
64
+ else: raise ValueError(f"Unknown system: {system()}")
65
+
66
+ if not reply:
67
+ from machineconfig.utils.ve import get_ve_install_script
68
+ program = get_ve_install_script()
53
69
 
54
70
  elif choice_key == Options.cli_install.value:
55
71
  import machineconfig.scripts.python.devops_devapps_install as helper
@@ -2,20 +2,21 @@
2
2
  """ID
3
3
  """
4
4
 
5
- import crocodile.toolbox as tb
5
+
6
6
  # from platform import system
7
+ from crocodile.file_management import P
7
8
  from machineconfig.utils.utils import display_options
8
9
 
9
10
 
10
11
  def main():
11
- private_keys = tb.P.home().joinpath(".ssh").search("*.pub").apply(lambda x: x.with_name(x.stem)).filter(lambda x: x.exists())
12
+ private_keys = P.home().joinpath(".ssh").search("*.pub").apply(lambda x: x.with_name(x.stem)).filter(lambda x: x.exists())
12
13
  choice = display_options(msg="Path to private key to be used when ssh'ing: ", options=private_keys.apply(str).list + ["I have the path to the key file", "I want to paste the key itself"])
13
- if choice == "I have the path to the key file": path_to_key = tb.P(input("Input path here: ")).expanduser().absolute()
14
- elif choice == "I want to paste the key itself": path_to_key = tb.P.home().joinpath(f".ssh/{input('file name (default: my_pasted_key): ') or 'my_pasted_key'}").write_text(input("Paste the private key here: "))
15
- elif isinstance(choice, str): path_to_key = tb.P(choice)
14
+ if choice == "I have the path to the key file": path_to_key = P(input("Input path here: ")).expanduser().absolute()
15
+ elif choice == "I want to paste the key itself": path_to_key = P.home().joinpath(f".ssh/{input('file name (default: my_pasted_key): ') or 'my_pasted_key'}").write_text(input("Paste the private key here: "))
16
+ elif isinstance(choice, str): path_to_key = P(choice)
16
17
  else: raise NotImplementedError(f"Choice {choice} not supported")
17
18
  txt = f"IdentityFile {path_to_key.collapseuser().as_posix()}" # adds this id for all connections, no host specified.
18
- config_path = tb.P.home().joinpath(".ssh/config")
19
+ config_path = P.home().joinpath(".ssh/config")
19
20
  if config_path.exists(): config_path.modify_text(txt_search=txt, txt_alt=txt, replace_line=True, notfound_append=True, prepend=True) # note that Identity line must come on top of config file otherwise it won't work, hence `prepend=True`
20
21
  else: config_path.write_text(txt)
21
22
  program = f"echo 'Finished adding identity to ssh config file. {'*'*50} Consider reloading config file.'"
@@ -2,14 +2,15 @@
2
2
  """SSH
3
3
  """
4
4
 
5
- import crocodile.toolbox as tb
5
+
6
6
  from platform import system
7
7
  from machineconfig.utils.utils import LIBRARY_ROOT, display_options
8
+ from crocodile.file_management import P
8
9
 
9
10
 
10
- def get_add_ssh_key_script(path_to_key: tb.P):
11
- if system() == "Linux": authorized_keys = tb.P.home().joinpath(".ssh/authorized_keys")
12
- elif system() == "Windows": authorized_keys = tb.P("C:/ProgramData/ssh/administrators_authorized_keys")
11
+ def get_add_ssh_key_script(path_to_key: P):
12
+ if system() == "Linux": authorized_keys = P.home().joinpath(".ssh/authorized_keys")
13
+ elif system() == "Windows": authorized_keys = P("C:/ProgramData/ssh/administrators_authorized_keys")
13
14
  else: raise NotImplementedError
14
15
 
15
16
  if authorized_keys.exists():
@@ -35,7 +36,7 @@ def get_add_ssh_key_script(path_to_key: tb.P):
35
36
  program = f"cat {path_to_key} > ~/.ssh/authorized_keys"
36
37
  else:
37
38
  program = LIBRARY_ROOT.joinpath("setup_windows/openssh-server_add-sshkey.ps1")
38
- program = tb.P(program).expanduser().read_text().replace('$sshfile=""', f'$sshfile="{path_to_key}"')
39
+ program = P(program).expanduser().read_text().replace('$sshfile=""', f'$sshfile="{path_to_key}"')
39
40
 
40
41
  if system() == "Linux": program += f"""
41
42
 
@@ -50,17 +51,17 @@ sudo service ssh --full-restart
50
51
 
51
52
 
52
53
  def main():
53
- pub_keys = tb.P.home().joinpath(".ssh").search("*.pub")
54
+ pub_keys = P.home().joinpath(".ssh").search("*.pub")
54
55
  all_keys_option = f"all pub keys available ({len(pub_keys)})"
55
56
  i_have_path_option = "I have the path to the key file"
56
57
  i_paste_option = "I want to paste the key itself"
57
58
  res = display_options("Which public key to add? ", options=pub_keys.apply(str).list + [all_keys_option, i_have_path_option, i_paste_option])
58
59
  assert isinstance(res, str), f"Got {res} of type {type(res)} instead of str."
59
60
  if res == all_keys_option: program = "\n\n\n".join(pub_keys.apply(get_add_ssh_key_script))
60
- elif res == i_have_path_option: program = get_add_ssh_key_script(tb.P(input("Path: ")).expanduser().absolute())
61
- elif res == i_paste_option: program = get_add_ssh_key_script(tb.P.home().joinpath(f".ssh/{input('file name (default: my_pasted_key.pub): ') or 'my_pasted_key.pub'}").write_text(input("Paste the pub key here: ")))
61
+ elif res == i_have_path_option: program = get_add_ssh_key_script(P(input("Path: ")).expanduser().absolute())
62
+ elif res == i_paste_option: program = get_add_ssh_key_script(P.home().joinpath(f".ssh/{input('file name (default: my_pasted_key.pub): ') or 'my_pasted_key.pub'}").write_text(input("Paste the pub key here: ")))
62
63
  else:
63
- program = get_add_ssh_key_script(tb.P(res))
64
+ program = get_add_ssh_key_script(P(res))
64
65
  print(program)
65
66
  return program
66
67
 
@@ -2,11 +2,11 @@
2
2
  """BR: Backup and Retrieve
3
3
  """
4
4
 
5
- from platform import system
6
5
  # import subprocess
7
- import crocodile.toolbox as tb
6
+ from crocodile.file_management import Read, P
8
7
  from machineconfig.utils.utils import LIBRARY_ROOT, DEFAULTS_PATH, print_code, choose_cloud_interactively, display_options
9
8
  from machineconfig.scripts.python.cloud_sync import ES
9
+ from platform import system
10
10
  from typing import Any, Literal, Optional
11
11
 
12
12
 
@@ -15,7 +15,7 @@ OPTIONS = Literal["BACKUP", "RETRIEVE"]
15
15
 
16
16
  def main(direction: OPTIONS, which: Optional[str] = None):
17
17
  try:
18
- cloud: str = tb.Read.ini(DEFAULTS_PATH)['general']['rclone_config_name']
18
+ cloud: str = Read.ini(DEFAULTS_PATH)['general']['rclone_config_name']
19
19
  print(f"\n{'--' * 50}\n ⚠️ Using default cloud: `{cloud}` ⚠️\n{'--' * 50}\n")
20
20
  except (FileNotFoundError, KeyError, IndexError): cloud = choose_cloud_interactively()
21
21
 
@@ -40,8 +40,8 @@ def main(direction: OPTIONS, which: Optional[str] = None):
40
40
  flags += 'r' if item['rel2home'] == 'True' else ''
41
41
  flags += 'o' if system().lower() in item_name else ''
42
42
  if flags: flags = "-" + flags
43
- if direction == "BACKUP": program += f"""\ncloud_copy "{tb.P(item['path']).as_posix()}" $cloud {flags}\n"""
44
- elif direction == "RETRIEVE": program += f"""\ncloud_copy $cloud "{tb.P(item['path']).as_posix()}" {flags}\n"""
43
+ if direction == "BACKUP": program += f"""\ncloud_copy "{P(item['path']).as_posix()}" $cloud {flags}\n"""
44
+ elif direction == "RETRIEVE": program += f"""\ncloud_copy $cloud "{P(item['path']).as_posix()}" {flags}\n"""
45
45
  else: raise RuntimeError(f"Unknown direction: {direction}")
46
46
  if item_name == "dotfiles" and system() == "Linux": program += f"""\nchmod 700 ~/.ssh/*\n"""
47
47
  print_code(program, lexer="shell", desc=f"{direction} script")
@@ -2,11 +2,11 @@
2
2
  """Devops Devapps Install
3
3
  """
4
4
 
5
- from platform import system
6
5
  # import subprocess
7
- import crocodile.toolbox as tb
6
+ from crocodile.core import List as L
8
7
  from machineconfig.utils.utils import LIBRARY_ROOT, choose_multiple_options
9
- from machineconfig.utils.installer import get_cli_py_installers_v2, Installer, install_all_v2
8
+ from machineconfig.utils.installer import get_installers, Installer, install_all
9
+ from platform import system
10
10
  from typing import Any, Optional, Literal, TypeAlias
11
11
 
12
12
 
@@ -15,7 +15,7 @@ WHICH: TypeAlias = Literal["AllEssentials", "EssentialsAndOthers", "SystemInstal
15
15
 
16
16
  def main(which: Optional[str] = None):
17
17
  sys = system()
18
- installers = get_cli_py_installers_v2(dev=False, system=sys)
18
+ installers = get_installers(dev=False, system=sys) + get_installers(dev=True, system=sys)
19
19
  default = "AllEssentials"
20
20
  options = ["SystemInstallers", "OtherDevApps", "EssentialsAndOthers", "PrecheckedCloudInstaller"]
21
21
  options = [default] + options
@@ -34,10 +34,10 @@ def main(which: Optional[str] = None):
34
34
 
35
35
  def get_program(program_name: str, options: list[str], installers: list[Installer]):
36
36
  if program_name == "AllEssentials" or program_name == "EssentialsAndOthers":
37
- installers_ = get_cli_py_installers_v2(dev=False, system=system())
37
+ installers_ = get_installers(dev=False, system=system())
38
38
  if program_name == "EssentialsAndOthers":
39
- installers_ += get_cli_py_installers_v2(dev=True, system=system())
40
- install_all_v2(installers=tb.L(installers))
39
+ installers_ += get_installers(dev=True, system=system())
40
+ install_all(installers=L(installers))
41
41
  program = ""
42
42
  elif program_name == "SystemInstallers":
43
43
  if system() == "Windows": options_system = parse_apps_installer_windows(LIBRARY_ROOT.joinpath("setup_windows/apps.ps1").read_text())
@@ -50,9 +50,10 @@ def get_program(program_name: str, options: list[str], installers: list[Installe
50
50
  if sub_program.startswith("#winget"): sub_program = sub_program[1:]
51
51
  program += "\n" + sub_program
52
52
  elif program_name == "OtherDevApps":
53
- installers = get_cli_py_installers_v2(dev=True, system=system())
53
+ installers = get_installers(dev=True, system=system())
54
54
  options__: list[str] = [x.get_description() for x in installers]
55
- program_names = choose_multiple_options(msg="", options=sorted(options__), header="CHOOSE DEV APP")
55
+ program_names = choose_multiple_options(msg="", options=sorted(options__) + ["all"], header="CHOOSE DEV APP")
56
+ if "all" in program_names: program_names = options__
56
57
  program = ""
57
58
  for name in program_names:
58
59
  try:
@@ -62,8 +63,6 @@ def get_program(program_name: str, options: list[str], installers: list[Installe
62
63
  print(f"{options__=}")
63
64
  raise ve
64
65
  sub_program = installers[idx].install_robust(version=None) # finish the task
65
- # sub_program = "echo 'Finished Installation'" # write an empty program
66
- # program += "\n" + ""sub_program
67
66
  elif program_name == "PrecheckedCloudInstaller":
68
67
  from machineconfig.jobs.python.check_installations import PrecheckedCloudInstaller
69
68
  ci = PrecheckedCloudInstaller()
@@ -97,7 +96,7 @@ def parse_apps_installer_windows(txt: str) -> dict[str, Any]:
97
96
  if idx == 0: continue
98
97
  if idx == 1: chunks.append(item)
99
98
  else: chunks.append("winget install" + item)
100
- # progs = tb.L(txt.splitlines()).filter(lambda x: x.startswith("winget ") or x.startswith("#winget"))
99
+ # progs = L(txt.splitlines()).filter(lambda x: x.startswith("winget ") or x.startswith("#winget"))
101
100
  res: dict[str, str] = {}
102
101
  for a_chunk in chunks:
103
102
  try:
@@ -110,8 +109,8 @@ def parse_apps_installer_windows(txt: str) -> dict[str, Any]:
110
109
  except IndexError as e:
111
110
  print(a_chunk)
112
111
  raise e
113
- # tb.Struct(res).print(as_config=True)
114
- # tb.L(chunks).print(sep="-----------------------------------------------------------------------\n\n")
112
+ # Struct(res).print(as_config=True)
113
+ # L(chunks).print(sep="-----------------------------------------------------------------------\n\n")
115
114
  # import time
116
115
  # time.sleep(10)
117
116
  return res
@@ -2,9 +2,10 @@
2
2
  """Update
3
3
  """
4
4
 
5
- from platform import system
6
- import crocodile.toolbox as tb
5
+ from crocodile.file_management import P, Read
6
+ from crocodile.core import install_n_import
7
7
  from machineconfig.utils.utils import DEFAULTS_PATH
8
+ from platform import system
8
9
 
9
10
 
10
11
  sep = "\n"
@@ -14,7 +15,7 @@ def main(verbose: bool = True) -> str:
14
15
  _ = verbose
15
16
  repos: list[str] = ["~/code/crocodile", "~/code/machineconfig", ]
16
17
  try:
17
- tmp = tb.Read.ini(DEFAULTS_PATH)['general']['repos'].split(",")
18
+ tmp = Read.ini(DEFAULTS_PATH)['general']['repos'].split(",")
18
19
  if tmp[-1] == "": tmp = tmp[:-1]
19
20
  repos += tmp
20
21
  except (FileNotFoundError, KeyError, IndexError):
@@ -30,7 +31,7 @@ to_email = myemail@email.com
30
31
  repos_objs = []
31
32
  for a_package_path in repos:
32
33
  try:
33
- repo = tb.install_n_import("git", "gitpython").Repo(str(tb.P(a_package_path).expanduser()), search_parent_directories=True)
34
+ repo = install_n_import("git", "gitpython").Repo(str(P(a_package_path).expanduser()), search_parent_directories=True)
34
35
  repos_objs.append(repo)
35
36
  except Exception as ex:
36
37
  print(ex)
@@ -1,8 +1,12 @@
1
1
 
2
- import argparse
3
- import crocodile.toolbox as tb
2
+ """Like yadm and dotter.
3
+ """
4
+
5
+
6
+ from crocodile.file_management import P
4
7
  from machineconfig.profile.create import symlink
5
8
  from machineconfig.utils.utils import LIBRARY_ROOT, REPO_ROOT
9
+ import argparse
6
10
 
7
11
 
8
12
  def main():
@@ -15,14 +19,14 @@ def main():
15
19
  parser.add_argument("-d", "--dest", help=f"destination folder", default="")
16
20
 
17
21
  args = parser.parse_args()
18
- orig_path = tb.P(args.file).expanduser().absolute()
22
+ orig_path = P(args.file).expanduser().absolute()
19
23
  if args.dest == "":
20
24
  if "Local" in orig_path: junction = orig_path.split(at="Local", sep=-1)[1]
21
25
  elif "Roaming" in orig_path: junction = orig_path.split(at="Roaming", sep=-1)[1]
22
26
  elif ".config" in orig_path: junction = orig_path.split(at=".config", sep=-1)[1]
23
27
  else: junction = orig_path.rel2home()
24
28
  new_path = REPO_ROOT.joinpath(junction)
25
- else: new_path = tb.P(args.dest).expanduser().absolute().create().joinpath(orig_path.name)
29
+ else: new_path = P(args.dest).expanduser().absolute().create().joinpath(orig_path.name)
26
30
 
27
31
  symlink(this=orig_path, to_this=new_path, prioritize_to_this=args.overwrite)
28
32