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
@@ -3,17 +3,23 @@
3
3
  """
4
4
  from rich.console import Console
5
5
 
6
- from crocodile.file_management import P, List as L, Read, Struct
6
+ from crocodile.file_management import P, List as L, Read
7
+ from crocodile.core import Struct
7
8
  from crocodile.meta import Terminal
8
9
  from machineconfig.utils.utils import INSTALL_VERSION_ROOT, INSTALL_TMP_DIR, LIBRARY_ROOT, check_tool_exists
9
10
 
10
11
  # from dataclasses import dataclass
11
- from typing import Optional, Any
12
+ from typing import Optional, Any, TypeAlias, Literal
12
13
  import platform
13
14
  # import os
14
15
 
15
16
 
16
- def find_move_delete_windows(downloaded_file_path: P, exe_name: Optional[str] = None, delete: bool = True, rename_to: Optional[str] = None):
17
+ LINUX_INSTALL_PATH = '/usr/local/bin'
18
+ WINDOWS_INSTALL_PATH = P.home().joinpath("AppData/Local/Microsoft/WindowsApps").__str__()
19
+ CATEGORY: TypeAlias = Literal["OS_SPECIFIC", "OS_GENERIC", "CUSTOM", "OS_SPECIFIC_DEV", "OS_GENERIC_DEV", "CUSTOM_DEV"]
20
+
21
+
22
+ def find_move_delete_windows(downloaded_file_path: P, exe_name: Optional[str] = None, delete: bool=True, rename_to: Optional[str] = None):
17
23
  if exe_name is not None and ".exe" in exe_name: exe_name = exe_name.replace(".exe", "")
18
24
  if downloaded_file_path.is_file():
19
25
  exe = downloaded_file_path
@@ -22,10 +28,14 @@ def find_move_delete_windows(downloaded_file_path: P, exe_name: Optional[str] =
22
28
  else:
23
29
  tmp = downloaded_file_path.search(f"{exe_name}.exe", r=True)
24
30
  if len(tmp) == 1: exe = tmp.list[0]
25
- else: exe = downloaded_file_path.search("*.exe", r=True).list[0]
31
+ else:
32
+ search_res = downloaded_file_path.search("*.exe", r=True)
33
+ if len(search_res) == 0: raise IndexError(f"No executable found in {downloaded_file_path}")
34
+ elif len(search_res) == 1: exe = search_res.list[0]
35
+ else: exe = search_res.sort(lambda x: x.size("kb")).list[-1]
26
36
  if rename_to and exe.name != rename_to:
27
37
  exe = exe.with_name(name=rename_to, inplace=True)
28
- exe_new_location = exe.move(folder=P.get_env().WindowsApps, overwrite=True) # latest version overwrites older installation.
38
+ exe_new_location = exe.move(folder=WINDOWS_INSTALL_PATH, overwrite=True) # latest version overwrites older installation.
29
39
  if delete: downloaded_file_path.delete(sure=True)
30
40
  return exe_new_location
31
41
 
@@ -41,33 +51,36 @@ def find_move_delete_linux(downloaded: P, tool_name: str, delete: Optional[bool]
41
51
  if len(exe_search_res) == 0:
42
52
  print(f"No search results for `{tool_name}` in `{downloaded}`")
43
53
  raise IndexError(f"No executable found in {downloaded}")
44
- else:
54
+ elif len(exe_search_res) == 1:
45
55
  exe = exe_search_res.list[0]
56
+ else:
57
+ exe = exe_search_res.sort(lambda x: x.size("kb")).list[-1]
46
58
  if rename_to and exe.name != rename_to:
47
59
  exe = exe.with_name(name=rename_to, inplace=True)
48
- print(f"MOVING file `{repr(exe)}` to '/usr/local/bin'")
60
+ print(f"MOVING file `{repr(exe)}` to '{LINUX_INSTALL_PATH}'")
49
61
  exe.chmod(0o777)
50
- # exe.move(folder=r"/usr/local/bin", overwrite=False)
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)
62
+ # exe.move(folder=LINUX_INSTALL_PATH, overwrite=False)
63
+ Terminal().run(f"sudo mv {exe} {LINUX_INSTALL_PATH}/").print_if_unsuccessful(desc=f"MOVING executable `{exe}` to {LINUX_INSTALL_PATH}", strict_err=True, strict_returncode=True)
52
64
  if delete: downloaded.delete(sure=True)
53
- exe_new_location = P(r"/usr/local/bin").joinpath(exe.name)
65
+ exe_new_location = P(LINUX_INSTALL_PATH).joinpath(exe.name)
54
66
  return exe_new_location
55
67
 
56
68
 
57
69
  class Installer:
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):
59
- self.repo_url = repo_url
60
- self.name = name
61
- self.doc = doc
62
- self.filename_template_windows_amd_64 = filename_template_windows_amd_64
63
- self.filename_template_linux_amd_64 = filename_template_linux_amd_64
64
- self.strip_v = strip_v
65
- self.exe_name = exe_name
70
+ def __init__(self, repo_url: str, name: str, doc: str, filename_template_windows_amd_64: str, filename_template_linux_amd_64: str,
71
+ strip_v: bool, exe_name: str):
72
+ self.repo_url: str=repo_url
73
+ self.name: str=name
74
+ self.doc: str=doc
75
+ self.filename_template_windows_amd_64: str=filename_template_windows_amd_64
76
+ self.filename_template_linux_amd_64: str=filename_template_linux_amd_64
77
+ self.strip_v: bool=strip_v
78
+ self.exe_name: str=exe_name
66
79
  def __repr__(self) -> str: return f"Installer of {self.repo_url}"
67
80
  def get_description(self):
68
81
  # old_version_cli = Terminal().run(f"{self.exe_name} --version").op.replace("\n", "")
69
82
  # old_version_cli = os.system(f"{self.exe_name} --version").replace("\n", "")
70
- old_version_cli = check_tool_exists(self.exe_name)
83
+ old_version_cli: bool=check_tool_exists(tool_name=self.exe_name)
71
84
  old_version_cli_str = "✅" if old_version_cli else "❌"
72
85
  # name_version = f"{self.exe_name} {old_version_cli_str}"
73
86
  return f"{self.exe_name:<12} {old_version_cli_str} {self.doc}"
@@ -83,39 +96,49 @@ class Installer:
83
96
  from machineconfig.utils.utils import choose_one_option
84
97
  path = choose_one_option(options=LIBRARY_ROOT.joinpath("jobs").search("config.json", r=True).list)
85
98
  config: dict[str, Any] = Read.json(path) # /python_generic_installers/config.json"))
86
- # binary = choose_one_option(options=list(config.keys()), fzf=True)
87
- for keys, dict_ in config.items():
88
- installer = Installer.from_dict(d=dict_, name=keys)
89
- installer.install(version=None)
99
+ app_name = choose_one_option(options=list(config.keys()), fzf=True)
100
+ # for keys, dict_ in config.items():
101
+ installer = Installer.from_dict(d=config[app_name], name=app_name)
102
+ version = input(f"Enter version to install for {installer.exe_name} [latest]: ") or None
103
+ installer.install(version=version)
90
104
 
91
105
  def install_robust(self, version: Optional[str]):
92
106
  try:
107
+
93
108
  old_version_cli = Terminal().run(f"{self.exe_name} --version").op.replace("\n", "")
94
109
  self.install(version=version)
95
110
  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}"
111
+
112
+ if old_version_cli == new_version_cli: return f"""echo "📦️ 😑 {self.exe_name}, same version: {old_version_cli}" """
113
+ else: return f"""echo "📦️ 🤩 {self.exe_name} updated from {old_version_cli} === to ===> {new_version_cli}" """
114
+
98
115
  except Exception as ex:
99
116
  print(ex)
100
- return f"📦️ Failed at {self.exe_name} with {ex}"
117
+ return f"""echo "📦️ Failed at `{self.name}` with {ex}" """
101
118
 
102
119
  def install(self, version: Optional[str]):
103
120
  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")
121
+
122
+ import machineconfig.jobs.python_custom_installers as python_custom_installers
123
+ installer_path = P(python_custom_installers.__file__).parent.joinpath(self.exe_name + ".py")
124
+ if not installer_path.exists():
125
+ installer_path = P(python_custom_installers.__file__).parent.joinpath("dev", self.exe_name + ".py")
126
+
106
127
  import runpy
107
- program = runpy.run_path(str(installer_path), run_name="__main__")['main'](version=version)
108
- Terminal().run(program, shell="default")
128
+ print(f"Executing func `main` from `{installer_path}`to get the program to run")
129
+ program: str=runpy.run_path(str(installer_path), run_name=None)['main'](version=version)
130
+ # print(program)
131
+ Terminal(stdin=None, stdout=None, stderr=None).run_script(script=program, shell="default").print(desc="Running custom installer", capture=True)
132
+ # import subprocess
133
+ # subprocess.run(program, shell=True, check=True)
109
134
  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"
135
+ elif "npm " in self.repo_url or "pip " in self.repo_url or "winget " in self.repo_url:
136
+ desc = self.repo_url.split(" ", maxsplit=1)[0] + "installation"
137
+ version_to_be_installed = self.repo_url.split(" ", maxsplit=1)[0] + "Latest"
138
+ Terminal().run(self.repo_url, shell="default").print_if_unsuccessful(desc=desc, strict_err=True, strict_returncode=True)
116
139
  else:
117
140
  downloaded, version_to_be_installed = self.download(version=version)
118
- if downloaded.str.endswith(".deb"):
141
+ if downloaded.to_str().endswith(".deb"):
119
142
  assert platform.system() == "Linux"
120
143
  Terminal().run(f"sudo apt install -y {downloaded}").print_if_unsuccessful(desc="Installing .deb", strict_err=True, strict_returncode=True)
121
144
  downloaded.delete(sure=True)
@@ -147,7 +170,7 @@ class Installer:
147
170
  else: raise NotImplementedError(f"📦️ System {platform.system()} not implemented")
148
171
  version_to_be_installed = "predefined_url"
149
172
  else:
150
- release_url, version_to_be_installed = self.get_github_release(repo_url=self.repo_url, version=version)
173
+ release_url, version_to_be_installed = Installer.get_github_release(repo_url=self.repo_url, version=version)
151
174
  print(f"📦️ Version to be installed: {version_to_be_installed}")
152
175
  print(f"📦️ Release URL: {release_url}")
153
176
  version_to_be_installed_stripped = version_to_be_installed.replace("v", "") if self.strip_v else version_to_be_installed
@@ -156,9 +179,9 @@ class Installer:
156
179
  elif platform.system() == "Linux":
157
180
  file_name = self.filename_template_linux_amd_64.format(version_to_be_installed_stripped)
158
181
  else: raise NotImplementedError(f"📦️ System {platform.system()} not implemented")
159
- print(f"📦️ File name", file_name)
182
+ print("📦️ File name", file_name)
160
183
  download_link = release_url.joinpath(file_name)
161
- print("📦️ Downloading: ", download_link.as_url_str())
184
+ print(f"📦️ Downloading {self.name}: ", download_link.as_url_str())
162
185
  downloaded = download_link.download(folder=INSTALL_TMP_DIR).decompress()
163
186
  return downloaded, version_to_be_installed
164
187
 
@@ -168,6 +191,7 @@ class Installer:
168
191
  print(f"📦️ Inspecting latest release @ {repo_url} ...")
169
192
  # with console.status("Installing..."): # makes troubles on linux when prompt asks for password to move file to /usr/bin
170
193
  if version is None:
194
+ # see this: https://api.github.com/repos/cointop-sh/cointop/releases/latest
171
195
  import requests # https://docs.github.com/en/repositories/releasing-projects-on-github/linking-to-releases
172
196
  _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
173
197
  version_to_be_installed = _latest_version
@@ -178,58 +202,137 @@ class Installer:
178
202
  return release_url, version_to_be_installed
179
203
 
180
204
  @staticmethod
181
- def check_if_installed_already(exe_name: str, version: str):
205
+ def check_if_installed_already(exe_name: str, version: str, use_cache: bool):
182
206
  version_to_be_installed = version
183
207
  tmp_path = INSTALL_VERSION_ROOT.joinpath(exe_name).create(parents_only=True)
184
- if tmp_path.exists(): existing_version = tmp_path.read_text().rstrip()
185
- else: existing_version = None
208
+
209
+ if use_cache:
210
+ if tmp_path.exists(): existing_version = tmp_path.read_text().rstrip()
211
+ else: existing_version = None
212
+ else:
213
+ # check_tool_exists(tool_name=exe_name)
214
+ # raise NotImplementedError("Not implemented")
215
+ # import subprocess
216
+ # try:
217
+ # existing_version = subprocess.check_output([exe_name, "--version"], text=True)
218
+ # existing_version = existing_version.strip()
219
+ # except (subprocess.CalledProcessError, FileNotFoundError):
220
+ # print(f"Failed to get version of {exe_name}")
221
+ # existing_version = None
222
+ resp = Terminal().run(exe_name, "--version", check=False).capture()
223
+ if resp.op == '': existing_version = None
224
+ else: existing_version = resp.op.strip()
186
225
 
187
226
  if existing_version is not None:
188
227
  if existing_version == version_to_be_installed:
189
228
  print(f"📦️ ⚠️ {exe_name} already installed at version {version_to_be_installed}. See {INSTALL_VERSION_ROOT}")
190
- return True
229
+ return ("✅ Uptodate", version.strip(), version_to_be_installed.strip())
191
230
  else:
192
231
  # print(f"Latest version is {version}, logged at {tmp_path}")
193
232
  print(f"📦️ ⬆️ {exe_name} installed at version {existing_version.rstrip()} --> Installing version {version_to_be_installed} ")
194
233
  tmp_path.write_text(version_to_be_installed)
234
+ return ("❌ Outdated", existing_version.strip(), version_to_be_installed.strip())
195
235
  else:
196
236
  print(f"📦️ {exe_name} has no known version. Installing version `{version_to_be_installed}` ")
197
237
  tmp_path.write_text(version_to_be_installed)
198
- return False
238
+ return ("⚠️NotInstalled", "None", version_to_be_installed.strip())
239
+
240
+
241
+ def check_latest():
242
+ installers = get_installers(system=platform.system(), dev=False)
243
+ # installers += get_installers(system=platform.system(), dev=True)
244
+ installers_gitshub = []
245
+ for inst__ in installers:
246
+ if "ntop" in inst__.name: continue
247
+ if "github" not in inst__.repo_url:
248
+ print(f"Skipping {inst__.name} as it is not a github release")
249
+ continue
250
+ installers_gitshub.append(inst__)
251
+
252
+ def func(inst: Installer):
253
+ _release_url, version_to_be_installed = inst.get_github_release(repo_url=inst.repo_url, version=None)
254
+ verdict, current_ver, new_ver = inst.check_if_installed_already(exe_name=inst.exe_name, version=version_to_be_installed, use_cache=False)
255
+ return inst.exe_name, verdict, current_ver, new_ver
256
+
257
+ res = L(installers_gitshub).apply(func=func, jobs=1)
258
+ import pandas as pd
259
+ res_df = pd.DataFrame(res, columns=["Tool", "Status", "Current Version", "New Version"]).groupby("Status").apply(lambda x: x).reset_index(drop=True)
260
+ from crocodile.core import Display
261
+ Display.set_pandas_display()
262
+ print(res_df)
199
263
 
200
264
 
201
265
  def get_installed_cli_apps():
202
266
  if platform.system() == "Windows": apps = P.home().joinpath("AppData/Local/Microsoft/WindowsApps").search("*.exe", not_in=["notepad"])
203
- elif platform.system() == "Linux": apps = P(r"/usr/local/bin").search("*")
267
+ elif platform.system() == "Linux": apps = P(LINUX_INSTALL_PATH).search("*")
204
268
  else: raise NotImplementedError("Not implemented for this OS")
205
269
  apps = L([app for app in apps if app.size("kb") > 0.1 and not app.is_symlink()]) # no symlinks like paint and wsl and bash
206
270
  return apps
207
271
 
208
272
 
209
273
  def get_installers(system: str, dev: bool) -> list[Installer]:
274
+ res_all = get_all_dicts(system=system)
275
+ if not dev:
276
+ del res_all["CUSTOM_DEV"]
277
+ del res_all["OS_SPECIFIC_DEV"]
278
+ del res_all["OS_GENERIC_DEV"]
279
+ res_final = {}
280
+ for _k, v in res_all.items():
281
+ res_final.update(v)
282
+ return [Installer.from_dict(d=vd, name=k) for k, vd in res_final.items()]
283
+
284
+
285
+ def get_all_dicts(system: str) -> dict[CATEGORY, dict[str, dict[str, Any]]]:
210
286
  if system == "Windows": import machineconfig.jobs.python_windows_installers as os_specific_installer
211
287
  else: import machineconfig.jobs.python_linux_installers as os_specific_installer
288
+
212
289
  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
215
- if dev:
216
- path = path.joinpath("dev")
217
- gens_path = gens_path.joinpath("dev")
218
- res1: dict[str, Any] = Read.json(path=path.joinpath("config.json"))
219
- res2: dict[str, Any] = Read.json(path=gens_path.joinpath("config.json"))
220
- res2.update(res1)
221
- return [Installer.from_dict(d=vd, name=k) for k, vd in res2.items()]
222
-
223
-
224
- def install_all(installers: L[Installer], safe: bool = False, jobs: int = 10, fresh: bool = False):
290
+ path_os_specific = P(os_specific_installer.__file__).parent
291
+ path_os_generic = P(generic_installer.__file__).parent
292
+
293
+ path_os_specific_dev = path_os_specific.joinpath("dev")
294
+ path_os_generic_dev = path_os_generic.joinpath("dev")
295
+
296
+ res_final: dict[CATEGORY, dict[str, dict[str, Any]]] = {}
297
+ res_final["OS_SPECIFIC"] = Read.json(path=path_os_specific.joinpath("config.json"))
298
+ res_final["OS_GENERIC"] = Read.json(path=path_os_generic.joinpath("config.json"))
299
+ res_final["OS_SPECIFIC_DEV"] = Read.json(path=path_os_specific_dev.joinpath("config.json"))
300
+ res_final["OS_GENERIC_DEV"] = Read.json(path=path_os_generic_dev.joinpath("config.json"))
301
+
302
+ path_custom_installer = path_os_generic.with_name("python_custom_installers")
303
+ path_custom_installer_dev = path_custom_installer.joinpath("dev")
304
+
305
+ import runpy
306
+ res_custom: dict[str, dict[str, Any]] = {}
307
+ for item in path_custom_installer.search("*.py", r=False, not_in=["__init__"]):
308
+ try:
309
+ config_dict = runpy.run_path(str(item), run_name=None)['config_dict']
310
+ res_custom[item.stem] = config_dict
311
+ except Exception as ex:
312
+ print(f"Failed to load {item}: {ex}")
313
+
314
+ res_custom_dev: dict[str, dict[str, Any]] = {}
315
+ for item in path_custom_installer_dev.search("*.py", r=False, not_in=["__init__"]):
316
+ try:
317
+ config_dict = runpy.run_path(str(item), run_name=None)['config_dict']
318
+ res_custom_dev[item.stem] = config_dict
319
+ except Exception as ex:
320
+ print(f"Failed to load {item}: {ex}")
321
+
322
+ res_final["CUSTOM"] = res_custom
323
+ res_final["CUSTOM_DEV"] = res_custom_dev
324
+ return res_final
325
+
326
+
327
+ def install_all(installers: L[Installer], safe: bool=False, jobs: int = 10, fresh: bool=False):
225
328
  if fresh: INSTALL_VERSION_ROOT.delete(sure=True)
226
329
  if safe:
227
330
  from machineconfig.jobs.python.check_installations import APP_SUMMARY_PATH
228
331
  apps_dir = APP_SUMMARY_PATH.readit()
229
332
  if platform.system().lower() == "windows":
230
- apps_dir.search("*").apply(lambda app: app.move(folder=P.get_env().WindowsApps))
333
+ apps_dir.search("*").apply(lambda app: app.move(folder=P.get_env().WindowsPaths().WindowsApps))
231
334
  elif platform.system().lower() == "linux":
232
- 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)
335
+ Terminal().run(f"sudo mv {apps_dir.as_posix()}/* {LINUX_INSTALL_PATH}/").print_if_unsuccessful(desc=f"MOVING executable to {LINUX_INSTALL_PATH}", strict_err=True, strict_returncode=True)
233
336
  else: raise NotImplementedError(f"I don't know this system {platform.system()}")
234
337
  apps_dir.delete(sure=True)
235
338
  return None
@@ -249,3 +352,7 @@ def install_all(installers: L[Installer], safe: bool = False, jobs: int = 10, fr
249
352
  print("\n")
250
353
  print("Completed Installation".center(100, "-"))
251
354
  print("\n" * 2)
355
+
356
+
357
+ if __name__ == "__main__":
358
+ pass
@@ -60,7 +60,7 @@ class ProcessManager:
60
60
  self.kill(pids=sub_df.pid.to_list())
61
61
  return
62
62
  kill_by_index = input("🔫 Kill by index? 1 4 ... /[n] ")
63
- if kill_by_index != "":
63
+ if kill_by_index != "" and kill_by_index != "n":
64
64
  indices = [int(val) for val in kill_by_index.split(" ")]
65
65
  sub_sub_df = sub_df.iloc[indices]
66
66
  for idx2, row in sub_sub_df.iterrows():
@@ -93,7 +93,7 @@ class ProcessManager:
93
93
  print(f'💀 Killed process with pid {pid} and name {proc.name()}. It lived {get_age(proc.create_time())}. RIP 🪦💐')
94
94
  except psutil.NoSuchProcess: print(f'No process with pid {pid} found')
95
95
  for command in commands:
96
- rows = self.df[self.df['command'].str.contains(command)]
96
+ rows = self.df[self.df['command'].to_str().contains(command)]
97
97
  if len(rows) > 0:
98
98
  for _idx, a_row in rows.iterrows():
99
99
  psutil.Process(a_row.pid).kill()
@@ -62,7 +62,7 @@ class Report:
62
62
  status: str
63
63
 
64
64
  @classmethod
65
- def from_path(cls, path: P, return_default_if_not_found: bool = False):
65
+ def from_path(cls, path: P, return_default_if_not_found: bool=False):
66
66
  if not path.exists():
67
67
  if return_default_if_not_found:
68
68
  return Report(name=path.parent.name, start=datetime(year=2000, month=1, day=1), end=datetime(year=2000, month=1, day=1), status="NA")
@@ -108,7 +108,7 @@ def read_task_from_dir(path: P):
108
108
  return task
109
109
 
110
110
 
111
- def main(root: Optional[str] = None, ignore_conditions: bool = True):
111
+ def main(root: Optional[str] = None, ignore_conditions: bool=True):
112
112
  if root is None: root_resolved = SCHEDULER_DEFAULT_ROOT
113
113
  else: root_resolved = P(root).expanduser().absolute()
114
114
  tasks_dirs = root_resolved.search(files=False, folders=True).filter(lambda x: x.joinpath("task.py").exists())
@@ -168,7 +168,7 @@ def should_task_run(task: Task, tolerance_mins: int = 1440) -> tuple[bool, Optio
168
168
  def run_task(task: Task) -> Report:
169
169
  start_time = datetime.now()
170
170
 
171
- shell_script = get_shell_script_executing_python_file(python_file=task.task_root.joinpath("task.py").str, ve_name=task.venv)
171
+ shell_script = get_shell_script_executing_python_file(python_file=task.task_root.joinpath("task.py").to_str(), ve_name=task.venv)
172
172
  shell_script_root = P.tmp().joinpath(f"tmp_scripts/scheduler/{task.name}").create()
173
173
  try:
174
174
  if platform.system() == 'Windows':