machineconfig 1.97__py3-none-any.whl → 2.1__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 (268) hide show
  1. machineconfig/cluster/cloud_manager.py +22 -29
  2. machineconfig/cluster/data_transfer.py +2 -3
  3. machineconfig/cluster/distribute.py +0 -2
  4. machineconfig/cluster/file_manager.py +4 -5
  5. machineconfig/cluster/job_params.py +1 -4
  6. machineconfig/cluster/loader_runner.py +8 -11
  7. machineconfig/cluster/remote_machine.py +4 -5
  8. machineconfig/cluster/script_execution.py +2 -2
  9. machineconfig/cluster/script_notify_upon_completion.py +0 -1
  10. machineconfig/cluster/sessions_managers/archive/create_zellij_template.py +4 -6
  11. machineconfig/cluster/sessions_managers/archive/session_managers.py +0 -1
  12. machineconfig/cluster/sessions_managers/enhanced_command_runner.py +35 -75
  13. machineconfig/cluster/sessions_managers/wt_local.py +113 -185
  14. machineconfig/cluster/sessions_managers/wt_local_manager.py +127 -197
  15. machineconfig/cluster/sessions_managers/wt_remote.py +60 -67
  16. machineconfig/cluster/sessions_managers/wt_remote_manager.py +110 -149
  17. machineconfig/cluster/sessions_managers/wt_utils/layout_generator.py +61 -64
  18. machineconfig/cluster/sessions_managers/wt_utils/process_monitor.py +72 -172
  19. machineconfig/cluster/sessions_managers/wt_utils/remote_executor.py +27 -60
  20. machineconfig/cluster/sessions_managers/wt_utils/session_manager.py +58 -137
  21. machineconfig/cluster/sessions_managers/wt_utils/status_reporter.py +46 -74
  22. machineconfig/cluster/sessions_managers/zellij_local.py +91 -147
  23. machineconfig/cluster/sessions_managers/zellij_local_manager.py +165 -190
  24. machineconfig/cluster/sessions_managers/zellij_remote.py +51 -58
  25. machineconfig/cluster/sessions_managers/zellij_remote_manager.py +40 -46
  26. machineconfig/cluster/sessions_managers/zellij_utils/example_usage.py +19 -17
  27. machineconfig/cluster/sessions_managers/zellij_utils/layout_generator.py +30 -31
  28. machineconfig/cluster/sessions_managers/zellij_utils/process_monitor.py +64 -134
  29. machineconfig/cluster/sessions_managers/zellij_utils/remote_executor.py +7 -11
  30. machineconfig/cluster/sessions_managers/zellij_utils/session_manager.py +27 -55
  31. machineconfig/cluster/sessions_managers/zellij_utils/status_reporter.py +14 -13
  32. machineconfig/cluster/templates/cli_click.py +0 -1
  33. machineconfig/cluster/templates/cli_gooey.py +0 -2
  34. machineconfig/cluster/templates/cli_trogon.py +0 -1
  35. machineconfig/cluster/templates/run_cloud.py +0 -1
  36. machineconfig/cluster/templates/run_cluster.py +0 -1
  37. machineconfig/cluster/templates/run_remote.py +0 -1
  38. machineconfig/cluster/templates/utils.py +27 -11
  39. machineconfig/jobs/__pycache__/__init__.cpython-313.pyc +0 -0
  40. machineconfig/jobs/linux/msc/cli_agents.sh +16 -0
  41. machineconfig/jobs/python/check_installations.py +9 -9
  42. machineconfig/jobs/python/create_bootable_media.py +0 -2
  43. machineconfig/jobs/python/python_cargo_build_share.py +2 -2
  44. machineconfig/jobs/python/python_ve_symlink.py +9 -11
  45. machineconfig/jobs/python/tasks.py +0 -1
  46. machineconfig/jobs/python/vscode/api.py +5 -5
  47. machineconfig/jobs/python/vscode/link_ve.py +20 -21
  48. machineconfig/jobs/python/vscode/select_interpreter.py +28 -29
  49. machineconfig/jobs/python/vscode/sync_code.py +14 -18
  50. machineconfig/jobs/python_custom_installers/__pycache__/__init__.cpython-313.pyc +0 -0
  51. machineconfig/jobs/python_custom_installers/archive/ngrok.py +15 -15
  52. machineconfig/jobs/python_custom_installers/dev/aider.py +10 -18
  53. machineconfig/jobs/python_custom_installers/dev/alacritty.py +12 -21
  54. machineconfig/jobs/python_custom_installers/dev/brave.py +13 -22
  55. machineconfig/jobs/python_custom_installers/dev/bypass_paywall.py +13 -20
  56. machineconfig/jobs/python_custom_installers/dev/code.py +17 -24
  57. machineconfig/jobs/python_custom_installers/dev/cursor.py +10 -21
  58. machineconfig/jobs/python_custom_installers/dev/docker_desktop.py +12 -11
  59. machineconfig/jobs/python_custom_installers/dev/espanso.py +19 -23
  60. machineconfig/jobs/python_custom_installers/dev/goes.py +9 -16
  61. machineconfig/jobs/python_custom_installers/dev/lvim.py +13 -21
  62. machineconfig/jobs/python_custom_installers/dev/nerdfont.py +15 -22
  63. machineconfig/jobs/python_custom_installers/dev/redis.py +15 -23
  64. machineconfig/jobs/python_custom_installers/dev/wezterm.py +15 -22
  65. machineconfig/jobs/python_custom_installers/dev/winget.py +32 -50
  66. machineconfig/jobs/python_custom_installers/docker.py +15 -24
  67. machineconfig/jobs/python_custom_installers/gh.py +18 -26
  68. machineconfig/jobs/python_custom_installers/hx.py +33 -17
  69. machineconfig/jobs/python_custom_installers/warp-cli.py +15 -23
  70. machineconfig/jobs/python_generic_installers/__pycache__/__init__.cpython-313.pyc +0 -0
  71. machineconfig/jobs/python_generic_installers/config.json +412 -389
  72. machineconfig/jobs/python_linux_installers/__pycache__/__init__.cpython-313.pyc +0 -0
  73. machineconfig/jobs/python_windows_installers/dev/config.json +1 -1
  74. machineconfig/jobs/windows/archive/archive_pygraphviz.ps1 +1 -1
  75. machineconfig/jobs/windows/msc/cli_agents.bat +0 -0
  76. machineconfig/jobs/windows/msc/cli_agents.ps1 +0 -0
  77. machineconfig/jobs/windows/start_terminal.ps1 +1 -1
  78. machineconfig/logger.py +50 -0
  79. machineconfig/profile/create.py +50 -36
  80. machineconfig/profile/create_hardlinks.py +33 -26
  81. machineconfig/profile/shell.py +87 -60
  82. machineconfig/scripts/__pycache__/__init__.cpython-313.pyc +0 -0
  83. machineconfig/scripts/cloud/init.sh +2 -2
  84. machineconfig/scripts/linux/checkout_versions +1 -1
  85. machineconfig/scripts/linux/choose_wezterm_theme +1 -1
  86. machineconfig/scripts/linux/cloud_copy +1 -1
  87. machineconfig/scripts/linux/cloud_manager +1 -1
  88. machineconfig/scripts/linux/cloud_mount +1 -1
  89. machineconfig/scripts/linux/cloud_repo_sync +1 -1
  90. machineconfig/scripts/linux/cloud_sync +1 -1
  91. machineconfig/scripts/linux/croshell +1 -1
  92. machineconfig/scripts/linux/devops +3 -5
  93. machineconfig/scripts/linux/fire +2 -1
  94. machineconfig/scripts/linux/fire_agents +3 -3
  95. machineconfig/scripts/linux/ftpx +1 -1
  96. machineconfig/scripts/linux/gh_models +1 -1
  97. machineconfig/scripts/linux/kill_process +1 -1
  98. machineconfig/scripts/linux/mcinit +2 -2
  99. machineconfig/scripts/linux/repos +1 -1
  100. machineconfig/scripts/linux/scheduler +1 -1
  101. machineconfig/scripts/linux/start_slidev +1 -1
  102. machineconfig/scripts/linux/start_terminals +1 -1
  103. machineconfig/scripts/linux/url2md +1 -1
  104. machineconfig/scripts/linux/warp-cli.sh +122 -0
  105. machineconfig/scripts/linux/wifi_conn +1 -1
  106. machineconfig/scripts/python/__pycache__/__init__.cpython-313.pyc +0 -0
  107. machineconfig/scripts/python/__pycache__/croshell.cpython-313.pyc +0 -0
  108. machineconfig/scripts/python/__pycache__/devops.cpython-313.pyc +0 -0
  109. machineconfig/scripts/python/__pycache__/devops_devapps_install.cpython-313.pyc +0 -0
  110. machineconfig/scripts/python/__pycache__/devops_update_repos.cpython-313.pyc +0 -0
  111. machineconfig/scripts/python/__pycache__/fire_jobs.cpython-313.pyc +0 -0
  112. machineconfig/scripts/python/ai/__init__.py +0 -0
  113. machineconfig/scripts/python/ai/__pycache__/__init__.cpython-313.pyc +0 -0
  114. machineconfig/scripts/python/ai/__pycache__/generate_files.cpython-313.pyc +0 -0
  115. machineconfig/scripts/python/ai/__pycache__/mcinit.cpython-313.pyc +0 -0
  116. machineconfig/scripts/python/ai/chatmodes/Thinking-Beast-Mode.chatmode.md +337 -0
  117. machineconfig/scripts/python/ai/chatmodes/Ultimate-Transparent-Thinking-Beast-Mode.chatmode.md +644 -0
  118. machineconfig/scripts/python/ai/chatmodes/deepResearch.chatmode.md +81 -0
  119. machineconfig/scripts/python/ai/configs/.gemini/settings.json +81 -0
  120. machineconfig/scripts/python/ai/generate_files.py +84 -0
  121. machineconfig/scripts/python/ai/instructions/python/dev.instructions.md +45 -0
  122. machineconfig/scripts/python/ai/mcinit.py +107 -0
  123. machineconfig/scripts/python/ai/prompts/allLintersAndTypeCheckers.prompt.md +5 -0
  124. machineconfig/scripts/python/ai/prompts/research-report-skeleton.prompt.md +38 -0
  125. machineconfig/scripts/python/ai/scripts/lint_and_type_check.sh +52 -0
  126. machineconfig/scripts/python/archive/tmate_conn.py +5 -5
  127. machineconfig/scripts/python/archive/tmate_start.py +3 -3
  128. machineconfig/scripts/python/choose_wezterm_theme.py +2 -2
  129. machineconfig/scripts/python/cloud_copy.py +20 -19
  130. machineconfig/scripts/python/cloud_mount.py +10 -8
  131. machineconfig/scripts/python/cloud_repo_sync.py +15 -15
  132. machineconfig/scripts/python/cloud_sync.py +1 -1
  133. machineconfig/scripts/python/croshell.py +18 -16
  134. machineconfig/scripts/python/devops.py +6 -6
  135. machineconfig/scripts/python/devops_add_identity.py +9 -7
  136. machineconfig/scripts/python/devops_add_ssh_key.py +19 -19
  137. machineconfig/scripts/python/devops_backup_retrieve.py +14 -14
  138. machineconfig/scripts/python/devops_devapps_install.py +3 -3
  139. machineconfig/scripts/python/devops_update_repos.py +141 -53
  140. machineconfig/scripts/python/dotfile.py +3 -3
  141. machineconfig/scripts/python/fire_agents.py +202 -41
  142. machineconfig/scripts/python/fire_jobs.py +20 -21
  143. machineconfig/scripts/python/ftpx.py +4 -3
  144. machineconfig/scripts/python/gh_models.py +94 -94
  145. machineconfig/scripts/python/helpers/__pycache__/__init__.cpython-313.pyc +0 -0
  146. machineconfig/scripts/python/helpers/__pycache__/helpers4.cpython-313.pyc +0 -0
  147. machineconfig/scripts/python/helpers/cloud_helpers.py +3 -3
  148. machineconfig/scripts/python/helpers/helpers2.py +3 -3
  149. machineconfig/scripts/python/helpers/helpers4.py +8 -7
  150. machineconfig/scripts/python/helpers/helpers5.py +7 -7
  151. machineconfig/scripts/python/helpers/repo_sync_helpers.py +2 -2
  152. machineconfig/scripts/python/mount_nfs.py +4 -3
  153. machineconfig/scripts/python/mount_nw_drive.py +4 -4
  154. machineconfig/scripts/python/mount_ssh.py +4 -3
  155. machineconfig/scripts/python/repos.py +9 -9
  156. machineconfig/scripts/python/scheduler.py +1 -1
  157. machineconfig/scripts/python/start_slidev.py +9 -8
  158. machineconfig/scripts/python/start_terminals.py +1 -1
  159. machineconfig/scripts/python/viewer.py +40 -40
  160. machineconfig/scripts/python/wifi_conn.py +65 -66
  161. machineconfig/scripts/python/wsl_windows_transfer.py +2 -2
  162. machineconfig/scripts/windows/checkout_version.ps1 +1 -3
  163. machineconfig/scripts/windows/choose_wezterm_theme.ps1 +1 -3
  164. machineconfig/scripts/windows/cloud_copy.ps1 +2 -6
  165. machineconfig/scripts/windows/cloud_manager.ps1 +1 -1
  166. machineconfig/scripts/windows/cloud_repo_sync.ps1 +1 -2
  167. machineconfig/scripts/windows/cloud_sync.ps1 +2 -2
  168. machineconfig/scripts/windows/croshell.ps1 +2 -2
  169. machineconfig/scripts/windows/devops.ps1 +1 -4
  170. machineconfig/scripts/windows/dotfile.ps1 +1 -3
  171. machineconfig/scripts/windows/fire.ps1 +1 -1
  172. machineconfig/scripts/windows/ftpx.ps1 +2 -2
  173. machineconfig/scripts/windows/gpt.ps1 +1 -1
  174. machineconfig/scripts/windows/kill_process.ps1 +1 -2
  175. machineconfig/scripts/windows/mcinit.ps1 +2 -2
  176. machineconfig/scripts/windows/mount_nfs.ps1 +1 -1
  177. machineconfig/scripts/windows/mount_ssh.ps1 +1 -1
  178. machineconfig/scripts/windows/pomodoro.ps1 +1 -1
  179. machineconfig/scripts/windows/py2exe.ps1 +1 -3
  180. machineconfig/scripts/windows/repos.ps1 +1 -1
  181. machineconfig/scripts/windows/scheduler.ps1 +1 -1
  182. machineconfig/scripts/windows/snapshot.ps1 +2 -2
  183. machineconfig/scripts/windows/start_slidev.ps1 +1 -1
  184. machineconfig/scripts/windows/start_terminals.ps1 +1 -1
  185. machineconfig/scripts/windows/wifi_conn.ps1 +1 -1
  186. machineconfig/scripts/windows/wsl_windows_transfer.ps1 +1 -3
  187. machineconfig/settings/lf/linux/lfrc +1 -1
  188. machineconfig/settings/linters/.ruff.toml +2 -2
  189. machineconfig/settings/linters/.ruff_cache/.gitignore +2 -0
  190. machineconfig/settings/linters/.ruff_cache/CACHEDIR.TAG +1 -0
  191. machineconfig/settings/lvim/windows/archive/config_additional.lua +1 -1
  192. machineconfig/settings/shells/ipy/profiles/default/startup/playext.py +71 -71
  193. machineconfig/settings/shells/wt/settings.json +8 -8
  194. machineconfig/settings/svim/linux/init.toml +1 -1
  195. machineconfig/settings/svim/windows/init.toml +1 -1
  196. machineconfig/setup_linux/web_shortcuts/croshell.sh +0 -54
  197. machineconfig/setup_linux/web_shortcuts/interactive.sh +6 -6
  198. machineconfig/setup_linux/web_shortcuts/tmp.sh +2 -0
  199. machineconfig/setup_windows/web_shortcuts/all.ps1 +2 -2
  200. machineconfig/setup_windows/web_shortcuts/ascii_art.ps1 +1 -1
  201. machineconfig/setup_windows/web_shortcuts/croshell.ps1 +1 -1
  202. machineconfig/setup_windows/web_shortcuts/interactive.ps1 +5 -5
  203. machineconfig/setup_windows/wt_and_pwsh/install_fonts.ps1 +51 -15
  204. machineconfig/setup_windows/wt_and_pwsh/set_pwsh_theme.py +75 -18
  205. machineconfig/setup_windows/wt_and_pwsh/set_wt_settings.py +52 -42
  206. machineconfig/utils/ai/browser_user_wrapper.py +5 -5
  207. machineconfig/utils/ai/generate_file_checklist.py +19 -22
  208. machineconfig/utils/ai/url2md.py +5 -3
  209. machineconfig/utils/cloud/onedrive/setup_oauth.py +5 -4
  210. machineconfig/utils/cloud/onedrive/transaction.py +192 -227
  211. machineconfig/utils/code.py +71 -43
  212. machineconfig/utils/installer.py +77 -85
  213. machineconfig/utils/installer_utils/installer_abc.py +29 -17
  214. machineconfig/utils/installer_utils/installer_class.py +188 -83
  215. machineconfig/utils/io_save.py +3 -15
  216. machineconfig/utils/links.py +22 -11
  217. machineconfig/utils/notifications.py +197 -0
  218. machineconfig/utils/options.py +38 -25
  219. machineconfig/utils/path.py +18 -6
  220. machineconfig/utils/path_reduced.py +637 -316
  221. machineconfig/utils/procs.py +69 -63
  222. machineconfig/utils/scheduling.py +11 -13
  223. machineconfig/utils/ssh.py +351 -0
  224. machineconfig/utils/terminal.py +225 -0
  225. machineconfig/utils/utils.py +13 -12
  226. machineconfig/utils/utils2.py +43 -10
  227. machineconfig/utils/utils5.py +242 -46
  228. machineconfig/utils/ve.py +11 -6
  229. {machineconfig-1.97.dist-info → machineconfig-2.1.dist-info}/METADATA +15 -9
  230. {machineconfig-1.97.dist-info → machineconfig-2.1.dist-info}/RECORD +232 -235
  231. machineconfig/cluster/self_ssh.py +0 -57
  232. machineconfig/jobs/__pycache__/__init__.cpython-311.pyc +0 -0
  233. machineconfig/jobs/python/__pycache__/__init__.cpython-311.pyc +0 -0
  234. machineconfig/jobs/python/archive/python_tools.txt +0 -12
  235. machineconfig/jobs/python/vscode/__pycache__/select_interpreter.cpython-311.pyc +0 -0
  236. machineconfig/jobs/python_custom_installers/__pycache__/__init__.cpython-311.pyc +0 -0
  237. machineconfig/jobs/python_generic_installers/__pycache__/__init__.cpython-311.pyc +0 -0
  238. machineconfig/jobs/python_generic_installers/update.py +0 -3
  239. machineconfig/jobs/python_linux_installers/__pycache__/__init__.cpython-311.pyc +0 -0
  240. machineconfig/profile/__pycache__/__init__.cpython-311.pyc +0 -0
  241. machineconfig/profile/__pycache__/create.cpython-311.pyc +0 -0
  242. machineconfig/profile/__pycache__/shell.cpython-311.pyc +0 -0
  243. machineconfig/scripts/__pycache__/__init__.cpython-311.pyc +0 -0
  244. machineconfig/scripts/linux/activate_ve +0 -87
  245. machineconfig/scripts/python/__pycache__/__init__.cpython-311.pyc +0 -0
  246. machineconfig/scripts/python/__pycache__/cloud_copy.cpython-311.pyc +0 -0
  247. machineconfig/scripts/python/__pycache__/cloud_mount.cpython-311.pyc +0 -0
  248. machineconfig/scripts/python/__pycache__/cloud_sync.cpython-311.pyc +0 -0
  249. machineconfig/scripts/python/__pycache__/croshell.cpython-311.pyc +0 -0
  250. machineconfig/scripts/python/__pycache__/devops.cpython-311.pyc +0 -0
  251. machineconfig/scripts/python/__pycache__/devops_backup_retrieve.cpython-311.pyc +0 -0
  252. machineconfig/scripts/python/__pycache__/devops_devapps_install.cpython-311.pyc +0 -0
  253. machineconfig/scripts/python/__pycache__/devops_update_repos.cpython-311.pyc +0 -0
  254. machineconfig/scripts/python/__pycache__/fire_agents.cpython-311.pyc +0 -0
  255. machineconfig/scripts/python/__pycache__/fire_jobs.cpython-311.pyc +0 -0
  256. machineconfig/scripts/python/__pycache__/get_zellij_cmd.cpython-311.pyc +0 -0
  257. machineconfig/scripts/python/__pycache__/repos.cpython-311.pyc +0 -0
  258. machineconfig/scripts/python/ai/__pycache__/init.cpython-311.pyc +0 -0
  259. machineconfig/scripts/python/ai/init.py +0 -56
  260. machineconfig/scripts/python/ai/rules/python/dev.md +0 -31
  261. machineconfig/scripts/python/helpers/__pycache__/__init__.cpython-311.pyc +0 -0
  262. machineconfig/scripts/python/helpers/__pycache__/cloud_helpers.cpython-311.pyc +0 -0
  263. machineconfig/scripts/python/helpers/__pycache__/helpers2.cpython-311.pyc +0 -0
  264. machineconfig/scripts/python/helpers/__pycache__/helpers4.cpython-311.pyc +0 -0
  265. machineconfig/scripts/python/helpers/__pycache__/repo_sync_helpers.cpython-311.pyc +0 -0
  266. machineconfig/scripts/windows/activate_ve.ps1 +0 -54
  267. {machineconfig-1.97.dist-info → machineconfig-2.1.dist-info}/WHEEL +0 -0
  268. {machineconfig-1.97.dist-info → machineconfig-2.1.dist-info}/top_level.txt +0 -0
