machineconfig 1.94__py3-none-any.whl → 1.95__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 (120) hide show
  1. machineconfig/cluster/data_transfer.py +2 -1
  2. machineconfig/cluster/job_params.py +1 -1
  3. machineconfig/cluster/script_execution.py +1 -1
  4. machineconfig/jobs/__pycache__/__init__.cpython-311.pyc +0 -0
  5. machineconfig/jobs/linux/msc/lid.sh +2 -4
  6. machineconfig/jobs/linux/msc/network.sh +3 -6
  7. machineconfig/jobs/python/check_installations.py +6 -6
  8. machineconfig/jobs/python/checkout_version.py +4 -4
  9. machineconfig/jobs/python/python_cargo_build_share.py +2 -2
  10. machineconfig/jobs/python/python_ve_symlink.py +4 -4
  11. machineconfig/jobs/python/vscode/api.py +2 -2
  12. machineconfig/jobs/python/vscode/link_ve.py +4 -4
  13. machineconfig/jobs/python/vscode/select_interpreter.py +4 -4
  14. machineconfig/jobs/python/vscode/sync_code.py +6 -6
  15. machineconfig/jobs/python_custom_installers/archive/ngrok.py +4 -4
  16. machineconfig/jobs/python_custom_installers/dev/aider.py +4 -4
  17. machineconfig/jobs/python_custom_installers/dev/alacritty.py +4 -4
  18. machineconfig/jobs/python_custom_installers/dev/brave.py +4 -4
  19. machineconfig/jobs/python_custom_installers/dev/bypass_paywall.py +4 -4
  20. machineconfig/jobs/python_custom_installers/dev/code.py +4 -4
  21. machineconfig/jobs/python_custom_installers/dev/docker.py +4 -4
  22. machineconfig/jobs/python_custom_installers/dev/docker_desktop.py +4 -4
  23. machineconfig/jobs/python_custom_installers/dev/espanso.py +8 -8
  24. machineconfig/jobs/python_custom_installers/dev/goes.py +4 -4
  25. machineconfig/jobs/python_custom_installers/dev/lvim.py +4 -4
  26. machineconfig/jobs/python_custom_installers/dev/nerdfont.py +4 -4
  27. machineconfig/jobs/python_custom_installers/dev/redis.py +4 -4
  28. machineconfig/jobs/python_custom_installers/dev/warp-cli.py +4 -4
  29. machineconfig/jobs/python_custom_installers/dev/wezterm.py +4 -4
  30. machineconfig/jobs/python_custom_installers/gh.py +6 -6
  31. machineconfig/jobs/python_custom_installers/hx.py +28 -58
  32. machineconfig/jobs/python_custom_installers/scripts/linux/brave.sh +4 -8
  33. machineconfig/jobs/python_custom_installers/scripts/linux/docker.sh +5 -10
  34. machineconfig/jobs/python_custom_installers/scripts/linux/docker_start.sh +3 -6
  35. machineconfig/jobs/python_custom_installers/scripts/linux/edge.sh +3 -6
  36. machineconfig/jobs/python_custom_installers/scripts/linux/nerdfont.sh +5 -10
  37. machineconfig/jobs/python_custom_installers/scripts/linux/pgsql.sh +4 -8
  38. machineconfig/jobs/python_custom_installers/scripts/linux/redis.sh +5 -10
  39. machineconfig/jobs/python_custom_installers/scripts/linux/timescaledb.sh +6 -12
  40. machineconfig/jobs/python_custom_installers/scripts/linux/vscode.sh +9 -8
  41. machineconfig/jobs/python_custom_installers/scripts/linux/warp-cli.sh +5 -10
  42. machineconfig/jobs/python_custom_installers/scripts/linux/wezterm.sh +3 -6
  43. machineconfig/jobs/python_generic_installers/__pycache__/__init__.cpython-311.pyc +0 -0
  44. machineconfig/jobs/python_linux_installers/__pycache__/__init__.cpython-311.pyc +0 -0
  45. machineconfig/profile/shell.py +26 -47
  46. machineconfig/scripts/__pycache__/__init__.cpython-311.pyc +0 -0
  47. machineconfig/scripts/cloud/init.sh +9 -18
  48. machineconfig/scripts/linux/fire +5 -24
  49. machineconfig/scripts/linux/share_cloud.sh +6 -12
  50. machineconfig/scripts/python/__pycache__/__init__.cpython-311.pyc +0 -0
  51. machineconfig/scripts/python/__pycache__/cloud_copy.cpython-311.pyc +0 -0
  52. machineconfig/scripts/python/__pycache__/cloud_mount.cpython-311.pyc +0 -0
  53. machineconfig/scripts/python/__pycache__/cloud_repo_sync.cpython-311.pyc +0 -0
  54. machineconfig/scripts/python/__pycache__/cloud_sync.cpython-311.pyc +0 -0
  55. machineconfig/scripts/python/__pycache__/croshell.cpython-311.pyc +0 -0
  56. machineconfig/scripts/python/__pycache__/devops.cpython-311.pyc +0 -0
  57. machineconfig/scripts/python/__pycache__/devops_devapps_install.cpython-311.pyc +0 -0
  58. machineconfig/scripts/python/__pycache__/devops_update_repos.cpython-311.pyc +0 -0
  59. machineconfig/scripts/python/__pycache__/fire_jobs.cpython-311.pyc +0 -0
  60. machineconfig/scripts/python/__pycache__/get_zellij_cmd.cpython-311.pyc +0 -0
  61. machineconfig/scripts/python/__pycache__/repos.cpython-311.pyc +0 -0
  62. machineconfig/scripts/python/archive/im2text.py +30 -30
  63. machineconfig/scripts/python/archive/tmate_conn.py +10 -13
  64. machineconfig/scripts/python/archive/tmate_start.py +12 -16
  65. machineconfig/scripts/python/choose_wezterm_theme.py +9 -18
  66. machineconfig/scripts/python/cloud_copy.py +38 -93
  67. machineconfig/scripts/python/cloud_manager.py +61 -53
  68. machineconfig/scripts/python/cloud_mount.py +23 -34
  69. machineconfig/scripts/python/cloud_repo_sync.py +20 -69
  70. machineconfig/scripts/python/cloud_sync.py +35 -45
  71. machineconfig/scripts/python/croshell.py +48 -73
  72. machineconfig/scripts/python/devops.py +50 -104
  73. machineconfig/scripts/python/devops_add_identity.py +41 -101
  74. machineconfig/scripts/python/devops_add_ssh_key.py +33 -140
  75. machineconfig/scripts/python/devops_backup_retrieve.py +23 -112
  76. machineconfig/scripts/python/devops_devapps_install.py +0 -4
  77. machineconfig/scripts/python/devops_update_repos.py +1 -1
  78. machineconfig/scripts/python/fire_jobs.py +73 -25
  79. machineconfig/scripts/python/helpers/__pycache__/__init__.cpython-311.pyc +0 -0
  80. machineconfig/scripts/python/helpers/__pycache__/cloud_helpers.cpython-311.pyc +0 -0
  81. machineconfig/scripts/python/helpers/__pycache__/helpers2.cpython-311.pyc +0 -0
  82. machineconfig/scripts/python/helpers/__pycache__/helpers4.cpython-311.pyc +0 -0
  83. machineconfig/scripts/python/helpers/__pycache__/repo_sync_helpers.cpython-311.pyc +0 -0
  84. machineconfig/scripts/python/helpers/cloud_helpers.py +37 -34
  85. machineconfig/scripts/python/helpers/helpers2.py +17 -31
  86. machineconfig/scripts/python/helpers/repo_sync_helpers.py +19 -54
  87. machineconfig/scripts/python/pomodoro.py +1 -1
  88. machineconfig/scripts/python/repos.py +49 -34
  89. machineconfig/scripts/python/wifi_conn.py +5 -3
  90. machineconfig/scripts/windows/fire.ps1 +27 -15
  91. machineconfig/settings/__pycache__/__init__.cpython-311.pyc +0 -0
  92. machineconfig/settings/shells/ipy/profiles/default/__pycache__/__init__.cpython-311.pyc +0 -0
  93. machineconfig/settings/shells/ipy/profiles/default/startup/__pycache__/__init__.cpython-311.pyc +0 -0
  94. machineconfig/settings/shells/ipy/profiles/default/startup/__pycache__/playext.cpython-311.pyc +0 -0
  95. machineconfig/setup_linux/nix/cli_installation.sh +9 -18
  96. machineconfig/setup_linux/others/openssh-server_add_pub_key.sh +3 -6
  97. machineconfig/setup_linux/web_shortcuts/all.sh +5 -10
  98. machineconfig/setup_linux/web_shortcuts/ascii_art.sh +7 -14
  99. machineconfig/setup_linux/web_shortcuts/croshell.sh +6 -12
  100. machineconfig/setup_linux/web_shortcuts/interactive.sh +34 -68
  101. machineconfig/setup_linux/web_shortcuts/ssh.sh +8 -16
  102. machineconfig/setup_linux/web_shortcuts/update_system.sh +7 -14
  103. machineconfig/setup_windows/wt_and_pwsh/set_wt_settings.py +16 -12
  104. machineconfig/utils/ai/browser_user_wrapper.py +60 -45
  105. machineconfig/utils/ai/generate_file_checklist.py +4 -7
  106. machineconfig/utils/ai/url2md.py +13 -5
  107. machineconfig/utils/{utils_code.py → code.py} +4 -10
  108. machineconfig/utils/installer.py +4 -10
  109. machineconfig/utils/{utils_links.py → links.py} +9 -20
  110. machineconfig/utils/{utils_options.py → options.py} +10 -20
  111. machineconfig/utils/{utils_path.py → path.py} +28 -80
  112. machineconfig/utils/procs.py +26 -30
  113. machineconfig/utils/scheduling.py +11 -11
  114. machineconfig/utils/utils.py +12 -19
  115. machineconfig/utils/ve.py +5 -21
  116. machineconfig/utils/ve_utils/ve2.py +15 -2
  117. {machineconfig-1.94.dist-info → machineconfig-1.95.dist-info}/METADATA +4 -2
  118. {machineconfig-1.94.dist-info → machineconfig-1.95.dist-info}/RECORD +120 -118
  119. {machineconfig-1.94.dist-info → machineconfig-1.95.dist-info}/WHEEL +1 -1
  120. {machineconfig-1.94.dist-info → machineconfig-1.95.dist-info}/top_level.txt +0 -0
