machineconfig 4.93__py3-none-any.whl → 4.96__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.
@@ -0,0 +1,4 @@
1
+
2
+
3
+ def func(a: int, b: int) -> int:
4
+ return a + b
@@ -9,16 +9,21 @@ import subprocess
9
9
  import random
10
10
  import string
11
11
  import json
12
+ import platform
12
13
  from typing import Dict, List, Optional, Any
13
14
  from pathlib import Path
14
15
  import logging
15
16
 
16
- from machineconfig.utils.schemas.layouts.layout_types import LayoutConfig, TabConfig
17
+ from machineconfig.utils.schemas.layouts.layout_types import LayoutConfig
17
18
 
18
19
  logging.basicConfig(level=logging.INFO)
19
20
  logger = logging.getLogger(__name__)
20
21
  TMP_LAYOUT_DIR = Path.home().joinpath("tmp_results", "session_manager", "wt", "layout_manager")
21
22
 
23
+ # Check if we're on Windows
24
+ IS_WINDOWS = platform.system().lower() == "windows"
25
+ POWERSHELL_CMD = "powershell" if IS_WINDOWS else "pwsh" # Use pwsh on non-Windows systems
26
+
22
27
 
23
28
  class WTLayoutGenerator:
24
29
  def __init__(self):
@@ -52,35 +57,7 @@ class WTLayoutGenerator:
52
57
  return f'"{text}"'
53
58
  return text
54
59
 
55
- @staticmethod
56
- def _create_tab_command(tab_config: TabConfig, is_first_tab: bool) -> str:
57
- """Create a Windows Terminal tab command string from tab config."""
58
- tab_name = tab_config["tabName"]
59
- cwd = tab_config["startDir"]
60
- command = tab_config["command"]
61
-
62
- # Convert paths to Windows format if needed
63
- if cwd.startswith("~/"):
64
- cwd = cwd.replace("~/", f"{Path.home()}/")
65
- elif cwd == "~":
66
- cwd = str(Path.home())
67
-
68
- # Build the wt command parts
69
- tab_parts = []
70
-
71
- if not is_first_tab:
72
- tab_parts.append("new-tab")
73
-
74
- # Add starting directory
75
- tab_parts.extend(["-d", WTLayoutGenerator._escape_for_wt(cwd)])
76
-
77
- # Add tab title
78
- tab_parts.extend(["--title", WTLayoutGenerator._escape_for_wt(tab_name)])
79
60
 
80
- # Add the command to execute
81
- tab_parts.append(WTLayoutGenerator._escape_for_wt(command))
82
-
83
- return " ".join(tab_parts)
84
61
 
85
62
  @staticmethod
86
63
  def _validate_layout_config(layout_config: LayoutConfig) -> None:
@@ -133,31 +110,39 @@ class WTLayoutGenerator:
133
110
 
134
111
  def _generate_wt_command_string(self, layout_config: LayoutConfig, window_name: str) -> str:
135
112
  """Generate complete Windows Terminal command string."""
136
- # Start building the wt command
137
- wt_parts = ["wt"]
138
-
139
- # Add window name
140
- wt_parts.extend(["-w", WTLayoutGenerator._escape_for_wt(window_name)])
141
-
142
- # Add tabs
143
- tab_commands = []
113
+ # Build the complete Windows Terminal command
114
+ command_parts = []
115
+
144
116
  for i, tab in enumerate(layout_config["layoutTabs"]):
145
117
  is_first = i == 0
146
- tab_cmd = self._create_tab_command(tab, is_first)
147
- tab_commands.append(tab_cmd)
148
-
149
- # Join all parts with semicolons (Windows Terminal command separator)
150
- if tab_commands:
151
- if len(tab_commands) == 1:
152
- # Single tab - just add to the main command
153
- wt_parts.extend(tab_commands[0].split())
118
+
119
+ if is_first:
120
+ # First tab: start with wt command and window name
121
+ tab_parts = ["wt", "-w", WTLayoutGenerator._escape_for_wt(window_name)]
154
122
  else:
155
- # Multiple tabs - join with semicolons
156
- wt_parts.append(tab_commands[0]) # First tab
157
- for tab_cmd in tab_commands[1:]:
158
- wt_parts.extend([";", tab_cmd])
159
-
160
- return " ".join(wt_parts)
123
+ # Subsequent tabs: use new-tab
124
+ tab_parts = ["new-tab"]
125
+
126
+ # Add common tab arguments
127
+ tab_name = tab["tabName"]
128
+ cwd = tab["startDir"]
129
+ command = tab["command"]
130
+
131
+ # Convert paths to Windows format if needed
132
+ if cwd.startswith("~/"):
133
+ cwd = cwd.replace("~/", f"{Path.home()}/")
134
+ elif cwd == "~":
135
+ cwd = str(Path.home())
136
+
137
+ # Add arguments in the correct order
138
+ tab_parts.extend(["-d", WTLayoutGenerator._escape_for_wt(cwd)])
139
+ tab_parts.extend(["--title", WTLayoutGenerator._escape_for_wt(tab_name)])
140
+ tab_parts.append(WTLayoutGenerator._escape_for_wt(command))
141
+
142
+ command_parts.append(" ".join(tab_parts))
143
+
144
+ # Join all tab commands with escaped semicolons for PowerShell
145
+ return " `; ".join(command_parts)
161
146
 
162
147
  def get_wt_layout_preview(self, layout_config: LayoutConfig) -> str:
163
148
  """Generate preview of the Windows Terminal command that would be created."""
@@ -179,29 +164,45 @@ class WTLayoutGenerator:
179
164
  @staticmethod
180
165
  def check_wt_session_status(session_name: str) -> Dict[str, Any]:
181
166
  try:
182
- # Check for Windows Terminal processes
183
- wt_check_cmd = ["powershell", "-Command", "Get-Process -Name 'WindowsTerminal' -ErrorAction SilentlyContinue | Select-Object Id, ProcessName, StartTime, MainWindowTitle | ConvertTo-Json -Depth 2"]
167
+ # Simplified Windows Terminal process check
168
+ ps_script = """
169
+ try {
170
+ $wtProcesses = Get-Process -Name 'WindowsTerminal' -ErrorAction SilentlyContinue
171
+ if ($wtProcesses) {
172
+ $processInfo = @()
173
+ $wtProcesses | ForEach-Object {
174
+ $info = @{
175
+ "Id" = $_.Id
176
+ "ProcessName" = $_.ProcessName
177
+ "StartTime" = $_.StartTime.ToString()
178
+ }
179
+ $processInfo += $info
180
+ }
181
+ $processInfo | ConvertTo-Json -Depth 2
182
+ }
183
+ } catch {
184
+ # No Windows Terminal processes found
185
+ }
186
+ """
184
187
 
185
- result = subprocess.run(wt_check_cmd, capture_output=True, text=True, timeout=10)
188
+ result = subprocess.run([POWERSHELL_CMD, "-Command", ps_script], capture_output=True, text=True, timeout=5)
186
189
 
187
190
  if result.returncode == 0:
188
191
  output = result.stdout.strip()
189
192
  if output and output != "":
190
193
  try:
191
- import json
192
-
193
194
  processes = json.loads(output)
194
195
  if not isinstance(processes, list):
195
196
  processes = [processes]
196
197
 
