machineconfig 1.8__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 (56) hide show
  1. machineconfig/__init__.py +4 -2
  2. machineconfig/jobs/python/check_installations.py +8 -6
  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/gh.py +53 -0
  8. machineconfig/jobs/python_custom_installers/hx.py +55 -0
  9. machineconfig/profile/create.py +26 -21
  10. machineconfig/profile/create_hardlinks.py +101 -0
  11. machineconfig/profile/shell.py +5 -5
  12. machineconfig/scripts/python/choose_wezterm_theme.py +96 -0
  13. machineconfig/scripts/python/cloud_copy.py +24 -17
  14. machineconfig/scripts/python/cloud_mount.py +20 -10
  15. machineconfig/scripts/python/cloud_repo_sync.py +109 -56
  16. machineconfig/scripts/python/cloud_sync.py +73 -68
  17. machineconfig/scripts/python/croshell.py +23 -14
  18. machineconfig/scripts/python/devops.py +19 -20
  19. machineconfig/scripts/python/devops_backup_retrieve.py +19 -10
  20. machineconfig/scripts/python/devops_devapps_install.py +81 -57
  21. machineconfig/scripts/python/devops_update_repos.py +5 -5
  22. machineconfig/scripts/python/dotfile.py +4 -4
  23. machineconfig/scripts/python/fire_jobs.py +139 -66
  24. machineconfig/scripts/python/ftpx.py +17 -7
  25. machineconfig/scripts/python/gh_models.py +53 -0
  26. machineconfig/scripts/python/mount_nfs.py +1 -1
  27. machineconfig/scripts/python/mount_nw_drive.py +3 -3
  28. machineconfig/scripts/python/mount_ssh.py +2 -3
  29. machineconfig/scripts/python/pomodoro.py +1 -1
  30. machineconfig/scripts/python/repos.py +26 -23
  31. machineconfig/scripts/python/scheduler.py +1 -1
  32. machineconfig/scripts/python/start_slidev.py +10 -4
  33. machineconfig/scripts/python/start_terminals.py +6 -5
  34. machineconfig/scripts/python/wifi_conn.py +34 -42
  35. machineconfig/scripts/python/wsl_windows_transfer.py +1 -1
  36. machineconfig/setup_windows/wt_and_pwsh/set_pwsh_theme.py +1 -1
  37. machineconfig/setup_windows/wt_and_pwsh/set_wt_settings.py +3 -2
  38. machineconfig/utils/installer.py +167 -60
  39. machineconfig/utils/procs.py +2 -2
  40. machineconfig/utils/scheduling.py +3 -3
  41. machineconfig/utils/utils.py +137 -56
  42. machineconfig/utils/ve.py +171 -100
  43. machineconfig-1.91.dist-info/LICENSE +201 -0
  44. {machineconfig-1.8.dist-info → machineconfig-1.91.dist-info}/METADATA +31 -11
  45. machineconfig-1.91.dist-info/RECORD +69 -0
  46. {machineconfig-1.8.dist-info → machineconfig-1.91.dist-info}/WHEEL +1 -1
  47. machineconfig/jobs/script_installer/azure_data_studio.py +0 -22
  48. machineconfig/jobs/script_installer/bypass_paywall.py +0 -23
  49. machineconfig/jobs/script_installer/code.py +0 -34
  50. machineconfig/jobs/script_installer/docker_desktop.py +0 -41
  51. machineconfig/jobs/script_installer/ngrok.py +0 -29
  52. machineconfig/jobs/script_installer/skim.py +0 -21
  53. machineconfig/jobs/script_installer/wezterm.py +0 -34
  54. machineconfig-1.8.dist-info/RECORD +0 -70
  55. /machineconfig/jobs/{script_installer → python_custom_installers}/__init__.py +0 -0
  56. {machineconfig-1.8.dist-info → machineconfig-1.91.dist-info}/top_level.txt +0 -0
machineconfig/__init__.py CHANGED
@@ -2,7 +2,9 @@
2
2
  """DS
3
3
  """
4
4
 
5
- __version__ = "1.8"
5
+ __version__ = "1.91"
6
6
  release_notes = """
7
- enhanced ve management
7
+
8
+ imporoved installer
9
+
8
10
  """
@@ -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
 
@@ -32,7 +32,7 @@ def scan(path: P, pct: float = 0.0):
32
32
  return None
33
33
  with open(str(path), "rb") as f:
34
34
  analysis = client.scan_file(f)
35
- repeat_counter = 0
35
+ repeat_counter: int = 0
36
36
  while True:
37
37
  with console.status(f"waiting for scan of {path} ... "):
38
38
  try:
@@ -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")
@@ -0,0 +1,53 @@
1
+
2
+ """gh-cli installer
3
+ """
4
+
5
+ import platform
6
+ from typing import Optional
7
+ from machineconfig.utils.installer import Installer
8
+ from crocodile.meta import Terminal
9
+
10
+ r"""
11
+ https://github.com/cli/cli
12
+
13
+ # as per https://docs.github.com/en/copilot/github-copilot-in-the-cli/using-github-copilot-in-the-cli
14
+ # gh auth login
15
+ # gh extension install github/gh-copilot
16
+
17
+ # & 'C:\Program Files\GitHub CLI\gh.exe' extension install github/gh-copilot
18
+ # & 'C:\Program Files\GitHub CLI\gh.exe' extension install auth login
19
+
20
+ """
21
+
22
+ config_dict = {
23
+ "repo_url": "https://github.com/cli/cli",
24
+ "doc": "GitHub CLI",
25
+ "filename_template_windows_amd_64": "gh_{}_windows_amd64.zip",
26
+ "filename_template_linux_amd_64": "gh_{}_linux_amd64.tar.gz",
27
+ "strip_v": True,
28
+ "exe_name": "gh"
29
+ }
30
+
31
+
32
+ def main(version: Optional[str]):
33
+ _ = version
34
+ inst = Installer.from_dict(d=config_dict, name="gh")
35
+ inst.install(version=version)
36
+ if platform.system() == "Windows":
37
+ program = "gh extension install github/gh-copilot"
38
+ elif platform.system() == "Linux":
39
+ program = """
40
+ gh extension install github/gh-copilot
41
+ """
42
+ else:
43
+ raise NotImplementedError("unsupported platform")
44
+
45
+ program += """
46
+ gh auth login --with-token $HOME/dotfiles/creds/git/gh_token.txt
47
+ """
48
+ Terminal().run(program, shell="default").print(desc="installing gh-copilot extension", capture=True)
49
+ return program
50
+
51
+
52
+ if __name__ == "__main__":
53
+ pass
@@ -0,0 +1,55 @@
1
+
2
+ """
3
+ Installers do not add runtime files to the machine, hence this script.
4
+ """
5
+
6
+ from crocodile.file_management import P
7
+ from machineconfig.utils.installer import Installer, WINDOWS_INSTALL_PATH
8
+ from typing import Optional
9
+ import platform
10
+
11
+
12
+ config_dict = {
13
+ "repo_url": "CUSTOM",
14
+ "doc": "Helix is a post-modern modal text editor.",
15
+ "filename_template_windows_amd_64": "helix-{}-x86_64-windows.zip",
16
+ "filename_template_linux_amd_64": "helix-{}-x86_64-linux.tar.xz",
17
+ "strip_v": False,
18
+ "exe_name": "hx"
19
+ }
20
+
21
+
22
+ def main(version: Optional[str]):
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")
26
+ downloaded, _version_to_be_installed = inst.download(version=version)
27
+ hx_file_search = downloaded.search("hx", folders=False, files=True, r=True)
28
+ assert len(hx_file_search) == 1
29
+ hx_file = hx_file_search.list[0]
30
+ contrib = hx_file.parent / "contrib"
31
+ runtime = contrib.parent / "runtime"
32
+ assert runtime.exists()
33
+ assert contrib.exists()
34
+ P.home().joinpath(".config/helix/runtime").delete(sure=True)
35
+ P.home().joinpath(".config/helix/contrib").delete(sure=True)
36
+ if platform.system() == "Linux":
37
+ # hx_file.move(folder=LINUX_INSTALL_PATH) # to be added later
38
+ contrib.move(folder="~/.config/helix")
39
+ runtime.move(folder="~/.config/helix")
40
+ elif platform.system() == "Windows":
41
+ hx_file.move(folder=WINDOWS_INSTALL_PATH)
42
+ contrib.move(folder="~/.config/helix")
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 ""
52
+
53
+
54
+ if __name__ == "__main__":
55
+ main(version=None)
@@ -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,32 +70,41 @@ 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)
91
93
 
92
94
  if system == "Linux": Terminal().run(f'chmod +x {LIBRARY_ROOT.joinpath(f"scripts/{system.lower()}")} -R')