@@ -6,16 +6,20 @@ from tqdm import tqdm
6
6
  from pytz import timezone
7
7
  from machineconfig.utils.utils import display_options
8
8
  from typing import Optional
9
+ from rich.console import Console
10
+ from rich.panel import Panel
11
+
12
+ console = Console()
13
+
14
+ BOX_WIDTH = 78 # width for box drawing
9
15
 
10
16
  pd.options.display.max_rows = 10000
11
17
 
12
18
 
13
19
  def get_processes_accessing_file(path: str):
14
- print(f"""
15
- ╔{'═'*78}╗
16
- 🔍 SEARCHING FOR PROCESSES ACCESSING FILE ║
17
- ╚{'═'*78}╝
18
- """)
20
+ # header for searching processes
21
+ title = "🔍 SEARCHING FOR PROCESSES ACCESSING FILE"
22
+ console.print(Panel(title, title="[bold blue]Process Info[/bold blue]", border_style="blue"))
19
23
  res: dict[int, list[str]] = {}
20
24
  for proc in tqdm(psutil.process_iter(), desc="🔎 Scanning processes"):
21
25
  try:
@@ -26,7 +30,7 @@ def get_processes_accessing_file(path: str):
26
30
  if len(tmp) > 0:
27
31
  res[proc.pid] = tmp
