machineconfig 4.92__py3-none-any.whl → 4.94__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of machineconfig might be problematic. Click here for more details.

@@ -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:
@@ -45,11 +44,11 @@ def route(args: FireJobArgs, fire_args: str = "") -> None:
45
44
  ipy_profile = "default"
46
45
 
47
46
  if choice_file.suffix == ".py":
48
- kwargs = extract_kwargs(args) # This now returns empty dict, but kept for compatibility
47
+ kwargs_dict = extract_kwargs(args) # This now returns empty dict, but kept for compatibility
49
48
  activate_ve_line = get_ve_activate_line(ve_root=args.ve or ve_root_from_file or "$HOME/code/machineconfig/.venv")
50
49
  else:
51
50
  activate_ve_line = ""
52
- kwargs = {}
51
+ kwargs_dict = {}
53
52
 
54
53
  # ========================= choosing function to run
55
54
  choice_function: Optional[str] = None # Initialize to avoid unbound variable
@@ -64,9 +63,9 @@ def route(args: FireJobArgs, fire_args: str = "") -> None:
64
63
 
65
64
  if choice_function == "RUN AS MAIN":
66
65
  choice_function = None
67
- if len(choice_function_args) > 0 and len(kwargs) == 0:
66
+ if len(choice_function_args) > 0 and len(kwargs_dict) == 0:
68
67
  for item in choice_function_args:
69
- kwargs[item.name] = input(f"Please enter a value for argument `{item.name}` (type = {item.type}) (default = {item.default}) : ") or item.default
68
+ kwargs_dict[item.name] = input(f"Please enter a value for argument `{item.name}` (type = {item.type}) (default = {item.default}) : ") or item.default
70
69
  elif choice_file.suffix == ".sh": # in this case, we choos lines.
71
70
  options = []
72
71
  for line in choice_file.read_text(encoding="utf-8").splitlines():
@@ -86,76 +85,15 @@ 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
- s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
92
- try:
93
- s.connect(("8.8.8.8", 1))
94
- local_ip_v4 = s.getsockname()[0]
95
- except Exception:
96
- local_ip_v4 = socket.gethostbyname(socket.gethostname())
97
- finally:
98
- s.close()
99
- computer_name = platform.node()
100
- port = 8501
101
- toml_path: Optional[PathExtended] = None
102
- toml_path_maybe = choice_file.parent.joinpath(".streamlit/config.toml")
103
- if toml_path_maybe.exists():
104
- toml_path = toml_path_maybe
105
- elif choice_file.parent.name == "pages":
106
- toml_path_maybe = choice_file.parent.parent.joinpath(".streamlit/config.toml")
107
- if toml_path_maybe.exists():
108
- toml_path = toml_path_maybe
109
- if toml_path is not None:
110
- print(f"📄 Reading config.toml @ {toml_path}")
111
- config = tomllib.loads(toml_path.read_text(encoding="utf-8"))
112
- if "server" in config:
113
- if "port" in config["server"]:
114
- port = config["server"]["port"]
115
- secrets_path = toml_path.with_name("secrets.toml")
116
- if repo_root is not None:
117
- secrets_template_path = PathExtended.home().joinpath(f"dotfiles/creds/streamlit/{PathExtended(repo_root).name}/{choice_file.name}/secrets.toml")
118
- if args.environment != "" and not secrets_path.exists() and secrets_template_path.exists():
119
- secrets_template = tomllib.loads(secrets_template_path.read_text(encoding="utf-8"))
120
- if args.environment == "ip":
121
- host_url = f"http://{local_ip_v4}:{port}/oauth2callback"
122
- elif args.environment == "localhost":
123
- host_url = f"http://localhost:{port}/oauth2callback"
124
- elif args.environment == "hostname":
125
- host_url = f"http://{computer_name}:{port}/oauth2callback"
126
- else:
127
- host_url = f"http://{args.environment}:{port}/oauth2callback"
128
- try:
129
- secrets_template["auth"]["redirect_uri"] = host_url
130
- secrets_template["auth"]["cookie_secret"] = randstr(35)
131
- secrets_template["auth"]["auth0"]["redirect_uri"] = host_url
132
- # save_toml(obj=secrets_template, path=secrets_path)
133
- except Exception as ex:
134
- print(ex)
135
- raise ex
136
- message = f"🚀 Streamlit app is running @:\n1- http://{local_ip_v4}:{port}\n2- http://{computer_name}:{port}\n3- http://localhost:{port}"
137
- from rich.panel import Panel
138
- from rich import print as rprint
139
-
140
- rprint(Panel(message))
141
- exe = f"streamlit run --server.address 0.0.0.0 --server.headless true --server.port {port}"
142
- # exe = f"cd '{choice_file.parent}'; " + exe
143
- elif args.interactive is False:
144
- exe = "python"
145
- elif args.jupyter:
146
- exe = "jupyter-lab"
147
- else:
148
- exe = f"ipython -i --no-banner --profile {ipy_profile} "
149
- elif choice_file.suffix == ".ps1" or choice_file.suffix == ".sh":
150
- exe = "."
151
- elif choice_file.suffix == "":
152
- exe = ""
153
- else:
154
- raise NotImplementedError(f"File type {choice_file.suffix} not supported, in the sense that I don't know how to fire it.")
155
-
156
- if (
157
- args.module or (args.debug and args.choose_function)
158
- ): # 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.
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.")
95
+
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.
159
97
  assert choice_file.suffix == ".py", f"File must be a python file to be imported as a module. Got {choice_file}"