@@ -1,3 +1,3 @@
1
1
  {
2
-
2
+
3
3
  }
@@ -5,7 +5,7 @@
5
5
  # winget install Microsoft.VC++2015-2022Redist-x86
6
6
 
7
7
 
8
- ~/scritps/activate_ve.ps1
8
+ . "$env:USERPROFILE\code\machineconfig\.venv\Scripts\Activate.ps1"
9
9
  Set-Location C:
10
10
  python -m pip install --global-option=build_ext --global-option="-IC:\Program Files\Graphviz\include" --global-option="-LC:\Program Files\Graphviz\lib" pygraphviz
11
11
  # not including the options as above (from https://pygraphviz.github.io/documentation/stable/install.html)
File without changes
File without changes
@@ -1,5 +1,5 @@
1
1
 
2
- wt --profile croshell -d . --title "MyTerminal" --tabColor "red"`; split-pane --vertical --size 0.55 pwsh machineconfig-workingdirectory ~/code/crocodile -Command "pwd" `; split-pane -V PowerShell -NoExit -Command "cd code/machineconfig" `; split-pane -H wsl.exe cmatrix`; split-pane -V wsl.exe sl
2
+ wt --profile croshell -d . --title "MyTerminal" --tabColor "red"`; split-pane --vertical --size 0.55 pwsh machineconfig-workingdirectory ~/code/machineconfig -Command "pwd" `; split-pane -V PowerShell -NoExit -Command "cd code/machineconfig" `; split-pane -H wsl.exe cmatrix`; split-pane -V wsl.exe sl
3
3
  # wt -p "Command Prompt" `; split-pane -p "Windows PowerShell" `; split-pane -H wsl.exe
