machineconfig 1.9__py3-none-any.whl → 1.91__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 (53) hide show
  1. machineconfig/__init__.py +1 -1
  2. machineconfig/jobs/python/check_installations.py +7 -5
  3. machineconfig/jobs/python/checkout_version.py +27 -32
  4. machineconfig/jobs/python/create_bootable_media.py +1 -1
  5. machineconfig/jobs/python/python_cargo_build_share.py +2 -2
  6. machineconfig/jobs/python/tasks.py +2 -2
  7. machineconfig/jobs/python_custom_installers/{helix.py → hx.py} +17 -5
  8. machineconfig/profile/create.py +23 -21
  9. machineconfig/profile/create_hardlinks.py +101 -0
  10. machineconfig/profile/shell.py +5 -5
  11. machineconfig/scripts/python/cloud_copy.py +19 -16
  12. machineconfig/scripts/python/cloud_repo_sync.py +92 -47
  13. machineconfig/scripts/python/cloud_sync.py +70 -63
  14. machineconfig/scripts/python/croshell.py +6 -6
  15. machineconfig/scripts/python/devops.py +19 -20
  16. machineconfig/scripts/python/devops_backup_retrieve.py +19 -10
  17. machineconfig/scripts/python/devops_devapps_install.py +80 -62
  18. machineconfig/scripts/python/devops_update_repos.py +5 -5
  19. machineconfig/scripts/python/dotfile.py +4 -4
  20. machineconfig/scripts/python/fire_jobs.py +57 -23
  21. machineconfig/scripts/python/gh_models.py +53 -0
  22. machineconfig/scripts/python/mount_nfs.py +1 -1
  23. machineconfig/scripts/python/mount_nw_drive.py +3 -3
  24. machineconfig/scripts/python/mount_ssh.py +2 -3
  25. machineconfig/scripts/python/pomodoro.py +1 -1
  26. machineconfig/scripts/python/repos.py +21 -22
  27. machineconfig/scripts/python/scheduler.py +1 -1
  28. machineconfig/scripts/python/start_slidev.py +10 -4
  29. machineconfig/scripts/python/start_terminals.py +5 -4
  30. machineconfig/scripts/python/wifi_conn.py +34 -42
  31. machineconfig/scripts/python/wsl_windows_transfer.py +1 -1
  32. machineconfig/setup_windows/wt_and_pwsh/set_pwsh_theme.py +1 -1
  33. machineconfig/setup_windows/wt_and_pwsh/set_wt_settings.py +3 -2
  34. machineconfig/utils/installer.py +78 -39
  35. machineconfig/utils/procs.py +2 -2
  36. machineconfig/utils/scheduling.py +3 -3
  37. machineconfig/utils/utils.py +131 -52
  38. machineconfig/utils/ve.py +145 -95
  39. {machineconfig-1.9.dist-info → machineconfig-1.91.dist-info}/METADATA +160 -155
  40. machineconfig-1.91.dist-info/RECORD +69 -0
  41. machineconfig/jobs/python_custom_installers/azuredatastudio.py +0 -36
  42. machineconfig/jobs/python_custom_installers/bypass_paywall.py +0 -30
  43. machineconfig/jobs/python_custom_installers/docker_desktop.py +0 -52
  44. machineconfig/jobs/python_custom_installers/goes.py +0 -35
  45. machineconfig/jobs/python_custom_installers/lvim.py +0 -48
  46. machineconfig/jobs/python_custom_installers/ngrok.py +0 -39
  47. machineconfig/jobs/python_custom_installers/nvim.py +0 -48
  48. machineconfig/jobs/python_custom_installers/vscode.py +0 -45
  49. machineconfig/jobs/python_custom_installers/wezterm.py +0 -41
  50. machineconfig-1.9.dist-info/RECORD +0 -76
  51. {machineconfig-1.9.dist-info → machineconfig-1.91.dist-info}/LICENSE +0 -0
  52. {machineconfig-1.9.dist-info → machineconfig-1.91.dist-info}/WHEEL +0 -0
  53. {machineconfig-1.9.dist-info → machineconfig-1.91.dist-info}/top_level.txt +0 -0
machineconfig/__init__.py CHANGED
@@ -2,7 +2,7 @@
2
2
  """DS
3
3
  """
4
4
 