28
32
  df = pd.DataFrame(res.items(), columns=['pid', 'files'])
29
- print(f"\n✅ Found {len(res)} processes accessing the specified file\n{'─'*80}\n")
33
+ console.print(Panel(f"✅ Found {len(res)} processes accessing the specified file", title="[bold blue]Process Info[/bold blue]", border_style="blue"))
30
34
  return df
31
35
 
32
36
 
@@ -45,11 +49,9 @@ def kill_process(name: str):
45
49
 
46
50
  class ProcessManager:
47
51
  def __init__(self):
48
- print(f"""
49
- ╔{'═'*78}╗
50
- 📊 INITIALIZING PROCESS MANAGER ║
51
- ╚{'═'*78}╝
52
- """)
52
+ # header for initializing process manager
53
+ title = "📊 INITIALIZING PROCESS MANAGER"
54
+ console.print(Panel(title, title="[bold blue]Process Info[/bold blue]", border_style="blue"))
53
55
  process_info = []
54
56
  for proc in tqdm(psutil.process_iter(), desc="🔍 Reading system processes"):
55
57
  try:
@@ -61,14 +63,12 @@ class ProcessManager:
61
63
  df['create_time'] = pd.to_datetime(df['create_time'], unit='s', utc=True).apply(lambda x: x.tz_convert(timezone('Australia/Adelaide')))