4
4
 
5
5
  # See more settings here: https://docs.microsoft.com/en-us/windows/terminal/
@@ -0,0 +1,50 @@
1
+ from __future__ import annotations
2
+
3
+ import logging
4
+ import os
5
+ import sys
6
+ from typing import Optional
7
+
8
+
9
+ def _configure_root_logger() -> logging.Logger:
10
+ """Create and configure the root logger for the machineconfig package.
11
+
12
+ The logger writes to stdout, honors MC_LOG_LEVEL env var, and avoids
13
+ duplicate handlers on repeated imports.
14
+ """
15
+ root = logging.getLogger("machineconfig")
16
+ if root.handlers:
17
+ return root
18
+
19
+ level_name = os.getenv("MC_LOG_LEVEL", "INFO").upper()
20
+ level = getattr(logging, level_name, logging.INFO)
21
+ root.setLevel(level)
22
+
23
+ handler = logging.StreamHandler(stream=sys.stdout)
24
+ fmt = "%(asctime)s | %(levelname)s | %(name)s | %(message)s"
25
+ datefmt = "%H:%M:%S"
26
+ handler.setFormatter(logging.Formatter(fmt=fmt, datefmt=datefmt))
27
+ root.addHandler(handler)
28
+ root.propagate = False
29
+ return root
30
+
31
+
32
+ _ROOT_LOGGER = _configure_root_logger()
33
+
34
+
35
+ def get_logger(name: Optional[str] = None) -> logging.Logger:
36
+ """Return a child logger of the package root.
37
+
38
+ Inputs:
39
+ - name: Optional dotted logger name; when None, returns the package root.
40
+
41
+ Returns:
42
+ - logging.Logger configured under the 'machineconfig' hierarchy.
43
+ """
44
+ if name is None:
45
+ return _ROOT_LOGGER
46
+ return _ROOT_LOGGER.getChild(name)
47
+
48
+
49
+ # Convenience alias for simple imports: `from machineconfig.logger import logger`
50
+ logger: logging.Logger = get_logger()
@@ -4,13 +4,15 @@ This script Takes away all config files from the computer, place them in one dir
4
4
 