160
98
  import_line = get_import_module_code(str(choice_file))
161
99
  if repo_root is not None:
@@ -178,7 +116,7 @@ except (ImportError, ModuleNotFoundError) as ex:
178
116
  txt = (
179
117
  txt
180
118
  + f"""
181
- res = {choice_function}({("**" + str(kwargs)) if kwargs else ""})
119
+ res = {choice_function}({("**" + str(kwargs_dict)) if kwargs_dict else ""})
182
120
  """
183
121
  )
184
122
 
@@ -227,21 +165,10 @@ except ImportError as _ex:
227
165
  else:
228
166
  # command = f"cd {choice_file.parent}\n{exe} {choice_file.name}\ncd {PathExtended.cwd()}"
229
167
  command = f"{exe} {choice_file} "
230
- if not args.cmd:
231
- if "ipdb" in command:
232
- command = f"pip install ipdb\n{command}"
233
- if "pudb" in command:
234
- command = f"pip install pudb\n{command}"
235
- command = f"{activate_ve_line}\n{command}"
168
+ if not args.cmd: command = f"{activate_ve_line}\n{command}"
236
169
  else:
237
- # CMD equivalent
238
- if "ipdb" in command:
239
- command = f"pip install ipdb & {command}"
240
- if "pudb" in command:
241
- command = f"pip install pudb & {command}"
242
170
  new_line = "\n"
243
171
  command = rf"""start cmd -Argument "/k {activate_ve_line.replace(".ps1", ".bat").replace(". ", "")} & {command.replace(new_line, " & ")} " """ # this works from powershell
244
-
245
172
  if args.submit_to_cloud:
246
173
  command = f"""
247
174
  {activate_ve_line}
@@ -252,39 +179,28 @@ python -m machineconfig.cluster.templates.cli_click --file {choice_file} """
252
179
  if args.Nprocess > 1:
253
180
  from machineconfig.cluster.sessions_managers.zellij_local import run_zellij_layout
254
181
  from machineconfig.utils.schemas.layouts.layout_types import LayoutConfig
255
-
256
182
  layout: LayoutConfig = {"layoutName": "fireNprocess", "layoutTabs": []}
257
183
  for an_arg in range(args.Nprocess):
258
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}"})
259
185
  run_zellij_layout(layout_config=layout)
260
186
  return None
261
-
262
187
  if args.optimized:
263
- # note that in ipython, optimization is meaningless.
264
188
  command = command.replace("python ", "python -OO ")
265
- # if platform.system() == "Linux":
266
- # command = "timeout 1s aafire -driver slang\nclear\n" + command
267
-
268
189
  from rich.panel import Panel
269
190
  from rich.console import Console
270
191
  from rich.syntax import Syntax
271
-
272
192
  console = Console()
273
-
274
193
  if args.zellij_tab is not None:
275
194
  comman_path__ = PathExtended.tmpfile(suffix=".sh")
276
195
  comman_path__.parent.mkdir(parents=True, exist_ok=True)
