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
@@ -1,8 +1,11 @@
1
1
 
2
2
  """Set Windows Terminal Settings
3
3
  """
4
- import crocodile.toolbox as tb
4
+
5
+ from crocodile.core import randstr, List as L
6
+ from crocodile.file_management import P, Read, Save
5
7
  import crocodile.environment as env
8
+ from machineconfig.utils.utils import LIBRARY_ROOT
6
9
  from uuid import uuid4
7
10
  import os
8
11
  from typing import Any
@@ -27,14 +30,14 @@ class TerminalSettings(object):
27
30
  tmp = os.getenv("LOCALAPPDATA")
28
31
  if not isinstance(tmp, str):
29
32
  raise ValueError("Could not find LOCALAPPDATA environment variable.")
30
- self.path = tb.P(tmp).joinpath(r"Packages\Microsoft.WindowsTerminal_8wekyb3d8bbwe\LocalState\settings.json")
31
- self.path.copy(append=".orig_" + tb.randstr())
32
- self.dat = self.path.readit()
33
- self.profs = tb.L(self.dat["profiles"]["list"])
33
+ self.path = P(tmp).joinpath(r"Packages\Microsoft.WindowsTerminal_8wekyb3d8bbwe\LocalState\settings.json")
34
+ self.path.copy(append=".orig_" + randstr())
35
+ self.dat: dict[str, Any] = Read.json(self.path)
36
+ self.profs = L(self.dat["profiles"]["list"])
34
37
 
35
38
  def save_terminal_settings(self):
36
39
  self.dat["profiles"]["list"] = list(self.profs)
37
- self.dat.save_json(self.path, indent=5)
40
+ Save.json(obj=self.dat, path=self.path, indent=5)
38
41
 
39
42
  # ========================= Terminal Settings =========================================
40
43
  def update_default_settings(self):
@@ -73,14 +76,10 @@ class TerminalSettings(object):
73
76
  else: print("Powershell profile was not found in the list of profile and therefore was not made the deafult.")
74
77
 
75
78
  def add_croshell(self):
76
- # Adding croshell if it is not there.
77
- # py_pr = tb.copy.deepcopy(pr) # use it as a template for the new profile.
78
- import machineconfig
79
- lib_root = tb.P(machineconfig.__file__).parent.collapseuser().as_posix()
80
79
  croshell = dict(name="croshell",
81
80
  guid="{" + str(uuid4()) + "}",
82
81
  # commandline=f"powershell.exe -Command \"{activate} ipython -i -c 'from crocodile.toolbox import *'\"",
83
- commandline=f'powershell.exe -Command "{lib_root}/scripts/windows/croshell.ps1"',
82
+ commandline=f'powershell.exe -Command "{LIBRARY_ROOT.as_posix()}/scripts/windows/croshell.ps1"',
84
83
  startingDirectory="%USERPROFILE%", # "%USERPROFILE%", # None: inherent from parent process.
85
84
  )
86
85
  # startingDirectory = None means: inheret from parent process, which will is the default, which point to /System32
@@ -114,7 +113,7 @@ class TerminalSettings(object):
114
113
  elif name == "Command Prompt": cmd = profile
115
114
  elif name == "Azure Cloud Shell": azure = profile
116
115
  else: others.append(profile)
117
- self.profs = tb.L([item for item in [pwsh, croshell, ubuntu, wpwsh, cmd, azure] + others if item is not None])
116
+ self.profs = L([item for item in [pwsh, croshell, ubuntu, wpwsh, cmd, azure] + others if item is not None])
118
117
 
119
118
 
120
119
  def main():
@@ -5,11 +5,12 @@ from rich.console import Console
5
5
 
6
6
  from crocodile.file_management import P, List as L, Read, Struct
7
7
  from crocodile.meta import Terminal