62
64
  df = df.sort_values(by='memory_usage_mb', ascending=False).reset_index(drop=True)
63
65
  self.df = df
64
- print(f"✅ Process Manager initialized with {len(df)} processes\n{'─'*80}\n")
66
+ console.print(Panel(f"✅ Process Manager initialized with {len(df)} processes", title="[bold blue]Process Info[/bold blue]", border_style="blue"))
65
67
 
66
68
  def choose_and_kill(self):
67
- print(f"""
68
- ╔{'═'*78}╗
69
- 🎯 INTERACTIVE PROCESS SELECTION AND TERMINATION ║
70
- ╚{'═'*78}╝
71
- """)
69
+ # header for interactive process selection
70
+ title = "🎯 INTERACTIVE PROCESS SELECTION AND TERMINATION"
71
+ console.print(Panel(title, title="[bold blue]Process Info[/bold blue]", border_style="blue"))
72
72
  options = str(self.df).split("\n")[1:]
73
73
  res = display_options(options=str(self.df).split("\n"), msg="📋 Select processes to manage:", fzf=True, multi=True)
74
74
  indices = [options.index(val) for val in res]
@@ -91,26 +91,22 @@ class ProcessManager:
91
91
  for idx2, row in sub_sub_df.iterrows():
92
92
  Struct(row.to_dict()).print(as_config=True, title=f"🎯 Target Process {idx2}")
93
93
  _ = self.kill(pids=sub_sub_df.pid.to_list()) if input("\n⚠️ Confirm termination? y/[n] ").lower() == "y" else None
94
- print(f"\n🔔 No processes were terminated.\n{'─'*80}\n")
94
+ console.print(Panel("🔔 No processes were terminated.", title="[bold blue]Process Info[/bold blue]", border_style="blue"))
95
95
 
96
96
  def filter_and_kill(self, name: Optional[str] = None):
97
- print(f"""
98
- ╔{'═'*78}╗
99
- 🔍 FILTERING AND TERMINATING PROCESSES BY NAME ║
100
- ╚{'═'*78}╝
101
- """)
97
+ # header for filtering processes by name
98
+ title = "🔍 FILTERING AND TERMINATING PROCESSES BY NAME"
99
+ console.print(Panel(title, title="[bold blue]Process Info[/bold blue]", border_style="blue"))
102
100
  _ = 20
103
101
  df_sub = self.df.query(f"name == '{name}' ").sort_values(by='create_time', ascending=True)