5
5
  """
6
6
 
7
-
8
- from crocodile.meta import Terminal
9
- from machineconfig.utils.path_reduced import P as PathExtended
7
+ from machineconfig.utils.path_reduced import PathExtended as PathExtended
10
8
  from machineconfig.utils.utils import symlink_func, symlink_copy, LIBRARY_ROOT, REPO_ROOT, display_options
9
+ from machineconfig.utils.utils2 import read_toml
11
10
  from machineconfig.profile.shell import create_default_shell_profile
11
+
12
12
  # import os
13
13
  import platform
14
+ import os
15
+ import ctypes
14
16
  import subprocess
15
17
  from rich.console import Console
16
18
  from typing import Optional, Any, TypedDict
@@ -29,10 +31,7 @@ class SymlinkMapper(TypedDict):
29
31
 
30
32
 
31
33
  def main_symlinks(choice: Optional[str] = None):
32
- symlink_mapper = LIBRARY_ROOT.joinpath("profile/mapper.toml").readit()
33
- # symlink_mapper['wsl_windows']['home']["to_this"] = symlink_mapper['wsl_windows']['home']["to_this"].replace("username", UserName)
34
- # symlink_mapper['wsl_linux']['home']["to_this"] = symlink_mapper['wsl_linux']['home']["to_this"].replace("username", UserName)
35
-
34
+ symlink_mapper: dict[str, dict[str, SymlinkMapper]] = read_toml(LIBRARY_ROOT.joinpath("profile/mapper.toml"))
36
35
  overwrite = True
37
36
  exclude: list[str] = [] # "wsl_linux", "wsl_windows"
38
37
 
@@ -41,56 +40,71 @@ def main_symlinks(choice: Optional[str] = None):
41
40
  for program_key in program_keys_raw:
42
41
  if program_key in exclude or OTHER_SYSTEM in program_key:
43
42
  continue
44
- else: program_keys.append(program_key)
43
+ else:
44
+ program_keys.append(program_key)
45
45
 
46
46
  program_keys.sort()
47
47
  if choice is None:
48
48
  choice_selected = display_options(msg="Which symlink to create?", options=program_keys + ["all", "none(EXIT)"], default="none(EXIT)", fzf=True, multi=True)
49
49
  assert isinstance(choice_selected, list)
50
- if len(choice_selected) == 1 and choice_selected[0] == "none(EXIT)": return # terminate function.
51
- elif len(choice_selected) == 1 and choice_selected[0] == "all": choice_selected = "all" # i.e. program_keys = program_keys
50
+ if len(choice_selected) == 1 and choice_selected[0] == "none(EXIT)":
51
+ return # terminate function.
52
+ elif len(choice_selected) == 1 and choice_selected[0] == "all":
53
+ choice_selected = "all" # i.e. program_keys = program_keys
52
54
  # overwrite = display_options(msg="Overwrite existing source file?", options=["yes", "no"], default="yes") == "yes"
53
55
  from rich.prompt import Confirm
56
+
54
57
  overwrite = Confirm.ask("Overwrite existing source file?", default=True)
55
- else: choice_selected = choice
58
+ else:
59
+ choice_selected = choice
56
60
 
57
61
  if isinstance(choice_selected, str):
58
- if str(choice_selected) == "all" and system == "Windows" and not Terminal.is_user_admin():
59
- print(f"""
60
- {'*' * 80}
62
+ if str(choice_selected) == "all" and system == "Windows":
63
+ if os.name == "nt":
64
+ try:
65
+ is_admin = ctypes.windll.shell32.IsUserAnAdmin()
66
+ except Exception:
67
+ is_admin = False
68
+ else:
69
+ is_admin = False
70
+ if not is_admin:
71
+ print(f"""
72
+ {"*" * 80}
61
73
  āš ļø WARNING: Administrator privileges required
62
- {'*' * 80}
74
+ {"*" * 80}
63
75
  """)
