machineconfig 2.0__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 (235) hide show
  1. machineconfig/cluster/cloud_manager.py +0 -3
  2. machineconfig/cluster/data_transfer.py +0 -1
  3. machineconfig/cluster/file_manager.py +0 -1
  4. machineconfig/cluster/job_params.py +0 -3
  5. machineconfig/cluster/loader_runner.py +0 -3
  6. machineconfig/cluster/remote_machine.py +0 -1
  7. machineconfig/cluster/script_notify_upon_completion.py +0 -1
  8. machineconfig/cluster/sessions_managers/archive/create_zellij_template.py +3 -5
  9. machineconfig/cluster/sessions_managers/archive/session_managers.py +0 -1
  10. machineconfig/cluster/sessions_managers/enhanced_command_runner.py +17 -57
  11. machineconfig/cluster/sessions_managers/wt_local.py +36 -110
  12. machineconfig/cluster/sessions_managers/wt_local_manager.py +42 -112
  13. machineconfig/cluster/sessions_managers/wt_remote.py +23 -30
  14. machineconfig/cluster/sessions_managers/wt_remote_manager.py +20 -62
  15. machineconfig/cluster/sessions_managers/wt_utils/layout_generator.py +10 -15
  16. machineconfig/cluster/sessions_managers/wt_utils/process_monitor.py +27 -127
  17. machineconfig/cluster/sessions_managers/wt_utils/remote_executor.py +10 -43
  18. machineconfig/cluster/sessions_managers/wt_utils/session_manager.py +22 -101
  19. machineconfig/cluster/sessions_managers/wt_utils/status_reporter.py +11 -39
  20. machineconfig/cluster/sessions_managers/zellij_local.py +49 -102
  21. machineconfig/cluster/sessions_managers/zellij_local_manager.py +34 -78
  22. machineconfig/cluster/sessions_managers/zellij_remote.py +17 -24
  23. machineconfig/cluster/sessions_managers/zellij_remote_manager.py +7 -13
  24. machineconfig/cluster/sessions_managers/zellij_utils/example_usage.py +4 -2
  25. machineconfig/cluster/sessions_managers/zellij_utils/layout_generator.py +6 -6
  26. machineconfig/cluster/sessions_managers/zellij_utils/process_monitor.py +18 -88
  27. machineconfig/cluster/sessions_managers/zellij_utils/remote_executor.py +2 -6
  28. machineconfig/cluster/sessions_managers/zellij_utils/session_manager.py +12 -40
  29. machineconfig/cluster/sessions_managers/zellij_utils/status_reporter.py +3 -2
  30. machineconfig/cluster/templates/cli_click.py +0 -1
  31. machineconfig/cluster/templates/cli_gooey.py +0 -2
  32. machineconfig/cluster/templates/cli_trogon.py +0 -1
  33. machineconfig/cluster/templates/run_cloud.py +0 -1
  34. machineconfig/cluster/templates/run_cluster.py +0 -1
  35. machineconfig/cluster/templates/run_remote.py +0 -1
  36. machineconfig/cluster/templates/utils.py +26 -10
  37. machineconfig/jobs/__pycache__/__init__.cpython-313.pyc +0 -0
  38. machineconfig/jobs/linux/msc/cli_agents.sh +16 -0
  39. machineconfig/jobs/python/check_installations.py +1 -0
  40. machineconfig/jobs/python/create_bootable_media.py +0 -2
  41. machineconfig/jobs/python/python_ve_symlink.py +9 -11
  42. machineconfig/jobs/python/tasks.py +0 -1
  43. machineconfig/jobs/python/vscode/api.py +5 -5
  44. machineconfig/jobs/python/vscode/link_ve.py +13 -14
  45. machineconfig/jobs/python/vscode/select_interpreter.py +21 -22
  46. machineconfig/jobs/python/vscode/sync_code.py +9 -13
  47. machineconfig/jobs/python_custom_installers/__pycache__/__init__.cpython-313.pyc +0 -0
  48. machineconfig/jobs/python_custom_installers/archive/ngrok.py +13 -13
  49. machineconfig/jobs/python_custom_installers/dev/aider.py +7 -15
  50. machineconfig/jobs/python_custom_installers/dev/alacritty.py +9 -18
  51. machineconfig/jobs/python_custom_installers/dev/brave.py +10 -19
  52. machineconfig/jobs/python_custom_installers/dev/bypass_paywall.py +8 -15
  53. machineconfig/jobs/python_custom_installers/dev/code.py +14 -21
  54. machineconfig/jobs/python_custom_installers/dev/cursor.py +3 -14
  55. machineconfig/jobs/python_custom_installers/dev/docker_desktop.py +8 -7
  56. machineconfig/jobs/python_custom_installers/dev/espanso.py +15 -19
  57. machineconfig/jobs/python_custom_installers/dev/goes.py +5 -12
  58. machineconfig/jobs/python_custom_installers/dev/lvim.py +9 -17
  59. machineconfig/jobs/python_custom_installers/dev/nerdfont.py +12 -19
  60. machineconfig/jobs/python_custom_installers/dev/redis.py +12 -20
  61. machineconfig/jobs/python_custom_installers/dev/wezterm.py +12 -19
  62. machineconfig/jobs/python_custom_installers/dev/winget.py +5 -23
  63. machineconfig/jobs/python_custom_installers/docker.py +12 -21
  64. machineconfig/jobs/python_custom_installers/gh.py +11 -19
  65. machineconfig/jobs/python_custom_installers/hx.py +32 -16
  66. machineconfig/jobs/python_custom_installers/warp-cli.py +12 -20
  67. machineconfig/jobs/python_generic_installers/__pycache__/__init__.cpython-313.pyc +0 -0
  68. machineconfig/jobs/python_linux_installers/__pycache__/__init__.cpython-313.pyc +0 -0
  69. machineconfig/jobs/windows/archive/archive_pygraphviz.ps1 +1 -1
  70. machineconfig/jobs/windows/msc/cli_agents.bat +0 -0
  71. machineconfig/jobs/windows/msc/cli_agents.ps1 +0 -0
  72. machineconfig/jobs/windows/start_terminal.ps1 +1 -1
  73. machineconfig/profile/create.py +29 -22
  74. machineconfig/profile/create_hardlinks.py +26 -19
  75. machineconfig/profile/shell.py +51 -28
  76. machineconfig/scripts/__pycache__/__init__.cpython-313.pyc +0 -0
  77. machineconfig/scripts/cloud/init.sh +2 -2
  78. machineconfig/scripts/linux/checkout_versions +1 -1
  79. machineconfig/scripts/linux/choose_wezterm_theme +1 -1
  80. machineconfig/scripts/linux/cloud_copy +1 -1
  81. machineconfig/scripts/linux/cloud_manager +1 -1
  82. machineconfig/scripts/linux/cloud_mount +1 -1
  83. machineconfig/scripts/linux/cloud_repo_sync +1 -1
  84. machineconfig/scripts/linux/cloud_sync +1 -1
  85. machineconfig/scripts/linux/croshell +1 -1
  86. machineconfig/scripts/linux/devops +4 -6
  87. machineconfig/scripts/linux/fire +1 -1
  88. machineconfig/scripts/linux/fire_agents +3 -2
  89. machineconfig/scripts/linux/ftpx +1 -1
  90. machineconfig/scripts/linux/gh_models +1 -1
  91. machineconfig/scripts/linux/kill_process +1 -1
  92. machineconfig/scripts/linux/mcinit +1 -1
  93. machineconfig/scripts/linux/repos +1 -1
  94. machineconfig/scripts/linux/scheduler +1 -1
  95. machineconfig/scripts/linux/start_slidev +1 -1
  96. machineconfig/scripts/linux/start_terminals +1 -1
  97. machineconfig/scripts/linux/url2md +1 -1
  98. machineconfig/scripts/linux/warp-cli.sh +122 -0
  99. machineconfig/scripts/linux/wifi_conn +1 -1
  100. machineconfig/scripts/python/__pycache__/__init__.cpython-313.pyc +0 -0
  101. machineconfig/scripts/python/__pycache__/croshell.cpython-313.pyc +0 -0
  102. machineconfig/scripts/python/__pycache__/devops.cpython-313.pyc +0 -0
  103. machineconfig/scripts/python/__pycache__/devops_devapps_install.cpython-313.pyc +0 -0
  104. machineconfig/scripts/python/__pycache__/devops_update_repos.cpython-313.pyc +0 -0
  105. machineconfig/scripts/python/__pycache__/fire_jobs.cpython-313.pyc +0 -0
  106. machineconfig/scripts/python/ai/__init__.py +0 -0
  107. machineconfig/scripts/python/ai/__pycache__/__init__.cpython-313.pyc +0 -0
  108. machineconfig/scripts/python/ai/__pycache__/generate_files.cpython-313.pyc +0 -0
  109. machineconfig/scripts/python/ai/__pycache__/mcinit.cpython-313.pyc +0 -0
  110. machineconfig/scripts/python/ai/generate_files.py +84 -0
  111. machineconfig/scripts/python/ai/instructions/python/dev.instructions.md +2 -2
  112. machineconfig/scripts/python/ai/mcinit.py +7 -3
  113. machineconfig/scripts/python/ai/scripts/lint_and_type_check.sh +10 -5
  114. machineconfig/scripts/python/cloud_copy.py +1 -1
  115. machineconfig/scripts/python/cloud_mount.py +1 -1
  116. machineconfig/scripts/python/cloud_repo_sync.py +4 -4
  117. machineconfig/scripts/python/croshell.py +5 -3
  118. machineconfig/scripts/python/devops_add_identity.py +1 -1
  119. machineconfig/scripts/python/devops_add_ssh_key.py +1 -1
  120. machineconfig/scripts/python/devops_backup_retrieve.py +1 -1
  121. machineconfig/scripts/python/devops_update_repos.py +140 -52
  122. machineconfig/scripts/python/dotfile.py +1 -1
  123. machineconfig/scripts/python/fire_agents.py +28 -9
  124. machineconfig/scripts/python/fire_jobs.py +3 -4
  125. machineconfig/scripts/python/ftpx.py +2 -1
  126. machineconfig/scripts/python/helpers/__pycache__/__init__.cpython-313.pyc +0 -0
  127. machineconfig/scripts/python/helpers/__pycache__/helpers4.cpython-313.pyc +0 -0
  128. machineconfig/scripts/python/helpers/helpers2.py +2 -2
  129. machineconfig/scripts/python/helpers/helpers4.py +1 -2
  130. machineconfig/scripts/python/helpers/repo_sync_helpers.py +1 -1
  131. machineconfig/scripts/python/mount_nfs.py +1 -1
  132. machineconfig/scripts/python/mount_ssh.py +1 -1
  133. machineconfig/scripts/python/repos.py +1 -1
  134. machineconfig/scripts/python/start_slidev.py +1 -1
  135. machineconfig/scripts/python/wsl_windows_transfer.py +1 -1
  136. machineconfig/scripts/windows/checkout_version.ps1 +1 -3
  137. machineconfig/scripts/windows/choose_wezterm_theme.ps1 +1 -3
  138. machineconfig/scripts/windows/cloud_copy.ps1 +2 -6
  139. machineconfig/scripts/windows/cloud_manager.ps1 +1 -1
  140. machineconfig/scripts/windows/cloud_repo_sync.ps1 +1 -2
  141. machineconfig/scripts/windows/cloud_sync.ps1 +2 -2
  142. machineconfig/scripts/windows/croshell.ps1 +2 -2
  143. machineconfig/scripts/windows/devops.ps1 +1 -4
  144. machineconfig/scripts/windows/dotfile.ps1 +1 -3
  145. machineconfig/scripts/windows/fire.ps1 +1 -1
  146. machineconfig/scripts/windows/ftpx.ps1 +2 -2
  147. machineconfig/scripts/windows/gpt.ps1 +1 -1
  148. machineconfig/scripts/windows/kill_process.ps1 +1 -2
  149. machineconfig/scripts/windows/mcinit.ps1 +1 -1
  150. machineconfig/scripts/windows/mount_nfs.ps1 +1 -1
  151. machineconfig/scripts/windows/mount_ssh.ps1 +1 -1
  152. machineconfig/scripts/windows/pomodoro.ps1 +1 -1
  153. machineconfig/scripts/windows/py2exe.ps1 +1 -3
  154. machineconfig/scripts/windows/repos.ps1 +1 -1
  155. machineconfig/scripts/windows/scheduler.ps1 +1 -1
  156. machineconfig/scripts/windows/snapshot.ps1 +2 -2
  157. machineconfig/scripts/windows/start_slidev.ps1 +1 -1
  158. machineconfig/scripts/windows/start_terminals.ps1 +1 -1
  159. machineconfig/scripts/windows/wifi_conn.ps1 +1 -1
  160. machineconfig/scripts/windows/wsl_windows_transfer.ps1 +1 -3
  161. machineconfig/settings/lf/linux/lfrc +1 -1
  162. machineconfig/settings/linters/.ruff_cache/.gitignore +2 -0
  163. machineconfig/settings/linters/.ruff_cache/CACHEDIR.TAG +1 -0
  164. machineconfig/settings/lvim/windows/archive/config_additional.lua +1 -1
  165. machineconfig/settings/svim/linux/init.toml +1 -1
  166. machineconfig/settings/svim/windows/init.toml +1 -1
  167. machineconfig/setup_linux/web_shortcuts/croshell.sh +0 -54
  168. machineconfig/setup_linux/web_shortcuts/interactive.sh +6 -6
  169. machineconfig/setup_windows/web_shortcuts/all.ps1 +2 -2
  170. machineconfig/setup_windows/web_shortcuts/ascii_art.ps1 +1 -1
  171. machineconfig/setup_windows/web_shortcuts/croshell.ps1 +1 -1
  172. machineconfig/setup_windows/web_shortcuts/interactive.ps1 +5 -5
  173. machineconfig/setup_windows/wt_and_pwsh/install_fonts.ps1 +51 -15
  174. machineconfig/setup_windows/wt_and_pwsh/set_pwsh_theme.py +66 -12
  175. machineconfig/setup_windows/wt_and_pwsh/set_wt_settings.py +44 -36
  176. machineconfig/utils/ai/generate_file_checklist.py +8 -10
  177. machineconfig/utils/ai/url2md.py +4 -2
  178. machineconfig/utils/cloud/onedrive/setup_oauth.py +1 -0
  179. machineconfig/utils/cloud/onedrive/transaction.py +63 -98
  180. machineconfig/utils/code.py +60 -39
  181. machineconfig/utils/installer.py +27 -33
  182. machineconfig/utils/installer_utils/installer_abc.py +8 -7
  183. machineconfig/utils/installer_utils/installer_class.py +149 -70
  184. machineconfig/utils/links.py +22 -11
  185. machineconfig/utils/notifications.py +197 -0
  186. machineconfig/utils/options.py +29 -23
  187. machineconfig/utils/path.py +13 -6
  188. machineconfig/utils/path_reduced.py +485 -216
  189. machineconfig/utils/procs.py +47 -41
  190. machineconfig/utils/scheduling.py +0 -1
  191. machineconfig/utils/ssh.py +157 -76
  192. machineconfig/utils/terminal.py +82 -37
  193. machineconfig/utils/utils.py +12 -10
  194. machineconfig/utils/utils2.py +38 -48
  195. machineconfig/utils/utils5.py +183 -116
  196. machineconfig/utils/ve.py +9 -4
  197. {machineconfig-2.0.dist-info → machineconfig-2.1.dist-info}/METADATA +3 -2
  198. {machineconfig-2.0.dist-info → machineconfig-2.1.dist-info}/RECORD +200 -217
  199. machineconfig/jobs/__pycache__/__init__.cpython-311.pyc +0 -0
  200. machineconfig/jobs/python/__pycache__/__init__.cpython-311.pyc +0 -0
  201. machineconfig/jobs/python/__pycache__/python_ve_symlink.cpython-311.pyc +0 -0
  202. machineconfig/jobs/python/archive/python_tools.txt +0 -12
  203. machineconfig/jobs/python/vscode/__pycache__/select_interpreter.cpython-311.pyc +0 -0
  204. machineconfig/jobs/python_custom_installers/__pycache__/__init__.cpython-311.pyc +0 -0
  205. machineconfig/jobs/python_generic_installers/__pycache__/__init__.cpython-311.pyc +0 -0
  206. machineconfig/jobs/python_generic_installers/update.py +0 -3
  207. machineconfig/jobs/python_linux_installers/__pycache__/__init__.cpython-311.pyc +0 -0
  208. machineconfig/profile/__pycache__/__init__.cpython-311.pyc +0 -0
  209. machineconfig/profile/__pycache__/create.cpython-311.pyc +0 -0
  210. machineconfig/profile/__pycache__/shell.cpython-311.pyc +0 -0
  211. machineconfig/scripts/__pycache__/__init__.cpython-311.pyc +0 -0
  212. machineconfig/scripts/linux/activate_ve +0 -87
  213. machineconfig/scripts/python/__pycache__/__init__.cpython-311.pyc +0 -0
  214. machineconfig/scripts/python/__pycache__/cloud_copy.cpython-311.pyc +0 -0
  215. machineconfig/scripts/python/__pycache__/cloud_mount.cpython-311.pyc +0 -0
  216. machineconfig/scripts/python/__pycache__/cloud_sync.cpython-311.pyc +0 -0
  217. machineconfig/scripts/python/__pycache__/croshell.cpython-311.pyc +0 -0
  218. machineconfig/scripts/python/__pycache__/devops.cpython-311.pyc +0 -0
  219. machineconfig/scripts/python/__pycache__/devops_backup_retrieve.cpython-311.pyc +0 -0
  220. machineconfig/scripts/python/__pycache__/devops_devapps_install.cpython-311.pyc +0 -0
  221. machineconfig/scripts/python/__pycache__/devops_update_repos.cpython-311.pyc +0 -0
  222. machineconfig/scripts/python/__pycache__/fire_agents.cpython-311.pyc +0 -0
  223. machineconfig/scripts/python/__pycache__/fire_jobs.cpython-311.pyc +0 -0
  224. machineconfig/scripts/python/__pycache__/get_zellij_cmd.cpython-311.pyc +0 -0
  225. machineconfig/scripts/python/__pycache__/repos.cpython-311.pyc +0 -0
  226. machineconfig/scripts/python/ai/__pycache__/init.cpython-311.pyc +0 -0
  227. machineconfig/scripts/python/ai/__pycache__/mcinit.cpython-311.pyc +0 -0
  228. machineconfig/scripts/python/helpers/__pycache__/__init__.cpython-311.pyc +0 -0
  229. machineconfig/scripts/python/helpers/__pycache__/cloud_helpers.cpython-311.pyc +0 -0
  230. machineconfig/scripts/python/helpers/__pycache__/helpers2.cpython-311.pyc +0 -0
  231. machineconfig/scripts/python/helpers/__pycache__/helpers4.cpython-311.pyc +0 -0
  232. machineconfig/scripts/python/helpers/__pycache__/repo_sync_helpers.cpython-311.pyc +0 -0
  233. machineconfig/scripts/windows/activate_ve.ps1 +0 -54
  234. {machineconfig-2.0.dist-info → machineconfig-2.1.dist-info}/WHEEL +0 -0
  235. {machineconfig-2.0.dist-info → machineconfig-2.1.dist-info}/top_level.txt +0 -0
