machineconfig 1.92__py3-none-any.whl → 1.94__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 (694) hide show
  1. machineconfig/__init__.py +0 -8
  2. machineconfig/cluster/__init__.py +0 -0
  3. machineconfig/cluster/cloud_manager.py +359 -0
  4. machineconfig/cluster/data_transfer.py +56 -0
  5. machineconfig/cluster/distribute.py +280 -0
  6. machineconfig/cluster/file_manager.py +238 -0
  7. machineconfig/cluster/job_params.py +148 -0
  8. machineconfig/cluster/loader_runner.py +150 -0
  9. machineconfig/cluster/remote_machine.py +281 -0
  10. machineconfig/cluster/script_execution.py +209 -0
  11. machineconfig/cluster/script_notify_upon_completion.py +63 -0
  12. machineconfig/cluster/self_ssh.py +59 -0
  13. machineconfig/cluster/session_managers.py +183 -0
  14. machineconfig/cluster/templates/__init__.py +0 -0
  15. machineconfig/cluster/templates/cli_click.py +104 -0
  16. machineconfig/cluster/templates/cli_gooey.py +119 -0
  17. machineconfig/cluster/templates/cli_trogon.py +21 -0
  18. machineconfig/cluster/templates/f.py +4 -0
  19. machineconfig/cluster/templates/run_cloud.py +52 -0
  20. machineconfig/cluster/templates/run_cluster.py +69 -0
  21. machineconfig/cluster/templates/run_remote.py +67 -0
  22. machineconfig/cluster/templates/utils.py +37 -0
  23. machineconfig/jobs/__pycache__/__init__.cpython-311.pyc +0 -0
  24. machineconfig/jobs/linux/msc/lid.sh +26 -0
  25. machineconfig/jobs/linux/msc/network.sh +39 -0
  26. machineconfig/jobs/python/__pycache__/__init__.cpython-311.pyc +0 -0
  27. machineconfig/jobs/python/__pycache__/check_installations.cpython-311.pyc +0 -0
  28. machineconfig/jobs/python/__pycache__/checkout_version.cpython-311.pyc +0 -0
  29. machineconfig/jobs/python/__pycache__/python_ve_symlink.cpython-311.pyc +0 -0
  30. machineconfig/jobs/python/archive/python_tools.txt +12 -0
  31. machineconfig/jobs/python/check_installations.py +26 -11
  32. machineconfig/jobs/python/checkout_version.py +24 -13
  33. machineconfig/jobs/python/create_zellij_template.py +4 -4
  34. machineconfig/jobs/python/python_cargo_build_share.py +13 -4
  35. machineconfig/jobs/python/python_ve_symlink.py +15 -4
  36. machineconfig/jobs/python/vscode/__pycache__/api.cpython-311.pyc +0 -0
  37. machineconfig/jobs/python/vscode/__pycache__/link_ve.cpython-311.pyc +0 -0
  38. machineconfig/jobs/python/vscode/api.py +48 -0
  39. machineconfig/jobs/python/vscode/link_ve.py +64 -0
  40. machineconfig/jobs/python/vscode/select_interpreter.py +84 -0
  41. machineconfig/jobs/python/vscode/sync_code.py +60 -0
  42. machineconfig/jobs/python_custom_installers/__pycache__/__init__.cpython-311.pyc +0 -0
  43. machineconfig/jobs/python_custom_installers/__pycache__/hx.cpython-311.pyc +0 -0
  44. machineconfig/jobs/python_custom_installers/archive/ngrok.py +62 -0
  45. machineconfig/jobs/python_custom_installers/dev/aider.py +37 -0
  46. machineconfig/jobs/python_custom_installers/dev/alacritty.py +72 -0
  47. machineconfig/jobs/python_custom_installers/dev/brave.py +67 -0
  48. machineconfig/jobs/python_custom_installers/dev/bypass_paywall.py +50 -0
  49. machineconfig/jobs/python_custom_installers/dev/code.py +62 -0
  50. machineconfig/jobs/python_custom_installers/dev/cursor.py +67 -0
  51. machineconfig/jobs/python_custom_installers/dev/docker.py +70 -0
  52. machineconfig/jobs/python_custom_installers/dev/docker_desktop.py +77 -0
  53. machineconfig/jobs/python_custom_installers/dev/espanso.py +82 -0
  54. machineconfig/jobs/python_custom_installers/dev/goes.py +59 -0
  55. machineconfig/jobs/python_custom_installers/dev/lvim.py +76 -0
  56. machineconfig/jobs/python_custom_installers/dev/nerdfont.py +67 -0
  57. machineconfig/jobs/python_custom_installers/dev/redis.py +69 -0
  58. machineconfig/jobs/python_custom_installers/dev/reverse_proxy.md +31 -0
  59. machineconfig/jobs/python_custom_installers/dev/warp-cli.py +71 -0
  60. machineconfig/jobs/python_custom_installers/dev/wezterm.py +71 -0
  61. machineconfig/jobs/python_custom_installers/gh.py +46 -4
  62. machineconfig/jobs/python_custom_installers/hx.py +103 -18
  63. machineconfig/jobs/python_custom_installers/scripts/linux/brave.sh +52 -0
  64. machineconfig/jobs/python_custom_installers/scripts/linux/docker.sh +140 -0
  65. machineconfig/jobs/python_custom_installers/scripts/linux/docker_start.sh +48 -0
  66. machineconfig/jobs/python_custom_installers/scripts/linux/edge.sh +47 -0
  67. machineconfig/jobs/python_custom_installers/scripts/linux/nerdfont.sh +64 -0
  68. machineconfig/jobs/python_custom_installers/scripts/linux/pgsql.sh +53 -0
  69. machineconfig/jobs/python_custom_installers/scripts/linux/redis.sh +76 -0
  70. machineconfig/jobs/python_custom_installers/scripts/linux/timescaledb.sh +91 -0
  71. machineconfig/jobs/python_custom_installers/scripts/linux/vscode.sh +66 -0
  72. machineconfig/jobs/python_custom_installers/scripts/linux/warp-cli.sh +77 -0
  73. machineconfig/jobs/python_custom_installers/scripts/linux/wezterm.sh +43 -0
  74. machineconfig/jobs/python_generic_installers/__pycache__/__init__.cpython-311.pyc +0 -0
  75. machineconfig/jobs/python_generic_installers/config.json +267 -0
  76. machineconfig/jobs/python_generic_installers/dev/config.archive.json +18 -0
  77. machineconfig/jobs/python_generic_installers/dev/config.json +394 -0
  78. machineconfig/jobs/python_linux_installers/__pycache__/__init__.cpython-311.pyc +0 -0
  79. machineconfig/jobs/python_linux_installers/archive/config.json +10 -0
  80. machineconfig/jobs/python_linux_installers/config.json +74 -0
  81. machineconfig/jobs/python_linux_installers/dev/config.json +138 -0
  82. machineconfig/jobs/python_windows_installers/__pycache__/__init__.cpython-311.pyc +0 -0
  83. machineconfig/jobs/python_windows_installers/archive/file.json +11 -0
  84. machineconfig/jobs/python_windows_installers/config.json +50 -0
  85. machineconfig/jobs/python_windows_installers/dev/config.json +3 -0
  86. machineconfig/jobs/windows/archive/archive_pygraphviz.ps1 +14 -0
  87. machineconfig/jobs/windows/archive/openssh-server_add_key.ps1 +7 -0
  88. machineconfig/jobs/windows/archive/openssh-server_copy-ssh-id.ps1 +14 -0
  89. machineconfig/jobs/windows/start_terminal.ps1 +6 -0
  90. machineconfig/jobs/windows/startup_file.cmd +2 -0
  91. machineconfig/profile/__pycache__/__init__.cpython-311.pyc +0 -0
  92. machineconfig/profile/__pycache__/create.cpython-311.pyc +0 -0
  93. machineconfig/profile/__pycache__/shell.cpython-311.pyc +0 -0
  94. machineconfig/profile/create.py +47 -13
  95. machineconfig/profile/create_hardlinks.py +42 -12
  96. machineconfig/profile/records/generic/shares.toml +5 -0
  97. machineconfig/profile/records/linux/apps_summary_report.csv +48 -0
  98. machineconfig/profile/records/linux/apps_summary_report.md +49 -0
  99. machineconfig/profile/records/windows/apps_summary_report.csv +1 -0
  100. machineconfig/profile/records/windows/apps_summary_report.md +2 -0
  101. machineconfig/profile/shell.py +62 -11
  102. machineconfig/scripts/__pycache__/__init__.cpython-311.pyc +0 -0
  103. machineconfig/scripts/cloud/init.sh +128 -0
  104. machineconfig/scripts/linux/activate_ve +87 -0
  105. machineconfig/scripts/linux/archive/tmate_conn +12 -0
  106. machineconfig/scripts/linux/archive/tmate_start +12 -0
  107. machineconfig/scripts/linux/archive/transfer_wsl_win +5 -0
  108. machineconfig/scripts/linux/checkout_versions +8 -0
  109. machineconfig/scripts/linux/choose_wezterm_theme +9 -0
  110. machineconfig/scripts/linux/cloud_copy +9 -0
  111. machineconfig/scripts/linux/cloud_manager +8 -0
  112. machineconfig/scripts/linux/cloud_mount +24 -0
  113. machineconfig/scripts/linux/cloud_repo_sync +22 -0
  114. machineconfig/scripts/linux/cloud_sync +24 -0
  115. machineconfig/scripts/linux/croshell +24 -0
  116. machineconfig/scripts/linux/devops +24 -0
  117. machineconfig/scripts/linux/fire +46 -0
  118. machineconfig/scripts/linux/ftpx +8 -0
  119. machineconfig/scripts/linux/fzf2g +21 -0
  120. machineconfig/scripts/linux/fzfag +17 -0
  121. machineconfig/scripts/linux/fzffg +25 -0
  122. machineconfig/scripts/linux/fzfg +23 -0
  123. machineconfig/scripts/linux/fzfrga +21 -0
  124. machineconfig/scripts/linux/gh_models +11 -0
  125. machineconfig/scripts/linux/kill_process +10 -0
  126. machineconfig/scripts/linux/mount_drive +128 -0
  127. machineconfig/scripts/linux/mount_nfs +62 -0
  128. machineconfig/scripts/linux/mount_nw_drive +72 -0
  129. machineconfig/scripts/linux/mount_smb +3 -0
  130. machineconfig/scripts/linux/programs +21 -0
  131. machineconfig/scripts/linux/repos +24 -0
  132. machineconfig/scripts/linux/scheduler +8 -0
  133. machineconfig/scripts/linux/share_cloud.sh +81 -0
  134. machineconfig/scripts/linux/share_nfs +49 -0
  135. machineconfig/scripts/linux/share_smb +1 -0
  136. machineconfig/scripts/linux/skrg +4 -0
  137. machineconfig/scripts/linux/start_docker +23 -0
  138. machineconfig/scripts/linux/start_slidev +23 -0
  139. machineconfig/scripts/linux/start_terminals +12 -0
  140. machineconfig/scripts/linux/switch_ip +20 -0
  141. machineconfig/scripts/linux/url2md +10 -0
  142. machineconfig/scripts/linux/z_ls +104 -0
  143. machineconfig/scripts/python/.mypy_cache/.gitignore +2 -0
  144. machineconfig/scripts/python/.mypy_cache/3.11/@plugins_snapshot.json +1 -0
  145. machineconfig/scripts/python/.mypy_cache/3.11/__future__.data.json +1 -0
  146. machineconfig/scripts/python/.mypy_cache/3.11/__future__.meta.json +1 -0
  147. machineconfig/scripts/python/.mypy_cache/3.11/_ast.data.json +1 -0
  148. machineconfig/scripts/python/.mypy_cache/3.11/_ast.meta.json +1 -0
  149. machineconfig/scripts/python/.mypy_cache/3.11/_bz2.data.json +1 -0
  150. machineconfig/scripts/python/.mypy_cache/3.11/_bz2.meta.json +1 -0
  151. machineconfig/scripts/python/.mypy_cache/3.11/_codecs.data.json +1 -0
  152. machineconfig/scripts/python/.mypy_cache/3.11/_codecs.meta.json +1 -0
  153. machineconfig/scripts/python/.mypy_cache/3.11/_collections_abc.data.json +1 -0
  154. machineconfig/scripts/python/.mypy_cache/3.11/_collections_abc.meta.json +1 -0
  155. machineconfig/scripts/python/.mypy_cache/3.11/_compression.data.json +1 -0
  156. machineconfig/scripts/python/.mypy_cache/3.11/_compression.meta.json +1 -0
  157. machineconfig/scripts/python/.mypy_cache/3.11/_decimal.data.json +1 -0
  158. machineconfig/scripts/python/.mypy_cache/3.11/_decimal.meta.json +1 -0
  159. machineconfig/scripts/python/.mypy_cache/3.11/_frozen_importlib.data.json +1 -0
  160. machineconfig/scripts/python/.mypy_cache/3.11/_frozen_importlib.meta.json +1 -0
  161. machineconfig/scripts/python/.mypy_cache/3.11/_frozen_importlib_external.data.json +1 -0
  162. machineconfig/scripts/python/.mypy_cache/3.11/_frozen_importlib_external.meta.json +1 -0
  163. machineconfig/scripts/python/.mypy_cache/3.11/_io.data.json +1 -0
  164. machineconfig/scripts/python/.mypy_cache/3.11/_io.meta.json +1 -0
  165. machineconfig/scripts/python/.mypy_cache/3.11/_locale.data.json +1 -0
  166. machineconfig/scripts/python/.mypy_cache/3.11/_locale.meta.json +1 -0
  167. machineconfig/scripts/python/.mypy_cache/3.11/_stat.data.json +1 -0
  168. machineconfig/scripts/python/.mypy_cache/3.11/_stat.meta.json +1 -0
  169. machineconfig/scripts/python/.mypy_cache/3.11/_struct.data.json +1 -0
  170. machineconfig/scripts/python/.mypy_cache/3.11/_struct.meta.json +1 -0
  171. machineconfig/scripts/python/.mypy_cache/3.11/_thread.data.json +1 -0
  172. machineconfig/scripts/python/.mypy_cache/3.11/_thread.meta.json +1 -0
  173. machineconfig/scripts/python/.mypy_cache/3.11/_typeshed/__init__.data.json +1 -0
  174. machineconfig/scripts/python/.mypy_cache/3.11/_typeshed/__init__.meta.json +1 -0
  175. machineconfig/scripts/python/.mypy_cache/3.11/_typeshed/importlib.data.json +1 -0
  176. machineconfig/scripts/python/.mypy_cache/3.11/_typeshed/importlib.meta.json +1 -0
  177. machineconfig/scripts/python/.mypy_cache/3.11/_warnings.data.json +1 -0
  178. machineconfig/scripts/python/.mypy_cache/3.11/_warnings.meta.json +1 -0
  179. machineconfig/scripts/python/.mypy_cache/3.11/_weakref.data.json +1 -0
  180. machineconfig/scripts/python/.mypy_cache/3.11/_weakref.meta.json +1 -0
  181. machineconfig/scripts/python/.mypy_cache/3.11/_weakrefset.data.json +1 -0
  182. machineconfig/scripts/python/.mypy_cache/3.11/_weakrefset.meta.json +1 -0
  183. machineconfig/scripts/python/.mypy_cache/3.11/abc.data.json +1 -0
  184. machineconfig/scripts/python/.mypy_cache/3.11/abc.meta.json +1 -0
  185. machineconfig/scripts/python/.mypy_cache/3.11/argparse.data.json +1 -0
  186. machineconfig/scripts/python/.mypy_cache/3.11/argparse.meta.json +1 -0
  187. machineconfig/scripts/python/.mypy_cache/3.11/ast.data.json +1 -0
  188. machineconfig/scripts/python/.mypy_cache/3.11/ast.meta.json +1 -0
  189. machineconfig/scripts/python/.mypy_cache/3.11/binascii.data.json +1 -0
  190. machineconfig/scripts/python/.mypy_cache/3.11/binascii.meta.json +1 -0
  191. machineconfig/scripts/python/.mypy_cache/3.11/builtins.data.json +1 -0
  192. machineconfig/scripts/python/.mypy_cache/3.11/builtins.meta.json +1 -0
  193. machineconfig/scripts/python/.mypy_cache/3.11/bz2.data.json +1 -0
  194. machineconfig/scripts/python/.mypy_cache/3.11/bz2.meta.json +1 -0
  195. machineconfig/scripts/python/.mypy_cache/3.11/calendar.data.json +1 -0
  196. machineconfig/scripts/python/.mypy_cache/3.11/calendar.meta.json +1 -0
  197. machineconfig/scripts/python/.mypy_cache/3.11/codecs.data.json +1 -0
  198. machineconfig/scripts/python/.mypy_cache/3.11/codecs.meta.json +1 -0
  199. machineconfig/scripts/python/.mypy_cache/3.11/collections/__init__.data.json +1 -0
  200. machineconfig/scripts/python/.mypy_cache/3.11/collections/__init__.meta.json +1 -0
  201. machineconfig/scripts/python/.mypy_cache/3.11/collections/abc.data.json +1 -0
  202. machineconfig/scripts/python/.mypy_cache/3.11/collections/abc.meta.json +1 -0
  203. machineconfig/scripts/python/.mypy_cache/3.11/configparser.data.json +1 -0
  204. machineconfig/scripts/python/.mypy_cache/3.11/configparser.meta.json +1 -0
  205. machineconfig/scripts/python/.mypy_cache/3.11/contextlib.data.json +1 -0
  206. machineconfig/scripts/python/.mypy_cache/3.11/contextlib.meta.json +1 -0
  207. machineconfig/scripts/python/.mypy_cache/3.11/dataclasses.data.json +1 -0
  208. machineconfig/scripts/python/.mypy_cache/3.11/dataclasses.meta.json +1 -0
  209. machineconfig/scripts/python/.mypy_cache/3.11/datetime.data.json +1 -0
  210. machineconfig/scripts/python/.mypy_cache/3.11/datetime.meta.json +1 -0
  211. machineconfig/scripts/python/.mypy_cache/3.11/decimal.data.json +1 -0
  212. machineconfig/scripts/python/.mypy_cache/3.11/decimal.meta.json +1 -0
  213. machineconfig/scripts/python/.mypy_cache/3.11/dis.data.json +1 -0
  214. machineconfig/scripts/python/.mypy_cache/3.11/dis.meta.json +1 -0
  215. machineconfig/scripts/python/.mypy_cache/3.11/email/__init__.data.json +1 -0
  216. machineconfig/scripts/python/.mypy_cache/3.11/email/__init__.meta.json +1 -0
  217. machineconfig/scripts/python/.mypy_cache/3.11/email/_policybase.data.json +1 -0
  218. machineconfig/scripts/python/.mypy_cache/3.11/email/_policybase.meta.json +1 -0
  219. machineconfig/scripts/python/.mypy_cache/3.11/email/charset.data.json +1 -0
  220. machineconfig/scripts/python/.mypy_cache/3.11/email/charset.meta.json +1 -0
  221. machineconfig/scripts/python/.mypy_cache/3.11/email/contentmanager.data.json +1 -0
  222. machineconfig/scripts/python/.mypy_cache/3.11/email/contentmanager.meta.json +1 -0
  223. machineconfig/scripts/python/.mypy_cache/3.11/email/errors.data.json +1 -0
  224. machineconfig/scripts/python/.mypy_cache/3.11/email/errors.meta.json +1 -0
  225. machineconfig/scripts/python/.mypy_cache/3.11/email/header.data.json +1 -0
  226. machineconfig/scripts/python/.mypy_cache/3.11/email/header.meta.json +1 -0
  227. machineconfig/scripts/python/.mypy_cache/3.11/email/message.data.json +1 -0
  228. machineconfig/scripts/python/.mypy_cache/3.11/email/message.meta.json +1 -0
  229. machineconfig/scripts/python/.mypy_cache/3.11/email/policy.data.json +1 -0
  230. machineconfig/scripts/python/.mypy_cache/3.11/email/policy.meta.json +1 -0
  231. machineconfig/scripts/python/.mypy_cache/3.11/enum.data.json +1 -0
  232. machineconfig/scripts/python/.mypy_cache/3.11/enum.meta.json +1 -0
  233. machineconfig/scripts/python/.mypy_cache/3.11/fnmatch.data.json +1 -0
  234. machineconfig/scripts/python/.mypy_cache/3.11/fnmatch.meta.json +1 -0
  235. machineconfig/scripts/python/.mypy_cache/3.11/functools.data.json +1 -0
  236. machineconfig/scripts/python/.mypy_cache/3.11/functools.meta.json +1 -0
  237. machineconfig/scripts/python/.mypy_cache/3.11/gc.data.json +1 -0
  238. machineconfig/scripts/python/.mypy_cache/3.11/gc.meta.json +1 -0
  239. machineconfig/scripts/python/.mypy_cache/3.11/genericpath.data.json +1 -0
  240. machineconfig/scripts/python/.mypy_cache/3.11/genericpath.meta.json +1 -0
  241. machineconfig/scripts/python/.mypy_cache/3.11/getpass.data.json +1 -0
  242. machineconfig/scripts/python/.mypy_cache/3.11/getpass.meta.json +1 -0
  243. machineconfig/scripts/python/.mypy_cache/3.11/git/__init__.data.json +1 -0
  244. machineconfig/scripts/python/.mypy_cache/3.11/git/__init__.meta.json +1 -0
  245. machineconfig/scripts/python/.mypy_cache/3.11/git/cmd.data.json +1 -0
  246. machineconfig/scripts/python/.mypy_cache/3.11/git/cmd.meta.json +1 -0
  247. machineconfig/scripts/python/.mypy_cache/3.11/git/compat.data.json +1 -0
  248. machineconfig/scripts/python/.mypy_cache/3.11/git/compat.meta.json +1 -0
  249. machineconfig/scripts/python/.mypy_cache/3.11/git/config.data.json +1 -0
  250. machineconfig/scripts/python/.mypy_cache/3.11/git/config.meta.json +1 -0
  251. machineconfig/scripts/python/.mypy_cache/3.11/git/db.data.json +1 -0
  252. machineconfig/scripts/python/.mypy_cache/3.11/git/db.meta.json +1 -0
  253. machineconfig/scripts/python/.mypy_cache/3.11/git/diff.data.json +1 -0
  254. machineconfig/scripts/python/.mypy_cache/3.11/git/diff.meta.json +1 -0
  255. machineconfig/scripts/python/.mypy_cache/3.11/git/exc.data.json +1 -0
  256. machineconfig/scripts/python/.mypy_cache/3.11/git/exc.meta.json +1 -0
  257. machineconfig/scripts/python/.mypy_cache/3.11/git/index/__init__.data.json +1 -0
  258. machineconfig/scripts/python/.mypy_cache/3.11/git/index/__init__.meta.json +1 -0
  259. machineconfig/scripts/python/.mypy_cache/3.11/git/index/base.data.json +1 -0
  260. machineconfig/scripts/python/.mypy_cache/3.11/git/index/base.meta.json +1 -0
  261. machineconfig/scripts/python/.mypy_cache/3.11/git/index/fun.data.json +1 -0
  262. machineconfig/scripts/python/.mypy_cache/3.11/git/index/fun.meta.json +1 -0
  263. machineconfig/scripts/python/.mypy_cache/3.11/git/index/typ.data.json +1 -0
  264. machineconfig/scripts/python/.mypy_cache/3.11/git/index/typ.meta.json +1 -0
  265. machineconfig/scripts/python/.mypy_cache/3.11/git/index/util.data.json +1 -0
  266. machineconfig/scripts/python/.mypy_cache/3.11/git/index/util.meta.json +1 -0
  267. machineconfig/scripts/python/.mypy_cache/3.11/git/objects/__init__.data.json +1 -0
  268. machineconfig/scripts/python/.mypy_cache/3.11/git/objects/__init__.meta.json +1 -0
  269. machineconfig/scripts/python/.mypy_cache/3.11/git/objects/base.data.json +1 -0
  270. machineconfig/scripts/python/.mypy_cache/3.11/git/objects/base.meta.json +1 -0
  271. machineconfig/scripts/python/.mypy_cache/3.11/git/objects/blob.data.json +1 -0
  272. machineconfig/scripts/python/.mypy_cache/3.11/git/objects/blob.meta.json +1 -0
  273. machineconfig/scripts/python/.mypy_cache/3.11/git/objects/commit.data.json +1 -0
  274. machineconfig/scripts/python/.mypy_cache/3.11/git/objects/commit.meta.json +1 -0
  275. machineconfig/scripts/python/.mypy_cache/3.11/git/objects/fun.data.json +1 -0
  276. machineconfig/scripts/python/.mypy_cache/3.11/git/objects/fun.meta.json +1 -0
  277. machineconfig/scripts/python/.mypy_cache/3.11/git/objects/submodule/__init__.data.json +1 -0
  278. machineconfig/scripts/python/.mypy_cache/3.11/git/objects/submodule/__init__.meta.json +1 -0
  279. machineconfig/scripts/python/.mypy_cache/3.11/git/objects/submodule/base.data.json +1 -0
  280. machineconfig/scripts/python/.mypy_cache/3.11/git/objects/submodule/base.meta.json +1 -0
  281. machineconfig/scripts/python/.mypy_cache/3.11/git/objects/submodule/root.data.json +1 -0
  282. machineconfig/scripts/python/.mypy_cache/3.11/git/objects/submodule/root.meta.json +1 -0
  283. machineconfig/scripts/python/.mypy_cache/3.11/git/objects/submodule/util.data.json +1 -0
  284. machineconfig/scripts/python/.mypy_cache/3.11/git/objects/submodule/util.meta.json +1 -0
  285. machineconfig/scripts/python/.mypy_cache/3.11/git/objects/tag.data.json +1 -0
  286. machineconfig/scripts/python/.mypy_cache/3.11/git/objects/tag.meta.json +1 -0
  287. machineconfig/scripts/python/.mypy_cache/3.11/git/objects/tree.data.json +1 -0
  288. machineconfig/scripts/python/.mypy_cache/3.11/git/objects/tree.meta.json +1 -0
  289. machineconfig/scripts/python/.mypy_cache/3.11/git/objects/util.data.json +1 -0
  290. machineconfig/scripts/python/.mypy_cache/3.11/git/objects/util.meta.json +1 -0
  291. machineconfig/scripts/python/.mypy_cache/3.11/git/refs/__init__.data.json +1 -0
  292. machineconfig/scripts/python/.mypy_cache/3.11/git/refs/__init__.meta.json +1 -0
  293. machineconfig/scripts/python/.mypy_cache/3.11/git/refs/head.data.json +1 -0
  294. machineconfig/scripts/python/.mypy_cache/3.11/git/refs/head.meta.json +1 -0
  295. machineconfig/scripts/python/.mypy_cache/3.11/git/refs/log.data.json +1 -0
  296. machineconfig/scripts/python/.mypy_cache/3.11/git/refs/log.meta.json +1 -0
  297. machineconfig/scripts/python/.mypy_cache/3.11/git/refs/reference.data.json +1 -0
  298. machineconfig/scripts/python/.mypy_cache/3.11/git/refs/reference.meta.json +1 -0
  299. machineconfig/scripts/python/.mypy_cache/3.11/git/refs/remote.data.json +1 -0
  300. machineconfig/scripts/python/.mypy_cache/3.11/git/refs/remote.meta.json +1 -0
  301. machineconfig/scripts/python/.mypy_cache/3.11/git/refs/symbolic.data.json +1 -0
  302. machineconfig/scripts/python/.mypy_cache/3.11/git/refs/symbolic.meta.json +1 -0
  303. machineconfig/scripts/python/.mypy_cache/3.11/git/refs/tag.data.json +1 -0
  304. machineconfig/scripts/python/.mypy_cache/3.11/git/refs/tag.meta.json +1 -0
  305. machineconfig/scripts/python/.mypy_cache/3.11/git/remote.data.json +1 -0
  306. machineconfig/scripts/python/.mypy_cache/3.11/git/remote.meta.json +1 -0
  307. machineconfig/scripts/python/.mypy_cache/3.11/git/repo/__init__.data.json +1 -0
  308. machineconfig/scripts/python/.mypy_cache/3.11/git/repo/__init__.meta.json +1 -0
  309. machineconfig/scripts/python/.mypy_cache/3.11/git/repo/base.data.json +1 -0
  310. machineconfig/scripts/python/.mypy_cache/3.11/git/repo/base.meta.json +1 -0
  311. machineconfig/scripts/python/.mypy_cache/3.11/git/repo/fun.data.json +1 -0
  312. machineconfig/scripts/python/.mypy_cache/3.11/git/repo/fun.meta.json +1 -0
  313. machineconfig/scripts/python/.mypy_cache/3.11/git/types.data.json +1 -0
  314. machineconfig/scripts/python/.mypy_cache/3.11/git/types.meta.json +1 -0
  315. machineconfig/scripts/python/.mypy_cache/3.11/git/util.data.json +1 -0
  316. machineconfig/scripts/python/.mypy_cache/3.11/git/util.meta.json +1 -0
  317. machineconfig/scripts/python/.mypy_cache/3.11/glob.data.json +1 -0
  318. machineconfig/scripts/python/.mypy_cache/3.11/glob.meta.json +1 -0
  319. machineconfig/scripts/python/.mypy_cache/3.11/gzip.data.json +1 -0
  320. machineconfig/scripts/python/.mypy_cache/3.11/gzip.meta.json +1 -0
  321. machineconfig/scripts/python/.mypy_cache/3.11/importlib/__init__.data.json +1 -0
  322. machineconfig/scripts/python/.mypy_cache/3.11/importlib/__init__.meta.json +1 -0
  323. machineconfig/scripts/python/.mypy_cache/3.11/importlib/_abc.data.json +1 -0
  324. machineconfig/scripts/python/.mypy_cache/3.11/importlib/_abc.meta.json +1 -0
  325. machineconfig/scripts/python/.mypy_cache/3.11/importlib/_bootstrap.data.json +1 -0
  326. machineconfig/scripts/python/.mypy_cache/3.11/importlib/_bootstrap.meta.json +1 -0
  327. machineconfig/scripts/python/.mypy_cache/3.11/importlib/_bootstrap_external.data.json +1 -0
  328. machineconfig/scripts/python/.mypy_cache/3.11/importlib/_bootstrap_external.meta.json +1 -0
  329. machineconfig/scripts/python/.mypy_cache/3.11/importlib/abc.data.json +1 -0
  330. machineconfig/scripts/python/.mypy_cache/3.11/importlib/abc.meta.json +1 -0
  331. machineconfig/scripts/python/.mypy_cache/3.11/importlib/machinery.data.json +1 -0
  332. machineconfig/scripts/python/.mypy_cache/3.11/importlib/machinery.meta.json +1 -0
  333. machineconfig/scripts/python/.mypy_cache/3.11/importlib/metadata/__init__.data.json +1 -0
  334. machineconfig/scripts/python/.mypy_cache/3.11/importlib/metadata/__init__.meta.json +1 -0
  335. machineconfig/scripts/python/.mypy_cache/3.11/importlib/metadata/_meta.data.json +1 -0
  336. machineconfig/scripts/python/.mypy_cache/3.11/importlib/metadata/_meta.meta.json +1 -0
  337. machineconfig/scripts/python/.mypy_cache/3.11/importlib/readers.data.json +1 -0
  338. machineconfig/scripts/python/.mypy_cache/3.11/importlib/readers.meta.json +1 -0
  339. machineconfig/scripts/python/.mypy_cache/3.11/importlib/resources/__init__.data.json +1 -0
  340. machineconfig/scripts/python/.mypy_cache/3.11/importlib/resources/__init__.meta.json +1 -0
  341. machineconfig/scripts/python/.mypy_cache/3.11/importlib/resources/_common.data.json +1 -0
  342. machineconfig/scripts/python/.mypy_cache/3.11/importlib/resources/_common.meta.json +1 -0
  343. machineconfig/scripts/python/.mypy_cache/3.11/importlib/resources/abc.data.json +1 -0
  344. machineconfig/scripts/python/.mypy_cache/3.11/importlib/resources/abc.meta.json +1 -0
  345. machineconfig/scripts/python/.mypy_cache/3.11/inspect.data.json +1 -0
  346. machineconfig/scripts/python/.mypy_cache/3.11/inspect.meta.json +1 -0
  347. machineconfig/scripts/python/.mypy_cache/3.11/io.data.json +1 -0
  348. machineconfig/scripts/python/.mypy_cache/3.11/io.meta.json +1 -0
  349. machineconfig/scripts/python/.mypy_cache/3.11/itertools.data.json +1 -0
  350. machineconfig/scripts/python/.mypy_cache/3.11/itertools.meta.json +1 -0
  351. machineconfig/scripts/python/.mypy_cache/3.11/locale.data.json +1 -0
  352. machineconfig/scripts/python/.mypy_cache/3.11/locale.meta.json +1 -0
  353. machineconfig/scripts/python/.mypy_cache/3.11/logging/__init__.data.json +1 -0
  354. machineconfig/scripts/python/.mypy_cache/3.11/logging/__init__.meta.json +1 -0
  355. machineconfig/scripts/python/.mypy_cache/3.11/mimetypes.data.json +1 -0
  356. machineconfig/scripts/python/.mypy_cache/3.11/mimetypes.meta.json +1 -0
  357. machineconfig/scripts/python/.mypy_cache/3.11/mmap.data.json +1 -0
  358. machineconfig/scripts/python/.mypy_cache/3.11/mmap.meta.json +1 -0
  359. machineconfig/scripts/python/.mypy_cache/3.11/numbers.data.json +1 -0
  360. machineconfig/scripts/python/.mypy_cache/3.11/numbers.meta.json +1 -0
  361. machineconfig/scripts/python/.mypy_cache/3.11/opcode.data.json +1 -0
  362. machineconfig/scripts/python/.mypy_cache/3.11/opcode.meta.json +1 -0
  363. machineconfig/scripts/python/.mypy_cache/3.11/os/__init__.data.json +1 -0
  364. machineconfig/scripts/python/.mypy_cache/3.11/os/__init__.meta.json +1 -0
  365. machineconfig/scripts/python/.mypy_cache/3.11/os/path.data.json +1 -0
  366. machineconfig/scripts/python/.mypy_cache/3.11/os/path.meta.json +1 -0
  367. machineconfig/scripts/python/.mypy_cache/3.11/pathlib.data.json +1 -0
  368. machineconfig/scripts/python/.mypy_cache/3.11/pathlib.meta.json +1 -0
  369. machineconfig/scripts/python/.mypy_cache/3.11/platform.data.json +1 -0
  370. machineconfig/scripts/python/.mypy_cache/3.11/platform.meta.json +1 -0
  371. machineconfig/scripts/python/.mypy_cache/3.11/posixpath.data.json +1 -0
  372. machineconfig/scripts/python/.mypy_cache/3.11/posixpath.meta.json +1 -0
  373. machineconfig/scripts/python/.mypy_cache/3.11/re.data.json +1 -0
  374. machineconfig/scripts/python/.mypy_cache/3.11/re.meta.json +1 -0
  375. machineconfig/scripts/python/.mypy_cache/3.11/resource.data.json +1 -0
  376. machineconfig/scripts/python/.mypy_cache/3.11/resource.meta.json +1 -0
  377. machineconfig/scripts/python/.mypy_cache/3.11/shlex.data.json +1 -0
  378. machineconfig/scripts/python/.mypy_cache/3.11/shlex.meta.json +1 -0
  379. machineconfig/scripts/python/.mypy_cache/3.11/shutil.data.json +1 -0
  380. machineconfig/scripts/python/.mypy_cache/3.11/shutil.meta.json +1 -0
  381. machineconfig/scripts/python/.mypy_cache/3.11/signal.data.json +1 -0
  382. machineconfig/scripts/python/.mypy_cache/3.11/signal.meta.json +1 -0
  383. machineconfig/scripts/python/.mypy_cache/3.11/src/__init__.data.json +1 -0
  384. machineconfig/scripts/python/.mypy_cache/3.11/src/__init__.meta.json +1 -0
  385. machineconfig/scripts/python/.mypy_cache/3.11/src/machineconfig/__init__.data.json +1 -0
  386. machineconfig/scripts/python/.mypy_cache/3.11/src/machineconfig/__init__.meta.json +1 -0
  387. machineconfig/scripts/python/.mypy_cache/3.11/src/machineconfig/scripts/__init__.data.json +1 -0
  388. machineconfig/scripts/python/.mypy_cache/3.11/src/machineconfig/scripts/__init__.meta.json +1 -0
  389. machineconfig/scripts/python/.mypy_cache/3.11/src/machineconfig/scripts/python/__init__.data.json +1 -0
  390. machineconfig/scripts/python/.mypy_cache/3.11/src/machineconfig/scripts/python/__init__.meta.json +1 -0
  391. machineconfig/scripts/python/.mypy_cache/3.11/sre_compile.data.json +1 -0
  392. machineconfig/scripts/python/.mypy_cache/3.11/sre_compile.meta.json +1 -0
  393. machineconfig/scripts/python/.mypy_cache/3.11/sre_constants.data.json +1 -0
  394. machineconfig/scripts/python/.mypy_cache/3.11/sre_constants.meta.json +1 -0
  395. machineconfig/scripts/python/.mypy_cache/3.11/sre_parse.data.json +1 -0
  396. machineconfig/scripts/python/.mypy_cache/3.11/sre_parse.meta.json +1 -0
  397. machineconfig/scripts/python/.mypy_cache/3.11/stat.data.json +1 -0
  398. machineconfig/scripts/python/.mypy_cache/3.11/stat.meta.json +1 -0
  399. machineconfig/scripts/python/.mypy_cache/3.11/string.data.json +1 -0
  400. machineconfig/scripts/python/.mypy_cache/3.11/string.meta.json +1 -0
  401. machineconfig/scripts/python/.mypy_cache/3.11/struct.data.json +1 -0
  402. machineconfig/scripts/python/.mypy_cache/3.11/struct.meta.json +1 -0
  403. machineconfig/scripts/python/.mypy_cache/3.11/subprocess.data.json +1 -0
  404. machineconfig/scripts/python/.mypy_cache/3.11/subprocess.meta.json +1 -0
  405. machineconfig/scripts/python/.mypy_cache/3.11/sys/__init__.data.json +1 -0
  406. machineconfig/scripts/python/.mypy_cache/3.11/sys/__init__.meta.json +1 -0
  407. machineconfig/scripts/python/.mypy_cache/3.11/tarfile.data.json +1 -0
  408. machineconfig/scripts/python/.mypy_cache/3.11/tarfile.meta.json +1 -0
  409. machineconfig/scripts/python/.mypy_cache/3.11/tempfile.data.json +1 -0
  410. machineconfig/scripts/python/.mypy_cache/3.11/tempfile.meta.json +1 -0
  411. machineconfig/scripts/python/.mypy_cache/3.11/textwrap.data.json +1 -0
  412. machineconfig/scripts/python/.mypy_cache/3.11/textwrap.meta.json +1 -0
  413. machineconfig/scripts/python/.mypy_cache/3.11/threading.data.json +1 -0
  414. machineconfig/scripts/python/.mypy_cache/3.11/threading.meta.json +1 -0
  415. machineconfig/scripts/python/.mypy_cache/3.11/time.data.json +1 -0
  416. machineconfig/scripts/python/.mypy_cache/3.11/time.meta.json +1 -0
  417. machineconfig/scripts/python/.mypy_cache/3.11/types.data.json +1 -0
  418. machineconfig/scripts/python/.mypy_cache/3.11/types.meta.json +1 -0
  419. machineconfig/scripts/python/.mypy_cache/3.11/typing.data.json +1 -0
  420. machineconfig/scripts/python/.mypy_cache/3.11/typing.meta.json +1 -0
  421. machineconfig/scripts/python/.mypy_cache/3.11/typing_extensions.data.json +1 -0
  422. machineconfig/scripts/python/.mypy_cache/3.11/typing_extensions.meta.json +1 -0
  423. machineconfig/scripts/python/.mypy_cache/3.11/urllib/__init__.data.json +1 -0
  424. machineconfig/scripts/python/.mypy_cache/3.11/urllib/__init__.meta.json +1 -0
  425. machineconfig/scripts/python/.mypy_cache/3.11/urllib/parse.data.json +1 -0
  426. machineconfig/scripts/python/.mypy_cache/3.11/urllib/parse.meta.json +1 -0
  427. machineconfig/scripts/python/.mypy_cache/3.11/uuid.data.json +1 -0
  428. machineconfig/scripts/python/.mypy_cache/3.11/uuid.meta.json +1 -0
  429. machineconfig/scripts/python/.mypy_cache/3.11/warnings.data.json +1 -0
  430. machineconfig/scripts/python/.mypy_cache/3.11/warnings.meta.json +1 -0
  431. machineconfig/scripts/python/.mypy_cache/3.11/weakref.data.json +1 -0
  432. machineconfig/scripts/python/.mypy_cache/3.11/weakref.meta.json +1 -0
  433. machineconfig/scripts/python/.mypy_cache/3.11/zipfile/__init__.data.json +1 -0
  434. machineconfig/scripts/python/.mypy_cache/3.11/zipfile/__init__.meta.json +1 -0
  435. machineconfig/scripts/python/.mypy_cache/3.11/zlib.data.json +1 -0
  436. machineconfig/scripts/python/.mypy_cache/3.11/zlib.meta.json +1 -0
  437. machineconfig/scripts/python/.mypy_cache/CACHEDIR.TAG +3 -0
  438. machineconfig/scripts/python/__pycache__/__init__.cpython-311.pyc +0 -0
  439. machineconfig/scripts/python/__pycache__/cloud_copy.cpython-311.pyc +0 -0
  440. machineconfig/scripts/python/__pycache__/cloud_mount.cpython-311.pyc +0 -0
  441. machineconfig/scripts/python/__pycache__/cloud_repo_sync.cpython-311.pyc +0 -0
  442. machineconfig/scripts/python/__pycache__/cloud_sync.cpython-311.pyc +0 -0
  443. machineconfig/scripts/python/__pycache__/croshell.cpython-311.pyc +0 -0
  444. machineconfig/scripts/python/__pycache__/devops.cpython-311.pyc +0 -0
  445. machineconfig/scripts/python/__pycache__/devops_backup_retrieve.cpython-311.pyc +0 -0
  446. machineconfig/scripts/python/__pycache__/devops_devapps_install.cpython-311.pyc +0 -0
  447. machineconfig/scripts/python/__pycache__/devops_update_repos.cpython-311.pyc +0 -0
  448. machineconfig/scripts/python/__pycache__/fire_jobs.cpython-311.pyc +0 -0
  449. machineconfig/scripts/python/__pycache__/gh_models.cpython-311.pyc +0 -0
  450. machineconfig/scripts/python/__pycache__/repos.cpython-311.pyc +0 -0
  451. machineconfig/scripts/python/__pycache__/url2md.cpython-311.pyc +0 -0
  452. machineconfig/scripts/python/__pycache__/viewer.cpython-311.pyc +0 -0
  453. machineconfig/scripts/python/__pycache__/vscode_api.cpython-311.pyc +0 -0
  454. machineconfig/scripts/python/archive/im2text.py +36 -0
  455. machineconfig/scripts/python/archive/tmate_conn.py +44 -0
  456. machineconfig/scripts/python/archive/tmate_start.py +48 -0
  457. machineconfig/scripts/python/choose_wezterm_theme.py +23 -4
  458. machineconfig/scripts/python/cloud_copy.py +131 -29
  459. machineconfig/scripts/python/cloud_manager.py +55 -2
  460. machineconfig/scripts/python/cloud_mount.py +43 -4
  461. machineconfig/scripts/python/cloud_repo_sync.py +114 -103
  462. machineconfig/scripts/python/cloud_sync.py +36 -220
  463. machineconfig/scripts/python/croshell.py +102 -32
  464. machineconfig/scripts/python/devops.py +143 -42
  465. machineconfig/scripts/python/devops_add_identity.py +112 -9
  466. machineconfig/scripts/python/devops_add_ssh_key.py +170 -15
  467. machineconfig/scripts/python/devops_backup_retrieve.py +132 -14
  468. machineconfig/scripts/python/devops_devapps_install.py +33 -11
  469. machineconfig/scripts/python/devops_update_repos.py +36 -29
  470. machineconfig/scripts/python/dotfile.py +8 -3
  471. machineconfig/scripts/python/fire_jobs.py +145 -289
  472. machineconfig/scripts/python/ftpx.py +76 -18
  473. machineconfig/scripts/python/get_zellij_cmd.py +14 -0
  474. machineconfig/scripts/python/gh_models.py +72 -25
  475. machineconfig/scripts/python/helpers/__init__.py +0 -0
  476. machineconfig/scripts/python/helpers/__pycache__/__init__.cpython-311.pyc +0 -0
  477. machineconfig/scripts/python/helpers/__pycache__/cloud_helpers.cpython-311.pyc +0 -0
  478. machineconfig/scripts/python/helpers/__pycache__/helpers2.cpython-311.pyc +0 -0
  479. machineconfig/scripts/python/helpers/__pycache__/helpers4.cpython-311.pyc +0 -0
  480. machineconfig/scripts/python/helpers/cloud_helpers.py +134 -0
  481. machineconfig/scripts/python/helpers/helpers2.py +149 -0
  482. machineconfig/scripts/python/helpers/helpers4.py +178 -0
  483. machineconfig/scripts/python/helpers/helpers5.py +50 -0
  484. machineconfig/scripts/python/helpers/repo_sync_helpers.py +126 -0
  485. machineconfig/scripts/python/mount_nfs.py +46 -15
  486. machineconfig/scripts/python/mount_nw_drive.py +22 -10
  487. machineconfig/scripts/python/mount_ssh.py +28 -12
  488. machineconfig/scripts/python/onetimeshare.py +23 -15
  489. machineconfig/scripts/python/pomodoro.py +38 -24
  490. machineconfig/scripts/python/repos.py +29 -32
  491. machineconfig/scripts/python/scheduler.py +19 -18
  492. machineconfig/scripts/python/snapshot.py +14 -6
  493. machineconfig/scripts/python/start_slidev.py +24 -32
  494. machineconfig/scripts/python/start_terminals.py +23 -10
  495. machineconfig/scripts/python/viewer.py +53 -0
  496. machineconfig/scripts/python/viewer_template.py +140 -0
  497. machineconfig/scripts/python/wifi_conn.py +20 -12
  498. machineconfig/scripts/python/wsl_windows_transfer.py +18 -10
  499. machineconfig/scripts/windows/activate_ve.ps1 +54 -0
  500. machineconfig/scripts/windows/archive/gource2vid.ps1 +14 -0
  501. machineconfig/scripts/windows/archive/im2text.ps1 +27 -0
  502. machineconfig/scripts/windows/archive/secure_pull.ps1 +46 -0
  503. machineconfig/scripts/windows/archive/secure_push.ps1 +85 -0
  504. machineconfig/scripts/windows/archive/tmate_conn.ps1 +7 -0
  505. machineconfig/scripts/windows/checkout_version.ps1 +6 -0
  506. machineconfig/scripts/windows/choose_wezterm_theme.ps1 +20 -0
  507. machineconfig/scripts/windows/cloud_copy.ps1 +17 -0
  508. machineconfig/scripts/windows/cloud_manager.ps1 +8 -0
  509. machineconfig/scripts/windows/cloud_mount.ps1 +25 -0
  510. machineconfig/scripts/windows/cloud_repo_sync.ps1 +8 -0
  511. machineconfig/scripts/windows/cloud_sync.ps1 +21 -0
  512. machineconfig/scripts/windows/croshell.ps1 +40 -0
  513. machineconfig/scripts/windows/devops.ps1 +32 -0
  514. machineconfig/scripts/windows/dotfile.ps1 +9 -0
  515. machineconfig/scripts/windows/fire.ps1 +33 -0
  516. machineconfig/scripts/windows/ftpx.ps1 +5 -0
  517. machineconfig/scripts/windows/fzfb.ps1 +3 -0
  518. machineconfig/scripts/windows/fzfg.ps1 +2 -0
  519. machineconfig/scripts/windows/fzfrga.bat +20 -0
  520. machineconfig/scripts/windows/gpt.ps1 +23 -0
  521. machineconfig/scripts/windows/grep.ps1 +2 -0
  522. machineconfig/scripts/windows/kill_process.ps1 +8 -0
  523. machineconfig/scripts/windows/mount_nfs.ps1 +44 -0
  524. machineconfig/scripts/windows/mount_nw.ps1 +9 -0
  525. machineconfig/scripts/windows/mount_smb.ps1 +2 -0
  526. machineconfig/scripts/windows/mount_ssh.ps1 +17 -0
  527. machineconfig/scripts/windows/nano.ps1 +3 -0
  528. machineconfig/scripts/windows/neofetch.ps1 +2 -0
  529. machineconfig/scripts/windows/pomodoro.ps1 +8 -0
  530. machineconfig/scripts/windows/py2exe.ps1 +12 -0
  531. machineconfig/scripts/windows/reload_path.ps1 +3 -0
  532. machineconfig/scripts/windows/repos.ps1 +27 -0
  533. machineconfig/scripts/windows/scheduler.ps1 +6 -0
  534. machineconfig/scripts/windows/share_cloud.cmd +34 -0
  535. machineconfig/scripts/windows/share_nfs.ps1 +0 -0
  536. machineconfig/scripts/windows/share_smb.ps1 +22 -0
  537. machineconfig/scripts/windows/snapshot.ps1 +5 -0
  538. machineconfig/scripts/windows/start_slidev.ps1 +21 -0
  539. machineconfig/scripts/windows/start_terminals.ps1 +22 -0
  540. machineconfig/scripts/windows/unlock_bitlocker.ps1 +10 -0
  541. machineconfig/scripts/windows/utils/op_script_delete.ps1 +7 -0
  542. machineconfig/scripts/windows/wifi_conn.ps1 +7 -0
  543. machineconfig/scripts/windows/wsl_rdp_windows_port_forwarding.ps1 +46 -0
  544. machineconfig/scripts/windows/wsl_ssh_windows_port_forwarding.ps1 +76 -0
  545. machineconfig/scripts/windows/wsl_windows_transfer.ps1 +7 -0
  546. machineconfig/settings/__pycache__/__init__.cpython-311.pyc +0 -0
  547. machineconfig/settings/broot/br.sh +51 -0
  548. machineconfig/settings/broot/brootcd.ps1 +32 -0
  549. machineconfig/settings/broot/conf.toml +5 -0
  550. machineconfig/settings/glow/glow.yml +11 -0
  551. machineconfig/settings/gromit-mpx/gromit-mpx.cfg +34 -0
  552. machineconfig/settings/helix/config.toml +27 -0
  553. machineconfig/settings/helix/languages.toml +22 -0
  554. machineconfig/settings/keras/keras.json +6 -0
  555. machineconfig/settings/keyboard/espanso/config/default.yml +45 -0
  556. machineconfig/settings/keyboard/espanso/match/base.yml +57 -0
  557. machineconfig/settings/keyboard/kanata/kanata.kbd +0 -0
  558. machineconfig/settings/lf/linux/autocall/delete.sh +0 -0
  559. machineconfig/settings/lf/linux/autocall/on-cd.sh +0 -0
  560. machineconfig/settings/lf/linux/autocall/on-quit.sh +0 -0
  561. machineconfig/settings/lf/linux/autocall/open.sh +0 -0
  562. machineconfig/settings/lf/linux/autocall/paste.sh +0 -0
  563. machineconfig/settings/lf/linux/autocall/pre-cd.sh +0 -0
  564. machineconfig/settings/lf/linux/autocall/rename.sh +0 -0
  565. machineconfig/settings/lf/linux/colors +196 -0
  566. machineconfig/settings/lf/linux/exe/cleaner.sh +7 -0
  567. machineconfig/settings/lf/linux/exe/fzf_nano.sh +16 -0
  568. machineconfig/settings/lf/linux/exe/leftpane_previewer.sh +5 -0
  569. machineconfig/settings/lf/linux/exe/lfcd.sh +32 -0
  570. machineconfig/settings/lf/linux/exe/previewer.sh +37 -0
  571. machineconfig/settings/lf/linux/exe/previewer_archive.sh +155 -0
  572. machineconfig/settings/lf/linux/icons +357 -0
  573. machineconfig/settings/lf/linux/lfrc +226 -0
  574. machineconfig/settings/lf/windows/autocall/delete.ps1 +0 -0
  575. machineconfig/settings/lf/windows/autocall/on-cd.ps1 +0 -0
  576. machineconfig/settings/lf/windows/autocall/on-quit.ps1 +0 -0
  577. machineconfig/settings/lf/windows/autocall/open.ps1 +0 -0
  578. machineconfig/settings/lf/windows/autocall/paste.ps1 +0 -0
  579. machineconfig/settings/lf/windows/autocall/pre-cd.ps1 +0 -0
  580. machineconfig/settings/lf/windows/autocall/rename.ps1 +0 -0
  581. machineconfig/settings/lf/windows/cd_tere.ps1 +4 -0
  582. machineconfig/settings/lf/windows/cd_zoxide.ps1 +4 -0
  583. machineconfig/settings/lf/windows/cd_zoxide2.ps1 +4 -0
  584. machineconfig/settings/lf/windows/colors +159 -0
  585. machineconfig/settings/lf/windows/fzf_edit.ps1 +6 -0
  586. machineconfig/settings/lf/windows/icons +357 -0
  587. machineconfig/settings/lf/windows/leftpane_previewer.ps1 +3 -0
  588. machineconfig/settings/lf/windows/lfcd.ps1 +35 -0
  589. machineconfig/settings/lf/windows/lfrc +133 -0
  590. machineconfig/settings/lf/windows/mkdir.ps1 +3 -0
  591. machineconfig/settings/lf/windows/mkfile.ps1 +3 -0
  592. machineconfig/settings/lf/windows/previewer.ps1 +7 -0
  593. machineconfig/settings/lf/windows/tst.ps1 +1 -0
  594. machineconfig/settings/linters/.flake8 +24 -0
  595. machineconfig/settings/linters/.mypy.ini +29 -0
  596. machineconfig/settings/linters/.pylintrc +91 -0
  597. machineconfig/settings/linters/.ruff.toml +77 -0
  598. machineconfig/settings/linters/.ruff_cache/.gitignore +2 -0
  599. machineconfig/settings/linters/.ruff_cache/CACHEDIR.TAG +1 -0
  600. machineconfig/settings/lvim/linux/config.lua +0 -0
  601. machineconfig/settings/lvim/windows/archive/config_additional.lua +39 -0
  602. machineconfig/settings/lvim/windows/lua/user/custom_config.lua +13 -0
  603. machineconfig/settings/mprocs/windows/mprocs.yaml +55 -0
  604. machineconfig/settings/mprocs/windows/other +12 -0
  605. machineconfig/settings/pistol/pistol.conf +8 -0
  606. machineconfig/settings/presenterm/config.yaml +76 -0
  607. machineconfig/settings/procs/.procs.toml +142 -0
  608. machineconfig/settings/pudb/pudb.cfg +25 -0
  609. machineconfig/settings/rofi/config.rasi +4 -0
  610. machineconfig/settings/rofi/config_default.rasi +147 -0
  611. machineconfig/settings/shells/alacritty/alacritty.toml +40 -0
  612. machineconfig/settings/shells/alacritty/alacritty.yml +0 -0
  613. machineconfig/settings/shells/bash/.inputrc +3 -0
  614. machineconfig/settings/shells/bash/init.sh +66 -0
  615. machineconfig/settings/shells/hyper/.hyper.js +201 -0
  616. machineconfig/settings/shells/ipy/profiles/default/__init__.py +0 -0
  617. machineconfig/settings/shells/ipy/profiles/default/__pycache__/__init__.cpython-311.pyc +0 -0
  618. machineconfig/settings/shells/ipy/profiles/default/startup/__init__.py +0 -0
  619. machineconfig/settings/shells/ipy/profiles/default/startup/__pycache__/__init__.cpython-311.pyc +0 -0
  620. machineconfig/settings/shells/ipy/profiles/default/startup/__pycache__/playext.cpython-311.pyc +0 -0
  621. machineconfig/settings/shells/ipy/profiles/default/startup/playext.py +83 -0
  622. machineconfig/settings/shells/kitty/kitty.conf +1476 -0
  623. machineconfig/settings/shells/nushell/config.nu +36 -0
  624. machineconfig/settings/shells/nushell/env.nu +13 -0
  625. machineconfig/settings/shells/pwsh/init.ps1 +88 -0
  626. machineconfig/settings/shells/pwsh/profile.ps1 +0 -0
  627. machineconfig/settings/shells/starship/starship.toml +58 -0
  628. machineconfig/settings/shells/vtm/settings.xml +297 -0
  629. machineconfig/settings/shells/wezterm/wezterm.lua +193 -0
  630. machineconfig/settings/shells/wt/settings.json +526 -0
  631. machineconfig/settings/streamlit/config.toml +22 -0
  632. machineconfig/settings/svim/linux/init.toml +48 -0
  633. machineconfig/settings/svim/windows/init.toml +48 -0
  634. machineconfig/settings/tere/terecd.ps1 +8 -0
  635. machineconfig/settings/tere/terecd.sh +8 -0
  636. machineconfig/settings/tmux/.tmate.conf +3 -0
  637. machineconfig/settings/tmux/.tmux.conf +6 -0
  638. machineconfig/settings/wsl/.wslconfig +35 -0
  639. machineconfig/settings/yazi/keymap.toml +0 -0
  640. machineconfig/settings/yazi/theme.toml +0 -0
  641. machineconfig/settings/yazi/yazi.toml +4 -0
  642. machineconfig/settings/zed/settings.json +35 -0
  643. machineconfig/settings/zellij/commands/monitor +9 -0
  644. machineconfig/settings/zellij/commands/standard_panes +33 -0
  645. machineconfig/settings/zellij/config.kdl +295 -0
  646. machineconfig/settings/zellij/config.orig.kdl +295 -0
  647. machineconfig/settings/zellij/layouts/hist +13 -0
  648. machineconfig/settings/zellij/layouts/panes.kdl +20 -0
  649. machineconfig/settings/zellij/layouts/st.kdl +21 -0
  650. machineconfig/settings/zellij/layouts/st2.kdl +59 -0
  651. machineconfig/settings/zellij/layouts/stacked_panes.kdl +11 -0
  652. machineconfig/setup_linux/nix/cli_installation.sh +166 -0
  653. machineconfig/setup_linux/others/mint_keyboard_shortcuts.sh +30 -0
  654. machineconfig/setup_linux/others/openssh-server_add_pub_key.sh +60 -0
  655. machineconfig/setup_linux/web_shortcuts/all.sh +53 -0
  656. machineconfig/setup_linux/web_shortcuts/ascii_art.sh +100 -0
  657. machineconfig/setup_linux/web_shortcuts/croshell.sh +66 -0
  658. machineconfig/setup_linux/web_shortcuts/interactive.sh +241 -0
  659. machineconfig/setup_linux/web_shortcuts/ssh.sh +64 -0
  660. machineconfig/setup_linux/web_shortcuts/update_system.sh +55 -0
  661. machineconfig/setup_windows/others/docker.ps1 +7 -0
  662. machineconfig/setup_windows/others/obs.ps1 +4 -0
  663. machineconfig/setup_windows/web_shortcuts/all.ps1 +18 -0
  664. machineconfig/setup_windows/web_shortcuts/ascii_art.ps1 +36 -0
  665. machineconfig/setup_windows/web_shortcuts/croshell.ps1 +16 -0
  666. machineconfig/setup_windows/web_shortcuts/interactive.ps1 +200 -0
  667. machineconfig/setup_windows/web_shortcuts/ssh.ps1 +11 -0
  668. machineconfig/setup_windows/wt_and_pwsh/install_fonts.ps1 +27 -0
  669. machineconfig/setup_windows/wt_and_pwsh/set_pwsh_theme.py +12 -2
  670. machineconfig/setup_windows/wt_and_pwsh/set_wt_settings.py +45 -9
  671. machineconfig/utils/ai/__init__.py +0 -0
  672. machineconfig/utils/ai/browser_user_wrapper.py +51 -0
  673. machineconfig/utils/ai/generate_file_checklist.py +74 -0
  674. machineconfig/utils/ai/url2md.py +75 -0
  675. machineconfig/utils/installer.py +101 -253
  676. machineconfig/utils/installer_utils/__init__.py +0 -0
  677. machineconfig/utils/installer_utils/installer_abc.py +100 -0
  678. machineconfig/utils/installer_utils/installer_class.py +253 -0
  679. machineconfig/utils/procs.py +69 -16
  680. machineconfig/utils/scheduling.py +47 -13
  681. machineconfig/utils/utils.py +39 -371
  682. machineconfig/utils/utils_code.py +82 -0
  683. machineconfig/utils/utils_links.py +88 -0
  684. machineconfig/utils/utils_options.py +163 -0
  685. machineconfig/utils/utils_path.py +151 -0
  686. machineconfig/utils/ve.py +37 -225
  687. machineconfig/utils/ve_utils/ve1.py +111 -0
  688. machineconfig/utils/ve_utils/ve2.py +142 -0
  689. {machineconfig-1.92.dist-info → machineconfig-1.94.dist-info}/METADATA +25 -21
  690. machineconfig-1.94.dist-info/RECORD +710 -0
  691. {machineconfig-1.92.dist-info → machineconfig-1.94.dist-info}/WHEEL +1 -1
  692. machineconfig-1.92.dist-info/LICENSE +0 -201
  693. machineconfig-1.92.dist-info/RECORD +0 -70
  694. {machineconfig-1.92.dist-info → machineconfig-1.94.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,280 @@
1
+ """
2
+ Distributed Computing
3
+ """
4
+
5
+
6
+ from typing import Optional, Any, Callable, Union
7
+ from math import ceil, floor
8
+ from enum import Enum
9
+ from dataclasses import dataclass
10
+ import psutil
11
+ import numpy as np
12
+
13
+ from crocodile.core import randstr, List as L, Struct as S, install_n_import
14
+ from crocodile.file_management import P, Save
15
+ from crocodile.meta import SSH, Terminal
16
+ from machineconfig.cluster.remote_machine import RemoteMachine, RemoteMachineConfig, WorkloadParams, LAUNCH_METHOD
17
+ from rich.console import Console
18
+ # from platform import system
19
+ # import time
20
+ # from rich.progress import track
21
+
22
+
23
+ console = Console()
24
+
25
+
26
+ class LoadCriterion(Enum):
27
+ cpu = "cpu"
28
+ ram = "ram"
29
+ product = "cpu * ram"
30
+ cpu_norm = "cpu_norm"
31
+ ram_norm = "ram_norm"
32
+ product_norm = "cpu_norm * ram_norm"
33
+
34
+
35
+ @dataclass
36
+ class MachineSpecs:
37
+ cpu: float
38
+ ram: float
39
+ product: float
40
+ cpu_norm: float
41
+ ram_norm: float
42
+ product_norm: float
43
+ @staticmethod
44
+ def get_this_machine_specs():
45
+ cpu, ram = psutil.cpu_count(), psutil.virtual_memory().total / 2 ** 30
46
+ assert cpu is not None
47
+ return MachineSpecs(cpu=cpu, ram=ram, product=cpu * ram, cpu_norm=cpu, ram_norm=ram, product_norm=cpu * ram)
48
+
49
+
50
+ class ThreadLoadCalculator:
51
+ """relies on relative values to a referenc machine specs.
52
+ Runs multiple instances of code per machine. Useful if code doesn't run faster with more resources avaliable.
53
+ equal distribution across instances of one machine"""
54
+ def __init__(self, num_jobs: Optional[int] = None, load_criterion: LoadCriterion = LoadCriterion.cpu, reference_specs: Optional[MachineSpecs] = None):
55
+ self.num_jobs = num_jobs
56
+ self.load_criterion = load_criterion
57
+ self.reference_specs: MachineSpecs = MachineSpecs.get_this_machine_specs() if reference_specs is None else reference_specs
58
+ def __getstate__(self): return self.__dict__
59
+ def __setstate__(self, state: dict[str, Any]): self.__dict__.update(state)
60
+ def get_num_threads(self, machine_specs: MachineSpecs) -> int:
61
+ if self.num_jobs is None: return 1
62
+ res = int(floor(self.num_jobs * (machine_specs.__dict__[self.load_criterion.name] / self.reference_specs.__dict__[self.load_criterion.name])))
63
+ return 1 if res == 0 else res
64
+
65
+
66
+ class MachineLoadCalculator:
67
+ def __init__(self, max_num: int = 1000, load_criterion: LoadCriterion = LoadCriterion.product, load_ratios_repr: str = ""):
68
+ self.load_ratios: list[float] = []
69
+ self.load_ratios_repr = load_ratios_repr
70
+ self.max_num: int = max_num
71
+ self.load_criterion = load_criterion
72
+ def __getstate__(self) -> dict[str, Any]: return self.__dict__
73
+ def __setstate__(self, d: dict[str, Any]) -> None: self.__dict__.update(d)
74
+ def get_workload_params(self, machines_specs: list[MachineSpecs], threads_per_machine: list[int]) -> list[WorkloadParams]:
75
+ """Note: like thread divider in parallelize function, the behaviour is to include the edge cases on both ends of subsequent intervals."""
76
+ tmp: list[WorkloadParams] = []
77
+ idx_so_far = 0
78
+ for machine_index, (machine_specs, a_threads_per_machine) in enumerate(zip(machines_specs, threads_per_machine)):
79
+ load_value = machine_specs.__dict__[self.load_criterion.name]
80
+ self.load_ratios.append(load_value)
81
+ idx1 = idx_so_far
82
+ idx2 = self.max_num if machine_index == len(threads_per_machine) - 1 else (floor(load_value * self.max_num) + idx1)
83
+ if idx2 > self.max_num:
84
+ print(machines_specs, '\n\n', threads_per_machine)
85
+ print(f"All values: {tmp=}, {idx_so_far=}, {idx1=}, {idx2=}, {self.max_num=}, {a_threads_per_machine=}, {machine_index=}, {machine_specs=}, {load_value=}, {self.load_ratios=}, {self.load_ratios_repr=}")
86
+ raise ValueError(f"idx2 ({idx2}) > max_num ({self.max_num})")
87
+ idx_so_far = idx2
88
+ tmp.append(WorkloadParams(idx_start=idx1, idx_end=idx2, idx_max=self.max_num, jobs=a_threads_per_machine))
89
+ return tmp
90
+
91
+
92
+ class Cluster:
93
+ def __getstate__(self) -> dict[str, Any]:
94
+ state = self.__dict__
95
+ state["func"] = None
96
+ return state
97
+ def __setstate__(self, state: dict[str, Any]) -> None: self.__dict__.update(state)
98
+ def save(self) -> P:
99
+ path = self.root_dir.joinpath("cluster.Cluster.pkl")
100
+ Save.pickle(obj=self.__getstate__(), path=path)
101
+ return path
102
+ @staticmethod
103
+ def load(job_id: str, base: Optional[str] = None) -> 'Cluster': return Cluster.get_cluster_path(job_id=job_id, base=base).joinpath("cluster.Cluster.pkl").readit()
104
+ @staticmethod
105
+ def get_cluster_path(job_id: str, base: Union[str, P, None] = None):
106
+ if base is None: base_obj = P.home().joinpath("tmp_results/remote_machines")
107
+ else: base_obj = P(base)
108
+ return base_obj.joinpath(f"job_id__{job_id}")
109
+ def __init__(self,
110
+ func: Callable[..., Any],
111
+ ssh_params: list[dict[str, Any]],
112
+ remote_machine_config: RemoteMachineConfig,
113
+ func_kwargs: Optional[dict[str, Any]] = None,
114
+ # workload_params: list[WorkloadParams] or None = None,
115
+ thread_load_calc: Optional[ThreadLoadCalculator] = None,
116
+ # machine_load_calc=None,
117
+ ditch_unavailable_machines: bool = False,
118
+ description: str = "",
119
+ job_id: Optional[str] = None,
120
+ base_dir: Union[str, P, None] = None):
121
+ self.job_id = job_id or randstr(noun=True)
122
+ self.root_dir = self.get_cluster_path(self.job_id, base=base_dir)
123
+ self.results_downloaded = False
124
+
125
+ self.thread_load_calc: ThreadLoadCalculator = thread_load_calc or ThreadLoadCalculator()
126
+ self.machine_load_calc: MachineLoadCalculator = MachineLoadCalculator(load_criterion=LoadCriterion[self.thread_load_calc.load_criterion.name + "_norm"], )
127
+
128
+ sshz: list[SSH] = []
129
+ for an_ssh_params in ssh_params:
130
+ try:
131
+ tmp = SSH(**an_ssh_params)
132
+ sshz.append(tmp)
133
+ except Exception as ex:
134
+ print(f"Couldn't connect to {an_ssh_params}")
135
+ if ditch_unavailable_machines: continue
136
+ else: raise Exception(f"Couldn't connect to {an_ssh_params}") from ex # type: ignore # pylint: disable=W0719
137
+
138
+ # lists of similar length:
139
+ self.sshz: list[SSH] = sshz
140
+ self.machines: list[RemoteMachine] = []
141
+ self.machines_specs: list[MachineSpecs] = []
142
+ self.threads_per_machine: list[int] = []
143
+ self.remote_machine_kwargs: RemoteMachineConfig = remote_machine_config
144
+ self.workload_params: list[WorkloadParams] = []
145
+
146
+ self.description: str = description
147
+ self.func = func
148
+ self.func_kwargs = func_kwargs if func_kwargs is not None else {}
149
+
150
+ # fire options
151
+ self.machines_per_tab: int = 1
152
+ self.window_number: int = 2
153
+
154
+ def __repr__(self): return "Cluster with following machines:\n" + "\n".join([repr(item) for item in (self.machines if self.machines else self.sshz)])
155
+ def print_func_kwargs(self):
156
+ print("\n" * 2)
157
+ console.rule(title="kwargs of functions to be run on machines")
158
+ for an_ssh, a_kwarg in zip(self.sshz, self.workload_params):
159
+ S(a_kwarg.__dict__).print(as_config=True, title=an_ssh.get_remote_repr())
160
+ def print_commands(self, launch_method: LAUNCH_METHOD):
161
+ print("\n" * 2)
162
+ console.rule(title="Commands to run on each machine:")
163
+ for machine in self.machines:
164
+ print(f"{repr(machine)} ==> {machine.file_manager.get_fire_command(launch_method=launch_method)}")
165
+
166
+ def generate_standard_kwargs(self) -> None:
167
+ if self.workload_params:
168
+ self.print_func_kwargs()
169
+ print(self.workload_params, len(self.workload_params), type(self.workload_params))
170
+ print("workload_params is not None, so not generating standard kwargs")
171
+ return None
172
+ cpus: list[float] = []
173
+ rams: list[float] = []
174
+ for an_ssh in self.sshz:
175
+ res = an_ssh.run_py("import psutil; print(psutil.cpu_count(), psutil.virtual_memory().total)", verbose=False).op
176
+ try: cpus.append(int(res.split(' ')[0]))
177
+ except ValueError as ve:
178
+ print(f"Couldn't get cpu count from {an_ssh}")
179
+ raise ValueError(f"Couldn't get cpu count from {an_ssh.get_remote_repr()}") from ve
180
+ rams.append(ceil(int(res.split(' ')[1]) / 2 ** 30))
181
+ total_cpu = np.array(cpus).sum()
182
+ total_ram = np.array(rams).sum()
183
+ total_product = (np.array(cpus) * np.array(rams)).sum()
184
+
185
+ self.machines_specs = [MachineSpecs(cpu=a_cpu, ram=a_ram, product=a_cpu * a_ram, cpu_norm=a_cpu / total_cpu, ram_norm=a_ram / total_ram, product_norm=a_cpu * a_ram / total_product) for a_cpu, a_ram in zip(cpus, rams)]
186
+ self.threads_per_machine = [self.thread_load_calc.get_num_threads(machine_specs=machine_specs) for machine_specs in self.machines_specs]
187
+ self.workload_params = self.machine_load_calc.get_workload_params(machines_specs=self.machines_specs, threads_per_machine=self.threads_per_machine)
188
+ self.print_func_kwargs()
189
+
190
+ def viz_load_ratios(self) -> None:
191
+ if not self.workload_params: raise RuntimeError("func_kwargs_list is None. You need to run generate_standard_kwargs() first.")
192
+ plt = install_n_import("plotext")
193
+ names = L(self.sshz).apply(lambda x: x.get_remote_repr(add_machine=True)).list
194
+
195
+ plt.simple_multiple_bar(names, [[machine_specs.cpu for machine_specs in self.machines_specs], [machine_specs.ram for machine_specs in self.machines_specs]], title="Resources per machine", labels=["#cpu threads", "memory size"])
196
+ plt.show()
197
+ print("")
198
+ plt.simple_bar(names, self.machine_load_calc.load_ratios, width=100, title=f"Load distribution for machines using criterion `{self.machine_load_calc.load_criterion}`")
199
+ plt.show()
200
+
201
+ tmp = S(dict(zip(names, L((np.array(self.machine_load_calc.load_ratios) * 100).round(1)).apply(lambda x: f"{int(x)}%")))).print(as_config=True, justify=75, return_str=True)
202
+ assert isinstance(tmp, str)
203
+ self.machine_load_calc.load_ratios_repr = tmp
204
+ print(self.machine_load_calc.load_ratios_repr)
205
+ # self.workload_params.
206
+ print("\n")
207
+
208
+ def submit(self) -> None:
209
+ if not self.workload_params: raise RuntimeError("You need to generate standard kwargs first.")
210
+ for idx, (a_workload_params, an_ssh) in enumerate(zip(self.workload_params, self.sshz)):
211
+ desc = self.description + f"\nLoad Ratios on machines:\n{self.machine_load_calc.load_ratios_repr}"
212
+ # if self.remote_machine_kwargs is not None:
213
+ config = self.remote_machine_kwargs
214
+ config.__dict__.update(dict(description=desc, job_id=self.job_id + f"_{idx}", base_dir=self.root_dir, workload_params=a_workload_params, ssh_obj=an_ssh))
215
+ # else: config = RemoteMachineConfig(description=desc, job_id=self.job_id + f"_{idx}", base_dir=self.root_dir.as_posix(), workload_params=a_workload_params, ssh_obj=an_ssh)
216
+ m = RemoteMachine(func=self.func, func_kwargs=self.func_kwargs, config=config)
217
+ m.generate_scripts()
218
+ m.submit()
219
+ self.machines.append(m)
220
+ try: self.save()
221
+ except Exception as re:
222
+ print(re)
223
+ print("Couldn't pickle cluster object")
224
+ # self.print_commands()
225
+
226
+ def open_mux(self, machines_per_tab: int = 1, window_number: Optional[int] = None):
227
+ self.machines_per_tab = machines_per_tab
228
+ self.window_number = window_number if window_number is not None else 0 # randstr(length=3, lower=False, upper=False)
229
+ cmd = f"wt -w {self.window_number} "
230
+ for idx, m in enumerate(self.machines):
231
+
232
+ sub_cmd = m.get_session_manager().get_new_session_ssh_command(ssh=m.ssh, sess_name=m.job_params.session_name)
233
+ if idx == 0: cmd += f""" new-tab --title '{str(m.ssh.hostname) + str(idx)}' pwsh -Command "{sub_cmd}" `;""" # avoid new tabs despite being even index
234
+ elif idx % self.machines_per_tab == 0: cmd += f""" new-tab --title {str(m.ssh.hostname) + str(idx)} pwsh -Command "{sub_cmd}" `;"""
235
+ else: cmd += f""" split-pane --horizontal --size {1 / self.machines_per_tab} pwsh -Command "{sub_cmd}" `;"""
236
+
237
+ print("Terminal launch command:\n", cmd)
238
+ if cmd.endswith("`;"): cmd = cmd[:-2]
239
+ Terminal().run_async(*cmd.replace("`;", ";").split(" ")) # `; only for powershell, cmd is okay for ; as it is not a special character
240
+ rm_last = self.machines[-1]
241
+ rm_last.get_session_manager().asssert_session_started(ssh=rm_last.ssh, sess_name=rm_last.job_params.session_name)
242
+
243
+ def fire(self, machines_per_tab: int = 1, window_number: Optional[int] = None, run: bool = False):
244
+ self.open_mux(machines_per_tab=machines_per_tab, window_number=window_number)
245
+ for m in self.machines:
246
+ m.fire(run=run, open_console=False)
247
+
248
+ def run(self, run: bool = False, machines_per_tab: int = 1, window_number: Optional[int] = None):
249
+ self.generate_standard_kwargs()
250
+ self.viz_load_ratios()
251
+ print(self)
252
+ self.submit()
253
+ self.fire(run=run, machines_per_tab=machines_per_tab, window_number=window_number)
254
+ self.save()
255
+ return self
256
+
257
+ def check_job_status(self) -> None: L(self.machines).apply(lambda machine: machine.check_job_status())
258
+ def download_results(self):
259
+ if self.results_downloaded:
260
+ print(f"All results downloaded to {self.root_dir} 🤗")
261
+ return True
262
+ for idx, a_m in enumerate(self.machines):
263
+ _ = idx
264
+ if a_m.results_path is None:
265
+ print(f"Results are not ready for machine {a_m}.")
266
+ print("Try to run `.check_job_status()` to check if the job is done and obtain results path.")
267
+ continue
268
+ # results_folder = P(a_m.results_path).expanduser()
269
+ if a_m.results_downloaded is False:
270
+ print("\n")
271
+ console.rule(f"Downloading results from {a_m}")
272
+ print("\n")
273
+ a_m.download_results(target=None) # TODO another way of resolve multiple machines issue is to create a directory at downlaod_results time.
274
+ if L(self.machines).results_downloaded.to_numpy().sum() == len(self.machines):
275
+ print(f"All results downloaded to {self.root_dir} 🤗")
276
+ self.results_downloaded = True
277
+
278
+
279
+ if __name__ == '__main__':
280
+ pass
@@ -0,0 +1,238 @@
1
+
2
+ from rich import inspect
3
+ from rich.console import Console
4
+ import pandas as pd
5
+
6
+ from crocodile.core import Struct as S, install_n_import
7
+ from crocodile.file_management import P, Save
8
+ from crocodile.meta import MACHINE
9
+ from machineconfig.cluster.loader_runner import JOB_STATUS, LAUNCH_METHOD, JobStatus
10
+
11
+ from typing import Union, Any
12
+ import time
13
+ import os
14
+ import platform
15
+
16
+ console = Console()
17
+
18
+
19
+ class FileManager:
20
+ running_path = P("~/tmp_results/remote_machines/file_manager/running_jobs.pkl")
21
+ queue_path = P("~/tmp_results/remote_machines/file_manager/queued_jobs.pkl")
22
+ history_path = P("~/tmp_results/remote_machines/file_manager/history_jobs.pkl")
23
+ shell_script_path_log = P("~/tmp_results/remote_machines/file_manager/last_cluster_script.txt")
24
+ default_base = P("~/tmp_results/remote_machines/jobs")
25
+ @staticmethod
26
+ def from_pickle(path: Union[str, P]):
27
+ fm = FileManager(job_id='1', remote_machine_type='Windows', lock_resources=True, max_simulataneous_jobs=1, base=None)
28
+ fm.__setstate__(dict(P(path).expanduser().readit()))
29
+ return fm
30
+ def __getstate__(self): return self.__dict__
31
+ def __setstate__(self, state: dict[str, Any]): self.__dict__ = state
32
+ def __init__(self, job_id: str, remote_machine_type: MACHINE, lock_resources: bool, max_simulataneous_jobs: int = 1, base: Union[str, P, None] = None):
33
+ """Log files to track execution process:
34
+ * A text file that cluster deletes at the begining then write to at the end of each job.
35
+ * pickle of Machine and clusters objects.
36
+ """
37
+ # EVERYTHING MUST REMAIN IN RELATIVE PATHS
38
+ self.remote_machine_type = remote_machine_type
39
+ self.job_id = job_id
40
+ self.max_simulataneous_jobs = max_simulataneous_jobs
41
+ self.lock_resources = lock_resources
42
+
43
+ self.submission_time = pd.Timestamp.now()
44
+
45
+ self.base_dir = P(base).collapseuser() if bool(base) else FileManager.default_base
46
+ status: JOB_STATUS
47
+ status = 'queued'
48
+ self.job_root = self.base_dir.joinpath(f"{status}/{self.job_id}")
49
+ @property
50
+ def py_script_path(self): return self.job_root.joinpath("python/cluster_wrap.py")
51
+ @property
52
+ def cloud_download_py_script_path(self): return self.job_root.joinpath("python/download_data.py")
53
+ @property
54
+ def shell_script_path(self): return self.job_root.joinpath("shell/cluster_script" + {"Windows": ".ps1", "Linux": ".sh"}[self.remote_machine_type]) # noqa: E501
55
+ @property
56
+ def kwargs_path(self): return self.job_root.joinpath("data/func_kwargs.pkl")
57
+ @property
58
+ def file_manager_path(self): return self.job_root.joinpath("data/file_manager.pkl")
59
+ @property
60
+ def remote_machine_path(self): return self.job_root.joinpath("data/remote_machine.Machine.pkl")
61
+ @property
62
+ def remote_machine_config_path(self): return self.job_root.joinpath("data/remote_machine_config.pkl")
63
+ @property
64
+ def execution_log_dir(self): return self.job_root.joinpath("logs")
65
+ def get_fire_command(self, launch_method: LAUNCH_METHOD):
66
+ _ = launch_method
67
+ script_path = self.shell_script_path.expanduser()
68
+ # if launch_method == "remotely": pass # shell_script is already repared for target machine.
69
+ # else:
70
+ if platform.system() == "Windows" and script_path.name.endswith(".sh"):
71
+ tmp = script_path.with_suffix(".ps1")
72
+ tmp.write_text(script_path.read_text(), encoding="utf-8", newline=None)
73
+ script_path = tmp
74
+ if platform.system() == "Linux" and script_path.name.endswith(".ps1"):
75
+ tmp = script_path.with_suffix(".sh")
76
+ tmp.write_text(script_path.read_text(), encoding="utf-8", newline='\n')
77
+ script_path = tmp
78
+ return f". {script_path}"
79
+ def fire_command_to_clip_memory(self, launch_method: LAUNCH_METHOD):
80
+ print("Execution command copied to clipboard 📋")
81
+ print(self.get_fire_command(launch_method=launch_method)); install_n_import("clipboard").copy(self.get_fire_command(launch_method=launch_method))
82
+ print("\n")
83
+ def get_job_status(self, session_name: str, tab_name: str) -> JOB_STATUS:
84
+ pid_path = self.execution_log_dir.expanduser().joinpath("pid.txt")
85
+ tmp = self.execution_log_dir.expanduser().joinpath("status.txt").read_text()
86
+ status: JOB_STATUS = tmp # type: ignore
87
+ if status == "running":
88
+ if not pid_path.exists():
89
+ print(f"Something wrong happened to job `{self.job_id}`. Its status log file says `{status}`, but pid_path doesn't exists. Moving to failed.")
90
+ status = 'failed'
91
+ self.execution_log_dir.expanduser().joinpath("status.txt").write_text(status)
92
+ return status
93
+ pid: int = int(pid_path.read_text().rstrip())
94
+ import psutil
95
+ try: proc = psutil.Process(pid=pid)
96
+ except psutil.NoSuchProcess:
97
+ print(f"Something wrong happened to job `{self.job_id}`.. Its status log file says `{status}`, but its declared `{pid=}` is dead. Moving to failed.")
98
+ status = 'failed'
99
+ self.execution_log_dir.expanduser().joinpath("status.txt").write_text(status)
100
+ return status
101
+ command = " ".join(proc.cmdline())
102
+ if self.job_id not in command:
103
+ print(f"Something wrong happened to job `{self.job_id}`. Its status log file says `{status}` but the `{pid=}` declared seem to belong to a different process as indicated by the firing command `{command=}`. Moving to failed.")
104
+ status = 'failed'
105
+ self.execution_log_dir.expanduser().joinpath("status.txt").write_text(status)
106
+ return status
107
+ print(f"Job `{self.job_id}` is running with {pid=} & {session_name=} & {tab_name=}.")
108
+ return status
109
+ return status
110
+
111
+ def add_to_queue(self, job_status: JobStatus):
112
+ try:
113
+ queue_file: list[JobStatus] = self.queue_path.expanduser().readit()
114
+ except FileNotFoundError:
115
+ print("Queue file was deleted by the locking job, creating an empty one and saving it.")
116
+ queue_file = []
117
+ Save.pickle(obj=queue_file, path=self.queue_path.expanduser())
118
+ job_ids = [job.job_id for job in queue_file]
119
+ if self.job_id not in job_ids:
120
+ print(f"Adding this job {self.job_id} to the queue and saving it. {len(queue_file)=}")
121
+ queue_file.append(job_status)
122
+ Save.pickle(obj=queue_file, path=self.queue_path.expanduser())
123
+ return queue_file
124
+
125
+ def get_resources_unlocking(self): # this one works at shell level in case python script failed.
126
+ return f"""
127
+ rm {self.running_path.collapseuser().as_posix()}
128
+ echo "Unlocked resources"
129
+ """
130
+
131
+ def secure_resources(self):
132
+ if self.lock_resources is False: return True
133
+ this_job = JobStatus(job_id=self.job_id, pid=os.getpid(), submission_time=self.submission_time, start_time=None, status='locked')
134
+ sleep_time_mins = 10
135
+ lock_status = 'locked'
136
+ while lock_status == 'locked':
137
+
138
+ try: running_file: list[JobStatus] = self.running_path.expanduser().readit()
139
+ except FileNotFoundError:
140
+ print("Running file was deleted by the locking job, making one.")
141
+ running_file = []
142
+ Save.pickle(obj=running_file, path=self.running_path.expanduser())
143
+
144
+ queue_file = self.add_to_queue(job_status=this_job)
145
+
146
+ if len(running_file) < self.max_simulataneous_jobs:
147
+ lock_status = 'unlocked'
148
+ break
149
+
150
+ # --------------- Clearning up queue_file from dead processes -----------------
151
+ import psutil
152
+ next_job_in_queue = queue_file[0] # only consider the first job in the queue
153
+ try: _ = psutil.Process(next_job_in_queue.pid)
154
+ except psutil.NoSuchProcess:
155
+ print(f"Next job in queue {next_job_in_queue} has no associated process, removing it from the queue.")
156
+ queue_file.pop(0)
157
+ Save.pickle(obj=queue_file, path=self.queue_path.expanduser())
158
+ continue
159
+
160
+ # --------------- Clearning up running_file from dead processes -----------------
161
+ found_dead_process = False
162
+ assert len(running_file) > 0, "Running file is empty. This should not happen. There should be a break before this point."
163
+
164
+ for running_job in running_file:
165
+ try: proc = psutil.Process(pid=running_job.pid)
166
+ except psutil.NoSuchProcess:
167
+ print(f"Locking process with pid {running_job.pid} is dead. Ignoring this lock file.")
168
+ S(running_job.__dict__).print(as_config=True, title="Ignored Lock File Details")
169
+ running_file.remove(running_job)
170
+ Save.pickle(obj=running_file, path=self.running_path.expanduser())
171
+ found_dead_process = True
172
+ continue # for for loop
173
+ attrs_txt = ['status', 'memory_percent', 'exe', 'num_ctx_switches',
174
+ 'ppid', 'num_threads', 'pid', 'cpu_percent', 'create_time', 'nice',
175
+ 'name', 'cpu_affinity', 'cmdline', 'username', 'cwd']
176
+ # if self.remote_machine_type == 'Windows': attrs_txt += ['num_handles']
177
+ # environ, memory_maps, 'io_counters'
178
+ attrs_objs = ['memory_info', 'memory_full_info', 'cpu_times', 'ionice', 'threads', 'open_files', 'connections']
179
+ inspect(S(proc.as_dict(attrs=attrs_objs)), value=False, title=f"Process holding the Lock (pid = {running_job.pid})", docs=False, sort=False)
180
+ inspect(S(proc.as_dict(attrs=attrs_txt)), value=False, title=f"Process holding the Lock (pid = {running_job.pid})", docs=False, sort=False)
181
+
182
+ if found_dead_process: continue # repeat while loop logic.
183
+ running_job = running_file[0] # arbitrary job in the running file.
184
+ assert running_job.start_time is not None, f"Running job {running_job} has no start time. This should not happen."
185
+
186
+ this_specs = {"Submission time": this_job.submission_time, "Time now": pd.Timestamp.now(),
187
+ "Time spent waiting in the queue so far 🛌": pd.Timestamp.now() - this_job.submission_time,
188
+ f"Time consumed by locking job so far (job_id = {running_job.job_id}) so far ⏰": pd.Timestamp.now() - running_job.start_time}
189
+ S(this_specs).print(as_config=True, title=f"This Job `{this_job.job_id}` Details")
190
+ console.rule(title=f"Resources are locked by another job `{running_job.job_id}`. Sleeping for {sleep_time_mins} minutes. 😴", style="bold red", characters="-")
191
+ print("\n")
192
+ time.sleep(sleep_time_mins * 60)
193
+ self.write_lock_file(job_status=this_job)
194
+ console.print(f"Resources are locked by this job `{self.job_id}`. Process pid = {os.getpid()}.", highlight=True)
195
+
196
+ def write_lock_file(self, job_status: JobStatus):
197
+ job_status.start_time = pd.Timestamp.now()
198
+ queue_path = self.queue_path.expanduser()
199
+ try: queue_file: list[JobStatus] = queue_path.readit()
200
+ except FileNotFoundError as fne: raise FileNotFoundError(f"Queue file {queue_path} does not exist. This method should not be called in the first place.") from fne
201
+
202
+ if job_status in queue_file: queue_file.remove(job_status)
203
+ print("Removed current job from waiting queue and added it to the running queue. Saving both files.")
204
+ Save.pickle(obj=queue_file, path=queue_path)
205
+
206
+ running_path = self.running_path.expanduser()
207
+ try: running_file: list[JobStatus] = running_path.readit()
208
+ except FileNotFoundError as fne: raise FileNotFoundError(f"Queue file {running_path} does not exist. This method should not be called in the first place.") from fne
209
+
210
+ assert job_status not in running_file, f"Job status {job_status} is already in the running file. This should not happen."
211
+ assert len(running_file) < self.max_simulataneous_jobs, f"Number of running jobs ({len(running_file)}) is greater than the maximum allowed ({self.max_simulataneous_jobs}). This method should not be called in the first place."
212
+ running_file.append(job_status)
213
+ Save.pickle(obj=running_file, path=running_path)
214
+
215
+ def unlock_resources(self):
216
+ if self.lock_resources is False: return True
217
+ running_file: list[JobStatus] = self.running_path.expanduser().readit()
218
+ for job_status in running_file:
219
+ if job_status.job_id == self.job_id:
220
+ this_job = job_status
221
+ break
222
+ else:
223
+ print(f"Job {self.job_id} is not in the running file. This should not happen. The file is corrupt.")
224
+ this_job = None
225
+ if this_job is not None:
226
+ running_file.remove(this_job)
227
+ console.print(f"Resources have been released by this job `{self.job_id}`. Saving new running file")
228
+ Save.pickle(path=self.running_path.expanduser(), obj=running_file)
229
+ start_time = pd.to_datetime(self.execution_log_dir.expanduser().joinpath("start_time.txt").readit(), utc=False)
230
+ end_time = pd.Timestamp.now()
231
+ item = {"job_id": self.job_id, "start_time": start_time, "end_time": end_time, "submission_time": self.submission_time}
232
+ hist_file = self.history_path.expanduser()
233
+ if hist_file.exists(): hist = hist_file.readit()
234
+ else: hist = []
235
+ hist.append(item)
236
+ print(f"Saved history file to {hist_file} with {len(hist)} items.")
237
+ Save.pickle(obj=hist, path=hist_file)
238
+ # this is further handled by the calling script in case this function failed.
@@ -0,0 +1,148 @@
1
+
2
+
3
+
4
+ import git
5
+ from crocodile.file_management import P
6
+
7
+ from typing import Optional, Callable, Union, Any
8
+ from machineconfig.cluster.remote_machine import WorkloadParams
9
+ from dataclasses import dataclass
10
+ import getpass
11
+ import platform
12
+
13
+
14
+ @dataclass
15
+ class JobParams:
16
+ """What Python script needs to run the job. This will be dynamically injected into the script. Notice that all attrs are either strings or integers."""
17
+ description: str
18
+ ssh_repr: str
19
+ ssh_repr_remote: str
20
+ error_message: str
21
+ session_name: str
22
+ tab_name: str
23
+ file_manager_path: str
24
+
25
+ repo_path_rh: str
26
+ file_path_rh: str
27
+ file_path_r: str
28
+ func_module: str
29
+ func_class: Optional[str] = None # the callable might be a function on its own, not a method of a class.
30
+ func_name: Optional[str] = None # the job might be running a script as is, no particular method.
31
+
32
+ def auto_commit(self):
33
+ from git.repo import Repo
34
+ repo = Repo(P(self.repo_path_rh).expanduser(), search_parent_directories=True)
35
+ # do a commit if the repo is dirty
36
+ if repo.is_dirty():
37
+ repo.git.add(update=True)
38
+ repo.index.commit(f"CloudManager auto commit by {getpass.getuser()}@{platform.node()}")
39
+ print(f"⚠️ Repo {repo.working_dir} was dirty, auto-committed.")
40
+ else: print(f"✅ Repo {repo.working_dir} was clean, no auto-commit.")
41
+
42
+ def is_installabe(self) -> bool: return True if "setup.py" in P(self.repo_path_rh).expanduser().absolute().listdir().apply(str) else False
43
+ @staticmethod
44
+ def from_empty() -> 'JobParams':
45
+ return JobParams(repo_path_rh="", file_path_rh="", file_path_r="", func_module="", func_class="", func_name="", description="", ssh_repr="", ssh_repr_remote="", error_message="", session_name="", tab_name="", file_manager_path="")
46
+ @staticmethod
47
+ def from_func(func: Union[Callable[[Any], Any], P, str]) -> 'JobParams':
48
+ # if callable(self.func): executed_obj = f"""**{self.func.__name__}** from *{P(self.func.__code__.co_filename).collapseuser().as_posix()}*""" # for email.
49
+ if callable(func) and not isinstance(func, P):
50
+ func_name = func.__name__
51
+ func_module = func.__module__
52
+ if func_module == "<run_path>": # function imported through readpy module.
53
+ func_module = P(func.__globals__['__file__']).name
54
+ assert func_module != "__main__", f"Function must be defined in a module, not in __main__. Consider importing `{func.__name__}` or, restart this session and import the contents of this module."
55
+ if func.__name__ != func.__qualname__:
56
+ # print(f"Passed function {func} is a method of a class.")
57
+ func_file, func_class = P(func.__code__.co_filename), func.__qualname__.split(".")[0]
58
+ else:
59
+ # print(f"Passed function {func} is not a method of a class.")
60
+ func_file, func_class = P(func.__code__.co_filename), None
61
+ elif type(func) is str or type(func) is P:
62
+ func_file = P(func)
63
+ # func = None
64
+ func_class = None
65
+ func_name = None
66
+ func_module = func_file.stem
67
+ else: raise TypeError(f"Passed function {func} is not a callable or a path to a python file.")
68
+ try:
69
+ repo_path = P(git.Repo(func_file, search_parent_directories=True).working_dir)
70
+ func_relative_file = func_file.relative_to(repo_path)
71
+ except Exception as e:
72
+ print(e)
73
+ repo_path, func_relative_file = func_file.parent, func_file.name
74
+ return JobParams(repo_path_rh=repo_path.collapseuser().as_posix(), file_path_rh=repo_path.collapseuser().joinpath(func_relative_file).collapseuser().as_posix(),
75
+ file_path_r=P(func_relative_file).as_posix(),
76
+ func_module=func_module, func_class=func_class, func_name=func_name,
77
+ description="", ssh_repr="", ssh_repr_remote="", error_message="",
78
+ session_name="", tab_name="", file_manager_path="")
79
+
80
+ def get_execution_line(self, workload_params: Optional[WorkloadParams], parallelize: bool, wrap_in_try_except: bool) -> str:
81
+ # P(self.repo_path_rh).name}.{self.file_path_r.replace(".py", '').replace('/', '.')#
82
+ # if func_module is not None:
83
+ # # noinspection PyTypeChecker
84
+ # module = __import__(func_module, fromlist=[None])
85
+ # exec_obj = module.__dict__[func_name] if not bool(func_class) else getattr(module.__dict__[func_class], func_name)
86
+ # elif func_name is not None:
87
+ # # This approach is not conducive to parallelization since "mymod" is not pickleable.
88
+ # module = SourceFileLoader("mymod", P.home().joinpath(rel_full_path).as_posix()).load_module() # loading the module assumes its not a script, there should be at least if __name__ == __main__ wrapping any script.
89
+ # exec_obj = getattr(module, func_name) if not bool(func_class) else getattr(getattr(module, func_class), func_name)
90
+ # else:
91
+ # module = P.home().joinpath(rel_full_path).readit() # uses runpy to read .py files.
92
+ # exec_obj = module # for README.md generation.
93
+
94
+ if workload_params is not None: base = f"""
95
+ workload_params = WorkloadParams(**{workload_params.__dict__})
96
+ repo_path = P(rf'{self.repo_path_rh}').expanduser().absolute()
97
+ file_root = P(rf'{self.file_path_rh}').expanduser().absolute().parent
98
+ tb.sys.path.insert(0, repo_path.str)
99
+ tb.sys.path.insert(0, file_root.str)
100
+ """
101
+ else: base = ""
102
+
103
+ # loading function ===============================================================
104
+ if self.func_name is not None:
105
+ if self.func_class is None: base += f"""
106
+ from {self.func_module.replace('.py', '')} import {self.func_name} as func
107
+ """
108
+ elif self.func_class is not None: # type: ignore
109
+ base += f"""
110
+ from {self.func_module.replace('.py', '')} import {self.func_class} as {self.func_class}
111
+ func = {self.func_class}.{self.func_name}
112
+ """
113
+ else: base = f"""
114
+ res = None # in case the file did not define it.
115
+ # --------------------------------- SCRIPT AS IS
116
+ {P(self.file_path_rh).expanduser().read_text()}
117
+ # --------------------------------- END OF SCRIPT AS IS
118
+ """
119
+
120
+ if workload_params is not None and parallelize is False: base += """
121
+ res = func(workload_params=workload_params, **func_kwargs)
122
+ """
123
+ elif workload_params is not None and parallelize is True: base += f"""
124
+ kwargs_workload = {list(workload_params.split_to_jobs().apply(lambda a_kwargs: a_kwargs.__dict__))}
125
+ workload_params = []
126
+ for idx, x in enumerate(kwargs_workload):
127
+ S(x).print(as_config=True, title=f"Instance {{idx}}")
128
+ workload_params.append(WorkloadParams(**x))
129
+ print("\\n" * 2)
130
+ res = L(workload_params).apply(lambda a_workload_params: func(workload_params=a_workload_params, **func_kwargs), jobs={workload_params.jobs})
131
+ """
132
+ else: base += """
133
+ res = func(**func_kwargs)
134
+ """
135
+
136
+ if wrap_in_try_except:
137
+ import textwrap
138
+ base = textwrap.indent(base, " " * 4)
139
+ base = f"""
140
+ try:
141
+ {base}
142
+ except Exception as e:
143
+ print(e)
144
+ params.error_message = str(e)
145
+ res = None
146
+
147
+ """
148
+ return base