machineconfig 1.5__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 (155) hide show
  1. machineconfig/__init__.py +8 -5
  2. machineconfig/jobs/python/check_installations.py +173 -163
  3. machineconfig/jobs/python/checkout_version.py +117 -0
  4. machineconfig/jobs/python/create_bootable_media.py +14 -14
  5. machineconfig/jobs/python/create_zellij_template.py +59 -56
  6. machineconfig/jobs/python/python_cargo_build_share.py +50 -45
  7. machineconfig/jobs/python/python_ve_symlink.py +20 -18
  8. machineconfig/jobs/python/tasks.py +4 -0
  9. machineconfig/jobs/script_installer/azure_data_studio.py +22 -0
  10. machineconfig/jobs/script_installer/bypass_paywall.py +23 -0
  11. machineconfig/jobs/script_installer/code.py +34 -0
  12. machineconfig/jobs/script_installer/docker_desktop.py +41 -0
  13. machineconfig/jobs/script_installer/ngrok.py +29 -0
  14. machineconfig/jobs/{python_linux_installers → script_installer}/skim.py +21 -19
  15. machineconfig/jobs/script_installer/wezterm.py +34 -0
  16. machineconfig/profile/create.py +107 -200
  17. machineconfig/profile/shell.py +127 -0
  18. machineconfig/scripts/__init__.py +6 -6
  19. machineconfig/scripts/python/cloud_copy.py +93 -0
  20. machineconfig/scripts/python/cloud_manager.py +38 -0
  21. machineconfig/scripts/python/cloud_mount.py +115 -52
  22. machineconfig/scripts/python/cloud_repo_sync.py +154 -114
  23. machineconfig/scripts/python/cloud_sync.py +261 -79
  24. machineconfig/scripts/python/croshell.py +151 -0
  25. machineconfig/scripts/python/devops.py +119 -87
  26. machineconfig/scripts/python/devops_add_identity.py +27 -23
  27. machineconfig/scripts/python/devops_add_ssh_key.py +70 -55
  28. machineconfig/scripts/python/devops_backup_retrieve.py +52 -46
  29. machineconfig/scripts/python/devops_devapps_install.py +120 -91
  30. machineconfig/scripts/python/devops_update_repos.py +82 -68
  31. machineconfig/scripts/python/dotfile.py +42 -38
  32. machineconfig/scripts/python/fire_jobs.py +351 -98
  33. machineconfig/scripts/python/ftpx.py +82 -0
  34. machineconfig/scripts/python/mount_nfs.py +54 -3
  35. machineconfig/scripts/python/mount_nw_drive.py +31 -0
  36. machineconfig/scripts/python/mount_ssh.py +44 -20
  37. machineconfig/scripts/python/onetimeshare.py +60 -51
  38. machineconfig/scripts/python/pomodoro.py +41 -37
  39. machineconfig/scripts/python/repos.py +195 -128
  40. machineconfig/scripts/python/scheduler.py +52 -0
  41. machineconfig/scripts/python/snapshot.py +21 -21
  42. machineconfig/scripts/python/start_slidev.py +104 -0
  43. machineconfig/scripts/python/start_terminals.py +97 -0
  44. machineconfig/scripts/python/wifi_conn.py +90 -71
  45. machineconfig/scripts/python/{transfer_wsl_win.py → wsl_windows_transfer.py} +47 -39
  46. machineconfig/setup_windows/wt_and_pwsh/set_pwsh_theme.py +44 -48
  47. machineconfig/setup_windows/wt_and_pwsh/set_wt_settings.py +136 -130
  48. machineconfig/utils/installer.py +251 -0
  49. machineconfig/utils/procs.py +114 -64
  50. machineconfig/utils/scheduling.py +188 -0
  51. machineconfig/utils/utils.py +353 -249
  52. machineconfig/utils/ve.py +222 -0
  53. {machineconfig-1.5.dist-info → machineconfig-1.8.dist-info}/METADATA +140 -110
  54. machineconfig-1.8.dist-info/RECORD +70 -0
  55. {machineconfig-1.5.dist-info → machineconfig-1.8.dist-info}/WHEEL +1 -1
  56. machineconfig/jobs/python/python_linux_installers_all.py +0 -73
  57. machineconfig/jobs/python/python_ve_installer.py +0 -73
  58. machineconfig/jobs/python/python_windows_installers_all.py +0 -23
  59. machineconfig/jobs/python_generic_installers/archive/nvim.py +0 -15
  60. machineconfig/jobs/python_generic_installers/archive/strongbox.py +0 -32
  61. machineconfig/jobs/python_generic_installers/archive/vtm.py +0 -25
  62. machineconfig/jobs/python_generic_installers/broot.py +0 -39
  63. machineconfig/jobs/python_generic_installers/browsh.py +0 -25
  64. machineconfig/jobs/python_generic_installers/bw.py +0 -26
  65. machineconfig/jobs/python_generic_installers/chatgpt.py +0 -24
  66. machineconfig/jobs/python_generic_installers/cpufetch.py +0 -23
  67. machineconfig/jobs/python_generic_installers/delta.py +0 -59
  68. machineconfig/jobs/python_generic_installers/dev/__init__.py +0 -0
  69. machineconfig/jobs/python_generic_installers/dev/autogpt.py +0 -28
  70. machineconfig/jobs/python_generic_installers/dev/bw.py +0 -29
  71. machineconfig/jobs/python_generic_installers/dev/evcxr.py +0 -22
  72. machineconfig/jobs/python_generic_installers/dev/kondo.py +0 -21
  73. machineconfig/jobs/python_generic_installers/dev/lvim.py +0 -60
  74. machineconfig/jobs/python_generic_installers/dev/ngrok.py +0 -35
  75. machineconfig/jobs/python_generic_installers/dev/opencommit.py +0 -21
  76. machineconfig/jobs/python_generic_installers/dev/qrcp.py +0 -25
  77. machineconfig/jobs/python_generic_installers/dev/qrscan.py +0 -16
  78. machineconfig/jobs/python_generic_installers/dev/rust-analyzer.py +0 -24
  79. machineconfig/jobs/python_generic_installers/dev/termscp.py +0 -23
  80. machineconfig/jobs/python_generic_installers/dev/tldr.py +0 -25
  81. machineconfig/jobs/python_generic_installers/dev/tokei.py +0 -24
  82. machineconfig/jobs/python_generic_installers/diskonaut.py +0 -26
  83. machineconfig/jobs/python_generic_installers/dua.py +0 -21
  84. machineconfig/jobs/python_generic_installers/evcxr.py +0 -21
  85. machineconfig/jobs/python_generic_installers/gitui.py +0 -23
  86. machineconfig/jobs/python_generic_installers/gopass.py +0 -19
  87. machineconfig/jobs/python_generic_installers/helix.py +0 -45
  88. machineconfig/jobs/python_generic_installers/kondo.py +0 -20
  89. machineconfig/jobs/python_generic_installers/lf.py +0 -25
  90. machineconfig/jobs/python_generic_installers/lvim.py +0 -34
  91. machineconfig/jobs/python_generic_installers/mprocs.py +0 -20
  92. machineconfig/jobs/python_generic_installers/navi.py +0 -20
  93. machineconfig/jobs/python_generic_installers/ots.py +0 -26
  94. machineconfig/jobs/python_generic_installers/ouch.py +0 -25
  95. machineconfig/jobs/python_generic_installers/pomodoro.py +0 -19
  96. machineconfig/jobs/python_generic_installers/procs.py +0 -20
  97. machineconfig/jobs/python_generic_installers/qrcp.py +0 -22
  98. machineconfig/jobs/python_generic_installers/qrscan.py +0 -14
  99. machineconfig/jobs/python_generic_installers/rclone.py +0 -21
  100. machineconfig/jobs/python_generic_installers/rust-analyzer.py +0 -24
  101. machineconfig/jobs/python_generic_installers/tere.py +0 -26
  102. machineconfig/jobs/python_generic_installers/termscp.py +0 -23
  103. machineconfig/jobs/python_generic_installers/tldr.py +0 -24
  104. machineconfig/jobs/python_generic_installers/tokei.py +0 -21
  105. machineconfig/jobs/python_generic_installers/vtm.py +0 -26
  106. machineconfig/jobs/python_generic_installers/watchexec.py +0 -21
  107. machineconfig/jobs/python_linux_installers/archive/__init__.py +0 -0
  108. machineconfig/jobs/python_linux_installers/archive/ranger.py +0 -18
  109. machineconfig/jobs/python_linux_installers/bandwhich.py +0 -11
  110. machineconfig/jobs/python_linux_installers/bottom.py +0 -17
  111. machineconfig/jobs/python_linux_installers/btop.py +0 -17
  112. machineconfig/jobs/python_linux_installers/dev/bandwhich.py +0 -13
  113. machineconfig/jobs/python_linux_installers/dev/bytehound.py +0 -20
  114. machineconfig/jobs/python_linux_installers/dev/nnn.py +0 -21
  115. machineconfig/jobs/python_linux_installers/gotty.py +0 -16
  116. machineconfig/jobs/python_linux_installers/joshuto.py +0 -28
  117. machineconfig/jobs/python_linux_installers/mcfly.py +0 -12
  118. machineconfig/jobs/python_linux_installers/nnn.py +0 -18
  119. machineconfig/jobs/python_linux_installers/topgrade.py +0 -15
  120. machineconfig/jobs/python_linux_installers/viu.py +0 -19
  121. machineconfig/jobs/python_linux_installers/xplr.py +0 -22
  122. machineconfig/jobs/python_linux_installers/zellij.py +0 -31
  123. machineconfig/jobs/python_windows_installers/archive/ntop.py +0 -20
  124. machineconfig/jobs/python_windows_installers/bat.py +0 -16
  125. machineconfig/jobs/python_windows_installers/boxes.py +0 -19
  126. machineconfig/jobs/python_windows_installers/bypass_paywall.py +0 -18
  127. machineconfig/jobs/python_windows_installers/dev/bypass_paywall.py +0 -21
  128. machineconfig/jobs/python_windows_installers/dev/obs_background_removal_plugin.py +0 -20
  129. machineconfig/jobs/python_windows_installers/fd.py +0 -17
  130. machineconfig/jobs/python_windows_installers/fzf.py +0 -19
  131. machineconfig/jobs/python_windows_installers/obs_background_removal_plugin.py +0 -19
  132. machineconfig/jobs/python_windows_installers/rg.py +0 -15
  133. machineconfig/jobs/python_windows_installers/ugrep.py +0 -14
  134. machineconfig/jobs/python_windows_installers/zoomit.py +0 -20
  135. machineconfig/jobs/python_windows_installers/zoxide.py +0 -20
  136. machineconfig/profile/fix_shell_profiles.py +0 -8
  137. machineconfig/scripts/python/archive/__init__.py +0 -0
  138. machineconfig/scripts/python/archive/bu_gdrive_rx.py +0 -41
  139. machineconfig/scripts/python/archive/bu_gdrive_sx.py +0 -40
  140. machineconfig/scripts/python/archive/bu_onedrive_rx.py +0 -59
  141. machineconfig/scripts/python/archive/bu_onedrive_sx.py +0 -45
  142. machineconfig/scripts/python/chatgpt.py +0 -28
  143. machineconfig/scripts/python/choose_ohmybash_theme.py +0 -25
  144. machineconfig/scripts/python/choose_ohmyposh_theme.py +0 -40
  145. machineconfig/scripts/python/cloud_rx.py +0 -42
  146. machineconfig/scripts/python/cloud_sx.py +0 -40
  147. machineconfig/scripts/python/ftprx.py +0 -37
  148. machineconfig/scripts/python/ftpsx.py +0 -36
  149. machineconfig/scripts/python/im2text.py +0 -15
  150. machineconfig/scripts/python/tmate_conn.py +0 -28
  151. machineconfig/scripts/python/tmate_start.py +0 -31
  152. machineconfig/utils/to_exe.py +0 -7
  153. machineconfig-1.5.dist-info/RECORD +0 -147
  154. /machineconfig/jobs/{python_generic_installers/archive → script_installer}/__init__.py +0 -0
  155. {machineconfig-1.5.dist-info → machineconfig-1.8.dist-info}/top_level.txt +0 -0