@@ -5,14 +5,7 @@ from pathlib import Path
5
5
  from typing import Optional
6
6
 
7
7
 
8
- config_dict = {
9
- "repo_url": "CUSTOM",
10
- "doc": "winget installer",
11
- "filename_template_windows_amd_64": "",
12
- "filename_template_linux_amd_64": "",
13
- "strip_v": False,
14
- "exe_name": "winget"
15
- }
8
+ config_dict = {"repo_url": "CUSTOM", "doc": "winget installer", "filename_template_windows_amd_64": "", "filename_template_linux_amd_64": "", "strip_v": False, "exe_name": "winget"}
16
9
 
17
10
 
18
11
  def is_winget_available() -> bool:
@@ -23,12 +16,7 @@ def is_winget_available() -> bool:
23
16
  bool: True if winget is available, False otherwise
24
17
  """
25
18
  try:
26
- result = subprocess.run(
27
- ["winget", "--version"],
28
- capture_output=True,
29
- text=True,
30
- timeout=10
31
- )
19
+ result = subprocess.run(["winget", "--version"], capture_output=True, text=True, timeout=10)
32
20
  return result.returncode == 0
33
21
  except (subprocess.TimeoutExpired, FileNotFoundError, subprocess.SubprocessError):
34
22
  return False
@@ -77,7 +65,7 @@ def download_file(url: str, destination: Path) -> bool:
77
65
  response = requests.get(url, stream=True, timeout=60)
78
66
  response.raise_for_status()
79
67
 
80
- with open(destination, 'wb') as f:
68
+ with open(destination, "wb") as f:
81
69
  for chunk in response.iter_content(chunk_size=8192):
82
70
  if chunk:
83
71
  f.write(chunk)
@@ -100,18 +88,13 @@ def install_msix_package(package_path: Path) -> bool:
100
88
  """