64
- raise RuntimeError("Run terminal as admin and try again, otherwise, there will be too many popups for admin requests and no chance to terminate the program.")
76
+ raise RuntimeError("Run terminal as admin and try again, otherwise, there will be too many popups for admin requests and no chance to terminate the program.")
65
77
  elif choice_selected == "all":
66
78
  print(f"""
67
- šŸ” Processing all program keys:
79
+ šŸ” Processing all program keys:
68
80
  {program_keys}
69
81
  """)
70
82
  pass # i.e. program_keys = program_keys
71
- else: program_keys = [choice_selected]
72
- else: program_keys = choice_selected
83
+ else:
84
+ program_keys = [choice_selected]
85
+ else:
86
+ program_keys = choice_selected
73
87
 
74
88
  for program_key in program_keys:
75
89
  print(f"\nšŸ”„ Processing {program_key} symlinks...")
76
90
  for file_key, file_map in symlink_mapper[program_key].items():
77
- this = PathExtended(file_map['this'])
78
- to_this = PathExtended(file_map['to_this'].replace("REPO_ROOT", REPO_ROOT.as_posix()).replace("LIBRARY_ROOT", LIBRARY_ROOT.as_posix()))
91
+ this = PathExtended(file_map["this"])
92
+ to_this = PathExtended(file_map["to_this"].replace("REPO_ROOT", REPO_ROOT.as_posix()).replace("LIBRARY_ROOT", LIBRARY_ROOT.as_posix()))
79
93
  if "contents" in file_map:
80
94
  try:
81
95
  for a_target in to_this.expanduser().search("*"):
82
96
  symlink_func(this=this.joinpath(a_target.name), to_this=a_target, prioritize_to_this=overwrite)
83
- except Exception as ex:
97
+ except Exception as ex:
84
98
  print(f"āŒ Config error: {program_key} | {file_key} | missing keys 'this ==> to_this'. {ex}")
85
99
  if "copy" in file_map:
86
100
  try:
87
101
  symlink_copy(this=this, to_this=to_this, prioritize_to_this=overwrite)
88
- except Exception as ex:
102
+ except Exception as ex:
89
103
  print(f"āŒ Config error: {program_key} | {file_key} | {ex}")
90
104
  else:
91
- try:
105
+ try:
92
106
  symlink_func(this=this, to_this=to_this, prioritize_to_this=overwrite)
93
- except Exception as ex:
107
+ except Exception as ex:
94
108
  print(f"āŒ Config error: {program_key} | {file_key} | missing keys 'this ==> to_this'. {ex}")
95
109
 
96
110
  if program_key == "ssh" and system == "Linux": # permissions of ~/dotfiles/.ssh should be adjusted
@@ -106,22 +120,22 @@ def main_symlinks(choice: Optional[str] = None):
106
120
 
107
121
  if system == "Linux":
108
122
  print("\nšŸ“œ Setting executable permissions for scripts...")
109
- Terminal().run(f'chmod +x {LIBRARY_ROOT.joinpath(f"scripts/{system.lower()}")} -R')
123
+ subprocess.run(f"chmod +x {LIBRARY_ROOT.joinpath(f'scripts/{system.lower()}')} -R", shell=True, capture_output=True, text=True)
110
124
  print("āœ… Script permissions updated")
111
-
125
+
112
126
  if len(ERROR_LIST) > 0:
113
127
  print(f"""
114
- {'*' * 80}
128
+ {"*" * 80}
115
129
  ā— ERRORS ENCOUNTERED DURING PROCESSING
116
- {'*' * 80}
130
+ {"*" * 80}
117
131
  {ERROR_LIST}
118
- {'*' * 80}
132
+ {"*" * 80}
119
133
  """)
120
134
  else:
121
135
  print(f"""
122
- {'*' * 80}
136
+ {"*" * 80}
123
137
  āœ… All symlinks created successfully!
124
- {'*' * 80}
138
+ {"*" * 80}
125
139
  """)
126
140
 
127
141
 
@@ -134,13 +148,13 @@ def main(choice: Optional[str] = None):
134
148
  print("\n")
135
149
  console.rule("[bold green]🐚 CREATING SHELL PROFILE 🐚")
136
150
  create_default_shell_profile()
137
-
151
+
138
152
  print(f"""
139
- {'=' * 80}
153
+ {"=" * 80}
140
154
  ✨ Configuration setup complete! ✨
141
- {'=' * 80}
155
+ {"=" * 80}
142
156
  """)
143
157
 
144
158
 
145
- if __name__ == '__main__':
159
+ if __name__ == "__main__":
146
160
  pass
@@ -4,12 +4,12 @@ This script Takes away all config files from the computer, place them in one dir
4
4
 