5
- __version__ = "1.9"
5
+ __version__ = "1.91"
6
6
  release_notes = """
7
7
 
8
8
  imporoved installer
@@ -18,7 +18,7 @@ from typing import Optional
18
18
 
19
19
 
20
20
  APP_SUMMARY_PATH = LIBRARY_ROOT.joinpath(f"profile/records/{platform.system().lower()}/apps_summary_report.csv")
21
- CLOUD: str = "gdw" # Read.ini(DEFAULTS_PATH)['general']['rclone_config_name']
21
+ CLOUD: str="gdw" # Read.ini(DEFAULTS_PATH)['general']['rclone_config_name']
22
22
  # my onedrive doesn't allow sharing.
23
23
 
24
24
 
@@ -42,7 +42,7 @@ def scan(path: P, pct: float = 0.0):
42
42
  repeat_counter += 1
43
43
  if repeat_counter > 2:
44
44
  raise ValueError(f"Error in scanning {path}") from ex
45
- print(f"Error in scanning, trying again.")
45
+ print("Error in scanning, trying again.")
46
46
  time.sleep(30)
47
47
  df = pd.DataFrame(anal.results.values())
48
48
  malicious = []
@@ -82,6 +82,7 @@ def main() -> None:
82
82
  apps_paths_raw.print()
83
83
  positive_pct: list[Optional[float]] = []
84
84
  detailed_results: list[dict[str, Optional[pd.DataFrame]]] = []
85
+
85
86
  for idx, app in enumerate(apps_paths_raw):
86
87
  try: res = scan(path=app, pct=idx / len(apps_paths_raw) * 100)
87
88
  except ValueError as ve:
@@ -105,12 +106,13 @@ def main() -> None:
105
106
  res_df["app_url"] = app_url
106
107
  res_df.to_csv(APP_SUMMARY_PATH.with_suffix(".csv").create(parents_only=True), index=False)
107
108
  APP_SUMMARY_PATH.with_suffix(".md").write_text(res_df.to_markdown())
108
- print(f"Safety Report:")
109
+ print("Safety Report:")
109
110
  print(res_df)
110
111
 
111
112
 
112
113
  def upload(path: P):
113
- set_time_out = install_n_import("call_function_with_timeout").SetTimeout
114
+ import call_function_with_timeout
115
+ set_time_out = call_function_with_timeout.SetTimeout
114
116
  func_with_timeout = set_time_out(lambda: path.to_cloud(CLOUD, rel2home=True, share=True, os_specific=True), timeout=180)
115
117
  is_done, _is_timeout, _erro_message, results = func_with_timeout()
116
118
  if is_done: return results
@@ -146,7 +148,7 @@ class PrecheckedCloudInstaller:
146
148
  exe.move(folder=P.home().joinpath("AppData/Local/Microsoft/WindowsApps"), overwrite=True)
147
149
  return True
148
150
 
149
- def download_safe_apps(self, name: str = "AllEssentials"):
151
+ def download_safe_apps(self, name: str="AllEssentials"):
150
152
  # if platform.system().lower() == "windows":
151
153
  # from machineconfig.jobs.python.python_windows_installers_all import get_cli_py_installers
152
154
  # cli_installers = get_cli_py_installers()
@@ -4,7 +4,7 @@
4
4
 
5
5
  from crocodile.file_management import P, Save, randstr
6
6
  from crocodile.meta import Terminal
7
- from machineconfig.utils.ve import get_ve_profile, get_ve_specs, get_ve_install_script
7
+ from machineconfig.utils.ve import get_ve_profile, get_ve_specs
8
8
  from machineconfig.scripts.python.repos import record_a_repo, install_repos
9
9
  import platform
10
10
 
@@ -12,12 +12,18 @@ import platform
12
12
  # TODO: add data requirements for added isolation of file system.
13
13
 
14
14
 
15
- def checkout_version(version: str, repo_root: P, exclude_editable: bool = False):
15
+ def checkout_version(version: str, repo_root: P, exclude_editable: bool=False):
16
16
  """Checkout a version of the repo and install its requirements."""
17
17
  ve_name = get_ve_profile(init_path=repo_root)
18
18
  ve_path = P.home().joinpath("venvs", ve_name)
19
19
  ve_specs = get_ve_specs(ve_path)
20
- py_version = ve_specs['version_major_minor']
20
+ try:
21
+ py_version = ve_specs['version']
22
+ except KeyError as err:
23
+ # print(f"❌ No python version found in {ve_specs}.")
24
+ # raise err
25
+ _ = err
26
+ py_version = ve_specs['version_info']
21
27
  sys = platform.system().lower()
22
28
 
23
29
  target_dir = repo_root.expanduser().absolute().joinpath(f"versions/{version}").as_posix()
@@ -33,24 +39,29 @@ def checkout_version(version: str, repo_root: P, exclude_editable: bool = False)
33
39
  checkout_ve = f"{repo_root.name}-{version}-prod" if not exclude_editable else ve_name
34
40
  checkout_ve = input(f"Name of the ve to create (default: {checkout_ve}): ") or checkout_ve
35
41
 
36
- ve_template = get_ve_install_script(ve_name=checkout_ve, py_version=py_version, system="Windows", delete_if_exists=False, install_crocodile_and_machineconfig=False)
37
- version_root_obj.joinpath("install_ve.ps1").write_text(ve_template)
38
- ve_template = get_ve_install_script(ve_name=checkout_ve, py_version=py_version, system="Linux", delete_if_exists=False, install_crocodile_and_machineconfig=False)
39
- version_root_obj.joinpath("install_ve.sh").write_text(ve_template)
42
+ install_env = f"""
40
43
 