101
89
  try:
102
90
  # Use PowerShell to install the MSIX package
103
- powershell_cmd = [
104
- "powershell.exe",
105
- "-ExecutionPolicy", "Bypass",
106
- "-Command",
107
- f"Add-AppxPackage -Path '{package_path}'"
108
- ]
91
+ powershell_cmd = ["powershell.exe", "-ExecutionPolicy", "Bypass", "-Command", f"Add-AppxPackage -Path '{package_path}'"]
109
92
 
110
93
  result = subprocess.run(
111
94
  powershell_cmd,
112
95
  capture_output=True,
113
96
  text=True,
114
- timeout=300 # 5 minutes timeout
97
+ timeout=300, # 5 minutes timeout
115
98
  )
116
99
 
117
100
  if result.returncode == 0:
@@ -191,4 +174,3 @@ if __name__ == "__main__":
191
174
  print("Winget is ready to use!")
192
175
  else:
193
176
  print("Failed to ensure winget availability.")
194
-
@@ -1,38 +1,29 @@
1
- """docker installer
2
- """
1
+ """docker installer"""
3
2
 
4
3
  import platform
5
4
  from typing import Optional
6
5
 
7
6
 
8
- config_dict = {
9
- "repo_url": "CUSTOM",
10
- "doc": "lightweight containerization",
11
- "filename_template_windows_amd_64": "",
12
- "filename_template_linux_amd_64": "",
13
- "strip_v": False,
14
- "exe_name": "docker"
15
- }
16
-
7
+ config_dict = {"repo_url": "CUSTOM", "doc": "lightweight containerization", "filename_template_windows_amd_64": "", "filename_template_linux_amd_64": "", "strip_v": False, "exe_name": "docker"}
17
8
 