5
5
  """
6
6
 
7
-
8
7
  import platform
9
- from crocodile.meta import Terminal
10
- from machineconfig.utils.path_reduced import P as PathExtended
8
+ from machineconfig.utils.path_reduced import PathExtended as PathExtended
11
9
  from machineconfig.utils.utils import symlink_copy as symlink_func, LIBRARY_ROOT, REPO_ROOT, display_options
10
+ from machineconfig.utils.utils2 import read_toml
12
11
  from machineconfig.profile.shell import create_default_shell_profile
12
+
13
13
  # import os
14
14
  import subprocess
15
15
  from rich.console import Console
@@ -23,7 +23,7 @@ SYSTEM = system.lower()
23
23
 
24
24
 
25
25
  def main_symlinks(choice: Optional[str] = None):
26
- symlink_mapper = LIBRARY_ROOT.joinpath("profile/mapper.toml").readit()
26
+ symlink_mapper = read_toml(LIBRARY_ROOT.joinpath("profile/mapper.toml"))
27
27
  # symlink_mapper['wsl_windows']['home']["to_this"] = symlink_mapper['wsl_windows']['home']["to_this"].replace("username", UserName)
28
28
  # symlink_mapper['wsl_linux']['home']["to_this"] = symlink_mapper['wsl_linux']['home']["to_this"].replace("username", UserName)
29
29
 
@@ -36,46 +36,53 @@ def main_symlinks(choice: Optional[str] = None):
36
36
  if program_key in exclude or OTHER_SYSTEM in program_key:
37
37
  # print(f"🚫 Skipping {program_key} for {system}")
38
38
  continue
39
- else: program_keys.append(program_key)
39
+ else:
40
+ program_keys.append(program_key)
40
41
 
41
42
  program_keys.sort()
42
43
  if choice is None:
43
44
  choice_selected = display_options(msg="Which symlink to create?", options=program_keys + ["all", "none(EXIT)"], default="none(EXIT)", fzf=True, multi=True)
44
45
  assert isinstance(choice_selected, list)
45
- if len(choice_selected) == 1 and choice_selected[0] == "none(EXIT)": return # terminate function.
46
- elif len(choice_selected) == 1 and choice_selected[0] == "all": choice_selected = "all" # i.e. program_keys = program_keys
46
+ if len(choice_selected) == 1 and choice_selected[0] == "none(EXIT)":
47
+ return # terminate function.
48
+ elif len(choice_selected) == 1 and choice_selected[0] == "all":
49
+ choice_selected = "all" # i.e. program_keys = program_keys
47
50
  # overwrite = display_options(msg="Overwrite existing source file?", options=["yes", "no"], default="yes") == "yes"
48
51
  from rich.prompt import Confirm
52
+
49
53
  overwrite = Confirm.ask("Overwrite existing source file?", default=True)
50
54
 
51
- else: choice_selected = choice
55
+ else:
56
+ choice_selected = choice
52
57
 
53
58
  if isinstance(choice_selected, str):
54
59
  if choice_selected == "all":
55
60
  print(f"""
56
- šŸ” Processing all program keys:
61
+ šŸ” Processing all program keys:
57
62
  {program_keys}
58
63
  """)
59
64
  pass # i.e. program_keys = program_keys
60
- else: program_keys = [choice_selected]
61
- else: program_keys = choice_selected
65
+ else:
66
+ program_keys = [choice_selected]
67
+ else:
68
+ program_keys = choice_selected
62
69
 
63
70
  for program_key in program_keys:
64
71
  print(f"\nšŸ”„ Creating hardlinks for {program_key}...")
65
72
  for file_key, file_map in symlink_mapper[program_key].items():
66
- this = PathExtended(file_map['this'])
67
- to_this = PathExtended(file_map['to_this'].replace("REPO_ROOT", REPO_ROOT.as_posix()).replace("LIBRARY_ROOT", LIBRARY_ROOT.as_posix()))
73
+ this = PathExtended(file_map["this"])
74
+ to_this = PathExtended(file_map["to_this"].replace("REPO_ROOT", REPO_ROOT.as_posix()).replace("LIBRARY_ROOT", LIBRARY_ROOT.as_posix()))
68
75
  if "contents" in file_map:
69
76
  try:
70
77
  for a_target in to_this.expanduser().search("*"):
71
78
  symlink_func(this=this.joinpath(a_target.name), to_this=a_target, prioritize_to_this=overwrite)
72
- except Exception as ex:
79
+ except Exception as ex:
73
80
  print(f"āŒ Config error: {program_key} | {file_key} | missing keys 'this ==> to_this'. {ex}")
74
81
  else:
75
- try:
82
+ try:
76
83
  symlink_func(this=this, to_this=to_this, prioritize_to_this=overwrite)
77
84
  print(f" āœ… Created hardlink from {this} to {to_this}")
78
- except Exception as ex:
85
+ except Exception as ex:
79
86
  print(f"āŒ Config error: {program_key} | {file_key} | missing keys 'this ==> to_this'. {ex}")
80
87
 
81
88
  if program_key == "ssh" and system == "Linux": # permissions of ~/dotfiles/.ssh should be adjusted
@@ -91,22 +98,22 @@ def main_symlinks(choice: Optional[str] = None):
91
98
 
92
99
  if system == "Linux":
93
100
  print("\nšŸ“œ Setting executable permissions for scripts...")
94
- Terminal().run(f'chmod +x {LIBRARY_ROOT.joinpath(f"scripts/{system.lower()}")} -R')
101
+ subprocess.run(f"chmod +x {LIBRARY_ROOT.joinpath(f'scripts/{system.lower()}')} -R", shell=True, capture_output=True, text=True)
95
102
  print("āœ… Script permissions updated")
96
103
 
97
104
  if len(ERROR_LIST) > 0:
98
105
  print(f"""
99
- {'=' * 80}
106
+ {"=" * 80}
100
107
  ā— ERRORS ENCOUNTERED DURING PROCESSING
101
- {'=' * 80}
108
+ {"=" * 80}
102
109
  {ERROR_LIST}
103
- {'=' * 80}
110
+ {"=" * 80}
104
111
  """)
105
112
  else:
106
113
  print(f"""
107
- {'=' * 80}
114
+ {"=" * 80}
108
115
  āœ… All hardlinks created successfully!
109
- {'=' * 80}
116
+ {"=" * 80}
110
117
  """)
111
118
 
112
119
 
@@ -119,13 +126,13 @@ def main(choice: Optional[str] = None):
119
126
  print("\n")
120
127
  console.rule("[bold green]🐚 CREATING SHELL PROFILE 🐚")
121
128
  create_default_shell_profile()
122
-
129
+
123
130
  print(f"""
124
- {'=' * 80}
131
+ {"=" * 80}
125
132
  ✨ Configuration setup complete! ✨