197
- # Look for windows that might belong to our session
198
- session_windows = []
199
- for proc in processes:
200
- window_title = proc.get("MainWindowTitle", "")
201
- if session_name in window_title or not window_title:
202
- session_windows.append(proc)
203
-
204
- return {"wt_running": True, "session_exists": len(session_windows) > 0, "session_name": session_name, "all_windows": processes, "session_windows": session_windows}
198
+ # For simplicity, assume session exists if WT is running
199
+ return {
200
+ "wt_running": True,
201
+ "session_exists": len(processes) > 0,
202
+ "session_name": session_name,
203
+ "all_windows": processes,
204
+ "session_windows": processes # Simplified - assume all windows could be session windows
205
+ }
205
206
  except Exception as e:
206
207
  return {"wt_running": True, "session_exists": False, "error": f"Failed to parse process info: {e}", "session_name": session_name}
207
208
  else:
@@ -212,7 +213,7 @@ class WTLayoutGenerator:
212
213
  except subprocess.TimeoutExpired:
213
214
  return {"wt_running": False, "error": "Timeout while checking Windows Terminal processes", "session_name": session_name}
214
215
  except FileNotFoundError:
215
- return {"wt_running": False, "error": "PowerShell not found in PATH", "session_name": session_name}
216
+ return {"wt_running": False, "error": f"PowerShell ({POWERSHELL_CMD}) not found in PATH", "session_name": session_name}
216
217
  except Exception as e:
217
218
  return {"wt_running": False, "error": str(e), "session_name": session_name}
218
219
 
@@ -232,55 +233,31 @@ class WTLayoutGenerator:
232
233
  command = tab_config["command"]
233
234
 
234
235
  try:
235
- # Create PowerShell script to check for processes
236
- cmd_parts = [part for part in command.split() if len(part) > 2]
237
- primary_cmd = cmd_parts[0] if cmd_parts else ""
236
+ # Extract the primary executable name from command
237
+ primary_cmd = command.split()[0] if command.strip() else ""
238
+ if not primary_cmd:
239
+ return {"status": "error", "error": "Empty command", "running": False, "command": command, "tab_name": tab_name}
238
240
 
241
+ # Use a much simpler PowerShell script that just checks for process names
239
242
  ps_script = f"""
240
- $targetCommand = '{command.replace("'", "''")}'
241
- $cmdParts = @({", ".join([f"'{part}'" for part in cmd_parts])})
242
- $primaryCmd = '{primary_cmd}'
243
- $currentPid = $PID
244
- $matchingProcesses = @()
245
-
246
- Get-Process | ForEach-Object {{
247
- try {{
248
- if ($_.Id -eq $currentPid) {{ return }}
249
-
250
- $cmdline = ""
251
- try {{
252
- $cmdline = (Get-WmiObject Win32_Process -Filter "ProcessId = $($_.Id)").CommandLine
253
- }} catch {{
254
- $cmdline = $_.ProcessName
255
- }}
256
-
257
- if ($cmdline -and $cmdline -ne "") {{
258
- if ($cmdline -like "*PowerShell*" -and $cmdline -like "*Get-Process*") {{ return }}
259
-
260
- $matchesPrimary = $cmdline -like "*$primaryCmd*" -and $primaryCmd -ne "powershell"
261
- $matchCount = 0
262
- foreach ($part in $cmdParts[1..($cmdParts.Length-1)]) {{
263
- if ($cmdline -like "*$part*") {{ $matchCount++ }}
264
- }}
265
-
266
- if ($matchesPrimary -and $matchCount -ge 1) {{
267
- $procInfo = @{{
268
- "pid" = $_.Id
269
- "name" = $_.ProcessName
270
- "cmdline" = $cmdline
271
- "status" = $_.Status
272
- "start_time" = $_.StartTime
273
- }} | ConvertTo-Json -Compress
274
- Write-Output $procInfo
243
+ try {{
244
+ $processes = Get-Process -Name '{primary_cmd}' -ErrorAction SilentlyContinue
245
+ if ($processes) {{
246
+ $processes | ForEach-Object {{
247
+ $procInfo = @{{
248
+ "pid" = $_.Id
249
+ "name" = $_.ProcessName
250
+ "start_time" = $_.StartTime.ToString()
275
251
  }}
252
+ Write-Output ($procInfo | ConvertTo-Json -Compress)
276
253
  }}
277
- }} catch {{
278
- # Ignore processes we can't access
279
254
  }}
255
+ }} catch {{
256
+ # No processes found or other error
280
257
  }}
281
258
  """
282
259
 
283
- result = subprocess.run(["powershell", "-Command", ps_script], capture_output=True, text=True, timeout=15)
260
+ result = subprocess.run([POWERSHELL_CMD, "-Command", ps_script], capture_output=True, text=True, timeout=5)
284
261
 
285
262
  if result.returncode == 0:
286
263
  output_lines = [line.strip() for line in result.stdout.strip().split("\n") if line.strip()]