18
9
 
19
10
  def main(version: Optional[str]):
20
11
  print(f"""
21
- {'=' * 150}
12
+ {"=" * 150}
22
13
  🐳 DOCKER INSTALLER | Setting up containerization platform
23
14
  💻 Platform: {platform.system()}
24
- 🔄 Version: {'latest' if version is None else version}
25
- {'=' * 150}
15
+ 🔄 Version: {"latest" if version is None else version}
16
+ {"=" * 150}
26
17
  """)
27
18
 
28
19
  _ = version
29
20
  if platform.system() == "Windows":
30
21
  error_msg = "Docker installation not supported on Windows through this installer"
31
22
  print(f"""
32
- {'⚠️' * 20}
23
+ {"⚠️" * 20}
33
24
  ❌ ERROR | {error_msg}
34
25
  💡 TIP: Please use Docker Desktop for Windows instead
35
- {'⚠️' * 20}
26
+ {"⚠️" * 20}
36
27
  """)
37
28
  raise NotImplementedError(error_msg)
38
29
  elif platform.system() in ["Linux", "Darwin"]:
@@ -40,6 +31,7 @@ def main(version: Optional[str]):
40
31
  print(f"🐧 Installing Docker on {system_name} using official script...")
41
32
  import machineconfig.jobs.python_custom_installers as module