277
196
  comman_path__.write_text(command, encoding="utf-8")
278
197
  console.print(Panel(Syntax(command, lexer="shell"), title=f"🔥 fire command @ {comman_path__}: "), style="bold red")
279
198
  import subprocess
280
-
281
199
  existing_tab_names = subprocess.run(["zellij", "action", "query-tab-names"], capture_output=True, text=True, check=True).stdout.splitlines()
282
200
  if args.zellij_tab in existing_tab_names:
283
201
  print(f"⚠️ Tab name `{args.zellij_tab}` already exists. Please choose a different name.")
284
- # args.zellij_tab = input("Please enter a new tab name: ")
285
202
  args.zellij_tab += f"_{randstr(3)}"
286
203
  from machineconfig.cluster.sessions_managers.zellij_local import run_command_in_zellij_tab
287
-
288
204
  command = run_command_in_zellij_tab(command=str(comman_path__), tab_name=args.zellij_tab, cwd=None)
289
205
  if args.watch:
290
206
  command = "watchexec --restart --exts py,sh,ps1 " + command
@@ -294,31 +210,19 @@ python -m machineconfig.cluster.templates.cli_click --file {choice_file} """
294
210
  if platform.system() in ["Linux", "Darwin"]:
295
211
  export_line = f"""export PYTHONPATH="{repo_root}""" + """:${PYTHONPATH}" """
296
212
  elif platform.system() == "Windows":
297
- # export_line = f"""set PYTHONPATH="{repo_root}""" + """:%PYTHONPATH%" """
298
- # powershell equivalent
299
213
  export_line = f"""$env:PYTHONPATH="{repo_root}""" + """:$env:PYTHONPATH" """
300
214
  else:
301
215
  raise NotImplementedError(f"Platform {platform.system()} not supported.")
302
216
  command = export_line + "\n" + command
303
-
304
- # program_path = os.environ.get("op_script", None)
305
- # program_path = PathExtended(program_path) if program_path is not None else PROGRAM_PATH
306
217
  if args.loop:
307
218
  if platform.system() in ["Linux", "Darwin"]:
308
219
  command = command + "\nsleep 0.5"
309
220
  elif platform.system() == "Windows":
310
- # command = command + "timeout 0.5\n"
311
- # pwsh equivalent
312
221
  command = "$ErrorActionPreference = 'SilentlyContinue';\n" + command + "\nStart-Sleep -Seconds 0.5"
313
222
  else:
314
223
  raise NotImplementedError(f"Platform {platform.system()} not supported.")
315
- # command = command + f"\n. {program_path}"
316
- console.print(Panel(Syntax(command, lexer="shell"), title=f"🔥 fire command @ {command}: "), style="bold red")
317
- # program_path.parent.mkdir(parents=True, exist_ok=True)
318
- # program_path.write_text(command, encoding="utf-8")
319
- import subprocess
320
-
321
- subprocess.run(command, shell=True, check=True)
224
+ from machineconfig.utils.code import run_script
225
+ run_script(command)
322
226
 
323
227
 