@@ -301,6 +278,9 @@ Get-Process | ForEach-Object {{
301
278
  else:
302
279
  return {"status": "error", "error": f"Command failed: {result.stderr}", "running": False, "command": command, "tab_name": tab_name}
303
280
 
281
+ except subprocess.TimeoutExpired:
282
+ logger.error(f"Timeout checking command status for tab '{tab_name}'")
283
+ return {"status": "timeout", "error": "Timeout checking process status", "running": False, "command": command, "tab_name": tab_name}
304
284
  except Exception as e:
305
285
  logger.error(f"Error checking command status for tab '{tab_name}': {e}")
306
286
  return {"status": "error", "error": str(e), "running": False, "command": command, "tab_name": tab_name}
@@ -400,29 +380,22 @@ wt new-tab --title "{tab_name}" {cwd_part} "{command}"
400
380
 
401
381
 
402
382
  if __name__ == "__main__":
403
- # Example usage with new schema
404
- sample_layout: LayoutConfig = {"layoutName": "TestLayout", "layoutTabs": [{"tabName": "Frontend", "startDir": "~/code", "command": "btm"}, {"tabName": "Monitor", "startDir": "~", "command": "lf"}]}
405
-
383
+ sample_layout: LayoutConfig = {"layoutName": "TestLayout",
384
+ "layoutTabs": [
385
+ {"tabName": "Frontend", "startDir": "~/code", "command": "btm"},
386
+ {"tabName": "Monitor", "startDir": "~", "command": "lf"}
387
+ ]}
406
388
  try:
407
- # Create layout using the generator
408
389
  generator = WTLayoutGenerator()
409
- script_path = generator.create_wt_layout(sample_layout, None)
390
+ script_path = generator.create_wt_layout(layout_config=sample_layout, output_dir=None)
410
391
  print(f"✅ Windows Terminal layout created: {script_path}")
411
-
412
- # Show preview
413
- preview = generator.get_wt_layout_preview(sample_layout)
414
- print(f"\n📋 Command Preview:\n{preview}")
415
-
416
- # Check status (won't find anything since we haven't run it)
417
- print("\n🔍 Current status:")
392
+ preview = generator.get_wt_layout_preview(layout_config=sample_layout)
393
+ print(f"📋 Command Preview:\n{preview}")
394
+ print("🔍 Current status:")
418
395
  generator.print_status_report()
419
-
420
- # Show how to run the layout
421
- print("\n▶️ To run this layout, execute:")
396
+ print("▶️ To run this layout, execute:")
422
397
  print(f' powershell -ExecutionPolicy Bypass -File "{script_path}"')
423
-
424
398
  except Exception as e:
425
399
  print(f"❌ Error: {e}")
426
400
  import traceback
427
-
428
401
  traceback.print_exc()
@@ -5,7 +5,6 @@ import typer
5
5
  from rich.console import Console
6
6
  from rich.panel import Panel
7
7
  from rich.table import Table
8
- from platform import system
9
8
  from typing import Optional, cast, get_args
10
9
  from machineconfig.jobs.installer.package_groups import PACKAGE_GROUPS
11
10
 
@@ -45,15 +44,12 @@ def _handle_installer_not_found(search_term: str, all_installers: list["Installe
45
44
  if len(all_installers) > 10:
46
45
  console.print(f" [dim]... and {len(all_installers) - 10} more[/dim]")
47
46
 
48
- panel = Panel(
49
- f"[bold blue]💡 Use 'ia' to interactively browse all available installers.[/bold blue]\n[bold blue]💡 Use one of the categories: {list(get_args(PACKAGE_GROUPS))}[/bold blue]", title="[yellow]Helpful Tips[/yellow]", border_style="yellow"
50
- )
47
+ panel = Panel(f"[bold blue]💡 Use 'ia' to interactively browse all available installers.[/bold blue]\n[bold blue]💡 Use one of the categories: {list(get_args(PACKAGE_GROUPS))}[/bold blue]", title="[yellow]Helpful Tips[/yellow]", border_style="yellow")
51
48
  console.print(panel)
52
49
 
53
50
 
54
51
  def main_with_parser():
55
52
  import typer
56
-
57
53
  app = typer.Typer()
58
54
  app.command()(main)
59
55
  app()
@@ -122,11 +118,12 @@ def get_programs_by_category(package_group: PACKAGE_GROUPS):
122
118
  case "DEV_SYSTEM" | "ESSENTIAL_SYSTEM":
123
119
  options_system = get_installers_system_groups()
124
120
  from machineconfig.utils.schemas.installer.installer_types import get_normalized_arch, get_os_name
121
+ from machineconfig.utils.code import run_script
125
122
  for an_item in options_system:
126
123
  if an_item["appName"] == package_group:
127
124
  program = an_item["fileNamePattern"][get_normalized_arch()][get_os_name()]
128
125
  if program is not None:
129
- install_terminal_packages(program)
126
+ run_script(program)
130
127
 
131
128
 
132
129
  def choose_from_system_package_groups(options_system: dict[str, tuple[str, str]]) -> str:
@@ -150,33 +147,6 @@ def choose_from_system_package_groups(options_system: dict[str, tuple[str, str]]
150
147
  return program
151
148
 
152
149
 
153
- def install_terminal_packages(program: str):
154
- from pathlib import Path
155
-
156
- if system() == "Windows":
157
- temp_script_path = Path("C:/Windows/Temp/temp_install_script.ps1")
158
- lexer = "powershell"
159
- else:
160
- temp_script_path = Path("/tmp/temp_install_script.sh")
161
- lexer = "bash"
162
- temp_script_path.write_text(program, encoding="utf-8")
163
- console.print(f"📝 [blue]Temporary script written to:[/blue] [green]{temp_script_path}[/green]")
164
- from rich.syntax import Syntax
165
-
166
- console.print(Panel(Syntax(code=program, lexer=lexer), title="📄 Installation Program", subtitle="shell code"), style="bold red")
167
- console.print("🚀 [bold yellow]Starting installation...[/bold yellow]")
168
- if system() == "Windows":
169
- import subprocess
170
-
171
- subprocess.run(["powershell", "-ExecutionPolicy", "Bypass", "-File", str(temp_script_path)], check=True)
172
- elif system() == "Linux":
173
- import subprocess
174
-
175
- subprocess.run(["bash", str(temp_script_path)], check=True)
176
- console.print("✅ [bold green]Installation completed.[/bold green]")
177
- temp_script_path.unlink(missing_ok=True)
178
-
179
-
180
150
  def install_clis(clis_names: list[str]):
181
151
  from machineconfig.utils.schemas.installer.installer_types import get_normalized_arch, get_os_name
182
152
  from machineconfig.utils.installer import get_installers
@@ -7,6 +7,7 @@ fire
7
7
 
8
8
  """
9
9
 
10
+ from machineconfig.scripts.python.fire_jobs_route_helper import get_command_streamlit
10
11
  from machineconfig.scripts.python.helpers.helpers4 import search_for_files_of_interest
11
12
  from machineconfig.scripts.python.helpers.helpers4 import parse_pyfile
12
13
  from machineconfig.scripts.python.helpers.helpers4 import get_import_module_code
@@ -20,9 +21,7 @@ from machineconfig.scripts.python.fire_jobs_args_helper import FireJobArgs, extr
20
21
  import platform
21
22
  from typing import Optional, Annotated
22
23
  from pathlib import Path
23
- import tomllib
24
24
  import typer
25
- # import os
26
25
 
27
26
 
28
27
  def route(args: FireJobArgs, fire_args: str = "") -> None:
@@ -86,73 +85,13 @@ def route(args: FireJobArgs, fire_args: str = "") -> None:
86
85
  choice_function = args.function
87
86
 
88
87
  if choice_file.suffix == ".py":
89
- if args.streamlit:
90
- import socket
91
-
92
- s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
93
- try:
94
- s.connect(("8.8.8.8", 1))
95
- local_ip_v4 = s.getsockname()[0]
96
- except Exception:
97
- local_ip_v4 = socket.gethostbyname(socket.gethostname())
98
- finally:
99
- s.close()
100
- computer_name = platform.node()
101
- port = 8501
102
- toml_path: Optional[PathExtended] = None
103
- toml_path_maybe = choice_file.parent.joinpath(".streamlit/config.toml")
104
- if toml_path_maybe.exists():
105
- toml_path = toml_path_maybe
106
- elif choice_file.parent.name == "pages":
107
- toml_path_maybe = choice_file.parent.parent.joinpath(".streamlit/config.toml")
108
- if toml_path_maybe.exists():
109
- toml_path = toml_path_maybe
110
- if toml_path is not None:
111
- print(f"📄 Reading config.toml @ {toml_path}")
112
- config = tomllib.loads(toml_path.read_text(encoding="utf-8"))
113
- if "server" in config:
114
- if "port" in config["server"]:
115
- port = config["server"]["port"]
116
- secrets_path = toml_path.with_name("secrets.toml")
117
- if repo_root is not None:
118
- secrets_template_path = PathExtended.home().joinpath(f"dotfiles/creds/streamlit/{PathExtended(repo_root).name}/{choice_file.name}/secrets.toml")
119
- if args.environment != "" and not secrets_path.exists() and secrets_template_path.exists():
120
- secrets_template = tomllib.loads(secrets_template_path.read_text(encoding="utf-8"))
121
- if args.environment == "ip":
122
- host_url = f"http://{local_ip_v4}:{port}/oauth2callback"
123
- elif args.environment == "localhost":
124
- host_url = f"http://localhost:{port}/oauth2callback"
125
- elif args.environment == "hostname":
126
- host_url = f"http://{computer_name}:{port}/oauth2callback"
127
- else:
128
- host_url = f"http://{args.environment}:{port}/oauth2callback"
129
- try:
130
- secrets_template["auth"]["redirect_uri"] = host_url
131
- secrets_template["auth"]["cookie_secret"] = randstr(35)
132
- secrets_template["auth"]["auth0"]["redirect_uri"] = host_url
133
- # save_toml(obj=secrets_template, path=secrets_path)
134
- except Exception as ex:
135
- print(ex)
136
- raise ex
137
- message = f"🚀 Streamlit app is running @:\n1- http://{local_ip_v4}:{port}\n2- http://{computer_name}:{port}\n3- http://localhost:{port}"
138
- from rich.panel import Panel
139
- from rich import print as rprint
140
-
141
- rprint(Panel(message))
142
- exe = f"streamlit run --server.address 0.0.0.0 --server.headless true --server.port {port}"
143
- # exe = f"cd '{choice_file.parent}'; " + exe
144
- elif args.interactive is False:
145
- exe = "python"
146
- elif args.jupyter:
147
- exe = "jupyter-lab"
148
- else:
149
- exe = f"ipython -i --no-banner --profile {ipy_profile} "
150
- elif choice_file.suffix == ".ps1" or choice_file.suffix == ".sh":
151
- exe = "."
152
- elif choice_file.suffix == "":
153
- exe = ""
154
- else:
155
- raise NotImplementedError(f"File type {choice_file.suffix} not supported, in the sense that I don't know how to fire it.")
88
+ if args.streamlit: exe = get_command_streamlit(choice_file, args.environment, repo_root)
89
+ elif args.interactive is False: exe = "python"
90
+ elif args.jupyter: exe = "jupyter-lab"
91
+ else: exe = f"ipython -i --no-banner --profile {ipy_profile} "
92
+ elif choice_file.suffix == ".ps1" or choice_file.suffix == ".sh": exe = "."
93
+ elif choice_file.suffix == "": exe = ""
94
+ else: raise NotImplementedError(f"File type {choice_file.suffix} not supported, in the sense that I don't know how to fire it.")
156
95
 
157
96
  if args.module or (args.debug and args.choose_function): # because debugging tools do not support choosing functions and don't interplay with fire module. So the only way to have debugging and choose function options is to import the file as a module into a new script and run the function of interest there and debug the new script.
158
97
  assert choice_file.suffix == ".py", f"File must be a python file to be imported as a module. Got {choice_file}"
@@ -226,21 +165,10 @@ except ImportError as _ex:
226
165
  else:
227
166
  # command = f"cd {choice_file.parent}\n{exe} {choice_file.name}\ncd {PathExtended.cwd()}"
228
167
  command = f"{exe} {choice_file} "
229
- if not args.cmd:
230
- if "ipdb" in command:
231
- command = f"pip install ipdb\n{command}"
232
- if "pudb" in command:
233
- command = f"pip install pudb\n{command}"
234
- command = f"{activate_ve_line}\n{command}"
168
+ if not args.cmd: command = f"{activate_ve_line}\n{command}"
235
169
  else:
236
- # CMD equivalent
237
- if "ipdb" in command:
238
- command = f"pip install ipdb & {command}"
239
- if "pudb" in command:
240
- command = f"pip install pudb & {command}"
241
170
  new_line = "\n"
242
171
  command = rf"""start cmd -Argument "/k {activate_ve_line.replace(".ps1", ".bat").replace(". ", "")} & {command.replace(new_line, " & ")} " """ # this works from powershell
243
-
244
172
  if args.submit_to_cloud:
245
173
  command = f"""
246
174
  {activate_ve_line}
@@ -251,39 +179,28 @@ python -m machineconfig.cluster.templates.cli_click --file {choice_file} """
251
179
  if args.Nprocess > 1:
252
180
  from machineconfig.cluster.sessions_managers.zellij_local import run_zellij_layout
253
181
  from machineconfig.utils.schemas.layouts.layout_types import LayoutConfig
254
-
255
182
  layout: LayoutConfig = {"layoutName": "fireNprocess", "layoutTabs": []}
256
183
  for an_arg in range(args.Nprocess):
257
184
  layout["layoutTabs"].append({"tabName": f"tab{an_arg}", "startDir": str(PathExtended.cwd()), "command": f"uv run -m fire {choice_file} {choice_function} --idx={an_arg} --idx_max={args.Nprocess}"})
258
185
  run_zellij_layout(layout_config=layout)
259
186
  return None
260
-
261
187
  if args.optimized:
262
- # note that in ipython, optimization is meaningless.
263
188
  command = command.replace("python ", "python -OO ")
264
- # if platform.system() == "Linux":
265
- # command = "timeout 1s aafire -driver slang\nclear\n" + command
266
-
267
189
  from rich.panel import Panel
268
190
  from rich.console import Console
269
191
  from rich.syntax import Syntax
270
-
271
192
  console = Console()
272
-
273
193
  if args.zellij_tab is not None:
274
194
  comman_path__ = PathExtended.tmpfile(suffix=".sh")
275
195
  comman_path__.parent.mkdir(parents=True, exist_ok=True)
276
196
  comman_path__.write_text(command, encoding="utf-8")
277
197
  console.print(Panel(Syntax(command, lexer="shell"), title=f"🔥 fire command @ {comman_path__}: "), style="bold red")
278
198
  import subprocess
279
-
280
199
  existing_tab_names = subprocess.run(["zellij", "action", "query-tab-names"], capture_output=True, text=True, check=True).stdout.splitlines()
281
200
  if args.zellij_tab in existing_tab_names:
282
201
  print(f"⚠️ Tab name `{args.zellij_tab}` already exists. Please choose a different name.")
283
- # args.zellij_tab = input("Please enter a new tab name: ")
284
202
  args.zellij_tab += f"_{randstr(3)}"
285
203
  from machineconfig.cluster.sessions_managers.zellij_local import run_command_in_zellij_tab
286
-
287
204
  command = run_command_in_zellij_tab(command=str(comman_path__), tab_name=args.zellij_tab, cwd=None)
288
205
  if args.watch:
289
206
  command = "watchexec --restart --exts py,sh,ps1 " + command
@@ -293,31 +210,19 @@ python -m machineconfig.cluster.templates.cli_click --file {choice_file} """
293
210
  if platform.system() in ["Linux", "Darwin"]:
294
211
  export_line = f"""export PYTHONPATH="{repo_root}""" + """:${PYTHONPATH}" """
295
212
  elif platform.system() == "Windows":
296
- # export_line = f"""set PYTHONPATH="{repo_root}""" + """:%PYTHONPATH%" """
297
- # powershell equivalent
298
213
  export_line = f"""$env:PYTHONPATH="{repo_root}""" + """:$env:PYTHONPATH" """
299
214
  else:
300
215
  raise NotImplementedError(f"Platform {platform.system()} not supported.")
301
216
  command = export_line + "\n" + command
302
-
303
- # program_path = os.environ.get("op_script", None)
304
- # program_path = PathExtended(program_path) if program_path is not None else PROGRAM_PATH
305
217
  if args.loop:
306
218
  if platform.system() in ["Linux", "Darwin"]:
307
219
  command = command + "\nsleep 0.5"
308
220
  elif platform.system() == "Windows":
309
- # command = command + "timeout 0.5\n"
310
- # pwsh equivalent
311
221
  command = "$ErrorActionPreference = 'SilentlyContinue';\n" + command + "\nStart-Sleep -Seconds 0.5"
312
222
  else:
313
223
  raise NotImplementedError(f"Platform {platform.system()} not supported.")
314
- # command = command + f"\n. {program_path}"
315
- console.print(Panel(Syntax(command, lexer="shell"), title=f"🔥 fire command @ {command}: "), style="bold red")
316
- # program_path.parent.mkdir(parents=True, exist_ok=True)
317
- # program_path.write_text(command, encoding="utf-8")
318
- import subprocess
319
-
320
- subprocess.run(command, shell=True, check=True)
224
+ from machineconfig.utils.code import run_script
225
+ run_script(command)
321
226
 
322
227
 
323
228
  def main(
@@ -44,6 +44,10 @@ def extract_kwargs(args: FireJobArgs) -> dict[str, object]:
44
44
 
45
45
  # Look for Fire-style arguments in sys.argv
46
46
  for arg in sys.argv:
47
+ # Skip the -- separator
48
+ if arg == '--':
49
+ continue
50
+
47
51
  # Match patterns like --key=value or --key value (but we'll focus on --key=value)
48
52
  if arg.startswith('--') and '=' in arg:
49
53
  key, value = arg[2:].split('=', 1) # Remove -- prefix and split on first =
@@ -53,6 +57,11 @@ def extract_kwargs(args: FireJobArgs) -> dict[str, object]:
53
57
  elif arg.startswith('--') and '=' not in arg:
54
58
  # Handle boolean flags like --debug
55
59
  key = arg[2:] # Remove -- prefix
60
+
61
+ # Skip empty key (this would happen if someone just used '--')
62
+ if not key:
63
+ continue
64
+
56
65
  # Check if next argument exists and doesn't start with --
57
66
  arg_index = sys.argv.index(arg)
58
67
  if arg_index + 1 < len(sys.argv) and not sys.argv[arg_index + 1].startswith('--'):
@@ -0,0 +1,65 @@
1
+
2
+
3
+ import platform
4
+ from typing import Optional
5
+ import tomllib
6
+ from pathlib import Path
7
+ from machineconfig.utils.accessories import randstr
8
+ from machineconfig.utils.path_extended import PathExtended
9
+
10
+
11
+ def get_command_streamlit(choice_file: Path, environment: str, repo_root: Optional[Path]) -> str:
12
+ import socket
13
+ s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
14
+ try:
15
+ s.connect(("8.8.8.8", 1))
16
+ local_ip_v4 = s.getsockname()[0]
17
+ except Exception:
18
+ local_ip_v4 = socket.gethostbyname(socket.gethostname())
19
+ finally:
20
+ s.close()
21
+ computer_name = platform.node()
22
+ port = 8501
23
+ toml_path: Optional[Path] = None
24
+ toml_path_maybe = choice_file.parent.joinpath(".streamlit/config.toml")
25
+ if toml_path_maybe.exists():
26
+ toml_path = toml_path_maybe
27
+ elif choice_file.parent.name == "pages":
28
+ toml_path_maybe = choice_file.parent.parent.joinpath(".streamlit/config.toml")
29
+ if toml_path_maybe.exists():
30
+ toml_path = toml_path_maybe
31
+ if toml_path is not None:
32
+ print(f"📄 Reading config.toml @ {toml_path}")
33
+ config = tomllib.loads(toml_path.read_text(encoding="utf-8"))
34
+ if "server" in config:
35
+ if "port" in config["server"]:
36
+ port = config["server"]["port"]
37
+ secrets_path = toml_path.with_name("secrets.toml")
38
+ if repo_root is not None:
39
+ secrets_template_path = Path.home().joinpath(f"dotfiles/creds/streamlit/{PathExtended(repo_root).name}/{choice_file.name}/secrets.toml")
40
+ if environment != "" and not secrets_path.exists() and secrets_template_path.exists():
41
+ secrets_template = tomllib.loads(secrets_template_path.read_text(encoding="utf-8"))
42
+ if environment == "ip":
43
+ host_url = f"http://{local_ip_v4}:{port}/oauth2callback"
44
+ elif environment == "localhost":
45
+ host_url = f"http://localhost:{port}/oauth2callback"
46
+ elif environment == "hostname":
47
+ host_url = f"http://{computer_name}:{port}/oauth2callback"
48
+ else:
49
+ host_url = f"http://{environment}:{port}/oauth2callback"
50
+ try:
51
+ secrets_template["auth"]["redirect_uri"] = host_url
52
+ secrets_template["auth"]["cookie_secret"] = randstr(35)
53
+ secrets_template["auth"]["auth0"]["redirect_uri"] = host_url
54
+ # save_toml(obj=secrets_template, path=secrets_path)
55
+ except Exception as ex:
56
+ print(ex)
57
+ raise ex
58
+ message = f"🚀 Streamlit app is running @:\n1- http://{local_ip_v4}:{port}\n2- http://{computer_name}:{port}\n3- http://localhost:{port}"
59
+ from rich.panel import Panel
60
+ from rich import print as rprint
61
+
62
+ rprint(Panel(message))
63
+ exe = f"streamlit run --server.address 0.0.0.0 --server.headless true --server.port {port}"
64
+ # exe = f"cd '{choice_file.parent}'; " + exe
65
+ return exe
@@ -1,7 +1,6 @@
1
- from typing import Any, Callable, Optional
2
- import inspect
3
- import os
4
1
 
2
+ from typing import Optional
3
+ import os
5
4
  from machineconfig.utils.path_extended import PathExtended as PathExtended
6
5
 
7
6
 
@@ -21,19 +20,6 @@ def search_for_files_of_interest(path_obj: PathExtended):
21
20
  return files
22
21
 
23
22
 
24
- def convert_kwargs_to_fire_kwargs_str(kwargs: dict[str, Any]) -> str:
25
- # https://google.github.io/python-fire/guide/
26
- # https://github.com/google/python-fire/blob/master/docs/guide.md#argument-parsing
27
- if not kwargs: # empty dict
28
- kwargs_str = ""
29
- else:
30
- # For fire module, all keyword arguments should be passed as --key value pairs
31
- tmp_list: list[str] = []
32
- for k, v in kwargs.items():
33
- tmp_list.append(f"--{k} {v}")
34
- kwargs_str = " " + " ".join(tmp_list) + " "
35
- return kwargs_str
36
-
37
23
 
38
24
  def parse_pyfile(file_path: str):
39
25
  print(f"🔍 Loading {file_path} ...")
@@ -84,58 +70,6 @@ def parse_pyfile(file_path: str):
84
70
  return options, func_args
85
71
 
86
72
 
87
- def interactively_run_function(func: Callable[[Any], Any]):
88
- sig = inspect.signature(func)
89
- params = list(sig.parameters.values())
90
- args = []
91
- kwargs = {}
92
- for param in params:
93
- if param.annotation is not inspect.Parameter.empty:
94
- hint = f" ({param.annotation.__name__})"
95
- else:
96
- hint = ""
97
- if param.default is not inspect.Parameter.empty:
98
- default = param.default
99
- value = input(f"Please enter a value for argument `{param.name}` (type = {hint}) (default = {default}) : ")
100
- if value == "":
101
- value = default
102
- else:
103
- value = input(f"Please enter a value for argument `{param.name}` (type = {hint}) : ")
104
- try:
105
- if param.annotation is not inspect.Parameter.empty:
106
- value = param.annotation
107
- except (TypeError, ValueError) as err:
108
- raise ValueError(f"Invalid input: {value} is not of type {param.annotation}") from err
109
- if param.kind == inspect.Parameter.KEYWORD_ONLY:
110
- kwargs[param.name] = value
111
- else:
112
- args.append((param.name, value))
113
- args_to_kwargs = dict(args)
114
- return args_to_kwargs, kwargs
115
-
116
-
117
- def get_attrs_recursively(obj: Any):
118
- if hasattr(obj, "__dict__"):
119
- res = {}
120
- for k, v in obj.__dict__.items():
121
- res[k] = get_attrs_recursively(v)
122
- return res
123
- return obj
124
-
125
-
126
- # def run_on_remote(func_file: str, args: argparse.Namespace):
127
- # host = choose_ssh_host(multi=False)
128
- # assert isinstance(host, str), f"host must be a string. Got {type(host)}"
129
- # from machineconfig.cluster.remote_machine import RemoteMachine, RemoteMachineConfig
130
- # config = RemoteMachineConfig(copy_repo=True, update_repo=False, update_essential_repos=True,
131
- # notify_upon_completion=True, ssh_params=dict(host=host),
132
- # # to_email=None, email_config_name='enaut',
133
- # data=[],
134
- # ipython=False, interactive=args.interactive, pdb=False, pudb=args.debug, wrap_in_try_except=False,
135
- # transfer_method="sftp")
136
- # m = RemoteMachine(func=func_file, func_kwargs=None, config=config)
137
- # m.run()
138
-
139
73
 
140
74
  def find_repo_root_path(start_path: str) -> Optional[str]:
141
75
  root_files = ["setup.py", "pyproject.toml", ".git"]
@@ -0,0 +1 @@
1
+ uv run --python 3.13 --no-dev --project $HOME/code/machineconfig agents $args
@@ -0,0 +1 @@
1
+ uv run --python 3.13 --no-dev --project $HOME/code/machineconfig sessions $args
@@ -21,13 +21,11 @@ echo "Executing `{exec_line}`"
21
21
  {exec_line}
22
22
  deactivate || true
23
23
  """
24
-
25
24
  if strict_execution:
26
25
  if platform.system() == "Windows":
27
26
  shell_script = """$ErrorActionPreference = "Stop" """ + "\n" + shell_script
28
27
  if platform.system() in ["Linux", "Darwin"]:
29
28
  shell_script = "set -e" + "\n" + shell_script
30
-
31
29
  if platform.system() in ["Linux", "Darwin"]:
32
30
  shell_script = "#!/bin/bash" + "\n" + shell_script # vs #!/usr/bin/env bash
33
31
  return shell_script
@@ -35,10 +33,8 @@ deactivate || true
35
33
 
36
34
  def get_shell_file_executing_python_script(python_script: str, ve_path: str, verbose: bool = True):
37
35
  if verbose:
38
- python_script = (
39
- f"""
40
- code = r'''{python_script}''' """
41
- + """
36
+ python_script = f"""
37
+ code = r'''{python_script}'''
42
38
  try:
43
39
  from machineconfig.utils.utils import print_code
44
40
  print_code(code=code, lexer="python", desc="Python Script")
@@ -47,9 +43,7 @@ except ImportError:
47
43
  from rich.panel import Panel
48
44
  console = Console()
49
45
  console.print(Panel(f'''📜 PYTHON SCRIPT:\n\n{{code}}''', title="Python Script", expand=False))
50
- """
51
- + python_script
52
- )
46
+ """ + python_script
53
47
  python_file = PathExtended.tmp().joinpath("tmp_scripts", "python", randstr() + ".py")
54
48
  python_file.parent.mkdir(parents=True, exist_ok=True)
55
49
  python_file.write_text(python_script, encoding="utf-8")
@@ -71,11 +65,6 @@ def write_shell_script_to_file(shell_script: str):
71
65
  return shell_file
72
66
 
73
67
 
74
- # Enhanced print/log/error/exception statements for better clarity and consistency
75
- # Improved formatting and language of messages
76
- # Ensured consistent use of f-strings with triple quotes where applicable
77
-
78
-
79
68
  def write_shell_script_to_default_program_path(program: str, desc: str, preserve_cwd: bool, display: bool, execute: bool):
80
69
  if preserve_cwd:
81
70
  if platform.system() == "Windows":
@@ -84,8 +73,6 @@ def write_shell_script_to_default_program_path(program: str, desc: str, preserve
84
73
  program = 'orig_path=$(cd -- "." && pwd)\n' + program + '\ncd "$orig_path" || exit'
85
74
  if display:
86
75
  print_code(code=program, lexer="shell", desc=desc, subtitle="PROGRAM")
87
- # PROGRAM_PATH.parent.mkdir(parents=True, exist_ok=True)
88
- # PROGRAM_PATH.write_text(program, encoding="utf-8")
89
76
  if execute:
90
77
  result = subprocess.run(program, shell=True, capture_output=True, text=True)
91
78
  success = result.returncode == 0 and result.stderr == ""
@@ -109,3 +96,27 @@ def print_code(code: str, lexer: str, desc: str, subtitle: str = ""):
109
96
  raise NotImplementedError(f"Platform {platform.system()} not supported for lexer {lexer}")
110
97
  console = Console()
111
98
  console.print(Panel(Syntax(code=code, lexer=lexer), title=f"📄 {desc}", subtitle=subtitle), style="bold red")
99
+
100
+
101
+ def run_script(program: str):
102
+ import tempfile
103
+ if platform.system() == "Windows":
104
+ suffix = ".ps1"
105
+ lexer = "powershell"
106
+ else:
107
+ suffix = ".sh"
108
+ lexer = "bash"
109
+ with tempfile.NamedTemporaryFile(mode='w', suffix=suffix, delete=False, encoding='utf-8') as temp_file:
110
+ temp_file.write(program)
111
+ temp_script_path = PathExtended(temp_file.name)
112
+ console = Console()
113
+ # console.print(f"📝 [blue]Temporary script written to:[/blue] [green]{temp_script_path}[/green]")
114
+ from rich.syntax import Syntax
115
+ console.print(Panel(Syntax(code=program, lexer=lexer), title=f"📄script @ {temp_script_path}", subtitle="shell code"), style="bold red")
116
+ if platform.system() == "Windows":
117
+ import subprocess
118
+ subprocess.run(["powershell", "-ExecutionPolicy", "Bypass", "-File", str(temp_script_path)], check=True, shell=True)
119
+ elif platform.system() == "Linux" or platform.system() == "Darwin":
120
+ import subprocess
121
+ subprocess.run(["bash", str(temp_script_path)], check=True, shell=True)
122
+ temp_script_path.unlink(missing_ok=True)
machineconfig/utils/ve.py CHANGED
@@ -1,10 +1,10 @@
1
- from machineconfig.utils.path_extended import PathExtended as PathExtended
2
1
  from machineconfig.utils.io import read_ini
3
2
  import platform
4
3
  from typing import Optional
4
+ from pathlib import Path
5
5
 
6
6
 
7
- def get_ve_path_and_ipython_profile(init_path: PathExtended) -> tuple[Optional[str], Optional[str]]:
7
+ def get_ve_path_and_ipython_profile(init_path: Path) -> tuple[Optional[str], Optional[str]]:
8
8
  """Works with .ve.ini .venv and .ve_path"""
9
9
  ve_path: Optional[str] = None
10
10
  ipy_profile: Optional[str] = None
@@ -40,7 +40,8 @@ def get_ve_path_and_ipython_profile(init_path: PathExtended) -> tuple[Optional[s
40
40
 
41
41
  def get_ve_activate_line(ve_root: str):
42
42
  if platform.system() == "Windows":
43
- activate_ve_line = f". {ve_root}/Scripts/activate.ps1"
43
+ q = Path(ve_root).expanduser().relative_to(Path.home()).as_posix()
44
+ activate_ve_line = f". $HOME/{q}/Scripts/activate.ps1"
44
45
  elif platform.system() in ["Linux", "Darwin"]:
45
46
  activate_ve_line = f". {ve_root}/bin/activate"
46
47
  else:
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: machineconfig
3
- Version: 4.93
3
+ Version: 4.96
4
4
  Summary: Dotfiles management package
5
5
  Author-email: Alex Al-Saffar <programmer@usa.com>
6
6
  License: Apache 2.0
@@ -11,7 +11,8 @@ machineconfig/cluster/remote/remote_machine.py,sha256=xRuoHKNsIT0-FTFSvF1q7scnGK
11
11
  machineconfig/cluster/remote/script_execution.py,sha256=4U70FDtjOh6A6C2Ei-Xh90S888q64VhRPbExoEbdepk,9980
12
12
  machineconfig/cluster/remote/script_notify_upon_completion.py,sha256=GRxnnbnOl1-hTovTN-zI_M9wdV7x293yA77_mou9I1o,2032
13
13
  machineconfig/cluster/sessions_managers/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
14
- machineconfig/cluster/sessions_managers/wt_local.py,sha256=-e4yNxvu6ytI-u1Kihhtn_wd_qNKZMzN_WrZ9ab1qYA,18220
14
+ machineconfig/cluster/sessions_managers/ffile.py,sha256=QzkBU5Ysnah9SxlzODsGprx4Q_VskWntChoejaOCEdw,52
15
+ machineconfig/cluster/sessions_managers/wt_local.py,sha256=cnLAcyVUr2d2ZPh0dEEr-LHrLiwTMVu7YWXM21IS7_4,17507
15
16
  machineconfig/cluster/sessions_managers/wt_local_manager.py,sha256=BaJNOOY5rAfssreJm8Nmr4we_PCxMkmQqzUMdimNwaM,24565
16
17
  machineconfig/cluster/sessions_managers/wt_remote.py,sha256=XmZV9rLubwxND5UYAS15mAcpzDdXvm4KyubVGYkVBmo,8743
17
18
  machineconfig/cluster/sessions_managers/wt_remote_manager.py,sha256=CnnOtPiwLx0pIfs_KlcKnclLSqiDTNzfm8t8sW6nXf0,19764
@@ -151,15 +152,16 @@ machineconfig/scripts/python/devops.py,sha256=fTEut6gTDfmNqzS8-gRyRAsmWJYPGGIt8X
151
152
  machineconfig/scripts/python/devops_add_identity.py,sha256=JfN3ZrYMCgmt4ks_VCfnV9BIIHAsOYO3E0W0wZ15FR8,3791
152
153
  machineconfig/scripts/python/devops_add_ssh_key.py,sha256=KaoX83KltBsmutfKhSfZjd7nP_R1hJ2OLAWRhbswO7o,6889
153
154
  machineconfig/scripts/python/devops_backup_retrieve.py,sha256=jZe5Vki7E2GCMG8hvqUZeOONFC4cNzISoGzq_dMG4GA,5601
154
- machineconfig/scripts/python/devops_devapps_install.py,sha256=U3Kl8QCHKmQg3o7c2IRsmFM25fGMX1CoH9wvkf2tdeU,10234
155
+ machineconfig/scripts/python/devops_devapps_install.py,sha256=T4h1ydHljQJrNBrye2q-FHUX9iAZnkCa889GgBjHZCE,9103
155
156
  machineconfig/scripts/python/devops_update_repos.py,sha256=c5qBc9cuTGDEqDHufkjDT4d_vvJsswv3tlqk9MAulYk,8063
156
157
  machineconfig/scripts/python/dotfile.py,sha256=SRcX-9Ak1jRvF-killBTTm2IWcsNxfiLucH6ZsytAFA,2202
157
158
  machineconfig/scripts/python/fire_agents_help_launch.py,sha256=1ymWiszfjCyPv3ofinWzfOmbzLEt3d7ntac_afLh-V4,5017
158
159
  machineconfig/scripts/python/fire_agents_help_search.py,sha256=qIfSS_su2YJ1Gb0_lu4cbjlJlYMBw0v52NTGiSrGjk8,2991
159
160
  machineconfig/scripts/python/fire_agents_helper_types.py,sha256=zKu8Vr6iucaGSkCm_Tkt_WrYU7-6Nript3coYyzTXzY,295
160
161
  machineconfig/scripts/python/fire_agents_load_balancer.py,sha256=mpqx3uaQdBXYieuvhdK-qsvLepf9oIMo3pwPj9mSEDI,1079
161
- machineconfig/scripts/python/fire_jobs.py,sha256=bad66rJK0_hsSzInXpXp_R-eXNyDMRvVV14zA5nANMg,20271
162
- machineconfig/scripts/python/fire_jobs_args_helper.py,sha256=VZIQ6ShZBt2WLcqa1fpl1419AGa0k7Xg-EzzrKpDIqw,4029
162
+ machineconfig/scripts/python/fire_jobs.py,sha256=CqtFt4VGtdEP0tbmRRZ-qU5G232jQj0umlS8C_qtQRM,15911
163
+ machineconfig/scripts/python/fire_jobs_args_helper.py,sha256=-gl5I-26Op12nToIpAA-YEpvn8MMkNlI5XjhUbj50I0,4273
164
+ machineconfig/scripts/python/fire_jobs_route_helper.py,sha256=EFWsg6F9TeSAtYQec57WtPopUbm2euGZTUZv6J4RhNE,3026
163
165
  machineconfig/scripts/python/fire_jobs_streamlit_helper.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
164
166
  machineconfig/scripts/python/ftpx.py,sha256=l_gdJS0QB2wVZErubtZvm4HJD9HZAJxSP68sbY73xwo,10278
165
167
  machineconfig/scripts/python/get_zellij_cmd.py,sha256=e35-18hoXM9N3PFbvbizfkNY_-63iMicieWE3TbGcCQ,576
@@ -216,9 +218,10 @@ machineconfig/scripts/python/ai/solutions/opencode/opencode.py,sha256=AbpHGcgLb-
216
218
  machineconfig/scripts/python/helpers/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
217
219
  machineconfig/scripts/python/helpers/cloud_helpers.py,sha256=GA-bxXouUmknk9fyQAsPT-Xl3RG9-yBed71a2tu9Pig,4914
218
220
  machineconfig/scripts/python/helpers/helpers2.py,sha256=ZdqeF1MLlaBRwoqsQAqnHi4b8rW0byFCBnbyCrPKkoA,7336
219
- machineconfig/scripts/python/helpers/helpers4.py,sha256=Iot8Pb9LeaxpSw1uZzx0m3Aswa30QV-tGLrtJtwiGmQ,7635
221
+ machineconfig/scripts/python/helpers/helpers4.py,sha256=rwAy7HK1CbKQZORzQMQULSKNHj0i4jo7KbUXj3qLG9I,4765
220
222
  machineconfig/scripts/python/helpers/helpers5.py,sha256=dPBvA9Tcyx9TMgM6On49A1CueGMhBdRzikDnlJGf3J0,1123
221
223
  machineconfig/scripts/python/helpers/repo_sync_helpers.py,sha256=39Q3XV8Zx0Y6_iWUtbwDIQI8riqLPSZ008zjqx-Gd-g,5328
224
+ machineconfig/scripts/windows/agents.ps1,sha256=DqdrC_Xc2rwQ6kGzT0xh5CJz4B_0p5ZwB7s8XE6rPCM,77
222
225
  machineconfig/scripts/windows/choose_wezterm_theme.ps1,sha256=LiXJ0a4LKjb6E-oH_bAg6DjegV4SqDUdiMp_svGCFlI,95
223
226
  machineconfig/scripts/windows/cloud_copy.ps1,sha256=llTFhN2uInZTcoZYZuuhJcf5Ifo5MF226I5MpOzvc3A,82
224
227
  machineconfig/scripts/windows/cloud_mount.ps1,sha256=wSQO5II8DbqktexRIuI-RUn8kVCEk-SWT7imZqd7Qdk,82
@@ -245,6 +248,7 @@ machineconfig/scripts/windows/pomodoro.ps1,sha256=9r61cwRy4M2_1A-NFb0fxUuUONxXBL
245
248
  machineconfig/scripts/windows/reload_path.ps1,sha256=81hQY18LFApVZWFiUfgMzzPH2pJ1WD1fHInfmicBZFA,217
246
249
  machineconfig/scripts/windows/repos.ps1,sha256=sjUcrURmYuxdcrdhwLHeWxwByyLgY4k13i8VYSFDKuo,76
247
250
  machineconfig/scripts/windows/scheduler.ps1,sha256=YfOlBxCkPfeQPeyCiNw0g3kIpdbjjf6daLEWuyHSaXY,81
251
+ machineconfig/scripts/windows/sessions.ps1,sha256=cQdgSS3rVWvhthsUi5lyFI05_GKiRGI-j4FB1SZNKpM,80
248
252
  machineconfig/scripts/windows/share_cloud.cmd,sha256=exD7JCdxw2LqVjw2MKCYHbVZlEqmelXtwnATng-dhJ4,1028
249
253
  machineconfig/scripts/windows/share_nfs.ps1,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
250
254
  machineconfig/scripts/windows/share_smb.ps1,sha256=_iJLdgm4pK6Qhz9MpgJlDKHOul38pT8F_VQXqPNBZDE,543
@@ -376,7 +380,7 @@ machineconfig/setup_windows/wt_and_pwsh/__init__.py,sha256=47DEQpj8HBSa-_TImW-5J
376
380
  machineconfig/setup_windows/wt_and_pwsh/set_wt_settings.py,sha256=rZZJamy3YxAeJhdMIFR6IWtjgn1u1HUdbk1J24NtryE,6116
377
381
  machineconfig/utils/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
378
382
  machineconfig/utils/accessories.py,sha256=W_9dLzjwNTW5JQk_pe3B2ijQ1nA2-8Kdg2r7VBtzgQs,4340
379
- machineconfig/utils/code.py,sha256=pKPHInKgXJWeACVbxuE7sMdYeZCbNttaYCsfonGhFfc,4464
383
+ machineconfig/utils/code.py,sha256=zsJ8jG6ESC6cAiHJHdEDso_V0wFuXtGpYtb0zRBxv4c,5197
380
384
  machineconfig/utils/installer.py,sha256=Aoq93RMOQFmv1iYJS90sxrBHeG_K6N5DtIthYffcIOU,9743
381
385
  machineconfig/utils/io.py,sha256=ZXB3aataS1IZ_0WMcCRSmoN1nbkvEO-bWYcs-TpngqU,2872
382
386
  machineconfig/utils/links.py,sha256=riNUrG8aGElRszdOPOic4M2AyOcpdcth_-y8JEiZpJ4,10253
@@ -391,7 +395,7 @@ machineconfig/utils/source_of_truth.py,sha256=GnjcVkKm11RyZFHGnPbne5YDEBYoZ5yryB
391
395
  machineconfig/utils/ssh.py,sha256=zkNUGeijrdoZYkp56DDC8m8LFqPmxQCDNTv5Ns5B7rk,21096
392
396
  machineconfig/utils/terminal.py,sha256=IXYhZ5a0qA6X9CdMT9S7IEKQtJXrDzmiDUGd4C85-oE,12436
393
397
  machineconfig/utils/upgrade_packages.py,sha256=H96zVJEWXJW07nh5vhjuSCrPtXGqoUb7xeJsFYYdmCI,3330
394
- machineconfig/utils/ve.py,sha256=qSUnRto6NI4-Hru0tuz4YzCZzaWAce5Xc__DV0sxsrc,2397
398
+ machineconfig/utils/ve.py,sha256=L-6PBXnQGXThiwWgheJMQoisAZOZA6SVCbGw2J-GFnI,2414
395
399
  machineconfig/utils/ai/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
396
400
  machineconfig/utils/ai/generate_file_checklist.py,sha256=ajbmhcBToRugl75c_KZRq2XJumxKgIqQhyf7_YtF5q4,2729
397
401
  machineconfig/utils/cloud/onedrive/setup_oauth.py,sha256=ZTVkqgrwbV_EoPvyT8dyOTUE0ur3BW4sa9o6QYtt5Bo,2341
@@ -404,8 +408,8 @@ machineconfig/utils/schemas/fire_agents/fire_agents_input.py,sha256=pTxvLzIpD5RF
404
408
  machineconfig/utils/schemas/installer/installer_types.py,sha256=QClRY61QaduBPJoSpdmTIdgS9LS-RvE-QZ-D260tD3o,1214
405
409
  machineconfig/utils/schemas/layouts/layout_types.py,sha256=TcqlZdGVoH8htG5fHn1KWXhRdPueAcoyApppZsPAPto,2020
406
410
  machineconfig/utils/schemas/repos/repos_types.py,sha256=ECVr-3IVIo8yjmYmVXX2mnDDN1SLSwvQIhx4KDDQHBQ,405
407
- machineconfig-4.93.dist-info/METADATA,sha256=04GF2cymQW0SDxwA0oGIroHpIP-TFvPJyz6zmgaCTrI,7061
408
- machineconfig-4.93.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
409
- machineconfig-4.93.dist-info/entry_points.txt,sha256=LcwklRJPY_uKBvStgtOJn5G_pmFCEdpgRNzUUc6twAQ,1134
410
- machineconfig-4.93.dist-info/top_level.txt,sha256=porRtB8qms8fOIUJgK-tO83_FeH6Bpe12oUVC670teA,14
411
- machineconfig-4.93.dist-info/RECORD,,
411
+ machineconfig-4.96.dist-info/METADATA,sha256=9UWC2rvt9CEmexbqBn9bBY39SnI54J7X_cv49wKr4mI,7061
412
+ machineconfig-4.96.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
413
+ machineconfig-4.96.dist-info/entry_points.txt,sha256=LcwklRJPY_uKBvStgtOJn5G_pmFCEdpgRNzUUc6twAQ,1134
414
+ machineconfig-4.96.dist-info/top_level.txt,sha256=porRtB8qms8fOIUJgK-tO83_FeH6Bpe12oUVC670teA,14
415
+ machineconfig-4.96.dist-info/RECORD,,