42
33
  from pathlib import Path
34
+
43
35
  if platform.system() == "Linux":
44
36
  program = Path(module.__file__).parent.joinpath("scripts/linux/docker.sh").read_text(encoding="utf-8")
45
37
  else: # Darwin/macOS
@@ -48,21 +40,21 @@ def main(version: Optional[str]):
48
40
  else:
49
41
  error_msg = f"Unsupported platform: {platform.system()}"
50
42
  print(f"""
51
- {'⚠️' * 20}
43
+ {"⚠️" * 20}
52
44
  ❌ ERROR | {error_msg}
53
- {'⚠️' * 20}
45
+ {"⚠️" * 20}
54
46
  """)
55
47
  raise NotImplementedError(error_msg)
56
48
 
57
49
  print(f"""
58
- {'=' * 150}
50
+ {"=" * 150}
59
51
  ℹ️ INFO | Docker features:
60
52
  📦 Container-based virtualization
61
53
  🚀 Simplified application deployment
62
54
  🔄 Consistent development environments
63
55
  🛡️ Isolated application environments
64
56
  📊 Efficient resource utilization
65
- {'=' * 150}
57
+ {"=" * 150}
66
58
  """)
67
59
 
68
60
  # _res = Terminal(stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE).run_script(script=program, shell="default").print(desc="Running custom installer", capture=True)
@@ -72,4 +64,3 @@ def main(version: Optional[str]):
72
64
 
73
65
  if __name__ == "__main__":
74
66
  pass
75
-
@@ -1,5 +1,4 @@
1
- """gh-cli installer
2
- """
1
+ """gh-cli installer"""
3
2
 
4
3
  import platform
5
4
  from typing import Optional
@@ -18,23 +17,16 @@ https://github.com/cli/cli
18
17
 
19
18
  """
20
19
 
21
- config_dict = {
22
- "repo_url": "https://github.com/cli/cli",
23
- "doc": "GitHub CLI",
24
- "filename_template_windows_amd_64": "gh_{}_windows_amd64.zip",
25
- "filename_template_linux_amd_64": "gh_{}_linux_amd64.tar.gz",
26
- "strip_v": True,
27
- "exe_name": "gh"
28
- }
20
+ config_dict = {"repo_url": "https://github.com/cli/cli", "doc": "GitHub CLI", "filename_template_windows_amd_64": "gh_{}_windows_amd64.zip", "filename_template_linux_amd_64": "gh_{}_linux_amd64.tar.gz", "strip_v": True, "exe_name": "gh"}
29
21
 
30
22
 
31
23
  def main(version: Optional[str]):
32
24
  print(f"""