41
- install_requirements = f"""
44
+ uv venv $HOME/venvs/{checkout_ve} --python {py_version} --python-preference only-managed
42
45
  . $HOME/scripts/activate_ve {ve_name}
43
- cd {version_root}
44
- pip install -r requirements_{sys}.txt
46
+
47
+ uv pip install pip
48
+
45
49
  {install_editable_packages}
50
+
51
+ cd {version_root}
52
+ uv pip install -r requirements_{sys}.txt
53
+
46
54
  """
47
55
  if sys == "windows":
48
- version_root_obj.joinpath("install_requirements.ps1").write_text(install_requirements)
49
- if not version_root_obj.joinpath("install_requirements.sh").exists(): version_root_obj.joinpath("install_requirements.sh").write_text(install_requirements)
56
+ version_root_obj.joinpath("install_env.ps1").write_text(install_env)
57
+ if not version_root_obj.joinpath("install_env.sh").exists():
58
+ version_root_obj.joinpath("install_env.sh").write_text(install_env)
50
59
  elif sys == "linux":
51
- version_root_obj.joinpath("install_requirements.sh").write_text(install_requirements)
52
- if not version_root_obj.joinpath("install_requirements.ps1").exists(): version_root_obj.joinpath("install_requirements.ps1").write_text(install_requirements)
53
- else: raise NotImplementedError(f"System {sys} not supported.")
60
+ version_root_obj.joinpath("install_env.sh").write_text(install_env)
61
+ if not version_root_obj.joinpath("install_env.ps1").exists():
62
+ version_root_obj.joinpath("install_env.ps1").write_text(install_env)
63
+ else:
64
+ raise NotImplementedError(f"System {sys} not supported.")
54
65
 
55
66
  pip_freeze_script = f"""
56
67
  cd '{target_dir}'
@@ -58,23 +69,6 @@ cd '{target_dir}'
58
69
  python -m pip freeze {'--exclude-editable' if exclude_editable else ''} > requirements_{sys}.txt
59
70
  """
60
71
  Terminal().run_script(pip_freeze_script, verbose=True, shell="default").print()
61
-
62
- install_all_script = r"""
63
- #!/usr/bin/bash
64
-
65
- CUR_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" &> /dev/null && pwd )"
66
- . $CUR_DIR/install_ve.sh
67
- . $CUR_DIR/install_requirements.sh
68
- """
69
- version_root_obj.joinpath("install.sh").write_text(install_all_script)
70
- install_all_script = r"""
71
-
72
- $CUR_DIR = Split-Path $MyInvocation.MyCommand.Path -Parent
73
- . $CUR_DIR/install_ve.ps1
74
- . $CUR_DIR/install_requirements.ps1
75
-
76
- """
77
- version_root_obj.joinpath("install.ps1").write_text(install_all_script)
78
72
  print(f"✅ Installed requirements for version {version}.")
79
73
 
80
74
 
@@ -97,6 +91,7 @@ def main():
97
91
 
98
92
  def get_editable_packages(ve_name: str):
99
93
  file = P.tmp().joinpath(f"tmp_files/editable_requirements_{randstr()}.txt")