104
102
  print(f"🎯 Found {len(df_sub)} processes matching name: '{name}'")
105
103
  self.kill(pids=df_sub.pid.to_list())
106
- print(f"{'─'*80}\n")
104
+ console.print(Panel("", title="[bold blue]Process Info[/bold blue]", border_style="blue"))
107
105
 
108
106
  def kill(self, names: Optional[list[str]] = None, pids: Optional[list[int]] = None, commands: Optional[list[str]] = None):
109
- print(f"""
110
- ╔{'═'*78}╗
111
- 💀 PROCESS TERMINATION ║
112
- ╚{'═'*78}╝
113
- """)
107
+ # header for process termination
108
+ title = "💀 PROCESS TERMINATION"
109
+ console.print(Panel(title, title="[bold blue]Process Info[/bold blue]", border_style="blue"))
114
110
  if names is None and pids is None and commands is None:
115
111
  print("❌ Error: No termination targets specified (names, pids, or commands)")
116
112
  raise ValueError('names, pids and commands cannot all be None')
@@ -151,7 +147,7 @@ class ProcessManager:
151
147
  else:
152
148
  print(f'❓ No process has "{command}" in its command.')
153
149
 
154
- print(f"\n✅ Termination complete: {killed_count} processes terminated\n{'─'*80}\n")
150
+ console.print(Panel(f"✅ Termination complete: {killed_count} processes terminated", title="[bold blue]Process Info[/bold blue]", border_style="blue"))
155
151
 
156
152
 
157
153
  def get_age(create_time: float):
@@ -10,6 +10,8 @@ import platform
10
10
  import subprocess
11
11
  from typing import Optional
12
12
  # from crocodile.meta import Scheduler
13
+ from rich.console import Console
14
+ from rich.panel import Panel
13
15
 
14
16
 
15
17
  SCHEDULER_DEFAULT_ROOT = P.home().joinpath("dotfiles/scripts/.scheduler")
@@ -111,11 +113,10 @@ def main(root: Optional[str] = None, ignore_conditions: bool=True):
111
113
  else: root_resolved = P(root).expanduser().absolute()
112
114
  tasks_dirs = root_resolved.search(files=False, folders=True).filter(lambda x: x.joinpath("task.py").exists())
113
115
 
114
- print(f"""
115
- ╔{'═'*78}╗
116
- ║ 📂 TASK SCHEDULER INITIALIZED
117
- ╚{'═'*78}╝
118
- """)
116
+ # Print a fancy box using rich
117
+ console = Console()
118
+ console.print(Panel("TASK SCHEDULER INITIALIZED", title="Status", expand=False))
119
+
119
120
  print(f"📁 Root directory resolved: {root_resolved}")
120
121
 
121
122
  tasks: list[Task] = []