8
- from machineconfig.utils.utils import INSTALL_VERSION_ROOT, INSTALL_TMP_DIR, LIBRARY_ROOT
8
+ from machineconfig.utils.utils import INSTALL_VERSION_ROOT, INSTALL_TMP_DIR, LIBRARY_ROOT, check_tool_exists
9
9
 
10
- from dataclasses import dataclass
10
+ # from dataclasses import dataclass
11
11
  from typing import Optional, Any
12
12
  import platform
13
+ # import os
13
14
 
14
15
 
15
16
  def find_move_delete_windows(downloaded_file_path: P, exe_name: Optional[str] = None, delete: bool = True, rename_to: Optional[str] = None):
@@ -24,9 +25,9 @@ def find_move_delete_windows(downloaded_file_path: P, exe_name: Optional[str] =
24
25
  else: exe = downloaded_file_path.search("*.exe", r=True).list[0]
25
26
  if rename_to and exe.name != rename_to:
26
27
  exe = exe.with_name(name=rename_to, inplace=True)
27
- exe.move(folder=P.get_env().WindowsApps, overwrite=True) # latest version overwrites older installation.
28
+ exe_new_location = exe.move(folder=P.get_env().WindowsApps, overwrite=True) # latest version overwrites older installation.
28
29
  if delete: downloaded_file_path.delete(sure=True)
29
- return exe
30
+ return exe_new_location
30
31
 
31
32
 
32
33
  def find_move_delete_linux(downloaded: P, tool_name: str, delete: Optional[bool] = True, rename_to: Optional[str] = None):
@@ -35,7 +36,13 @@ def find_move_delete_linux(downloaded: P, tool_name: str, delete: Optional[bool]
35
36
  else:
36
37
  res = downloaded.search(f"*{tool_name}*", folders=False, r=True)
37
38
  if len(res) == 1: exe = res.list[0]
38
- else: exe = downloaded.search(tool_name, folders=False, r=True).list[0]
39
+ else:
40
+ exe_search_res = downloaded.search(tool_name, folders=False, r=True)
41
+ if len(exe_search_res) == 0:
42
+ print(f"No search results for `{tool_name}` in `{downloaded}`")
43
+ raise IndexError(f"No executable found in {downloaded}")
44
+ else:
45
+ exe = exe_search_res.list[0]
39
46
  if rename_to and exe.name != rename_to:
40
47
  exe = exe.with_name(name=rename_to, inplace=True)
41
48
  print(f"MOVING file `{repr(exe)}` to '/usr/local/bin'")
@@ -43,79 +50,128 @@ def find_move_delete_linux(downloaded: P, tool_name: str, delete: Optional[bool]
43
50
  # exe.move(folder=r"/usr/local/bin", overwrite=False)
44
51
  Terminal().run(f"sudo mv {exe} /usr/local/bin/").print_if_unsuccessful(desc="MOVING executable to /usr/local/bin", strict_err=True, strict_returncode=True)
45
52
  if delete: downloaded.delete(sure=True)
46
- return exe
53
+ exe_new_location = P(r"/usr/local/bin").joinpath(exe.name)
54
+ return exe_new_location
47
55
 
48
56
 
49
57
  class Installer:
50
- def __init__(self, repo_url: str, doc: str, filename_template_windows_amd_64: str, filename_template_linux_amd_64: str, strip_v: bool, exe_name: str):
58
+ def __init__(self, repo_url: str, name: str, doc: str, filename_template_windows_amd_64: str, filename_template_linux_amd_64: str, strip_v: bool, exe_name: str):
51
59
  self.repo_url = repo_url
60
+ self.name = name
52
61
  self.doc = doc
53
62
  self.filename_template_windows_amd_64 = filename_template_windows_amd_64
54
63
  self.filename_template_linux_amd_64 = filename_template_linux_amd_64
55
64
  self.strip_v = strip_v
56
65
  self.exe_name = exe_name
57
66
  def __repr__(self) -> str: return f"Installer of {self.repo_url}"
58
- def get_description(self): return f"{self.exe_name} -- {self.doc}"
67
+ def get_description(self):
68
+ # old_version_cli = Terminal().run(f"{self.exe_name} --version").op.replace("\n", "")
69
+ # old_version_cli = os.system(f"{self.exe_name} --version").replace("\n", "")
70
+ old_version_cli = check_tool_exists(self.exe_name)
71
+ old_version_cli_str = "✅" if old_version_cli else "❌"
72
+ # name_version = f"{self.exe_name} {old_version_cli_str}"
73
+ return f"{self.exe_name:<12} {old_version_cli_str} {self.doc}"
59
74
  def to_dict(self): return self.__dict__
60
75
  @staticmethod
61
- def from_dict(d: dict[str, Any]):
62
- try: return Installer(**d)
76
+ def from_dict(d: dict[str, Any], name: str):
77
+ try: return Installer(name=name, **d)
63
78
  except Exception as ex:
64
79
  Struct(d).print(as_config=True)
65
80
  raise ex
66
81
  @staticmethod
67
- def choose_and_install():
82
+ def choose_app_and_install():
68
83
  from machineconfig.utils.utils import choose_one_option
69
84
  path = choose_one_option(options=LIBRARY_ROOT.joinpath("jobs").search("config.json", r=True).list)
70
85
  config: dict[str, Any] = Read.json(path) # /python_generic_installers/config.json"))
71
86
  # binary = choose_one_option(options=list(config.keys()), fzf=True)
72
- for binary in list(config.keys()):
73
- installer = Installer.from_dict(config[binary])
87
+ for keys, dict_ in config.items():
88
+ installer = Installer.from_dict(d=dict_, name=keys)
74
89
  installer.install(version=None)
75
90
 
76
91
  def install_robust(self, version: Optional[str]):
77
92
  try:
78
- old_version = Terminal().run(f"{self.exe_name} --version", shell="powershell").op.replace("\n", "")
93
+ old_version_cli = Terminal().run(f"{self.exe_name} --version").op.replace("\n", "")
79
94
  self.install(version=version)
80
- new_version = Terminal().run(f"{self.exe_name} --version", shell="powershell").op.replace("\n", "")
81
- if old_version == new_version: return f"😑 {self.exe_name}, same version: {old_version}"
82
- else: return f"🤩 {self.exe_name} updated from {old_version} === to ===> {new_version}"
95
+ new_version_cli = Terminal().run(f"{self.exe_name} --version").op.replace("\n", "")
96
+ if old_version_cli == new_version_cli: return f"📦️ 😑 {self.exe_name}, same version: {old_version_cli}"
97
+ else: return f"📦️ 🤩 {self.exe_name} updated from {old_version_cli} === to ===> {new_version_cli}"
83
98
  except Exception as ex:
84
99
  print(ex)
85
- return f"Failed at {self.exe_name} with {ex}"
86
-
100
+ return f"📦️ Failed at {self.exe_name} with {ex}"
87
101
 
88
102
  def install(self, version: Optional[str]):
103
+ if self.repo_url == "CUSTOM":
104
+ import machineconfig.jobs.script_installer as custom_installer
105
+ installer_path = P(custom_installer.__file__).parent.joinpath(self.exe_name + ".py")
106
+ import runpy
107
+ program = runpy.run_path(str(installer_path), run_name="__main__")['main'](version=version)
108
+ Terminal().run(program, shell="default")
109
+ version_to_be_installed = str(version)
110
+ elif "npm " in self.repo_url:
111
+ Terminal().run(self.repo_url, shell="default").print_if_unsuccessful(desc="npm install", strict_err=True, strict_returncode=True)
112
+ version_to_be_installed = "npmLatest"
113
+ elif "pip " in self.repo_url:
114
+ Terminal().run(self.repo_url, shell="default").print_if_unsuccessful(desc="pip install", strict_err=True, strict_returncode=True)
115
+ version_to_be_installed = "pipLatest"
116
+ else:
117
+ downloaded, version_to_be_installed = self.download(version=version)
118
+ if downloaded.str.endswith(".deb"):
119
+ assert platform.system() == "Linux"
120
+ Terminal().run(f"sudo apt install -y {downloaded}").print_if_unsuccessful(desc="Installing .deb", strict_err=True, strict_returncode=True)
121
+ downloaded.delete(sure=True)
122
+ else:
123
+ if platform.system() == "Windows":
124
+ exe = find_move_delete_windows(downloaded_file_path=downloaded, exe_name=self.exe_name, delete=True, rename_to=self.exe_name + ".exe")
125
+ elif platform.system() == "Linux":
126
+ exe = find_move_delete_linux(downloaded=downloaded, tool_name=self.exe_name, delete=True, rename_to=self.exe_name)
127
+ else: raise NotImplementedError(f"System {platform.system()} not implemented")
128
+ _ = exe
129
+ if exe.name.replace(".exe", "") != self.exe_name.replace(".exe", ""):
130
+ from rich import print as pprint
131
+ from rich.panel import Panel
132
+ pprint(Panel(f"Expected exe name: [red]{self.exe_name}[/red] \nAttained name: [red]{exe.name.replace('.exe', '')}[/red]", title="exe name mismatch", subtitle=self.repo_url))
133
+ new_exe_name = self.exe_name + ".exe" if platform.system() == "Windows" else self.exe_name
134
+ exe.with_name(name=new_exe_name, inplace=True, overwrite=True)
135
+ INSTALL_VERSION_ROOT.joinpath(self.exe_name).create(parents_only=True).write_text(version_to_be_installed)
136
+
137
+ def download(self, version: Optional[str]):
89
138
  if "github" not in self.repo_url or ".zip" in self.repo_url or ".tar.gz" in self.repo_url:
90
139
  download_link = P(self.repo_url)
140
+ version_to_be_installed = "predefined_url"
141
+ print(f"📦️ Version to be installed: {version_to_be_installed}")
142
+ elif "http" in self.filename_template_linux_amd_64 or "http" in self.filename_template_windows_amd_64:
143
+ if platform.system() == "Windows":
144
+ download_link = P(self.filename_template_windows_amd_64)
145
+ elif platform.system() == "Linux":
146
+ download_link = P(self.filename_template_linux_amd_64)
147
+ else: raise NotImplementedError(f"📦️ System {platform.system()} not implemented")
148
+ version_to_be_installed = "predefined_url"
91
149
  else:
92
150
  release_url, version_to_be_installed = self.get_github_release(repo_url=self.repo_url, version=version)
151
+ print(f"📦️ Version to be installed: {version_to_be_installed}")
152
+ print(f"📦️ Release URL: {release_url}")
93
153
  version_to_be_installed_stripped = version_to_be_installed.replace("v", "") if self.strip_v else version_to_be_installed
94
154
  if platform.system() == "Windows":
95
155
  file_name = self.filename_template_windows_amd_64.format(version_to_be_installed_stripped)
96
156
  elif platform.system() == "Linux":
97
157
  file_name = self.filename_template_linux_amd_64.format(version_to_be_installed_stripped)
98
- else: raise NotImplementedError(f"System {platform.system()} not implemented")
158
+ else: raise NotImplementedError(f"📦️ System {platform.system()} not implemented")
159
+ print(f"📦️ File name", file_name)
99
160
  download_link = release_url.joinpath(file_name)
100
- print("Downloading", download_link.as_url_str())
161
+ print("📦️ Downloading: ", download_link.as_url_str())
101
162
  downloaded = download_link.download(folder=INSTALL_TMP_DIR).decompress()
102
- if platform.system() == "Windows": exe = find_move_delete_windows(downloaded_file_path=downloaded, exe_name=self.exe_name, delete=True, rename_to=self.exe_name + ".exe")
103
- elif platform.system() == "Linux": exe = find_move_delete_linux(downloaded=downloaded, tool_name=self.exe_name, delete=True, rename_to=self.exe_name)
104
- else: raise NotImplementedError(f"System {platform.system()} not implemented")
105
- if exe.name.replace(".exe", "") != self.exe_name:
106
- from rich import print as pprint
107
- from rich.panel import Panel
108
- pprint(Panel(f"Expected exe name, [red]{self.exe_name}! Attained name: {exe.name}", title="exe mismatch", subtitle=self.repo_url))
163
+ return downloaded, version_to_be_installed
109
164
 
110
165
  @staticmethod
111
166
  def get_github_release(repo_url: str, version: Optional[str] = None):
112
167
  print("\n\n\n")
113
- print(f"Inspecting latest release @ {repo_url} ...")
168
+ print(f"📦️ Inspecting latest release @ {repo_url} ...")
114
169
  # with console.status("Installing..."): # makes troubles on linux when prompt asks for password to move file to /usr/bin
115
170
  if version is None:
116
171
  import requests # https://docs.github.com/en/repositories/releasing-projects-on-github/linking-to-releases
117
172
  _latest_version = requests.get(str(repo_url) + "/releases/latest", timeout=10).url.split("/")[-1] # this is to resolve the redirection that occures: https://stackoverflow.com/questions/36070821/how-to-get-redirect-url-using-python-requests
118
173
  version_to_be_installed = _latest_version
174
+ # print(version_to_be_installed)
119
175
  else:
120
176
  version_to_be_installed = version
121
177
  release_url = P(repo_url + "/releases/download/" + version_to_be_installed)
@@ -124,188 +180,24 @@ class Installer:
124
180
  @staticmethod
125
181
  def check_if_installed_already(exe_name: str, version: str):
126
182
  version_to_be_installed = version
127
- # existing_version_cli = Terminal().run(f"{exe_name or tool_name} --version", shell="powershell").op_if_successfull_or_default(strict_err=True, strict_returcode=True)
128
183
  tmp_path = INSTALL_VERSION_ROOT.joinpath(exe_name).create(parents_only=True)
129
184
  if tmp_path.exists(): existing_version = tmp_path.read_text().rstrip()
130
185
  else: existing_version = None
131
186
 
132
187
  if existing_version is not None:
133
188
  if existing_version == version_to_be_installed:
134
- print(f"⚠️ {exe_name} already installed at version {version_to_be_installed}. See {INSTALL_VERSION_ROOT}")
189
+ print(f"📦️ ⚠️ {exe_name} already installed at version {version_to_be_installed}. See {INSTALL_VERSION_ROOT}")
135
190
  return True
136
191
  else:
137
192
  # print(f"Latest version is {version}, logged at {tmp_path}")
138
- print(f"⬆️ {exe_name} installed at version {existing_version.rstrip()} --> Installing version {version_to_be_installed} ")
193
+ print(f"📦️ ⬆️ {exe_name} installed at version {existing_version.rstrip()} --> Installing version {version_to_be_installed} ")
139
194
  tmp_path.write_text(version_to_be_installed)
140
195
  else:
141
- print(f"{exe_name} has no known version. Installing version `{version_to_be_installed}` ")
196
+ print(f"📦️ {exe_name} has no known version. Installing version `{version_to_be_installed}` ")
142
197
  tmp_path.write_text(version_to_be_installed)
143
198
  return False
144
199
 
145
200
 
146
- # ------------------------ ARCHIVE ------------------------
147
- @dataclass
148
- class ReleaseFileNameStructure:
149
- repo_url: str
150
- fixed_file_name_windows_amd_64: Optional[str] # the release has a fixed file name, so no need to compose it
151
- fixed_file_name_linux_amd_64: Optional[str] # the release has a fixed file name, so no need to compose it
152
- tool_name: str # as it appears in the release file name
153
- exe_name: str # as it is called from the terminal, i.e. the name of the executable file
154
- suffix_window_amd_64: Optional[str]
155
- suffix_linux_amd_64: Optional[str]
156
- compression_windows: Optional[str]
157
- compression_linux: Optional[str]
158
- sep: str = "-"
159
- strip_v: bool = False
160
- doc: str = ""
161
-
162
- def to_dict(self):
163
- return self.__dict__
164
-
165
- @staticmethod
166
- def from_dict(d: dict[str, Any]):
167
- return ReleaseFileNameStructure(**d)
168
-
169
- def compose_filename(self, version: Optional[str]) -> str:
170
- if platform.system() == "Windows": fixed_file_name = self.fixed_file_name_windows_amd_64
171
- elif platform.system() == "Linux": fixed_file_name = self.fixed_file_name_linux_amd_64
172
- else: raise NotImplementedError(f"System {platform.system()} not implemented")
173
- if fixed_file_name is not None: return fixed_file_name
174
- assert version is not None, f"Version must be passed if fixed_file_name is None"
175
- version_in_filename = version.replace("v", "") if self.strip_v else version
176
- if platform.system() == "Windows":
177
- compression = self.compression_windows
178
- suffix = self.suffix_window_amd_64
179
- assert suffix is not None, f"No binaries for windows found for {self.tool_name}"
180
- elif platform.system() == "Linux":
181
- compression = self.compression_linux
182
- suffix = self.suffix_linux_amd_64
183
- assert suffix is not None, f"No binaries for linux found for {self.tool_name}"
184
- else: raise NotImplementedError(f"System {platform.system()} not implemented")
185
- file_name = f'{self.tool_name}{self.sep}{version_in_filename}{self.sep}{suffix}'
186
- if compression is not None: file_name += f".{compression}"
187
- return file_name
188
-
189
- def compose_download_link(self, version: Optional[str]):
190
- release_url, version_to_be_installed = Installer.get_github_release(repo_url=self.repo_url, version=version)
191
- file_name = self.compose_filename(version=version_to_be_installed)
192
- download_link = release_url.joinpath(file_name)
193
- return download_link
194
-
195
- def install(self, version: Optional[str] = None):
196
- gh_release = self
197
- release_url, version_to_be_installed = Installer.get_github_release(repo_url=gh_release.repo_url, version=version)
198
- installed_already = Installer.check_if_installed_already(exe_name=gh_release.exe_name, version=version_to_be_installed)
199
-
200
- if installed_already: return None
201
- # if not download_n_extract: return release_url
202
- console = Console()
203
- console.rule(f"Installing {gh_release.exe_name} version {version_to_be_installed}")
204
- file_name = gh_release.compose_filename(version=version_to_be_installed)
205
- download_link = release_url.joinpath(file_name)
206
-
207
- print("Downloading", download_link.as_url_str())
208
- downloaded = download_link.download(folder=INSTALL_TMP_DIR).decompress()
209
- if not platform.system() == "Linux": return find_move_delete_windows(downloaded_file_path=downloaded, exe_name=gh_release.exe_name, delete=True)
210
- return find_move_delete_linux(downloaded=downloaded, tool_name=gh_release.exe_name, delete=True)
211
-
212
-
213
- def get_latest_release(repo_url: str, exe_name: str,
214
- download_n_extract: bool = False,
215
- suffix: Optional[str] = "x86_64-pc-windows-msvc",
216
- file_name: Optional[str] = None, # e.g. windows_x86_64.zip
217
- tool_name: Optional[str] = None,
218
- delete: bool = True, strip_v: bool = False,
219
- compression: Optional[str] = None,
220
- sep: str = "-", version: Optional[str] = None):
221
- """Arguments help form last part of URL `filename = f'{tool_name}{sep}{version}{sep}{suffix}.{compression}'`
222
- Unless `file_name` is passed directly, in which case it is used as is and parameters above are ignored.
223
- """
224
-
225
- console = Console()
226
- if platform.system() == "Windows":
227
- gh_release = ReleaseFileNameStructure(repo_url=repo_url, fixed_file_name_linux_amd_64=None, fixed_file_name_windows_amd_64=file_name,
228
- tool_name=tool_name or exe_name, exe_name=exe_name,
229
- suffix_window_amd_64=suffix, suffix_linux_amd_64=suffix, compression_windows=compression, compression_linux=compression, sep=sep, strip_v=strip_v)
230
- elif platform.system() == "Linux":
231
- gh_release = ReleaseFileNameStructure(repo_url=repo_url, fixed_file_name_windows_amd_64=None, fixed_file_name_linux_amd_64=file_name, tool_name=tool_name or exe_name, exe_name=exe_name, suffix_window_amd_64=suffix, suffix_linux_amd_64=suffix, compression_windows=compression, compression_linux=compression, sep=sep, strip_v=strip_v)
232
- else: raise NotImplementedError(f"System {platform.system()} not implemented")
233
-
234
- release_url, version_to_be_installed = Installer.get_github_release(repo_url=gh_release.repo_url, version=version)
235
- installed_already = Installer.check_if_installed_already(exe_name=exe_name, version=version_to_be_installed)
236
-
237
- if installed_already: return None
238
- if not download_n_extract: return release_url
239
-
240
- console.rule(f"Installing {exe_name} version {version_to_be_installed}")
241
- file_name = gh_release.compose_filename(version=version_to_be_installed)
242
- download_link = release_url.joinpath(file_name)
243
-
244
- print("Downloading", download_link.as_url_str())
245
- downloaded = download_link.download(folder=INSTALL_TMP_DIR).decompress()
246
- if not platform.system() == "Linux": return find_move_delete_windows(downloaded_file_path=downloaded, exe_name=exe_name, delete=delete)
247
- return find_move_delete_linux(downloaded=downloaded, tool_name=exe_name, delete=delete)
248
- # console.rule(f"Completed Installation")
249
- # return res
250
-
251
-
252
- def run_python_installer(py_file: P, version: Optional[str] = None):
253
- try:
254
- old_version = Terminal().run(f"{py_file.stem} --version", shell="powershell").op.replace("\n", "")
255
- Read.py(py_file)["main"](version=version)
256
- new_version = Terminal().run(f"{py_file.stem} --version", shell="powershell").op.replace("\n", "")
257
- if old_version == new_version: return f"😑 {py_file.stem}, same version: {old_version}"
258
- else: return f"🤩 {py_file.stem} updated from {old_version} === to ===> {new_version}"
259
- except Exception as ex:
260
- print(ex)
261
- return f"Failed at {py_file.stem} with {ex}"
262
-
263
- def get_cli_py_installers(system: str, dev: bool, use_config: bool = False):
264
- if system == "Windows": import machineconfig.jobs.python_windows_installers as inst
265
- else: import machineconfig.jobs.python_linux_installers as inst
266
- import machineconfig.jobs.python_generic_installers as gens
267
- path = P(inst.__file__).parent
268
- gens_path = P(gens.__file__).parent
269
- if dev:
270
- path = path.joinpath("dev")
271
- gens_path = gens_path.joinpath("dev")
272
- if use_config: return L([path.joinpath("config.json"), gens_path.joinpath("config.json")])
273
- return path.search("*.py", filters=[lambda x: "__init__" not in str(x)]) + gens_path.search("*.py", filters=[lambda x: "__init__" not in str(x)])
274
-
275
- def install_all(installers: L[P], safe: bool = False, jobs: int = 10, fresh: bool = False):
276
- if fresh: INSTALL_VERSION_ROOT.delete(sure=True)
277
- if safe:
278
- from machineconfig.jobs.python.check_installations import APP_SUMMARY_PATH
279
- apps_dir = APP_SUMMARY_PATH.readit()
280
- if platform.system().lower() == "windows":
281
- apps_dir.search("*").apply(lambda app: app.move(folder=P.get_env().WindowsApps))
282
- elif platform.system().lower() == "linux":
283
- Terminal().run(f"sudo mv {apps_dir.as_posix()}/* /usr/local/bin/").print_if_unsuccessful(desc="MOVING executable to /usr/local/bin", strict_err=True, strict_returncode=True)
284
- else: raise NotImplementedError(f"I don't know this system {platform.system()}")
285
- apps_dir.delete(sure=True)
286
- return None
287
-
288
- run_python_installer(installers.list[0]) # try out the first installer alone cause it will ask for password, so the rest will inherit the sudo session.
289
- # summarize results
290
- res: L[str] = installers.slice(start=1).apply(run_python_installer, jobs=jobs)
291
- console = Console()
292
- print("\n")
293
- console.rule("Same version apps")
294
- print(f"{res.filter(lambda x: 'same version' in x).print()}")
295
- print("\n")
296
- console.rule("Updated apps")
297
- print(f"{res.filter(lambda x: 'updated from' in x).print()}")
298
- print("\n")
299
- console.rule("Failed apps")
300
- print(f"{res.filter(lambda x: 'Failed at' in x).print()}")
301
-
302
- print("\n")
303
- print("Completed Installation".center(100, "-"))
304
- print("\n" * 2)
305
-
306
- # ------------------------ ARCHIVE ------------------------
307
-
308
-
309
201
  def get_installed_cli_apps():
310
202
  if platform.system() == "Windows": apps = P.home().joinpath("AppData/Local/Microsoft/WindowsApps").search("*.exe", not_in=["notepad"])
311
203
  elif platform.system() == "Linux": apps = P(r"/usr/local/bin").search("*")
@@ -314,22 +206,22 @@ def get_installed_cli_apps():
314
206
  return apps
315
207
 
316
208
 
317
- def get_cli_py_installers_v2(system: str, dev: bool) -> list[Installer]:
318
- if system == "Windows": import machineconfig.jobs.python_windows_installers as inst
319
- else: import machineconfig.jobs.python_linux_installers as inst
320
- import machineconfig.jobs.python_generic_installers as gens
321
- path = P(inst.__file__).parent
322
- gens_path = P(gens.__file__).parent
209
+ def get_installers(system: str, dev: bool) -> list[Installer]:
210
+ if system == "Windows": import machineconfig.jobs.python_windows_installers as os_specific_installer
211
+ else: import machineconfig.jobs.python_linux_installers as os_specific_installer
212
+ import machineconfig.jobs.python_generic_installers as generic_installer
213
+ path = P(os_specific_installer.__file__).parent
214
+ gens_path = P(generic_installer.__file__).parent
323
215
  if dev:
324
216
  path = path.joinpath("dev")
325
217
  gens_path = gens_path.joinpath("dev")
326
218
  res1: dict[str, Any] = Read.json(path=path.joinpath("config.json"))
327
219
  res2: dict[str, Any] = Read.json(path=gens_path.joinpath("config.json"))
328
220
  res2.update(res1)
329
- return [Installer.from_dict(d) for d in res2.values()]
221
+ return [Installer.from_dict(d=vd, name=k) for k, vd in res2.items()]
330
222
 
331
223
 
332
- def install_all_v2(installers: L[Installer], safe: bool = False, jobs: int = 10, fresh: bool = False):
224
+ def install_all(installers: L[Installer], safe: bool = False, jobs: int = 10, fresh: bool = False):
333
225
  if fresh: INSTALL_VERSION_ROOT.delete(sure=True)
334
226
  if safe:
335
227
  from machineconfig.jobs.python.check_installations import APP_SUMMARY_PATH
@@ -19,7 +19,7 @@ SUCCESS = "success"
19
19
  DEFAULT_CONFIG = """
20
20
  [specs]
21
21
  frequency = 30d
22
- start = 2023-11-01 01:00
22
+ start = 2024-01-01 01:00
23
23
 
24
24
  [runtime]
25
25
  venv = ve