machineconfig/__init__.py CHANGED
@@ -1,5 +1,8 @@
1
-
2
- __version__ = "1.5"
3
- release_notes = """
4
- added gpt script
5
- """
1
+
2
+ """DS
3
+ """
4
+
5
+ __version__ = "1.8"
6
+ release_notes = """
7
+ enhanced ve management
8
+ """
@@ -1,163 +1,173 @@
1
-
2
- import crocodile.toolbox as tb
3
- import time
4
- import pandas as pd
5
- import platform
6
- from rich.console import Console
7
- # from rich.progress import track
8
- from machineconfig.utils.utils import LIBRARY_ROOT
9
- from machineconfig.jobs.python.python_linux_installers_all import get_installed_cli_apps
10
- from tqdm import tqdm
11
-
12
-
13
- safe_apps_records = LIBRARY_ROOT.joinpath(f"profile/records/{platform.system().lower()}/safe_cli_apps.json")
14
- safe_apps_url = LIBRARY_ROOT.joinpath(f"profile/records/{platform.system().lower()}/safe_cli_apps_url.txt")
15
- cloud = "gdpo"
16
-
17
-
18
- def scan(path, pct=0.0):
19
- vt = tb.install_n_import(package="vt", name="vt-py")
20
- client = vt.Client(tb.P.home().joinpath("dotfiles/creds/tokens/virustotal").read_text().split("\n")[0])
21
- console = Console()
22
- console.rule(f"Scanning {path}. {pct:.2f}% done")
23
- if path.is_dir():
24
- print(f"Skipping {path} as it is a directory.")
25
- return None
26
- with open(str(path), "rb") as f:
27
- analysis = client.scan_file(f)
28
-
29
- repeat_counter = 0
30
- while True:
31
- with console.status(f"waiting for scan of {path} ... "):
32
- try:
33
- anal = client.get_object("/analyses/{}", analysis.id)
34
- # print(anal.status)
35
- if anal.status == "completed": break
36
- except:
37
- repeat_counter += 1
38
- if repeat_counter > 2:
39
- raise ValueError(f"Error in scanning {path}")
40
- print(f"Error in scanning, trying again.")
41
- time.sleep(30)
42
-
43
- df = pd.DataFrame(anal.results).T
44
- malicious = []
45
- for idx, row in df.iterrows():
46
- if row.result is None and row.category in ["undetected", "type-unsupported", "failure", "timeout", "confirmed-timeout"]: continue
47
- else:
48
- tb.Struct(row.to_dict()).print(as_config=True, title=f"Found Category {row.category}")
49
- malicious.append(row)
50
-
51
- positive_pct = len(malicious) / len(df) * 100
52
- print(f"positive_ratio = {positive_pct:.1f} %")
53
- return positive_pct
54
-
55
-
56
- def main():
57
- apps_paths_raw = get_installed_cli_apps()
58
-
59
- app_versions = []
60
- versions = tb.P.home().joinpath(f"tmp_results/cli_tools_installers/versions").search()
61
- for an_app in apps_paths_raw:
62
- if an_app.stem in versions.stem: app_versions.append(versions.filter(lambda x: x.stem == an_app.stem.replace(".exe", ""))[0].read_text())
63
- else: app_versions.append(None)
64
-
65
- positive_pct = []
66
- # for app in track(apps, description="App apps scanning..."):
67
- for idx, app in enumerate(apps_paths_raw):
68
- try: res = scan(app, idx/len(apps_paths_raw)*100)
69
- except ValueError as ve:
70
- print(ve)
71
- res = None
72
- positive_pct.append(res)
73
-
74
- res_df = pd.DataFrame({"app_name": apps_paths_raw.stem.list, "version": app_versions, "positive_pct": positive_pct,
75
- "app_path": apps_paths_raw.apply(lambda x: x.collapseuser(strict=False).as_posix()).list})
76
-
77
- apps_safe_df = res_df.query("positive_pct < 5")
78
-
79
- app_url = []
80
- for idx, row in tqdm(apps_safe_df.iterrows(), total=apps_safe_df.shape[0]):
81
- apps_safe_url = upload(tb.P(row["app_path"]).expanduser())
82
- app_url.append(apps_safe_url.as_posix() if type(apps_safe_url) == tb.P else apps_safe_url)
83
- res_df["app_url"] = app_url
84
-
85
- res_df.to_json(safe_apps_records.create(parents_only=True), index=False, orient='split')
86
- share_url = safe_apps_records.to_cloud(cloud, rel2home=True, share=True)
87
- safe_apps_url.write_text(share_url.as_posix())
88
- print(res_df)
89
-
90
-
91
- def upload(path):
92
- set_time_out = tb.install_n_import("call_function_with_timeout").SetTimeout
93
- def func():
94
- return path.to_cloud(cloud, rel2home=True, share=True)
95
- func_with_timeout = set_time_out(func, timeout=180)
96
- is_done, is_timeout, erro_message, results = func_with_timeout()
97
- if is_done: return results
98
- else: return None
99
-
100
-
101
- class PrecompliedInstaller:
102
- @staticmethod
103
- def download_rclone_links(url, name=None):
104
- if "drive.google.com" in str(url): url = str(url).replace("open?", "uc?")
105
- else: raise NotImplementedError("Only google drive is supported for now.")
106
- return tb.P(url).download(name=name)
107
-
108
- def __init__(self, from_cloud=True):
109
- if from_cloud: file = PrecompliedInstaller.download_rclone_links(safe_apps_url.read_text(), name=safe_apps_records.name)
110
- else: file = safe_apps_records
111
- tmp = file.readit()
112
- self.df = pd.DataFrame(tmp['data'], columns=tmp['columns'])
113
-
114
- def install(self, name):
115
- res = self.df.query(f"app == '{name}'")
116
- if len(res) == 0 or len(res) > 1:
117
- print(f"Couldn't find unique result when searching safe_apps_records @ {self.safe_apps_records}")
118
- return None
119
- tb.P(res.app_url).download()
120
-
121
- def download_safe_apps(self):
122
- if platform.system().lower() == "windows":
123
- from machineconfig.jobs.python.python_windows_installers_all import get_cli_py_installers
124
- cli_installers = get_cli_py_installers()
125
- elif platform.system().lower() == "linux":
126
- from machineconfig.jobs.python.python_linux_installers_all import get_cli_py_installers
127
- cli_installers = get_cli_py_installers()
128
- else: raise NotImplementedError(f"Platform {platform.system().lower()} is not supported yet.")
129
-
130
- def install_cli_apps(row):
131
- if row["app_url"] is None:
132
- print(f"{row['app_name']} url is not available, trying to download from its sources:")
133
- version = row["version"]
134
- if version is None:
135
- print(f"Version is not available, either, I can't trust the latest version. Skipping installation of this program.")
136
- return False
137
- else:
138
- tmp = cli_installers.filter(lambda x: x.stem == row["app_name"].replace(".exe", ""))
139
- if len(tmp) == 0:
140
- print(f"Can't find the installer for {row['app_name']}, skipping installation of this program.")
141
- return False
142
- else: tb.Read.py(tmp[0])["main"](version=version)
143
- else:
144
- name = row["app_name"]
145
- if platform.system().lower() == "windows" and not name.endswith(".exe"): name += ".exe"
146
- exe = self.download_rclone_links(row["app_url"], name=name)
147
- if platform.system().lower() == "linux":
148
- tb.Terminal().run(f"chmod +x {exe}")
149
- tb.Terminal().run(f"mv {exe} /usr/local/bin/")
150
- elif platform.system().lower() == "windows":
151
- exe.move(folder=tb.P.home().joinpath("AppData/Local/Microsoft/WindowsApps"), overwrite=True)
152
- return True
153
-
154
- res = tb.L(self.df.iterrows()).apply(lambda x: install_cli_apps(x[1]), jobs=20)
155
-
156
- print("\n"*3)
157
- for item_flag, item_name in zip(res, self.df["app_name"]):
158
- if item_flag: print(f"✅ {item_name} is installed. 😁")
159
- else: print(f" {item_name} failed to install for reasons explained in the log above, try manually.")
160
-
161
-
162
- if __name__ == '__main__':
163
- pass
1
+
2
+ """CI
3
+ """
4
+
5
+
6
+ import time
7
+ import pandas as pd
8
+ import platform
9
+ from rich.console import Console
10
+ # from rich.progress import track
11
+ from machineconfig.utils.utils import LIBRARY_ROOT, INSTALL_VERSION_ROOT
12
+ from machineconfig.utils.installer import get_installed_cli_apps
13
+ from crocodile.core import List as L, install_n_import, Struct
14
+ from crocodile.file_management import P
15
+ from crocodile.meta import Terminal
16
+ from tqdm import tqdm
17
+ from typing import Optional
18
+
19
+
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']
22
+ # my onedrive doesn't allow sharing.
23
+
24
+
25
+ def scan(path: P, pct: float = 0.0):
26
+ vt = install_n_import(library="vt", package="vt-py")
27
+ client = vt.Client(P.home().joinpath("dotfiles/creds/tokens/virustotal").read_text().split("\n")[0])
28
+ console = Console()
29
+ console.rule(f"Scanning {path}. {pct:.2f}% done")
30
+ if path.is_dir():
31
+ print(f"Skipping {path} as it is a directory.")
32
+ return None
33
+ with open(str(path), "rb") as f:
34
+ analysis = client.scan_file(f)
35
+ repeat_counter = 0
36
+ while True:
37
+ with console.status(f"waiting for scan of {path} ... "):
38
+ try:
39
+ anal = client.get_object("/analyses/{}", analysis.id)
40
+ if anal.status == "completed": break
41
+ except Exception as ex: # type: ignore
42
+ repeat_counter += 1
43
+ if repeat_counter > 2:
44
+ raise ValueError(f"Error in scanning {path}") from ex
45
+ print(f"Error in scanning, trying again.")
46
+ time.sleep(30)
47
+ df = pd.DataFrame(anal.results.values())
48
+ malicious = []
49
+ for _idx, row in df.iterrows():
50
+ # try:
51
+ # print(row.result)
52
+ # except Exception as ex: # type: ignore
53
+ # print(row)
54
+ if row.result is None and row.category in ["undetected", "type-unsupported", "failure", "timeout", "confirmed-timeout"]: continue
55
+ else:
56
+ Struct(row.to_dict()).print(as_config=True, title=f"Found Category {row.category}")
57
+ malicious.append(row)
58
+ positive_pct: float = round(number=len(malicious) / len(df) * 100, ndigits=1)
59
+ print(f"positive_ratio = {positive_pct:.1f} %")
60
+ return positive_pct, df
61
+
62
+
63
+ def main() -> None:
64
+ apps_paths_tmp: L[P] = get_installed_cli_apps()
65
+ versions_files_paths: L[P] = INSTALL_VERSION_ROOT.search()
66
+ app_versions: list[Optional[str]] = []
67
+ apps_paths_raw: L[P] = L([])
68
+ for an_app in apps_paths_tmp:
69
+ version_path = versions_files_paths.filter(lambda x: x.stem == an_app.stem)
70
+ if len(version_path) == 1:
71
+ app_versions.append(version_path.list[0].read_text())
72
+ apps_paths_raw.append(an_app)
73
+ # if an_app.stem in versions_files_paths.stem:
74
+ # app_versions.append(versions_files_paths.filter(lambda x: x.stem == an_app.stem.replace(".exe", "")).list[0].read_text())
75
+ # else:
76
+ # print(f"🤔 Cloud not find a documented version for installation of {an_app.stem}, trying to get it from the app itself.")
77
+ # tmp = Terminal().run(f"{an_app.stem} --version", shell="powershell").capture().op_if_successfull_or_default(strict_err=False, strict_returcode=False)
78
+ # if tmp is not None: tmp = tmp.split("\n")[0]
79
+ # print(f"➡️ Found version `{tmp}` for {an_app.stem}.")
80
+ # app_versions.append(None)
81
+ print(f"Checking tools collected from `{INSTALL_VERSION_ROOT}`:")
82
+ apps_paths_raw.print()
83
+ positive_pct: list[Optional[float]] = []
84
+ detailed_results: list[dict[str, Optional[pd.DataFrame]]] = []
85
+ for idx, app in enumerate(apps_paths_raw):
86
+ try: res = scan(path=app, pct=idx / len(apps_paths_raw) * 100)
87
+ except ValueError as ve:
88
+ print(ve)
89
+ res = None
90
+ if res is None:
91
+ positive_pct.append(None)
92
+ detailed_results.append({app.stem: None})
93
+ else:
94
+ ppct, df = res
95
+ positive_pct.append(ppct)
96
+ detailed_results.append({app.stem: df})
97
+
98
+ res_df = pd.DataFrame({"app_name": apps_paths_raw.apply(lambda x: x.stem).list, "version": app_versions, "positive_pct": positive_pct,
99
+ "app_path": apps_paths_raw.apply(lambda x: x.collapseuser(strict=False).as_posix()).list})
100
+
101
+ app_url: list[Optional[str]] = []
102
+ for idx, row in tqdm(res_df.iterrows(), total=res_df.shape[0]):
103
+ apps_safe_url = upload(P(str(row["app_path"])).expanduser())
104
+ app_url.append(apps_safe_url.as_posix() if type(apps_safe_url) is P else apps_safe_url)
105
+ res_df["app_url"] = app_url
106
+ res_df.to_csv(APP_SUMMARY_PATH.with_suffix(".csv").create(parents_only=True), index=False)
107
+ APP_SUMMARY_PATH.with_suffix(".md").write_text(res_df.to_markdown())
108
+ print(f"Safety Report:")
109
+ print(res_df)
110
+
111
+
112
+ def upload(path: P):
113
+ set_time_out = install_n_import("call_function_with_timeout").SetTimeout
114
+ func_with_timeout = set_time_out(lambda: path.to_cloud(CLOUD, rel2home=True, share=True, os_specific=True), timeout=180)
115
+ is_done, _is_timeout, _erro_message, results = func_with_timeout()
116
+ if is_done: return results
117
+ else: return None
118
+
119
+
120
+ class PrecheckedCloudInstaller:
121
+ def __init__(self):
122
+ install_n_import("gdown")
123
+ self.df = pd.read_csv(APP_SUMMARY_PATH)
124
+
125
+ @staticmethod
126
+ def download_google_links(url: str):
127
+ # if "drive.google.com" in str(url): url = str(url).replace("open?", "uc?")
128
+ # else: raise NotImplementedError("Only google drive is supported for now.")
129
+ # return P(url).download(name=name)
130
+ gdrive_id = P(url).parts[-1].split("id=")[1]
131
+ gdown = install_n_import("gdown")
132
+ result = P(gdown.download(id=gdrive_id)).absolute()
133
+ return result
134
+
135
+ @staticmethod
136
+ def install_cli_apps(app_url: str):
137
+ try:
138
+ exe = PrecheckedCloudInstaller.download_google_links(app_url)
139
+ except Exception as ex: # type: ignore
140
+ print(f"Error in downloading {app_url} {ex}")
141
+ return None
142
+ if platform.system().lower() == "linux":
143
+ Terminal().run(f"chmod +x {exe}")
144
+ Terminal().run(f"mv {exe} /usr/local/bin/")
145
+ elif platform.system().lower() == "windows":
146
+ exe.move(folder=P.home().joinpath("AppData/Local/Microsoft/WindowsApps"), overwrite=True)
147
+ return True
148
+
149
+ def download_safe_apps(self, name: str = "AllEssentials"):
150
+ # if platform.system().lower() == "windows":
151
+ # from machineconfig.jobs.python.python_windows_installers_all import get_cli_py_installers
152
+ # cli_installers = get_cli_py_installers()
153
+ # elif platform.system().lower() == "linux":
154
+ # from machineconfig.jobs.python.python_linux_installers_all import get_cli_py_installers
155
+ # cli_installers = get_cli_py_installers()
156
+ # else: raise NotImplementedError(f"Platform {platform.system().lower()} is not supported yet.")
157
+
158
+ if name == "AllEssentials":
159
+ print(f"Downloading {self.df.shape[0]} apps ...")
160
+ print(self.df)
161
+ _res = L(self.df.app_url).apply(PrecheckedCloudInstaller.install_cli_apps, jobs=20)
162
+ else:
163
+ app_url = self.df[self.df.app_name == name].iloc[0].app_url
164
+ _res = PrecheckedCloudInstaller.install_cli_apps(app_url=app_url)
165
+
166
+ # print("\n" * 3)
167
+ # for item_flag, item_name in zip(res, self.df["app_name"]):
168
+ # if item_flag: print(f"✅ {item_name} is installed. 😁")
169
+ # else: print(f"❌ {item_name} failed to install for reasons explained in the log above, try manually.")
170
+
171
+
172
+ if __name__ == '__main__':
173
+ pass
@@ -0,0 +1,117 @@
1
+
2
+ """checkout_version.py
3
+ """
4
+
5
+ from crocodile.file_management import P, Save, randstr
6
+ from crocodile.meta import Terminal
7
+ from machineconfig.utils.ve import get_ve_profile, get_ve_specs, get_ve_install_script
8
+ from machineconfig.scripts.python.repos import record_a_repo, install_repos
9
+ import platform
10
+
11
+
12
+ # TODO: add data requirements for added isolation of file system.
13
+
14
+
15
+ def checkout_version(version: str, repo_root: P, exclude_editable: bool = False):
16
+ """Checkout a version of the repo and install its requirements."""
17
+ ve_name = get_ve_profile(init_path=repo_root)
18
+ ve_path = P.home().joinpath("venvs", ve_name)
19
+ ve_specs = get_ve_specs(ve_path)
20
+ py_version = ve_specs['version_major_minor']
21
+ sys = platform.system().lower()
22
+
23
+ target_dir = repo_root.expanduser().absolute().joinpath(f"versions/{version}").as_posix()
24
+ if exclude_editable:
25
+ editable_json = get_editable_packages(ve_name=ve_name)
26
+ specs_path = P(target_dir).expanduser().joinpath("editable_packages.json")
27
+ Save.json(obj=editable_json, path=specs_path, indent=4)
28
+ install_editable_packages = install_repos(specs_path=str(specs_path), editable_install=True)
29
+ else: install_editable_packages = ""
30
+
31
+ version_root = repo_root.collapseuser().joinpath(f"versions/{version}").as_posix()
32
+ version_root_obj = P(version_root).expanduser().create()
33
+ checkout_ve = f"{repo_root.name}-{version}-prod" if not exclude_editable else ve_name
34
+ checkout_ve = input(f"Name of the ve to create (default: {checkout_ve}): ") or checkout_ve
35
+
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)
40
+
41
+ install_requirements = f"""
42
+ . $HOME/scripts/activate_ve {ve_name}
43
+ cd {version_root}
44
+ pip install -r requirements_{sys}.txt
45
+ {install_editable_packages}
46
+ """
47
+ 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)
50
+ 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.")
54
+
55
+ pip_freeze_script = f"""
56
+ cd '{target_dir}'
57
+ . "$HOME/scripts/activate_ve" {ve_name}
58
+ python -m pip freeze {'--exclude-editable' if exclude_editable else ''} > requirements_{sys}.txt
59
+ """
60
+ 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
+ print(f"✅ Installed requirements for version {version}.")
79
+
80
+
81
+ def main():
82
+ from git.repo import Repo
83
+ from git.exc import InvalidGitRepositoryError
84
+ try:
85
+ repo = Repo(P.cwd(), search_parent_directories=True)
86
+ print(f"✅ Found repo at {repo.working_dir}")
87
+ except InvalidGitRepositoryError as err:
88
+ print(f"❌ No repo found at {P.cwd()} or its parents.")
89
+ raise err
90
+ version = input("Enter version name: ")
91
+ from rich.prompt import Confirm
92
+ exclude_editable = Confirm.ask("Exclude editable packages?", default=False)
93
+
94
+ repo_root = P(repo.working_dir)
95
+ checkout_version(version, repo_root, exclude_editable=exclude_editable)
96
+
97
+
98
+ def get_editable_packages(ve_name: str):
99
+ file = P.tmp().joinpath(f"tmp_files/editable_requirements_{randstr()}.txt")
100
+ editable_packages_script = f"""
101
+ . $HOME/scripts/activate_ve {ve_name}
102
+ pip list --editable > {file}
103
+ """
104
+ Terminal().run_script(editable_packages_script, verbose=True, shell="default").print()
105
+ try: tmp3 = file.read_text(encoding='utf-16').splitlines()[2:]
106
+ except UnicodeError: tmp3 = file.read_text().splitlines()[2:]
107
+
108
+ res = []
109
+ for a_pkg in tmp3:
110
+ tmp = P(a_pkg.split(" ")[-1].rstrip())
111
+ tmp1 = record_a_repo(tmp, search_parent_directories=True) # pip list --editable returns path to package or repo in a way not yet understood.
112
+ res.append(tmp1)
113
+ return res
114
+
115
+
116
+ if __name__ == "__main__":
117
+ pass
@@ -1,14 +1,14 @@
1
-
2
-
3
- import crocodile.toolbox as tb
4
-
5
- # one can either install rufus: https://rufus.ie/en/
6
- # however, to create bootable media with multiple OSs to choose from:
7
-
8
- tb.P(r'https://github.com/ventoy/Ventoy/archive/refs/tags/v1.0.78.zip').download().unzip().find()()
9
- tb.P(r'https://mirrors.layeronline.com/linuxmint/stable/21/linuxmint-21-cinnamon-64bit.iso').download(folder=tb.P.home().joinpath("Downloads/os").create())
10
- tb.P(r'https://download.manjaro.org/kde/21.3.7/manjaro-kde-21.3.7-minimal-220816-linux515.iso').download(folder=tb.P.home().joinpath("Downloads/os").create())
11
-
12
-
13
- if __name__ == '__main__':
14
- pass
1
+
2
+
3
+ #
4
+
5
+ # # one can either install rufus: https://rufus.ie/en/
6
+ # # however, to create bootable media with multiple OSs to choose from:
7
+
8
+ # P(r'https://github.com/ventoy/Ventoy/archive/refs/tags/v1.0.78.zip').download().unzip().search[0]()
9
+ # P(r'https://mirrors.layeronline.com/linuxmint/stable/21/linuxmint-21-cinnamon-64bit.iso').download(folder=P.home().joinpath("Downloads/os").create())
10
+ # P(r'https://download.manjaro.org/kde/21.3.7/manjaro-kde-21.3.7-minimal-220816-linux515.iso').download(folder=P.home().joinpath("Downloads/os").create())
11
+
12
+
13
+ # if __name__ == '__main__':
14
+ # pass
@@ -1,56 +1,59 @@
1
-
2
- import crocodile.toolbox as tb
3
- import socket
4
- from machineconfig.utils.utils import choose_ssh_host, write_shell_script
5
-
6
- prefix = """
7
-
8
- layout {
9
- default_tab_template {
10
- pane size=1 borderless=true {
11
- plugin location="zellij:compact-bar"
12
- }
13
- children
14
-
15
- }
16
-
17
- """
18
-
19
- suffix = """
20
-
21
- tab name="THISMACHINE" focus=true // the default_tab_template
22
- }
23
- """
24
-
25
- tab = """
26
-
27
- tab name="TABNAME" focus=false { // the default_tab_template with three vertical panes between the plugins
28
- pane name="fpane" {
29
- command "TABCOMMAND"
30
- args "TABARGS"
31
- }
32
- }
33
-
34
- """
35
-
36
-
37
- def build_template(tabs: list):
38
- res = prefix
39
- for t in tabs:
40
- res += tab.replace("TABNAME", t).replace("TABCOMMAND", f"ssh").replace("TABARGS", t)
41
- res += suffix.replace("THISMACHINE", socket.gethostname())
42
- file = tb.P.tmp().joinpath(f"tmp_files/templates/zellij_template.kdl").create(parents_only=True).write_text(res)
43
- res = f"zellij --layout {file}"
44
- return res
45
-
46
-
47
- def launch_from_ssh_config():
48
- hosts = choose_ssh_host()
49
- res = build_template(hosts)
50
- write_shell_script(res, execute=False, desc="zellij launch script")
51
- return None
52
-
53
-
54
-
55
- if __name__ == '__main__':
56
- launch_from_ssh_config()
1
+
2
+ """ZT
3
+ """
4
+
5
+ import socket
6
+ from machineconfig.utils.utils import choose_ssh_host, write_shell_script
7
+ from crocodile.file_management import P
8
+
9
+ prefix = """
10
+
11
+ layout {
12
+ default_tab_template {
13
+ pane size=1 borderless=true {
14
+ plugin location="zellij:compact-bar"
15
+ }
16
+ children
17
+
18
+ }
19
+
20
+ """
21
+
22
+ suffix = """
23
+
24
+ tab name="THISMACHINE" focus=true // the default_tab_template
25
+ }
26
+ """
27
+
28
+ tab = """
29
+
30
+ tab name="TABNAME" focus=false { // the default_tab_template with three vertical panes between the plugins
31
+ pane name="fpane" {
32
+ command "TABCOMMAND"
33
+ args "TABARGS"
34
+ }
35
+ }
36
+
37
+ """
38
+
39
+
40
+ def build_template(tabs: list[str]):
41
+ res = prefix
42
+ for t in tabs:
43
+ res += tab.replace("TABNAME", t).replace("TABCOMMAND", f"ssh").replace("TABARGS", t)
44
+ res += suffix.replace("THISMACHINE", socket.gethostname())
45
+ file = P.tmp().joinpath(f"tmp_files/templates/zellij_template.kdl").create(parents_only=True).write_text(res)
46
+ res = f"zellij --layout {file}"
47
+ return res
48
+
49
+
50
+ def launch_from_ssh_config():
51
+ hosts = choose_ssh_host(multi=True)
52
+ assert isinstance(hosts, list)
53
+ res = build_template(hosts)
54
+ write_shell_script(res, execute=False, desc="zellij launch script")
55
+ return None
56
+
57
+
58
+ if __name__ == '__main__':
59
+ launch_from_ssh_config()