33
- {'' * 150}
25
+ {"" * 150}
34
26
  🔱 GITHUB CLI INSTALLER | Command line tool for GitHub
35
27
  💻 Platform: {platform.system()}
36
- 🔄 Version: {'latest' if version is None else version}
37
- {'' * 150}
28
+ 🔄 Version: {"latest" if version is None else version}
29
+ {"" * 150}
38
30
  """)
39
31
 
40
32
  _ = version
@@ -45,9 +37,9 @@ def main(version: Optional[str]):
45
37
  inst.install(version=version)
46
38
 
47
39
  print(f"""
48
- {'' * 150}
40
+ {"" * 150}
49
41
  🤖 GITHUB COPILOT | Setting up GitHub Copilot CLI extension
50
- {'' * 150}
42
+ {"" * 150}
51
43
  """)
52
44
 
53
45
  if platform.system() == "Windows":
@@ -66,9 +58,9 @@ gh extension install github/gh-copilot
66
58
  else:
67
59
  error_msg = f"Unsupported platform: {platform.system()}"
68
60
  print(f"""
69
- {'⚠️' * 20}
61
+ {"⚠️" * 20}
70
62
  ❌ ERROR | {error_msg}
71
- {'⚠️' * 20}
63
+ {"⚠️" * 20}
72
64
  """)
73
65
  raise NotImplementedError(error_msg)
74
66
 
@@ -82,11 +74,11 @@ gh auth login --with-token $HOME/dotfiles/creds/git/gh_token.txt
82
74
  Terminal().run(program, shell="default").print(desc="Installing GitHub Copilot extension", capture=True)
83
75
 
84
76
  print(f"""
85
- {'' * 150}
77
+ {"" * 150}
86
78
  ✅ SUCCESS | GitHub CLI installation completed
87
79
  🚀 GitHub Copilot CLI extension installed
88
80
  🔑 Authentication configured with token
89
- {'' * 150}
81
+ {"" * 150}
90
82
  """)
91
83
 
92
84
  return program
@@ -2,7 +2,7 @@
2
2
  Installers do not add runtime files to the machine, hence this script.
3
3
  """
4
4
 
5
- from machineconfig.utils.path_reduced import P as PathExtended
5
+ from machineconfig.utils.path_reduced import PathExtended as PathExtended
6
6
  from machineconfig.utils.installer_utils.installer_abc import WINDOWS_INSTALL_PATH
7
7
  from typing import Optional
8
8
  import platform
@@ -14,13 +14,13 @@ from rich.panel import Panel
14
14
 
15
15
 
16
16
  config_dict = {
17
- "repo_url": "CUSTOM",
18
- "doc": "Helix is a post-modern modal text editor.",
19
- "filename_template_windows_amd_64": "helix-{}-x86_64-windows.zip",
20
- "filename_template_linux_amd_64": "helix-{}-x86_64-linux.tar.xz",
21
- "strip_v": False,
22
- "exe_name": "hx"
23
- }
17
+ "repo_url": "CUSTOM",
18
+ "doc": "Helix is a post-modern modal text editor.",
19
+ "filename_template_windows_amd_64": "helix-{}-x86_64-windows.zip",
20
+ "filename_template_linux_amd_64": "helix-{}-x86_64-linux.tar.xz",
21
+ "strip_v": False,
22
+ "exe_name": "hx",
23
+ }
24
24
 
25
25
 
26
26
  def main(version: Optional[str], install_lib: bool = False):
@@ -59,7 +59,6 @@ def main(version: Optional[str], install_lib: bool = False):
59
59
  raise FileNotFoundError(f"'contrib' directory not found at expected location: {contrib}")
60
60
  print(" ✨ Executable and components located.")
61
61
 
62
-
63
62
  print("\n🗑️ [Step 3/5] Cleaning up previous installation (if any)...")
64
63
  runtime_path = PathExtended.home().joinpath(".config/helix/runtime")
65
64
  contrib_path = PathExtended.home().joinpath(".config/helix/contrib")
@@ -67,7 +66,6 @@ def main(version: Optional[str], install_lib: bool = False):
67
66
  contrib_path.delete(sure=True, verbose=False)
68
67
  print(f" ✨ Cleaned '{runtime_path}' and '{contrib_path}'.")
69
68
 
70
-
71
69
  print("\n📦 [Step 4/5] Installing Helix components...")
72
70
  target_config_dir = PathExtended("~/.config/helix").expanduser()
73
71
  target_config_dir.mkdir(parents=True, exist_ok=True)
@@ -80,10 +78,16 @@ def main(version: Optional[str], install_lib: bool = False):
80
78
  contrib.move(folder=target_config_dir, overwrite=True)
81
79
  runtime.move(folder=target_config_dir, overwrite=True)
82
80
  system_name = "Linux" if platform.system() == "Linux" else "macOS"
83
- console.print(Panel(f"""✅ SUCCESS | Helix editor installed successfully on {system_name}!
81
+ console.print(
82
+ Panel(
83
+ f"""✅ SUCCESS | Helix editor installed successfully on {system_name}!
84
84
 
85
85
  📂 Executable: {target_bin_path / exe_name}
86
- 🔧 Config: {target_config_dir}""", title="Success", expand=False))
86
+ 🔧 Config: {target_config_dir}""",
87
+ title="Success",
88
+ expand=False,
89
+ )
90
+ )
87
91
  elif platform.system() == "Windows":