94
+ file.parent.mkdir(parents=True, exist_ok=True)
100
95
  editable_packages_script = f"""
101
96
  . $HOME/scripts/activate_ve {ve_name}
102
97
  pip list --editable > {file}
@@ -1,6 +1,6 @@
1
1
 
2
2
 
3
- #
3
+ # try ventory or netboot.xyz
4
4
 
5
5
  # # one can either install rufus: https://rufus.ie/en/
6
6
  # # however, to create bootable media with multiple OSs to choose from:
@@ -8,7 +8,7 @@ from crocodile.file_management import P
8
8
  import platform
9
9
 
10
10
 
11
- def build_rust_executable(url: str = r"https://github.com/atanunq/viu"):
11
+ def build_rust_executable(url: str=r"https://github.com/atanunq/viu"):
12
12
  tool_name = url.split('/')[-1]
13
13
 
14
14
  # move command is not required since tool will go to .cargo/bin which is in PATH by default.
@@ -35,7 +35,7 @@ cargo install --path .
35
35
  print(f"PermissionError, couldn't delete: {P.home().joinpath(tool_name)}")
36
36
 
37
37
  if platform.system() == "Windows":
38
- exe = exe.move(folder=P.get_env().WindowsApps)
38
+ exe = exe.move(folder=P.get_env().WindowsPaths().WindowsApps)
39
39
  elif platform.system() == "Linux":
40
40
  Terminal().run(f"sudo mv {exe} /usr/local/bin")
41
41
  exe = P(r"/usr/local/bin").joinpath(exe.name)
@@ -1,4 +1,4 @@
1
1
 
2
- from machineconfig.scripts.python.devops_backup_retrieve import main
2
+ from machineconfig.scripts.python.devops_backup_retrieve import main_backup_retrieve
3
3
 
4
- program = main(direction="BACKUP", which="all")
4
+ program = main_backup_retrieve(direction="BACKUP", which="all")
@@ -3,14 +3,14 @@
3
3
  Installers do not add runtime files to the machine, hence this script.
4
4
  """
5
5
 
6
- # from pathlib import Path
7
- from machineconfig.utils.installer import Installer, LINUX_INSTALL_PATH, WINDOWS_INSTALL_PATH
6
+ from crocodile.file_management import P
7
+ from machineconfig.utils.installer import Installer, WINDOWS_INSTALL_PATH
8
8
  from typing import Optional
9
9
  import platform
10
10
 
11
11
 