@@ -189,12 +190,11 @@ def should_task_run(task: Task, tolerance_mins: int = 1440) -> tuple[bool, Optio
189
190
  def run_task(task: Task) -> Report:
190
191
  start_time = datetime.now()
191
192
 
192
- print(f"""
193
- ╔{'═'*78}╗
194
- ║ 🚀 RUNNING TASK
195
- ╚{'═'*78}╝
196
- """)
197
- print(f"🔧 Task Name: {task.name}")
193
+ # Print a fancy box using rich
194
+ console = Console()
195
+ console.print(Panel("RUNNING TASK", title="Status", expand=False))
196
+
197
+ print(f"Task: {task.name}")
198
198
 
199
199
  shell_script = get_shell_script_executing_python_file(python_file=task.task_root.joinpath("task.py").to_str(), ve_name=task.venv)
200
200
  shell_script_root = P.tmp().joinpath(f"tmp_scripts/scheduler/{task.name}").create()
@@ -5,10 +5,12 @@ Utils
5
5
  from crocodile.file_management import P
6
6
  # import crocodile.environment as env
7
7
  import machineconfig
8
- from machineconfig.utils.utils_options import check_tool_exists, choose_cloud_interactively, choose_multiple_options, choose_one_option, choose_ssh_host, display_options
9
- from machineconfig.utils.utils_links import build_links, symlink_copy, symlink_func
10
- from machineconfig.utils.utils_code import get_shell_script_executing_python_file, get_shell_file_executing_python_script, write_shell_script_to_default_program_path, print_code, PROGRAM_PATH
11
- from machineconfig.utils.utils_path import sanitize_path, match_file_name
8
+ from machineconfig.utils.options import check_tool_exists, choose_cloud_interactively, choose_multiple_options, choose_one_option, choose_ssh_host, display_options
9
+ from rich.console import Console
10
+ from rich.panel import Panel
11
+ from machineconfig.utils.links import build_links, symlink_copy, symlink_func
12
+ from machineconfig.utils.code import get_shell_script_executing_python_file, get_shell_file_executing_python_script, write_shell_script_to_default_program_path, print_code, PROGRAM_PATH
13
+ from machineconfig.utils.path import sanitize_path, match_file_name
12
14
 
13
15
  # Split into multiple assignments to fix incompatible tuple sizes
14
16
  _ = get_shell_script_executing_python_file, get_shell_file_executing_python_script, print_code, PROGRAM_PATH, display_options, write_shell_script_to_default_program_path
@@ -58,11 +60,8 @@ def check_dotfiles_version_is_beyond(commit_dtm: str, update: bool=False):
58
60
  dtm = datetime(dtm.year, dtm.month, dtm.day, dtm.hour, dtm.minute, dtm.second)
59
61
  res = dtm > datetime.fromisoformat(commit_dtm)
60
62
  if res is False and update is True:
61
- print(f"""
62
- {'=' * 60}
63
- 🔄 UPDATE REQUIRED | Updating dotfiles because {dtm} < {datetime.fromisoformat(commit_dtm)}
64
- {'=' * 60}
65
- """)
63
+ console = Console()
64
+ console.print(Panel(f"🔄 UPDATE REQUIRED | Updating dotfiles because {dtm} < {datetime.fromisoformat(commit_dtm)}", border_style="bold blue", expand=False))
66
65
  from machineconfig.scripts.python.cloud_repo_sync import main
67
66
  main(cloud=None, path=dotfiles_path)
68
67
  return res
@@ -76,18 +75,12 @@ def wait_for_jobs_to_finish(root: P, pattern: str, wait_for_n_jobs: int, max_wai
76
75
  counter = len(parts)
77
76
  if counter == wait_for_n_jobs:
78
77
  wait_finished = True
79
- print(f"""
80
- {'=' * 60}
81
- ✅ JOB COMPLETE | {counter} Jobs finished successfully. Exiting.
82
- {'=' * 60}
83
- """)
78
+ console = Console()
79
+ console.print(Panel(f"✅ JOB COMPLETE | {counter} Jobs finished successfully. Exiting.", border_style="bold blue", expand=False))
84
80
  return True
85
81
  if (time.time() - t0) > 60 * max_wait_minutes:
86
- print(f"""
87
- {'=' * 60}
88
- ⏱️ TIMEOUT | Waited for {max_wait_minutes} minutes. Exiting.
89
- {'=' * 60}
90
- """)
82
+ console = Console()
83
+ console.print(Panel(f"⏱️ TIMEOUT | Waited for {max_wait_minutes} minutes. Exiting.", border_style="bold blue", expand=False))
91
84
  return False
92
85
  print(f"""
93
86
  ⏳ PROGRESS | {counter}/{wait_for_n_jobs} jobs finished. Waiting for {wait_for_n_jobs - counter} more jobs to complete, sleeping for 60 seconds.
machineconfig/utils/ve.py CHANGED
@@ -5,7 +5,6 @@ from crocodile.core import Struct, List
5
5
  from crocodile.file_management import P
6
6
 
7
7
  import platform
8
- from dataclasses import dataclass
9
8
  from typing import Optional, Literal
10
9
 
11
10
  from machineconfig.utils.ve_utils.ve1 import get_installed_interpreters
@@ -16,39 +15,24 @@ from machineconfig.utils.ve_utils.ve2 import get_bash_ve_install_script
16
15
  from machineconfig.utils.ve_utils.ve2 import get_ps1_ve_install_script
17
16
  from machineconfig.utils.ve_utils.ve2 import create_symlinks
18
17
  from machineconfig.utils.ve_utils.ve2 import make_installation_recipe
19
-
20
-
21
-
22
- @dataclass
23
- class VE_Specs:
24
- ve_name: str
25
- py_version: str
26
- ipy_profile: str
27
- os: str
28
-
29
-
30
- @dataclass
31
- class VE_INI:
32
- specs: VE_Specs
18
+ from rich.console import Console
19
+ from rich.panel import Panel
33
20
 
34
21
 
35
22
  def get_ve_install_script(ve_name: Optional[str] = None, py_version: Optional[str] = None,
36
23
  install_crocodile_and_machineconfig: Optional[bool] = None,
37
24
  delete_if_exists: bool=True,
38
25
  ) -> str:
39
- from rich.console import Console
40
26
  console = Console()
41
27
  if py_version is None:
42
- print("""
28
+ console.print(Panel("""
43
29
  {'=' * 60}
44
30
  🔍 AVAILABLE PYTHON VERSIONS
45
31
  {'=' * 60}
46
- """)
32
+ """, title="Python Versions", expand=False))
47
33
  res = get_installed_interpreters()
48
34
  List(res).print()
49
- print("""
50
- {'=' * 60}
51
- """)
35
+ console.print(Panel("", title="Python Versions", expand=False))
52
36
  dotted_py_version = input("🔢 Enter python version (3.11): ") or "3.11"
53
37
  else:
54
38
  dotted_py_version = py_version
@@ -4,9 +4,22 @@ from crocodile.file_management import P, Read
4
4
 
5
5
 
6
6
  from typing import Literal
7
-
7
+ from dataclasses import dataclass
8
8
  from machineconfig.utils.utils import LIBRARY_ROOT
9
- from machineconfig.utils.ve import VE_INI, VE_Specs
9
+
10
+
11
+
12
+ @dataclass
13
+ class VE_Specs:
14
+ ve_name: str
15
+ py_version: str
16
+ ipy_profile: str
17
+ os: str
18
+
19
+
20
+ @dataclass
21
+ class VE_INI:
22
+ specs: VE_Specs
10
23
 
11
24
 
12
25
  def get_install_requirements_template(repo_root: P, requirements_subpath: str, ve_name: str, system: Literal["Windows", "Linux"]):
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: machineconfig
3
- Version: 1.94
3
+ Version: 1.95
4
4
  Summary: Dotfiles management package
5
5
  Author-email: Alex Al-Saffar <programmer@usa.com>
6
6
  License: Apache 2.0
@@ -9,7 +9,7 @@ Project-URL: Bug Tracker, https://github.com/thisismygitrepo/machineconfig/issue
9
9
  Classifier: Programming Language :: Python :: 3
10
10
  Classifier: License :: OSI Approved :: Apache Software License
11
11
  Classifier: Operating System :: OS Independent
12
- Requires-Python: >=3.10
12
+ Requires-Python: >=3.11
13
13
  Description-Content-Type: text/markdown
14
14
  Requires-Dist: crocodile
15
15
  Requires-Dist: rich>=14.0.0
@@ -27,6 +27,8 @@ Requires-Dist: pyfzf>=0.3.1
27
27
  Requires-Dist: call-function-with-timeout>=1.1.1
28
28
  Provides-Extra: windows
29
29
  Requires-Dist: pywin32; extra == "windows"
30
+ Provides-Extra: docs
31
+ Requires-Dist: pdoc>=15.0.2; extra == "docs"
30
32
 
31
33
 
32
34
  <p align="center">