88
92
  target_bin_path = PathExtended(WINDOWS_INSTALL_PATH)
89
93
  exe_name = "hx.exe"
@@ -91,12 +95,24 @@ def main(version: Optional[str], install_lib: bool = False):
91
95
  if install_lib:
92
96
  contrib.move(folder=target_config_dir, overwrite=True)
93
97
  runtime.move(folder=target_config_dir, overwrite=True)
94
- console.print(Panel(f"""✅ SUCCESS | Helix editor installed successfully on Windows!
98
+ console.print(
99
+ Panel(
100
+ f"""✅ SUCCESS | Helix editor installed successfully on Windows!
95
101
  📂 Executable: {target_bin_path / exe_name}
96
- 🔧 Config: {target_config_dir}""", title="Success", expand=False))
102
+ 🔧 Config: {target_config_dir}""",
103
+ title="Success",
104
+ expand=False,
105
+ )
106
+ )
97
107
  else:
98
- console.print(Panel(f"""⚠️ WARNING | Unsupported operating system: {platform.system()}
99
- | Installation aborted.""", title="Warning", expand=False))
108
+ console.print(
109
+ Panel(
110
+ f"""⚠️ WARNING | Unsupported operating system: {platform.system()}
111
+ | Installation aborted.""",
112
+ title="Warning",
113
+ expand=False,
114
+ )
115
+ )
100
116
  print("\n🧹 [Step 5/5] Cleaning up temporary download files...")
101
117
  downloaded.delete(sure=True)
102
118
  print(" ✨ Cleanup complete.")
@@ -1,37 +1,29 @@
1
- """warp-cli installer
2
- """
1
+ """warp-cli installer"""
3
2
 
4
3
  import platform
5
4
  from typing import Optional
6
5
 
7
6
 
8
- config_dict = {
9
- "repo_url": "CUSTOM",
10
- "doc": "cli for warp from cloudflare",
11
- "filename_template_windows_amd_64": "",
12
- "filename_template_linux_amd_64": "",
13
- "strip_v": False,
14
- "exe_name": "warp-cli"
15
- }
7
+ config_dict = {"repo_url": "CUSTOM", "doc": "cli for warp from cloudflare", "filename_template_windows_amd_64": "", "filename_template_linux_amd_64": "", "strip_v": False, "exe_name": "warp-cli"}
16
8
 
17
9
 
18
10
  def main(version: Optional[str]):
19
11
  print(f"""
20
- {'' * 150}
12
+ {"" * 150}
21
13
  🌐 CLOUDFLARE WARP | Installing Cloudflare WARP CLI
22
14
  💻 Platform: {platform.system()}
23
- 🔄 Version: {'latest' if version is None else version}
24
- {'' * 150}
15
+ 🔄 Version: {"latest" if version is None else version}
16
+ {"" * 150}
25
17
  """)
26
18
 
27
19
  _ = version
28
20
  if platform.system() == "Windows":
29
21
  error_msg = "WARP CLI installation not supported on Windows through this installer"
30
22
  print(f"""
31
- {'⚠️' * 20}
23
+ {"⚠️" * 20}
32
24
  ❌ ERROR | {error_msg}
33
25
  💡 TIP: Please download and install manually from Cloudflare website
34
- {'⚠️' * 20}
26
+ {"⚠️" * 20}
35
27
  """)
36
28
  raise NotImplementedError(error_msg)
37
29
  elif platform.system() in ["Linux", "Darwin"]:
@@ -40,25 +32,26 @@ def main(version: Optional[str]):
40
32
  """)
41
33
  import machineconfig.jobs.python_custom_installers as module
42
34
  from pathlib import Path
35
+
43
36
  program = Path(module.__file__).parent.joinpath("scripts/linux/warp-cli.sh").read_text(encoding="utf-8")
44
37
  else:
45
38
  error_msg = f"Unsupported platform: {platform.system()}"
46
39
  print(f"""
47
- {'⚠️' * 20}
40
+ {"⚠️" * 20}
48
41
  ❌ ERROR | {error_msg}
49
- {'⚠️' * 20}
42
+ {"⚠️" * 20}
50
43
  """)
51
44
  raise NotImplementedError(error_msg)
52
45
 
53
46
  print(f"""
54
- {'' * 150}
47
+ {"" * 150}
55
48
  ℹ️ INFO | Cloudflare WARP Features:
56
49
  🔒 Secure your internet connection
57
50
  🚀 Improve browsing performance
58
51
  🛡️ Hide your IP address
59
52
  🔐 Encrypt your DNS queries
60
53
  🌐 Access Cloudflare Zero Trust services
61
- {'' * 150}
54
+ {"" * 150}
62
55
  """)
63
56
 
64
57
  # _res = Terminal(stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE).run_script(script=program, shell="default").print(desc="Running custom installer", capture=True)
@@ -68,4 +61,3 @@ def main(version: Optional[str]):
68
61
 
69
62
  if __name__ == "__main__":
70
63
  pass
71
-
@@ -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/
@@ -4,11 +4,11 @@ This script Takes away all config files from the computer, place them in one dir
4
4
 
5
5
  """
6
6
 
