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.
- machineconfig/cluster/sessions_managers/wt_local.py +96 -123
- machineconfig/scripts/python/devops_devapps_install.py +3 -33
- machineconfig/scripts/python/fire_jobs.py +22 -116
- machineconfig/scripts/python/fire_jobs_args_helper.py +62 -4
- machineconfig/scripts/python/fire_jobs_route_helper.py +65 -0
- machineconfig/scripts/windows/agents.ps1 +1 -0
- machineconfig/scripts/windows/sessions.ps1 +1 -0
- machineconfig/settings/linters/.ruff.toml +1 -1
- machineconfig/utils/code.py +27 -16
- machineconfig/utils/ve.py +4 -3
- {machineconfig-4.92.dist-info → machineconfig-4.94.dist-info}/METADATA +1 -1
- {machineconfig-4.92.dist-info → machineconfig-4.94.dist-info}/RECORD +15 -12
- {machineconfig-4.92.dist-info → machineconfig-4.94.dist-info}/WHEEL +0 -0
- {machineconfig-4.92.dist-info → machineconfig-4.94.dist-info}/entry_points.txt +0 -0
- {machineconfig-4.92.dist-info → machineconfig-4.94.dist-info}/top_level.txt +0 -0
|
@@ -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
|
|
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
|
-
#
|
|
137
|
-
|
|
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
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
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
|
-
#
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
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
|
-
#
|
|
183
|
-
|
|
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(
|
|
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
|
-
#
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
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
|
-
#
|
|
236
|
-
|
|
237
|
-
|
|
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
|
-
|
|
241
|
-
$
|
|
242
|
-
$
|
|
243
|
-
$
|
|
244
|
-
$
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
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([
|
|
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
|
-
|
|
404
|
-
|
|
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
|
-
|
|
413
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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(
|
|
66
|
+
if len(choice_function_args) > 0 and len(kwargs_dict) == 0:
|
|
68
67
|
for item in choice_function_args:
|
|
69
|
-
|
|
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
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
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(
|
|
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
|
-
|
|
316
|
-
|
|
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
|
|
33
|
+
"""Extract kwargs from command line arguments in Fire format.
|
|
34
34
|
|
|
35
|
-
|
|
36
|
-
|
|
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
|
-
|
|
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
|
machineconfig/utils/code.py
CHANGED
|
@@ -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
|
-
|
|
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:
|
|
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
|
-
|
|
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:
|
|
@@ -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
|
|
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=
|
|
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=
|
|
162
|
-
machineconfig/scripts/python/fire_jobs_args_helper.py,sha256=
|
|
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=
|
|
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=
|
|
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=
|
|
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.
|
|
408
|
-
machineconfig-4.
|
|
409
|
-
machineconfig-4.
|
|
410
|
-
machineconfig-4.
|
|
411
|
-
machineconfig-4.
|
|
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,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|