12
12
  config_dict = {
13
- "repo_url": "https://github.com/helix-editor/helix",
13
+ "repo_url": "CUSTOM",
14
14
  "doc": "Helix is a post-modern modal text editor.",
15
15
  "filename_template_windows_amd_64": "helix-{}-x86_64-windows.zip",
16
16
  "filename_template_linux_amd_64": "helix-{}-x86_64-linux.tar.xz",
@@ -20,7 +20,9 @@ config_dict = {
20
20
 
21
21
 
22
22
  def main(version: Optional[str]):
23
- inst = Installer.from_dict(d=config_dict, name="hx")
23
+ config_dict_copy = config_dict.copy()
24
+ config_dict_copy["repo_url"] = "https://github.com/helix-editor/helix"
25
+ inst = Installer.from_dict(d=config_dict_copy, name="hx")
24
26
  downloaded, _version_to_be_installed = inst.download(version=version)
25
27
  hx_file_search = downloaded.search("hx", folders=False, files=True, r=True)
26
28
  assert len(hx_file_search) == 1
@@ -29,14 +31,24 @@ def main(version: Optional[str]):
29
31
  runtime = contrib.parent / "runtime"
30
32
  assert runtime.exists()
31
33
  assert contrib.exists()
34
+ P.home().joinpath(".config/helix/runtime").delete(sure=True)
35
+ P.home().joinpath(".config/helix/contrib").delete(sure=True)
32
36
  if platform.system() == "Linux":
33
- hx_file.move(folder=LINUX_INSTALL_PATH)
37
+ # hx_file.move(folder=LINUX_INSTALL_PATH) # to be added later
34
38
  contrib.move(folder="~/.config/helix")
35
39
  runtime.move(folder="~/.config/helix")
36
40
  elif platform.system() == "Windows":
37
41
  hx_file.move(folder=WINDOWS_INSTALL_PATH)
38
42
  contrib.move(folder="~/.config/helix")
39
43
  runtime.move(folder="~/.config/helix")
44
+ else:
45
+ print("Unsupported OS")
46
+ downloaded.delete(sure=True)
47
+
48
+ if platform.system() == "Linux":
49
+ inst.install(version=version) # because we can't normally move hx (without privliage) # hx_file.move(folder=LINUX_INSTALL_PATH)
50
+
51
+ return ""
40
52
 
41
53
 
42
54
  if __name__ == "__main__":
@@ -6,15 +6,15 @@ This script Takes away all config files from the computer, place them in one dir
6
6
  """
7
7
 
8
8
 
9
- from crocodile.environment import system, UserName # ProgramFiles, WindowsApps # , exe
9
+ from crocodile.environment import system # ProgramFiles, WindowsApps # , exe
10
10
  from crocodile.meta import Terminal
11
11
  from crocodile.file_management import P
12
- from machineconfig.utils.utils import symlink, LIBRARY_ROOT, REPO_ROOT, display_options
12
+ from machineconfig.utils.utils import symlink_func, symlink_copy, LIBRARY_ROOT, REPO_ROOT, display_options
13
13
  from machineconfig.profile.shell import create_default_shell_profile
14
14
  # import os
15
15
  import subprocess
16
16
  from rich.console import Console
17
- from typing import Optional, Any
17
+ from typing import Optional, Any, TypedDict
18
18
 
19
19
 
20
20
  ERROR_LIST: list[Any] = [] # append to this after every exception captured.
@@ -23,18 +23,16 @@ OTHER_SYSTEM = "windows" if system == "Linux" else "linux"
23
23
  SYSTEM = system.lower()
24
24
 
25
25
 
26
- # =================== SYMLINKS ====================================
27
-
28
-
29
- def symlink_contents(source_dir: P, target_dir: P, overwrite: bool = True):
30
- for a_target in target_dir.expanduser().search("*"):
31
- symlink(this=source_dir.joinpath(a_target.name), to_this=a_target, prioritize_to_this=overwrite)
26
+ class SymlinkMapper(TypedDict):
27
+ this: str
28
+ to_this: str
29
+ contents: Optional[bool]
32
30
 
33
31
 
34
32
  def main_symlinks(choice: Optional[str] = None):
35
33
  symlink_mapper = LIBRARY_ROOT.joinpath("profile/mapper.toml").readit()
36
- symlink_mapper['wsl_windows']['home']["to_this"] = symlink_mapper['wsl_windows']['home']["to_this"].replace("username", UserName)
37
- symlink_mapper['wsl_linux']['home']["to_this"] = symlink_mapper['wsl_linux']['home']["to_this"].replace("username", UserName)
34
+ # symlink_mapper['wsl_windows']['home']["to_this"] = symlink_mapper['wsl_windows']['home']["to_this"].replace("username", UserName)
35
+ # symlink_mapper['wsl_linux']['home']["to_this"] = symlink_mapper['wsl_linux']['home']["to_this"].replace("username", UserName)
38
36
 
39
37
  overwrite = True
40
38
  exclude: list[str] = [] # "wsl_linux", "wsl_windows"
@@ -43,7 +41,6 @@ def main_symlinks(choice: Optional[str] = None):
43
41
  program_keys: list[str] = []
44
42
  for program_key in program_keys_raw:
45
43
  if program_key in exclude or OTHER_SYSTEM in program_key:
46
- # print(f"Skipping {program_key} for {system}")
47
44
  continue
48
45
  else: program_keys.append(program_key)
49
46
 
@@ -56,13 +53,12 @@ def main_symlinks(choice: Optional[str] = None):
56
53
  # overwrite = display_options(msg="Overwrite existing source file?", options=["yes", "no"], default="yes") == "yes"
57
54
  from rich.prompt import Confirm
58
55
  overwrite = Confirm.ask("Overwrite existing source file?", default=True)
59
-
60
56
  else: choice_selected = choice
61
57
 
62
58
  if isinstance(choice_selected, str):
63
59
  if str(choice_selected) == "all" and system == "Windows" and not Terminal.is_user_admin():
64
60
  print("*" * 200)
65
- raise RuntimeError(f"Run terminal as admin and try again, otherwise, there will be too many popups for admin requests and no chance to terminate the program.")
61
+ raise RuntimeError("Run terminal as admin and try again, otherwise, there will be too many popups for admin requests and no chance to terminate the program.")
66
62
  elif choice_selected == "all":
67
63
  print(f"{program_keys=}")
68
64
  pass # i.e. program_keys = program_keys
@@ -74,17 +70,23 @@ def main_symlinks(choice: Optional[str] = None):
74
70
  this = P(file_map['this'])
75
71
  to_this = P(file_map['to_this'].replace("REPO_ROOT", REPO_ROOT.as_posix()).replace("LIBRARY_ROOT", LIBRARY_ROOT.as_posix()))
76
72
  if "contents" in file_map:
77
- try: symlink_contents(source_dir=this, target_dir=to_this, overwrite=overwrite)
73
+ try:
74
+ for a_target in to_this.expanduser().search("*"):
75
+ symlink_func(this=this.joinpath(a_target.name), to_this=a_target, prioritize_to_this=overwrite)
78
76
  except Exception as ex: print("Config error: ", program_key, file_key, "missing keys 'this ==> to_this'.", ex)
77
+ if "copy" in file_map:
78
+ try:
79
+ symlink_copy(this=this, to_this=to_this, prioritize_to_this=overwrite)
80
+ except Exception as ex: print("Config error: ", program_key, file_key, ex)
79
81
  else:
80
- try: symlink(this=this, to_this=to_this, prioritize_to_this=overwrite)
82
+ try: symlink_func(this=this, to_this=to_this, prioritize_to_this=overwrite)
81
83
  except Exception as ex: print("Config error: ", program_key, file_key, "missing keys 'this ==> to_this'.", ex)
82
84
 
83
85
  if program_key == "ssh" and system == "Linux": # permissions of ~/dotfiles/.ssh should be adjusted
84
86
  try:
85
- subprocess.run(f"chmod 700 ~/.ssh/", check=True)
86
- subprocess.run(f"chmod 700 ~/dotfiles/creds/.ssh/", check=True) # may require sudo
87
- subprocess.run(f"chmod 600 ~/dotfiles/creds/.ssh/*", check=True)
87
+ subprocess.run("chmod 700 ~/.ssh/", check=True)
88
+ subprocess.run("chmod 700 ~/dotfiles/creds/.ssh/", check=True) # may require sudo
89
+ subprocess.run("chmod 600 ~/dotfiles/creds/.ssh/*", check=True)
88
90
  except Exception as e:
89
91
  ERROR_LIST.append(e)
90
92
  print("Caught error", e)
@@ -98,11 +100,11 @@ def main_symlinks(choice: Optional[str] = None):
98
100
  def main(choice: Optional[str] = None):
99
101
  console = Console()
100
102
  print("\n")
101
- console.rule(f"CREATING SYMLINKS")
103
+ console.rule("CREATING SYMLINKS")
102
104
  main_symlinks(choice=choice)
103
105
 
104
106
  print("\n")
105
- console.rule(f"CREATING SYMLINKS")
107
+ console.rule("CREATING SYMLINKS")
106
108
  create_default_shell_profile()
107
109
 
108
110
 
@@ -0,0 +1,101 @@
1
+
2
+ """
3
+ This script Takes away all config files from the computer, place them in one directory
4
+ `dotfiles`, and create symlinks to those files from thier original locations.
5
+
6
+ """
7
+
8
+
9
+ from crocodile.environment import system # ProgramFiles, WindowsApps # , exe
10
+ from crocodile.meta import Terminal
11
+ from crocodile.file_management import P
12
+ from machineconfig.utils.utils import symlink_copy as symlink_func, LIBRARY_ROOT, REPO_ROOT, display_options
13
+ from machineconfig.profile.shell import create_default_shell_profile
14
+ # import os
15
+ import subprocess
16
+ from rich.console import Console
17
+ from typing import Optional, Any
18
+
19
+
20
+ ERROR_LIST: list[Any] = [] # append to this after every exception captured.
21
+ CONFIG_ROOT = LIBRARY_ROOT.parent.parent.joinpath("settings")
22
+ OTHER_SYSTEM = "windows" if system == "Linux" else "linux"
23
+ SYSTEM = system.lower()
24
+
25
+
26
+ def main_symlinks(choice: Optional[str] = None):
27
+ symlink_mapper = LIBRARY_ROOT.joinpath("profile/mapper.toml").readit()
28
+ # symlink_mapper['wsl_windows']['home']["to_this"] = symlink_mapper['wsl_windows']['home']["to_this"].replace("username", UserName)
29
+ # symlink_mapper['wsl_linux']['home']["to_this"] = symlink_mapper['wsl_linux']['home']["to_this"].replace("username", UserName)
30
+
31
+ overwrite = True
32
+ exclude: list[str] = [] # "wsl_linux", "wsl_windows"
33
+
34
+ program_keys_raw: list[str] = list(symlink_mapper.keys())
35
+ program_keys: list[str] = []
36
+ for program_key in program_keys_raw:
37
+ if program_key in exclude or OTHER_SYSTEM in program_key:
38
+ # print(f"Skipping {program_key} for {system}")
39
+ continue
40
+ else: program_keys.append(program_key)
41
+
42
+ program_keys.sort()
43
+ if choice is None:
44
+ choice_selected = display_options(msg="Which symlink to create?", options=program_keys + ["all", "none(EXIT)"], default="none(EXIT)", fzf=True, multi=True)
45
+ assert isinstance(choice_selected, list)
46
+ if len(choice_selected) == 1 and choice_selected[0] == "none(EXIT)": return # terminate function.
47
+ elif len(choice_selected) == 1 and choice_selected[0] == "all": choice_selected = "all" # i.e. program_keys = program_keys
48
+ # overwrite = display_options(msg="Overwrite existing source file?", options=["yes", "no"], default="yes") == "yes"
49
+ from rich.prompt import Confirm
50
+ overwrite = Confirm.ask("Overwrite existing source file?", default=True)
51
+
52
+ else: choice_selected = choice
53
+
54
+ if isinstance(choice_selected, str):
55
+ if choice_selected == "all":
56
+ print(f"{program_keys=}")
57
+ pass # i.e. program_keys = program_keys
58
+ else: program_keys = [choice_selected]
59
+ else: program_keys = choice_selected
60
+
61
+ for program_key in program_keys:
62
+ for file_key, file_map in symlink_mapper[program_key].items():
63
+ this = P(file_map['this'])
64
+ to_this = P(file_map['to_this'].replace("REPO_ROOT", REPO_ROOT.as_posix()).replace("LIBRARY_ROOT", LIBRARY_ROOT.as_posix()))
65
+ if "contents" in file_map:
66
+ try:
67
+ for a_target in to_this.expanduser().search("*"):
68
+ symlink_func(this=this.joinpath(a_target.name), to_this=a_target, prioritize_to_this=overwrite)
69
+ except Exception as ex: print("Config error: ", program_key, file_key, "missing keys 'this ==> to_this'.", ex)
70
+ else:
71
+ try: symlink_func(this=this, to_this=to_this, prioritize_to_this=overwrite)
72
+ except Exception as ex: print("Config error: ", program_key, file_key, "missing keys 'this ==> to_this'.", ex)
73
+
74
+ if program_key == "ssh" and system == "Linux": # permissions of ~/dotfiles/.ssh should be adjusted
75
+ try:
76
+ subprocess.run("chmod 700 ~/.ssh/", check=True)
77
+ subprocess.run("chmod 700 ~/dotfiles/creds/.ssh/", check=True) # may require sudo
78
+ subprocess.run("chmod 600 ~/dotfiles/creds/.ssh/*", check=True)
79
+ except Exception as e:
80
+ ERROR_LIST.append(e)
81
+ print("Caught error", e)
82
+
83
+ if system == "Linux": Terminal().run(f'chmod +x {LIBRARY_ROOT.joinpath(f"scripts/{system.lower()}")} -R')
84
+ print("\n\n", "*" * 200)
85
+ if len(ERROR_LIST) > 0:
86
+ print("Errors caught: ", ERROR_LIST)
87
+
88
+
89
+ def main(choice: Optional[str] = None):
90
+ console = Console()
91
+ print("\n")
92
+ console.rule("CREATING SYMLINKS")
93
+ main_symlinks(choice=choice)
94
+
95
+ print("\n")
96
+ console.rule("CREATING SYMLINKS")
97
+ create_default_shell_profile()
98
+
99
+
100
+ if __name__ == '__main__':
101
+ pass
@@ -22,10 +22,10 @@ system = platform.system()
22
22
  def create_default_shell_profile():
23
23
  profile_path = get_shell_profile_path()
24
24
  profile = profile_path.read_text()
25
- if system == "Windows": source = f". {LIBRARY_ROOT.joinpath('settings/shells/pwsh/init.ps1').collapseuser().str.replace('~', '$HOME')}"
26
- else: source = f"source {LIBRARY_ROOT.joinpath('settings/shells/bash/init.sh').collapseuser().str.replace('~', '$HOME')}"
25
+ if system == "Windows": source = f". {LIBRARY_ROOT.joinpath('settings/shells/pwsh/init.ps1').collapseuser().to_str().replace('~', '$HOME')}"
26
+ else: source = f"source {LIBRARY_ROOT.joinpath('settings/shells/bash/init.sh').collapseuser().to_str().replace('~', '$HOME')}"
27
27
 
28
- if source in profile: print(f"Skipping sourcing init script; already in profile")
28
+ if source in profile: print("Skipping sourcing init script; already in profile")
29
29
  else:
30
30
  profile += "\n" + source + "\n"
31
31
  if system == "Linux":
@@ -50,7 +50,7 @@ def main_env_path(choice: Optional[str] = None, profile_path: Optional[str] = No
50
50
  env_path = LIBRARY_ROOT.joinpath("profile/env_path.toml").readit()
51
51
  dirs = env_path[f'path_{system.lower()}']['extension']
52
52
 
53
- print(f"Current PATH: ", "\n============")
53
+ print("Current PATH: ", "\n============")
54
54
  P.get_env().PATH.print()
55
55
 
56
56
  if choice is None:
@@ -62,7 +62,7 @@ def main_env_path(choice: Optional[str] = None, profile_path: Optional[str] = No
62
62
 
63
63
  addition = PathVar.append_temporarily(dirs=dirs)
64
64
  profile_path_obj = P(profile_path) if isinstance(profile_path, str) else get_shell_profile_path()
65
- profile_path_obj.copy(name=profile_path_obj.name + f".orig_" + randstr())
65
+ profile_path_obj.copy(name=profile_path_obj.name + ".orig_" + randstr())
66
66
  profile_path_obj.modify_text(addition, addition, replace_line=False, notfound_append=True)
67
67
 
68
68
 
@@ -1,8 +1,10 @@
1
1
 
2
- """CC
2
+ """
3
+ CC
3
4
  """
4
5
 
5
- from crocodile.file_management import P, Struct
6
+ from crocodile.file_management import P
7
+ from crocodile.core import Struct
6
8
  from crocodile.meta import RepeatUntilNoException
7
9
  import getpass
8
10
  from machineconfig.scripts.python.cloud_sync import parse_cloud_source_target, ArgsDefaults, Args
@@ -13,22 +15,20 @@ import os
13
15
  from typing import Optional
14
16
 
15
17
 
16
- @RepeatUntilNoException()
18
+ @RepeatUntilNoException(retry=3, sleep=1)
17
19
  def get_securely_shared_file(url: Optional[str] = None, folder: Optional[str] = None) -> None:
18
20
  folder_obj = P.cwd() if folder is None else P(folder)
19
21
 
20
22
  if os.environ.get("DECRYPTION_PASSWORD") is not None:
21
- pwd: str = str(os.environ.get("DECRYPTION_PASSWORD"))
23
+ pwd: str=str(os.environ.get("DECRYPTION_PASSWORD"))
22
24
  else:
23
25
  pwd = getpass.getpass(prompt="Enter decryption password: ")
24
-
25
26
  if url is None:
26
27
  if os.environ.get("SHARE_URL") is not None:
27
28
  url = os.environ.get("SHARE_URL")
28
29
  assert url is not None
29
30
  else:
30
31
  url = input("Enter share url: ")
31
-
32
32
  from rich.progress import Progress
33
33
  with Progress(transient=True) as progress:
34
34
  _task = progress.add_task("Downloading ... ", total=None)
@@ -63,23 +63,26 @@ def arg_parser() -> None:
63
63
 
64
64
  args = parser.parse_args()
65
65
  args_dict = vars(args)
66
- source: str = args_dict.pop("source")
67
- target: str = args_dict.pop("target")
66
+ source: str=args_dict.pop("source")
67
+ target: str=args_dict.pop("target")
68
68
  args_obj = Args(**args_dict)
69
- Struct(args_obj.__dict__).print(as_config=True, title=f"CLI config")
69
+ Struct(args_obj.__dict__).print(as_config=True, title="CLI config")
70
70
 
71
- if args_obj.config == "ss" and (source.startswith("http") or source.startswith("bit.ly")): return get_securely_shared_file(url=source, folder=target)
72
- if args_obj.rel2home is True and args_obj.root is None: args_obj.root = "myhome"
71
+ if args_obj.config == "ss" and (source.startswith("http") or source.startswith("bit.ly")):
72
+ return get_securely_shared_file(url=source, folder=target)
73
+ if args_obj.rel2home is True and args_obj.root is None:
74
+ args_obj.root = "myhome"
73
75
 
76
+ # print(f"source: {source}")
74
77
  cloud, source, target = parse_cloud_source_target(args=args_obj, source=source, target=target)
75
78
 
76
- assert args_obj.key is None, f"Key is not supported yet."
79
+ assert args_obj.key is None, "Key is not supported yet."
77
80
  if cloud in source:
78
81
  P(target).from_cloud(cloud=cloud, remotepath=source.replace(cloud + ":", ""),
79
- unzip=args_obj.zip, decrypt=args_obj.encrypt, pwd=args_obj.pwd,
80
- overwrite=args_obj.overwrite,
81
- rel2home=args_obj.rel2home, os_specific=args_obj.os_specific, root=args_obj.root, strict=False,
82
- )
82
+ unzip=args_obj.zip, decrypt=args_obj.encrypt, pwd=args_obj.pwd,
83
+ overwrite=args_obj.overwrite,
84
+ rel2home=args_obj.rel2home, os_specific=args_obj.os_specific, root=args_obj.root, strict=False,
85
+ )
83
86
  elif cloud in target:
84
87
  res = P(source).to_cloud(cloud=cloud, remotepath=target.replace(cloud + ":", ""),
85
88
  zip=args_obj.zip, encrypt=args_obj.encrypt, pwd=args_obj.pwd,