7
-
8
- from machineconfig.utils.path_reduced import P as PathExtended
7
+ from machineconfig.utils.path_reduced import PathExtended as PathExtended
9
8
  from machineconfig.utils.utils import symlink_func, symlink_copy, LIBRARY_ROOT, REPO_ROOT, display_options
10
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
14
  import os
@@ -40,22 +40,27 @@ def main_symlinks(choice: Optional[str] = None):
40
40
  for program_key in program_keys_raw:
41
41
  if program_key in exclude or OTHER_SYSTEM in program_key:
42
42
  continue
43
- else: program_keys.append(program_key)
43
+ else:
44
+ program_keys.append(program_key)
44
45
 
45
46
  program_keys.sort()
46
47
  if choice is None:
47
48
  choice_selected = display_options(msg="Which symlink to create?", options=program_keys + ["all", "none(EXIT)"], default="none(EXIT)", fzf=True, multi=True)
48
49
  assert isinstance(choice_selected, list)
49
- if len(choice_selected) == 1 and choice_selected[0] == "none(EXIT)": return # terminate function.
50
- 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
51
54
  # overwrite = display_options(msg="Overwrite existing source file?", options=["yes", "no"], default="yes") == "yes"
52
55
  from rich.prompt import Confirm
56
+
53
57
  overwrite = Confirm.ask("Overwrite existing source file?", default=True)
54
- else: choice_selected = choice
58
+ else:
59
+ choice_selected = choice
55
60
 
56
61
  if isinstance(choice_selected, str):
57
62
  if str(choice_selected) == "all" and system == "Windows":
58
- if os.name == 'nt':
63
+ if os.name == "nt":
59
64
  try:
60
65
  is_admin = ctypes.windll.shell32.IsUserAnAdmin()
61
66
  except Exception:
@@ -64,9 +69,9 @@ def main_symlinks(choice: Optional[str] = None):
64
69
  is_admin = False
65
70
  if not is_admin:
66
71
  print(f"""
67
- {'*' * 80}
72
+ {"*" * 80}
68
73
  ⚠️ WARNING: Administrator privileges required
69
- {'*' * 80}
74
+ {"*" * 80}
70
75
  """)
71
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.")
72
77
  elif choice_selected == "all":
@@ -75,14 +80,16 @@ def main_symlinks(choice: Optional[str] = None):
75
80
  {program_keys}
76
81
  """)
77
82
  pass # i.e. program_keys = program_keys
78
- else: program_keys = [choice_selected]
79
- else: program_keys = choice_selected
83
+ else:
84
+ program_keys = [choice_selected]
85
+ else:
86
+ program_keys = choice_selected
80
87
 
81
88
  for program_key in program_keys:
82
89
  print(f"\n🔄 Processing {program_key} symlinks...")
83
90
  for file_key, file_map in symlink_mapper[program_key].items():
84
- this = PathExtended(file_map['this'])
85
- 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()))
86
93
  if "contents" in file_map:
87
94
  try:
88
95
  for a_target in to_this.expanduser().search("*"):
@@ -113,22 +120,22 @@ def main_symlinks(choice: Optional[str] = None):
113
120
 
114
121
  if system == "Linux":
115
122
  print("\n📜 Setting executable permissions for scripts...")
116
- subprocess.run(f'chmod +x {LIBRARY_ROOT.joinpath(f"scripts/{system.lower()}")} -R', shell=True, capture_output=True, text=True)
123
+ subprocess.run(f"chmod +x {LIBRARY_ROOT.joinpath(f'scripts/{system.lower()}')} -R", shell=True, capture_output=True, text=True)
117
124
  print("✅ Script permissions updated")
118
125
 
119
126
  if len(ERROR_LIST) > 0:
120
127
  print(f"""
121
- {'*' * 80}
128
+ {"*" * 80}
122
129
  ❗ ERRORS ENCOUNTERED DURING PROCESSING
123
- {'*' * 80}
130
+ {"*" * 80}
124
131
  {ERROR_LIST}
125
- {'*' * 80}
132
+ {"*" * 80}
126
133
  """)
127
134
  else:
128
135
  print(f"""
129
- {'*' * 80}
136
+ {"*" * 80}
130
137
  ✅ All symlinks created successfully!
131
- {'*' * 80}
138
+ {"*" * 80}
132
139
  """)
133
140
 
134
141
 
@@ -143,11 +150,11 @@ def main(choice: Optional[str] = None):
143
150
  create_default_shell_profile()
144
151
 
145
152
  print(f"""
146
- {'=' * 80}
153
+ {"=" * 80}
147
154
  ✨ Configuration setup complete! ✨
148
- {'=' * 80}
155
+ {"=" * 80}
149
156
  """)
150
157
 
151
158
 
152
- if __name__ == '__main__':
159
+ if __name__ == "__main__":
153
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 machineconfig.utils.path_reduced import P as PathExtended
8
+ from machineconfig.utils.path_reduced import PathExtended as PathExtended
10
9
  from machineconfig.utils.utils import symlink_copy as symlink_func, LIBRARY_ROOT, REPO_ROOT, display_options
11
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
@@ -36,19 +36,24 @@ 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":
@@ -57,14 +62,16 @@ def main_symlinks(choice: Optional[str] = None):
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("*"):
@@ -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
- subprocess.run(f'chmod +x {LIBRARY_ROOT.joinpath(f"scripts/{system.lower()}")} -R', shell=True, capture_output=True, text=True)
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
 
@@ -121,11 +128,11 @@ def main(choice: Optional[str] = None):
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