126
- {'=' * 80}
133
+ {"=" * 80}
127
134
  """)
128
135
 
129
136
 
130
- if __name__ == '__main__':
137
+ if __name__ == "__main__":
131
138
  pass
@@ -1,9 +1,8 @@
1
- """shell
2
- """
1
+ """shell"""
3
2
 
4
3
  from machineconfig.utils.utils2 import randstr
5
- from machineconfig.utils.path_reduced import P as PathExtended, modify_text
6
- from crocodile.meta import Terminal
4
+ from machineconfig.utils.path_reduced import PathExtended as PathExtended, modify_text
5
+ from machineconfig.utils.terminal import Terminal
7
6
  from machineconfig.utils.utils import LIBRARY_ROOT, REPO_ROOT, display_options
8
7
  import platform
9
8
  import os
@@ -24,13 +23,15 @@ BOX_WIDTH = 100 # Define BOX_WIDTH or get it from a config
24
23
  # for windows it won't change the profile, if the profile was modified already e.g. due to syncing
25
24
 
26
25
 
27
- def create_default_shell_profile():
26
+ def create_default_shell_profile() -> None:
28
27
  profile_path = get_shell_profile_path()
29
- profile = profile_path.read_text()
30
- if system == "Windows": source = f". {str(LIBRARY_ROOT.joinpath('settings/shells/pwsh/init.ps1').collapseuser()).replace('~', '$HOME')}"
31
- else: source = f"source {str(LIBRARY_ROOT.joinpath('settings/shells/bash/init.sh').collapseuser()).replace('~', '$HOME')}"
28
+ profile = profile_path.read_text(encoding="utf-8")
29
+ if system == "Windows":
30
+ source = f""". {str(LIBRARY_ROOT.joinpath("settings/shells/pwsh/init.ps1").collapseuser()).replace("~", "$HOME")}"""
31
+ else:
32
+ source = f"""source {str(LIBRARY_ROOT.joinpath("settings/shells/bash/init.sh").collapseuser()).replace("~", "$HOME")}"""
32
33
 
33
- if source in profile:
34
+ if source in profile:
34
35
  console.print(Panel("šŸ”„ PROFILE | Skipping init script sourcing - already present in profile", title="[bold blue]Profile[/bold blue]", border_style="blue"))
35
36
  else:
36
37
  console.print(Panel("šŸ“ PROFILE | Adding init script sourcing to profile", title="[bold blue]Profile[/bold blue]", border_style="blue"))
@@ -38,28 +39,31 @@ def create_default_shell_profile():
38
39
  if system == "Linux":
39
40
  res = Terminal().run("cat /proc/version").op
40
41
  if "microsoft" in res.lower() or "wsl" in res.lower():
41
- profile += "\ncd ~" # this is to make sure that the current dir is not in the windows file system, which is terribly slow and its a bad idea to be there anyway.
42
+ profile += "\ncd ~"
42
43
  console.print("šŸ“Œ WSL detected - adding 'cd ~' to profile to avoid Windows filesystem")
43
44
  profile_path.parent.mkdir(parents=True, exist_ok=True)
44
- profile_path.write_text(profile)
45
+ profile_path.write_text(profile, encoding="utf-8")
45
46
  console.print(Panel("āœ… Profile updated successfully", title="[bold blue]Profile[/bold blue]", border_style="blue"))
46
47
 
47
48
 
48
- def get_shell_profile_path():
49
+ def get_shell_profile_path() -> PathExtended:
49
50
  if system == "Windows":
50
51
  obj = Terminal().run("$PROFILE", shell="pwsh")
51
52
  res = obj.op2path()
52
- if isinstance(res, PathExtended): profile_path = res
53
+ if isinstance(res, PathExtended):
54
+ profile_path = res
53
55
  else:
54
56
  obj.print(capture=False)
55
- raise ValueError(f"Could not get profile path for Windows. Got {res}")
56
- elif system == "Linux": profile_path = PathExtended("~/.bashrc").expanduser()
57
- else: raise ValueError(f"Not implemented for this system {system}")
58
- console.print(Panel(f"🐚 SHELL PROFILE | Working with path: `{profile_path}`", title="[bold blue]Shell Profile[/bold blue]", border_style="blue"))
57
+ raise ValueError(f"""Could not get profile path for Windows. Got {res}""")
58
+ elif system == "Linux":
59
+ profile_path = PathExtended("~/.bashrc").expanduser()
60
+ else:
61
+ raise ValueError(f"""Not implemented for this system {system}""")
62
+ console.print(Panel(f"""🐚 SHELL PROFILE | Working with path: `{profile_path}`""", title="[bold blue]Shell Profile[/bold blue]", border_style="blue"))
59
63
  return profile_path
60
64
 
61
65
 
62
- def append_temporarily(dirs: list[str], kind: Literal['append', 'prefix', 'replace'] = "append"):
66
+ def append_temporarily(dirs: list[str], kind: Literal["append", "prefix", "replace"]) -> str:
63
67
  dirs_ = []
64
68
  for path in dirs:
65
69
  path_rel = PathExtended(path).collapseuser(strict=False)
@@ -68,22 +72,33 @@ def append_temporarily(dirs: list[str], kind: Literal['append', 'prefix', 'repla
68
72
  else:
69
73
  dirs_.append(path_rel.as_posix() if system == "Linux" else str(path_rel))
70
74
  dirs = dirs_
71
- if len(dirs) == 0: return ""
75
+ if len(dirs) == 0:
76
+ return ""
72
77
 
73
78
  if system == "Windows":
74
79
  """Source: https://docs.microsoft.com/en-us/powershell/module/microsoft.powershell.core/about/about_environment_variables?view=powershell-7.2"""
75
- if kind == "append": command = fr'$env:Path += ";{sep.join(dirs)}"' # Append to the Path variable in the current window:
76
- elif kind == "prefix": command = fr'$env:Path = "{sep.join(dirs)};" + $env:Path' # Prefix the Path variable in the current window:
77
- elif kind == "replace": command = fr'$env:Path = "{sep.join(dirs)}"' # Replace the Path variable in the current window (use with caution!):
78
- else: raise KeyError
80
+ if kind == "append":
81
+ command = rf'$env:Path += ";{sep.join(dirs)}"' # Append to the Path variable in the current window:
82
+ elif kind == "prefix":
83
+ command = rf'$env:Path = "{sep.join(dirs)};" + $env:Path' # Prefix the Path variable in the current window:
84
+ elif kind == "replace":
85
+ command = rf'$env:Path = "{sep.join(dirs)}"' # Replace the Path variable in the current window (use with caution!):
86
+ else:
87
+ raise KeyError
79
88
  return command # if run is False else tm.run(command, shell="powershell")
80
- elif system in ["Linux", "Darwin"]: result = f'export PATH="{sep.join(dirs)}:$PATH"'
81
- else: raise ValueError
89
+ elif system in ["Linux", "Darwin"]:
90
+ result = f'export PATH="{sep.join(dirs)}:$PATH"'
91
+ else:
92
+ raise ValueError
82
93
  return result
83
94
 
84
- def main_env_path(choice: Optional[str] = None, profile_path: Optional[str] = None):
85
- env_path = LIBRARY_ROOT.joinpath("profile/env_path.toml").readit()
86
- dirs = env_path[f'path_{system.lower()}']['extension']
95
+
96
+ def main_env_path(choice: Optional[str], profile_path: Optional[str]) -> None:
97
+ from machineconfig.utils.utils2 import read_toml
98
+
99
+ env_path = read_toml(LIBRARY_ROOT.joinpath("profile/env_path.toml"))
100
+ # env_path = LIBRARY_ROOT.joinpath("profile/env_path.toml").readit()
101
+ dirs = env_path[f"path_{system.lower()}"]["extension"]
87
102
 
88
103
  console.print(Panel("šŸ” ENVIRONMENT | Current PATH variables:", title="[bold blue]Environment[/bold blue]", border_style="blue"))
89
104
 