324
228
  def main(
@@ -346,10 +250,10 @@ def main(
346
250
  watch: Annotated[bool, typer.Option("--watch", "-w", help="Watch the file for changes")] = False,
347
251
  ) -> None:
348
252
  """Main function to process fire jobs arguments."""
349
-
253
+
350
254
  # Get Fire arguments from context
351
255
  fire_args = parse_fire_args_from_context(ctx)
352
-
256
+
353
257
  args = FireJobArgs(
354
258
  path=path,
355
259
  function=function,
@@ -381,6 +285,7 @@ def main(
381
285
  except Exception as e:
382
286
  # For other exceptions, print clean error message and exit
383
287
  import sys
288
+
384
289
  print(f"❌ Error: {e}", file=sys.stderr)
385
290
  sys.exit(1)
386
291
 
@@ -389,6 +294,7 @@ def main_from_parser():
389
294
  # from trogon.typer import init_tui
390
295
  # from trogon.typer import init_tui
391
296
  from typer import Typer
297
+
392
298
  app = Typer(add_completion=False)
393
299
  app.command(context_settings={"allow_extra_args": True, "allow_interspersed_args": False})(main)
394
300
  # typer.run(main)
@@ -30,12 +30,70 @@ class FireJobArgs:
30
30
 
31
31
 
32
32
  def extract_kwargs(args: FireJobArgs) -> dict[str, object]:
33
- """Extract kwargs from command line using -- separator.
33
+ """Extract kwargs from command line arguments in Fire format.
34
34
 
35
- Returns empty dict since kwargs are now parsed directly from sys.argv
36
- using the -- separator pattern in the main function.
35
+ Parses Fire-like arguments (e.g., --a=2, --name=value) from sys.argv
36
+ and returns them as a dictionary.
37
+
38
+ Returns:
39
+ Dictionary mapping argument names to their values
37
40
  """
38
- return {}
41
+ import sys
42
+
43
+ kwargs: dict[str, object] = {}
44
+
45
+ # Look for Fire-style arguments in sys.argv
46
+ for arg in sys.argv:
47
+ # Match patterns like --key=value or --key value (but we'll focus on --key=value)
48
+ if arg.startswith('--') and '=' in arg:
49
+ key, value = arg[2:].split('=', 1) # Remove -- prefix and split on first =
50
+
51
+ # Try to convert value to appropriate type
52
+ kwargs[key] = _convert_value_type(value)
53
+ elif arg.startswith('--') and '=' not in arg:
54
+ # Handle boolean flags like --debug
55
+ key = arg[2:] # Remove -- prefix
56
+ # Check if next argument exists and doesn't start with --
57
+ arg_index = sys.argv.index(arg)
58
+ if arg_index + 1 < len(sys.argv) and not sys.argv[arg_index + 1].startswith('--'):
59
+ # Next argument is the value
60
+ value = sys.argv[arg_index + 1]
61
+ kwargs[key] = _convert_value_type(value)
62
+ else:
63
+ # It's a boolean flag
64
+ kwargs[key] = True
65
+
66
+ return kwargs
67
+
68
+
69
+ def _convert_value_type(value: str) -> object:
70
+ """Convert string value to appropriate Python type."""
71
+ # Try to convert to int
72
+ try:
73
+ if '.' not in value and 'e' not in value.lower():
74
+ return int(value)
75
+ except ValueError:
76
+ pass
77
+
78
+ # Try to convert to float
79
+ try:
80
+ return float(value)
81
+ except ValueError:
82
+ pass
83
+
84
+ # Try to convert boolean strings
85
+ if value.lower() in ('true', '1', 'yes', 'on'):
86
+ return True
87
+ elif value.lower() in ('false', '0', 'no', 'off'):
88
+ return False
89
+
90
+ # Try to parse as list (comma-separated values)
91
+ if ',' in value:
92
+ items = [_convert_value_type(item.strip()) for item in value.split(',')]
93
+ return items
94
+
95
+ # Return as string if no conversion possible
96
+ return value
39
97
 
40
98
 
41
99
  def parse_fire_args_from_argv() -> str:
@@ -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
@@ -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
@@ -30,7 +30,7 @@ exclude = [
30
30
  ]
31
31
 
32
32
  # Same as Black.
33
- line-length = 250
33
+ line-length = 350
34
34
  indent-width = 4
35
35
 
36
36
  # Assume Python 3.13
@@ -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.92
3
+ Version: 4.94
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,7 @@ 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/wt_local.py,sha256=cnLAcyVUr2d2ZPh0dEEr-LHrLiwTMVu7YWXM21IS7_4,17507
15
15
  machineconfig/cluster/sessions_managers/wt_local_manager.py,sha256=BaJNOOY5rAfssreJm8Nmr4we_PCxMkmQqzUMdimNwaM,24565
16
16
  machineconfig/cluster/sessions_managers/wt_remote.py,sha256=XmZV9rLubwxND5UYAS15mAcpzDdXvm4KyubVGYkVBmo,8743
17
17
  machineconfig/cluster/sessions_managers/wt_remote_manager.py,sha256=CnnOtPiwLx0pIfs_KlcKnclLSqiDTNzfm8t8sW6nXf0,19764
@@ -151,15 +151,16 @@ machineconfig/scripts/python/devops.py,sha256=fTEut6gTDfmNqzS8-gRyRAsmWJYPGGIt8X
151
151
  machineconfig/scripts/python/devops_add_identity.py,sha256=JfN3ZrYMCgmt4ks_VCfnV9BIIHAsOYO3E0W0wZ15FR8,3791
152
152
  machineconfig/scripts/python/devops_add_ssh_key.py,sha256=KaoX83KltBsmutfKhSfZjd7nP_R1hJ2OLAWRhbswO7o,6889
153
153
  machineconfig/scripts/python/devops_backup_retrieve.py,sha256=jZe5Vki7E2GCMG8hvqUZeOONFC4cNzISoGzq_dMG4GA,5601
154
- machineconfig/scripts/python/devops_devapps_install.py,sha256=U3Kl8QCHKmQg3o7c2IRsmFM25fGMX1CoH9wvkf2tdeU,10234
154
+ machineconfig/scripts/python/devops_devapps_install.py,sha256=T4h1ydHljQJrNBrye2q-FHUX9iAZnkCa889GgBjHZCE,9103
155
155
  machineconfig/scripts/python/devops_update_repos.py,sha256=c5qBc9cuTGDEqDHufkjDT4d_vvJsswv3tlqk9MAulYk,8063
156
156
  machineconfig/scripts/python/dotfile.py,sha256=SRcX-9Ak1jRvF-killBTTm2IWcsNxfiLucH6ZsytAFA,2202
157
157
  machineconfig/scripts/python/fire_agents_help_launch.py,sha256=1ymWiszfjCyPv3ofinWzfOmbzLEt3d7ntac_afLh-V4,5017
158
158
  machineconfig/scripts/python/fire_agents_help_search.py,sha256=qIfSS_su2YJ1Gb0_lu4cbjlJlYMBw0v52NTGiSrGjk8,2991
159
159
  machineconfig/scripts/python/fire_agents_helper_types.py,sha256=zKu8Vr6iucaGSkCm_Tkt_WrYU7-6Nript3coYyzTXzY,295
160
160
  machineconfig/scripts/python/fire_agents_load_balancer.py,sha256=mpqx3uaQdBXYieuvhdK-qsvLepf9oIMo3pwPj9mSEDI,1079
161
- machineconfig/scripts/python/fire_jobs.py,sha256=7R4CO7wGRkG6akPLK6SMHr82_RdIeXIJNicCAdgh1ok,20262
162
- machineconfig/scripts/python/fire_jobs_args_helper.py,sha256=5zqnYvBjXSLFUqMHg5fgI62YnDu7CpVC4RLmXUKpI2I,2050
161
+ machineconfig/scripts/python/fire_jobs.py,sha256=CqtFt4VGtdEP0tbmRRZ-qU5G232jQj0umlS8C_qtQRM,15911
162
+ machineconfig/scripts/python/fire_jobs_args_helper.py,sha256=VZIQ6ShZBt2WLcqa1fpl1419AGa0k7Xg-EzzrKpDIqw,4029
163
+ machineconfig/scripts/python/fire_jobs_route_helper.py,sha256=EFWsg6F9TeSAtYQec57WtPopUbm2euGZTUZv6J4RhNE,3026
163
164
  machineconfig/scripts/python/fire_jobs_streamlit_helper.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
164
165
  machineconfig/scripts/python/ftpx.py,sha256=l_gdJS0QB2wVZErubtZvm4HJD9HZAJxSP68sbY73xwo,10278
165
166
  machineconfig/scripts/python/get_zellij_cmd.py,sha256=e35-18hoXM9N3PFbvbizfkNY_-63iMicieWE3TbGcCQ,576
@@ -219,6 +220,7 @@ machineconfig/scripts/python/helpers/helpers2.py,sha256=ZdqeF1MLlaBRwoqsQAqnHi4b
219
220
  machineconfig/scripts/python/helpers/helpers4.py,sha256=Iot8Pb9LeaxpSw1uZzx0m3Aswa30QV-tGLrtJtwiGmQ,7635
220
221
  machineconfig/scripts/python/helpers/helpers5.py,sha256=dPBvA9Tcyx9TMgM6On49A1CueGMhBdRzikDnlJGf3J0,1123
221
222
  machineconfig/scripts/python/helpers/repo_sync_helpers.py,sha256=39Q3XV8Zx0Y6_iWUtbwDIQI8riqLPSZ008zjqx-Gd-g,5328
223
+ machineconfig/scripts/windows/agents.ps1,sha256=DqdrC_Xc2rwQ6kGzT0xh5CJz4B_0p5ZwB7s8XE6rPCM,77
222
224
  machineconfig/scripts/windows/choose_wezterm_theme.ps1,sha256=LiXJ0a4LKjb6E-oH_bAg6DjegV4SqDUdiMp_svGCFlI,95
223
225
  machineconfig/scripts/windows/cloud_copy.ps1,sha256=llTFhN2uInZTcoZYZuuhJcf5Ifo5MF226I5MpOzvc3A,82
224
226
  machineconfig/scripts/windows/cloud_mount.ps1,sha256=wSQO5II8DbqktexRIuI-RUn8kVCEk-SWT7imZqd7Qdk,82
@@ -245,6 +247,7 @@ machineconfig/scripts/windows/pomodoro.ps1,sha256=9r61cwRy4M2_1A-NFb0fxUuUONxXBL
245
247
  machineconfig/scripts/windows/reload_path.ps1,sha256=81hQY18LFApVZWFiUfgMzzPH2pJ1WD1fHInfmicBZFA,217
246
248
  machineconfig/scripts/windows/repos.ps1,sha256=sjUcrURmYuxdcrdhwLHeWxwByyLgY4k13i8VYSFDKuo,76
247
249
  machineconfig/scripts/windows/scheduler.ps1,sha256=YfOlBxCkPfeQPeyCiNw0g3kIpdbjjf6daLEWuyHSaXY,81
250
+ machineconfig/scripts/windows/sessions.ps1,sha256=cQdgSS3rVWvhthsUi5lyFI05_GKiRGI-j4FB1SZNKpM,80
248
251
  machineconfig/scripts/windows/share_cloud.cmd,sha256=exD7JCdxw2LqVjw2MKCYHbVZlEqmelXtwnATng-dhJ4,1028
249
252
  machineconfig/scripts/windows/share_nfs.ps1,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
250
253
  machineconfig/scripts/windows/share_smb.ps1,sha256=_iJLdgm4pK6Qhz9MpgJlDKHOul38pT8F_VQXqPNBZDE,543
@@ -306,7 +309,7 @@ machineconfig/settings/lf/windows/autocall/rename.ps1,sha256=47DEQpj8HBSa-_TImW-
306
309
  machineconfig/settings/linters/.flake8,sha256=1By04Qwy5saCudYKOw2bKHSNQg4N128SJudwD3SVGhQ,1958
307
310
  machineconfig/settings/linters/.mypy.ini,sha256=BNxVtNuliJZVeFpCRRIQpSWFDQYuKqKtcVKYcZ-sApc,811
308
311
  machineconfig/settings/linters/.pylintrc,sha256=_hYrPgtMvQc877u5NTU_HlkJMZwuDrmB6Yt3u5zg3-c,3593
309
- machineconfig/settings/linters/.ruff.toml,sha256=CiLFhFLJzQc1UvJF2ecRjO4hjmC_xx9j0JCKHKi-po8,1655
312
+ machineconfig/settings/linters/.ruff.toml,sha256=5C-8Fkj9mdZxs3ajeideTNUOKRSo31dDYW1VQmDzK6w,1655
310
313
  machineconfig/settings/lvim/linux/config.lua,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
311
314
  machineconfig/settings/lvim/windows/config.lua,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
312
315
  machineconfig/settings/lvim/windows/archive/config_additional.lua,sha256=zj-VDn-Av4IomJ3EqM1gf_6VsZ9ieG815O9QK1slyPI,792
@@ -376,7 +379,7 @@ machineconfig/setup_windows/wt_and_pwsh/__init__.py,sha256=47DEQpj8HBSa-_TImW-5J
376
379
  machineconfig/setup_windows/wt_and_pwsh/set_wt_settings.py,sha256=rZZJamy3YxAeJhdMIFR6IWtjgn1u1HUdbk1J24NtryE,6116
377
380
  machineconfig/utils/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
378
381
  machineconfig/utils/accessories.py,sha256=W_9dLzjwNTW5JQk_pe3B2ijQ1nA2-8Kdg2r7VBtzgQs,4340
379
- machineconfig/utils/code.py,sha256=pKPHInKgXJWeACVbxuE7sMdYeZCbNttaYCsfonGhFfc,4464
382
+ machineconfig/utils/code.py,sha256=zsJ8jG6ESC6cAiHJHdEDso_V0wFuXtGpYtb0zRBxv4c,5197
380
383
  machineconfig/utils/installer.py,sha256=Aoq93RMOQFmv1iYJS90sxrBHeG_K6N5DtIthYffcIOU,9743
381
384
  machineconfig/utils/io.py,sha256=ZXB3aataS1IZ_0WMcCRSmoN1nbkvEO-bWYcs-TpngqU,2872
382
385
  machineconfig/utils/links.py,sha256=riNUrG8aGElRszdOPOic4M2AyOcpdcth_-y8JEiZpJ4,10253
@@ -391,7 +394,7 @@ machineconfig/utils/source_of_truth.py,sha256=GnjcVkKm11RyZFHGnPbne5YDEBYoZ5yryB
391
394
  machineconfig/utils/ssh.py,sha256=zkNUGeijrdoZYkp56DDC8m8LFqPmxQCDNTv5Ns5B7rk,21096
392
395
  machineconfig/utils/terminal.py,sha256=IXYhZ5a0qA6X9CdMT9S7IEKQtJXrDzmiDUGd4C85-oE,12436
393
396
  machineconfig/utils/upgrade_packages.py,sha256=H96zVJEWXJW07nh5vhjuSCrPtXGqoUb7xeJsFYYdmCI,3330
394
- machineconfig/utils/ve.py,sha256=qSUnRto6NI4-Hru0tuz4YzCZzaWAce5Xc__DV0sxsrc,2397
397
+ machineconfig/utils/ve.py,sha256=L-6PBXnQGXThiwWgheJMQoisAZOZA6SVCbGw2J-GFnI,2414
395
398
  machineconfig/utils/ai/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
396
399
  machineconfig/utils/ai/generate_file_checklist.py,sha256=ajbmhcBToRugl75c_KZRq2XJumxKgIqQhyf7_YtF5q4,2729
397
400
  machineconfig/utils/cloud/onedrive/setup_oauth.py,sha256=ZTVkqgrwbV_EoPvyT8dyOTUE0ur3BW4sa9o6QYtt5Bo,2341
@@ -404,8 +407,8 @@ machineconfig/utils/schemas/fire_agents/fire_agents_input.py,sha256=pTxvLzIpD5RF
404
407
  machineconfig/utils/schemas/installer/installer_types.py,sha256=QClRY61QaduBPJoSpdmTIdgS9LS-RvE-QZ-D260tD3o,1214
405
408
  machineconfig/utils/schemas/layouts/layout_types.py,sha256=TcqlZdGVoH8htG5fHn1KWXhRdPueAcoyApppZsPAPto,2020
406
409
  machineconfig/utils/schemas/repos/repos_types.py,sha256=ECVr-3IVIo8yjmYmVXX2mnDDN1SLSwvQIhx4KDDQHBQ,405
407
- machineconfig-4.92.dist-info/METADATA,sha256=V-IP6VGb9kPGkPancTAaV6j7EqHTKnCqAPBEer-enBg,7061
408
- machineconfig-4.92.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
409
- machineconfig-4.92.dist-info/entry_points.txt,sha256=LcwklRJPY_uKBvStgtOJn5G_pmFCEdpgRNzUUc6twAQ,1134
410
- machineconfig-4.92.dist-info/top_level.txt,sha256=porRtB8qms8fOIUJgK-tO83_FeH6Bpe12oUVC670teA,14
411
- machineconfig-4.92.dist-info/RECORD,,
410
+ machineconfig-4.94.dist-info/METADATA,sha256=1OGor4zIf7weP_BjiCtbh8ObObGacnY9kMIMYUeakIA,7061
411
+ machineconfig-4.94.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
412
+ machineconfig-4.94.dist-info/entry_points.txt,sha256=LcwklRJPY_uKBvStgtOJn5G_pmFCEdpgRNzUUc6twAQ,1134
413
+ machineconfig-4.94.dist-info/top_level.txt,sha256=porRtB8qms8fOIUJgK-tO83_FeH6Bpe12oUVC670teA,14
414
+ machineconfig-4.94.dist-info/RECORD,,