95
+ print("\n\n", "*" * 200)
96
+ if len(ERROR_LIST) > 0:
97
+ print("Errors caught: ", ERROR_LIST)
93
98
 
94
99
 
95
100
  def main(choice: Optional[str] = None):
96
101
  console = Console()
97
102
  print("\n")
98
- console.rule(f"CREATING SYMLINKS")
103
+ console.rule("CREATING SYMLINKS")
99
104
  main_symlinks(choice=choice)
100
105
 
101
106
  print("\n")
102
- console.rule(f"CREATING SYMLINKS")
107
+ console.rule("CREATING SYMLINKS")
103
108
  create_default_shell_profile()
104
109
 
105
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
 
@@ -0,0 +1,96 @@
1
+
2
+ """
3
+ Choose a theme for Wezterm
4
+ """
5
+
6
+ from machineconfig.utils.utils import choose_one_option, P
7
+ from typing import Any
8
+ import time
9
+
10
+
11
+ schemes_list = [
12
+ 'Pro',
13
+ 'Spiderman',
14
+ 'shades-of-purple',
15
+ 'synthwave',
16
+ 'Symfonic',
17
+ 'PaulMillr',
18
+ 'Neon',
19
+ 'LiquidCarbonTransparentInverse',
20
+ 'Laser',
21
+ 'IR_Black',
22
+ 'Hurtado',
23
+ 'Homebrew',
24
+ 'Hipster Green',
25
+ 'Firefly Traditional',
26
+ 'Elementary',
27
+ 'deep',
28
+ 'Dark Pastel',
29
+ 'Bright Lights',
30
+ 'Adventure',
31
+ 'Nancy (terminal.sexy)',
32
+ 'Bim (Gogh)',
33
+ 'BlueDolphin',
34
+ 'Borland',
35
+ 'Grass (Gogh)',
36
+ 'Greenscreen (light) (terminal.sexy)',
37
+ 'Grayscale (dark) (terminal.sexy)',
38
+ ]
39
+
40
+
41
+ def main2():
42
+ option = choose_one_option(options=schemes_list, header="Choose a theme for Wezterm", fzf=True)
43
+ set_theme(option)
44
+
45
+
46
+ def set_theme(theme: str):
47
+ txt_lines = P("~/.config/wezterm/wezterm.lua").expanduser().read_text().splitlines()
48
+ res_lines = []
49
+ for line in txt_lines:
50
+ if 'config.color_scheme = ' in line:
51
+ res_lines.append(f"config.color_scheme = '{theme}'")
52
+ else: res_lines.append(line)
53
+ P("~/.config/wezterm/wezterm.lua").expanduser().write_text('\n'.join(res_lines))
54
+ time.sleep(0.1)
55
+
56
+
57
+ def main():
58
+ import curses # not availble on windows: https://docs.python.org/3/howto/curses.html
59
+ # from curses import wrapper
60
+ curses.wrapper(accessory)
61
+
62
+ def accessory(stdscr: Any):
63
+ import curses
64
+ options = schemes_list
65
+ current_option = 0
66
+ page_size = stdscr.getmaxyx()[0] - 1 # curses.LINES - 1 # Number of lines in the terminal, -1 for status line
67
+
68
+ while True:
69
+ stdscr.clear()
70
+
71
+ # Calculate start and end indices for options
72
+ start_index = (current_option // page_size) * page_size
73
+ end_index = start_index + page_size
74
+
75
+ # Display options
76
+ for i, option in enumerate(options[start_index:end_index]):
77
+ if start_index + i == current_option:
78
+ stdscr.addstr(i, 0, option, curses.A_REVERSE) # Highlighted
79
+ else:
80
+ stdscr.addstr(i, 0, option)
81
+
82
+ # Display status line
83
+ status_line = f"Option {current_option+1} of {len(options)}. Use arrow keys to navigate, Enter to select."
84
+ stdscr.addstr(page_size, 0, status_line)
85
+
86
+ # Get key press
87
+ key = stdscr.getch()
88
+
89
+ # Handle key press
90
+ if key == curses.KEY_UP and current_option > 0:
91
+ current_option -= 1
92
+ elif key == curses.KEY_DOWN and current_option < len(options) - 1:
93
+ current_option += 1
94
+ elif key == ord('\n'): # Enter key
95
+ break # Exit the loop
96
+ set_theme(options[current_option])