@@ -91,85 +106,97 @@ def main_env_path(choice: Optional[str] = None, profile_path: Optional[str] = No
91
106
  tmp = display_options(msg="Which directory to add?", options=dirs + ["all", "none(EXIT)"], default="none(EXIT)")
92
107
  assert isinstance(tmp, str), f"Choice must be a string or a list of strings, not {type(choice)}"
93
108
  choice = tmp
94
- if str(choice) != "all": dirs = [choice]
95
- if choice == "none(EXIT)": return
109
+ if str(choice) != "all":
110
+ dirs = [choice]
111
+ if choice == "none(EXIT)":
112
+ return
96
113
 
97
114
  console.print(f"\nšŸ“Œ Adding directories to PATH: {dirs}")
98
- addition = append_temporarily(dirs=dirs)
115
+ addition = append_temporarily(dirs=dirs, kind="append")
99
116
  profile_path_obj = PathExtended(profile_path) if isinstance(profile_path, str) else get_shell_profile_path()
100
117
  profile_path_obj.copy(name=profile_path_obj.name + ".orig_" + randstr())
101
118
  console.print(f"šŸ’¾ Created backup of profile: {profile_path_obj.name}.orig_*")
102
119
  # Inline deprecated P.modify_text: if file missing, seed with search text before modification
103
- current = profile_path_obj.read_text() if profile_path_obj.exists() else addition
120
+ current = profile_path_obj.read_text(encoding="utf-8") if profile_path_obj.exists() else addition
104
121
  updated = modify_text(current, addition, addition, replace_line=False, notfound_append=True)
105
- profile_path_obj.write_text(updated)
122
+ profile_path_obj.write_text(updated, encoding="utf-8")
106
123
  console.print(Panel("āœ… PATH variables added to profile successfully", title="[bold blue]Environment[/bold blue]", border_style="blue"))
107
124
 
108
125
 
109
- def main_add_sources_to_shell_profile(profile_path: Optional[str] = None, choice: Optional[str] = None):
110
- sources: list[str] = LIBRARY_ROOT.joinpath("profile/sources.toml").readit()[system.lower()]['files']
126
+ def main_add_sources_to_shell_profile(profile_path: Optional[str], choice: Optional[str]) -> None:
127
+ # sources: list[str] = LIBRARY_ROOT.joinpath("profile/sources.toml").readit()[system.lower()]['files']
128
+ from machineconfig.utils.utils2 import read_toml
129
+
130
+ sources: list[str] = read_toml(LIBRARY_ROOT.joinpath("profile/sources.toml"))[system.lower()]["files"]
111
131
 
112
132
  console.print(Panel("šŸ”„ Adding sources to shell profile", title="[bold blue]Sources[/bold blue]", border_style="blue"))
113
133
 
114
134
  if choice is None:
115
135
  choice_obj = display_options(msg="Which patch to add?", options=sources + ["all", "none(EXIT)"], default="none(EXIT)", multi=True)
116
136
  if isinstance(choice_obj, str):
117
- if choice_obj == "all": choice = choice_obj
118
- elif choice_obj == "none(EXIT)": return
119
- else: sources = [choice_obj]
137
+ if choice_obj == "all":
138
+ choice = choice_obj
139
+ elif choice_obj == "none(EXIT)":
140
+ return
141
+ else:
142
+ sources = [choice_obj]
120
143
  else: # isinstance(choice_obj, list):
121
144
  sources = choice_obj
122
- elif choice == "none(EXIT)": return
145
+ elif choice == "none(EXIT)":
146
+ return
123
147
 
124
148
  if isinstance(profile_path, str):
125
149
  profile_path_obj = PathExtended(profile_path)
126
- else: profile_path_obj = get_shell_profile_path()
127
- profile = profile_path_obj.read_text()
150
+ else:
151
+ profile_path_obj = get_shell_profile_path()
152
+ profile = profile_path_obj.read_text(encoding="utf-8")
128
153
 
129
154
  for a_file in sources:
130
155
  tmp = a_file.replace("REPO_ROOT", REPO_ROOT.as_posix()).replace("LIBRARY_ROOT", LIBRARY_ROOT.as_posix())
131
156
  file = PathExtended(tmp).collapseuser() # this makes the shell profile interuseable across machines.
132
157
  file = file.as_posix() if system == "Linux" else str(file)
133
158
  if file not in profile:
134
- if system == "Windows":
159
+ if system == "Windows":
135
160
  profile += f"\n. {file}"
136
161
  console.print(f"āž• Added PowerShell source: {file}")
137
- elif system == "Linux":
162
+ elif system == "Linux":
138
163
  profile += f"\nsource {file}"
139
164
  console.print(f"āž• Added Bash source: {file}")
140
- else: raise ValueError(f"Not implemented for this system {system}")
141
- else:
165
+ else:
166
+ raise ValueError(f"Not implemented for this system {system}")
167
+ else:
142
168
  console.print(f"ā­ļø Source already present: {file}")
143
-
144
- profile_path_obj.write_text(profile)
169
+
170
+ profile_path_obj.write_text(profile, encoding="utf-8")
145
171
  console.print(Panel("āœ… Shell profile updated with sources", title="[bold blue]Sources[/bold blue]", border_style="blue"))
146
172
 
147
173
 
148
- def main_add_patches_to_shell_profile(profile_path: Optional[str] = None, choice: Optional[str] = None):
149
- patches: list[str] = list(LIBRARY_ROOT.joinpath(f"profile/patches/{system.lower()}").search().apply(lambda x: x.as_posix()))
150
-
174
+ def main_add_patches_to_shell_profile(profile_path: Optional[str], choice: Optional[str]) -> None:
175
+ patches: list[str] = [item.as_posix() for item in LIBRARY_ROOT.joinpath(f"profile/patches/{system.lower()}").search()]
176
+
151
177
  console.print(Panel("🩹 Adding patches to shell profile", title="[bold blue]Patches[/bold blue]", border_style="blue"))
152
-
178
+
153
179
  if choice is None:
154
180
  choice_chosen = display_options(msg="Which patch to add?", options=list(patches) + ["all", "none(EXIT)"], default="none(EXIT)", multi=False)
155
181
  assert isinstance(choice_chosen, str), f"Choice must be a string or a list of strings, not {type(choice)}"
156
182
  choice = choice_chosen
157
- if choice == "none(EXIT)": return None
158
- elif str(choice) == "all":
183
+ if choice == "none(EXIT)":
184
+ return None
185
+ elif str(choice) == "all":
159
186
  console.print("šŸ“Œ Adding all patches to profile")
160
- else:
187
+ else:
161
188
  patches = [choice]
162
189
  console.print(f"šŸ“Œ Adding selected patch: {choice}")
163
190
 
164
191
  profile_path_obj = PathExtended(profile_path) if isinstance(profile_path, str) else get_shell_profile_path()
165
- profile = profile_path_obj.read_text()
192
+ profile = profile_path_obj.read_text(encoding="utf-8")
166
193
 
167
194
  for patch_path in patches:
168
195
  patch_path_obj = PathExtended(patch_path)
169
- patch = patch_path_obj.read_text()
170
- if patch in profile:
196
+ patch = patch_path_obj.read_text(encoding="utf-8")
197
+ if patch in profile:
171
198
  console.print(f"ā­ļø Patch already present: {patch_path_obj.name}")
172
- else:
199
+ else:
173
200
  profile += "\n" + patch
174
201
  console.print(f"āž• Added patch: {patch_path_obj.name}")
175
202
 
@@ -179,9 +206,9 @@ def main_add_patches_to_shell_profile(profile_path: Optional[str] = None, choice
179
206
  profile += "\ncd ~" # this is to make sure that the current dir is not in the windows file system, which is terribly slow and its a bad idea to be there anyway.
180
207
  console.print("šŸ“Œ WSL detected - adding 'cd ~' to profile to avoid Windows filesystem")
181
208
 
182
- profile_path_obj.write_text(profile)
209
+ profile_path_obj.write_text(profile, encoding="utf-8")
183
210
  console.print(Panel("āœ… Shell profile updated with patches", title="[bold blue]Patches[/bold blue]", border_style="blue"))
184
211
 
185
212
 
186
- if __name__ == '__main__':
213
+ if __name__ == "__main__":
187
214
  pass