machineconfig 6.84__py3-none-any.whl → 6.86__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 +16 -221
- machineconfig/cluster/sessions_managers/wt_local_manager.py +33 -174
- machineconfig/cluster/sessions_managers/wt_remote_manager.py +39 -197
- machineconfig/cluster/sessions_managers/wt_utils/manager_persistence.py +52 -0
- machineconfig/cluster/sessions_managers/wt_utils/monitoring_helpers.py +50 -0
- machineconfig/cluster/sessions_managers/wt_utils/status_reporting.py +76 -0
- machineconfig/cluster/sessions_managers/wt_utils/wt_helpers.py +199 -0
- machineconfig/scripts/python/agents.py +18 -7
- machineconfig/scripts/python/ai/vscode_tasks.py +7 -2
- machineconfig/scripts/python/env_manager/path_manager_tui.py +1 -1
- machineconfig/scripts/python/fire_jobs.py +31 -66
- machineconfig/scripts/python/{helpers_fire → helpers_agents}/agentic_frameworks/fire_crush.py +6 -5
- machineconfig/scripts/python/{helpers_fire → helpers_agents}/agentic_frameworks/fire_cursor_agents.py +1 -1
- machineconfig/scripts/python/{helpers_fire → helpers_agents}/agentic_frameworks/fire_gemini.py +2 -3
- machineconfig/scripts/python/{helpers_fire → helpers_agents}/agentic_frameworks/fire_qwen.py +2 -2
- machineconfig/scripts/python/{helpers_fire → helpers_agents}/fire_agents_help_launch.py +4 -4
- machineconfig/scripts/python/{helpers_fire → helpers_agents}/fire_agents_helper_types.py +2 -2
- machineconfig/scripts/python/helpers_agents/templates/prompt.txt +6 -0
- machineconfig/scripts/python/helpers_agents/templates/template.sh +24 -0
- machineconfig/scripts/python/helpers_devops/cli_config.py +1 -1
- machineconfig/scripts/python/helpers_devops/cli_nw.py +50 -0
- machineconfig/scripts/python/helpers_devops/cli_self.py +3 -3
- machineconfig/scripts/python/helpers_devops/cli_utils.py +18 -1
- machineconfig/scripts/python/{helpers_fire/helpers4.py → helpers_fire_command/file_wrangler.py} +15 -0
- machineconfig/scripts/python/helpers_fire_command/fire_jobs_route_helper.py +1 -1
- machineconfig/scripts/python/helpers_repos/cloud_repo_sync.py +1 -1
- machineconfig/scripts/python/helpers_sessions/sessions_multiprocess.py +1 -1
- machineconfig/scripts/python/nw/mount_nfs +1 -1
- machineconfig/scripts/python/nw/wifi_conn.py +1 -53
- machineconfig/scripts/python/sessions.py +1 -1
- machineconfig/scripts/python/terminal.py +46 -17
- machineconfig/scripts/python/utils.py +10 -21
- machineconfig/scripts/windows/mounts/mount_ssh.ps1 +1 -1
- machineconfig/scripts/windows/term.ps1 +48 -0
- machineconfig/setup_linux/web_shortcuts/interactive.sh +1 -1
- machineconfig/setup_windows/web_shortcuts/interactive.ps1 +1 -1
- machineconfig/utils/code.py +18 -13
- machineconfig/utils/installer.py +0 -1
- machineconfig/utils/meta.py +4 -3
- machineconfig/utils/path_helper.py +1 -1
- machineconfig/utils/scheduling.py +0 -2
- machineconfig/utils/schemas/fire_agents/fire_agents_input.py +1 -1
- machineconfig/utils/ssh.py +2 -2
- machineconfig/utils/upgrade_packages.py +28 -24
- {machineconfig-6.84.dist-info → machineconfig-6.86.dist-info}/METADATA +1 -1
- {machineconfig-6.84.dist-info → machineconfig-6.86.dist-info}/RECORD +55 -52
- machineconfig/scripts/linux/warp-cli.sh +0 -122
- machineconfig/scripts/python/helpers_fire/prompt.txt +0 -2
- machineconfig/scripts/python/helpers_fire/template.sh +0 -15
- /machineconfig/scripts/python/{helpers_fire → helpers_agents}/__init__.py +0 -0
- /machineconfig/scripts/python/{helpers_fire → helpers_agents}/agentic_frameworks/__init__.py +0 -0
- /machineconfig/scripts/python/{helpers_fire → helpers_agents}/agentic_frameworks/fire_crush.json +0 -0
- /machineconfig/scripts/python/{helpers_fire → helpers_agents}/fire_agents_help_search.py +0 -0
- /machineconfig/scripts/python/{helpers_fire → helpers_agents}/fire_agents_load_balancer.py +0 -0
- /machineconfig/scripts/python/{helpers_fire → helpers_agents/templates}/template.ps1 +0 -0
- {machineconfig-6.84.dist-info → machineconfig-6.86.dist-info}/WHEEL +0 -0
- {machineconfig-6.84.dist-info → machineconfig-6.86.dist-info}/entry_points.txt +0 -0
- {machineconfig-6.84.dist-info → machineconfig-6.86.dist-info}/top_level.txt +0 -0
|
@@ -54,6 +54,52 @@ def debug_ssh():
|
|
|
54
54
|
else:
|
|
55
55
|
raise NotImplementedError(f"Platform {system()} is not supported.")
|
|
56
56
|
|
|
57
|
+
def wifi_select(
|
|
58
|
+
ssid: Annotated[str, typer.Option("-n", "--ssid", help="🔗 SSID of WiFi (from config)")] = "MyPhoneHotSpot",
|
|
59
|
+
manual: Annotated[bool, typer.Option("-m", "--manual", help="🔍 Manual network selection mode")] = False,
|
|
60
|
+
list_: Annotated[bool, typer.Option("-l", "--list", help="📡 List available networks only")] = False,
|
|
61
|
+
) -> None:
|
|
62
|
+
"""Main function with fallback network selection"""
|
|
63
|
+
from rich.panel import Panel
|
|
64
|
+
from rich.prompt import Confirm
|
|
65
|
+
from rich.console import Console
|
|
66
|
+
from machineconfig.scripts.python.nw.wifi_conn import try_config_connection, manual_network_selection, display_available_networks
|
|
67
|
+
console = Console()
|
|
68
|
+
console.print(Panel("📶 Welcome to the WiFi Connector Tool", title="[bold blue]WiFi Connection[/bold blue]", border_style="blue"))
|
|
69
|
+
|
|
70
|
+
# If user just wants to list networks
|
|
71
|
+
if list_:
|
|
72
|
+
display_available_networks()
|
|
73
|
+
return
|
|
74
|
+
|
|
75
|
+
# If user wants manual mode, skip config and go straight to selection
|
|
76
|
+
if manual:
|
|
77
|
+
console.print("[blue]🔍 Manual network selection mode[/blue]")
|
|
78
|
+
if manual_network_selection():
|
|
79
|
+
console.print("[green]🎉 Successfully connected![/green]")
|
|
80
|
+
else:
|
|
81
|
+
console.print("[red]❌ Failed to connect[/red]")
|
|
82
|
+
return
|
|
83
|
+
|
|
84
|
+
# Try to connect using configuration first
|
|
85
|
+
console.print(f"[blue]🔍 Attempting to connect to configured network: {ssid}[/blue]")
|
|
86
|
+
|
|
87
|
+
if try_config_connection(ssid):
|
|
88
|
+
console.print("[green]🎉 Successfully connected using configuration![/green]")
|
|
89
|
+
return
|
|
90
|
+
|
|
91
|
+
# Configuration failed, offer fallback options
|
|
92
|
+
console.print("\n[yellow]⚠️ Configuration connection failed or not available[/yellow]")
|
|
93
|
+
|
|
94
|
+
if Confirm.ask("[blue]Would you like to manually select a network?[/blue]", default=True):
|
|
95
|
+
if manual_network_selection():
|
|
96
|
+
console.print("[green]🎉 Successfully connected![/green]")
|
|
97
|
+
else:
|
|
98
|
+
console.print("[red]❌ Failed to connect[/red]")
|
|
99
|
+
else:
|
|
100
|
+
console.print("[blue]👋 Goodbye![/blue]")
|
|
101
|
+
|
|
102
|
+
|
|
57
103
|
def get_app():
|
|
58
104
|
nw_apps = typer.Typer(help="🔐 [n] Network subcommands", no_args_is_help=True, add_help_option=False, add_completion=False)
|
|
59
105
|
nw_apps.command(name="share-terminal", help="📡 [t] Share terminal via web browser")(cli_terminal.main)
|
|
@@ -70,4 +116,8 @@ def get_app():
|
|
|
70
116
|
nw_apps.command(name="a", help="Show this computer addresses on network", hidden=True)(show_address)
|
|
71
117
|
nw_apps.command(name="debug-ssh", help="🐛 [d] Debug SSH connection")(debug_ssh)
|
|
72
118
|
nw_apps.command(name="d", help="Debug SSH connection", hidden=True)(debug_ssh)
|
|
119
|
+
|
|
120
|
+
nw_apps.command(name="wifi-select", no_args_is_help=True, help="[w] WiFi connection utility.")(wifi_select)
|
|
121
|
+
nw_apps.command(name="w", no_args_is_help=True, hidden=True)(wifi_select)
|
|
122
|
+
|
|
73
123
|
return nw_apps
|
|
@@ -41,9 +41,9 @@ def install(no_copy_assets: Annotated[bool, typer.Option("--no-assets-copy", "-n
|
|
|
41
41
|
else:
|
|
42
42
|
import platform
|
|
43
43
|
if platform.system() == "Windows":
|
|
44
|
-
run_shell_script(r"""& "$HOME\.local\bin\uv.exe" tool install --upgrade "machineconfig>=6.
|
|
44
|
+
run_shell_script(r"""& "$HOME\.local\bin\uv.exe" tool install --upgrade "machineconfig>=6.86" """)
|
|
45
45
|
else:
|
|
46
|
-
run_shell_script("""$HOME/.local/bin/uv tool install --upgrade "machineconfig>=6.
|
|
46
|
+
run_shell_script("""$HOME/.local/bin/uv tool install --upgrade "machineconfig>=6.86" """)
|
|
47
47
|
from machineconfig.profile.create_shell_profile import create_default_shell_profile
|
|
48
48
|
if not no_copy_assets:
|
|
49
49
|
create_default_shell_profile() # involves copying assets too
|
|
@@ -68,7 +68,7 @@ def navigate():
|
|
|
68
68
|
path = Path(navigator.__file__).resolve().parent.joinpath("devops_navigator.py")
|
|
69
69
|
from machineconfig.utils.code import run_shell_script
|
|
70
70
|
if Path.home().joinpath("code/machineconfig").exists(): executable = f"""--project "{str(Path.home().joinpath("code/machineconfig"))}" --with textual"""
|
|
71
|
-
else: executable = """--with "machineconfig>=6.
|
|
71
|
+
else: executable = """--with "machineconfig>=6.86,textual" """
|
|
72
72
|
run_shell_script(f"""uv run {executable} {path}""")
|
|
73
73
|
|
|
74
74
|
|
|
@@ -198,7 +198,7 @@ def init_project(python: Annotated[Literal["3.13", "3.14"], typer.Option("--pyth
|
|
|
198
198
|
if not (repo_root / "pyproject.toml").exists():
|
|
199
199
|
typer.echo("❌ Error: pyproject.toml not found.", err=True)
|
|
200
200
|
raise typer.Exit(code=1)
|
|
201
|
-
print(
|
|
201
|
+
print("Adding group `plot` with common data science and plotting packages...")
|
|
202
202
|
script = """
|
|
203
203
|
uv add --group plot \
|
|
204
204
|
# Data & computation
|
|
@@ -219,3 +219,20 @@ uv add --group plot \
|
|
|
219
219
|
"""
|
|
220
220
|
from machineconfig.utils.code import run_shell_script
|
|
221
221
|
run_shell_script(script)
|
|
222
|
+
# def add_dev_packages(repo_dir: Annotated[Optional[str], typer.Option(..., "--repo-dir", "-r", help="Path to the repository root directory")] = None):
|
|
223
|
+
# if repo_dir is None:
|
|
224
|
+
# r_dir = Path.cwd()
|
|
225
|
+
# else:
|
|
226
|
+
# r_dir = Path(repo_dir).resolve()
|
|
227
|
+
# if not r_dir.exists() or not r_dir.is_dir() or not (r_dir / "pyproject.toml").exists():
|
|
228
|
+
# typer.echo(f"❌ The provided repo directory `{r_dir}` is not valid or does not contain a `pyproject.toml` file.")
|
|
229
|
+
# raise typer.Exit(code=1)
|
|
230
|
+
# command = f"""
|
|
231
|
+
# cd "{r_dir}" || exit 1
|
|
232
|
+
# uv add nbformat ipdb ipykernel ipython pylint pyright mypy pyrefly ty pytest
|
|
233
|
+
# """
|
|
234
|
+
# from machineconfig.utils.code import run_shell_script
|
|
235
|
+
# typer.echo(f"➡️ Installing dev packages in repo at `{r_dir}`...")
|
|
236
|
+
# run_shell_script(command)
|
|
237
|
+
# typer.echo(f"✅ Dev packages installed successfully in repo at `{r_dir}`.")
|
|
238
|
+
# # TODO: see upgrade packages.
|
machineconfig/scripts/python/{helpers_fire/helpers4.py → helpers_fire_command/file_wrangler.py}
RENAMED
|
@@ -110,3 +110,18 @@ def get_import_module_code(module_path: str):
|
|
|
110
110
|
module_name = "IncorrectModuleName"
|
|
111
111
|
# TODO: use py_compile to check if the statement is valid code to avoid syntax errors that can't be caught.
|
|
112
112
|
return f"from {module_name} import *"
|
|
113
|
+
|
|
114
|
+
|
|
115
|
+
def wrap_import_in_try_except(import_line: str, pyfile: str, repo_root: Optional[str] = None) -> None:
|
|
116
|
+
try:
|
|
117
|
+
exec(import_line) # type: ignore
|
|
118
|
+
except (ImportError, ModuleNotFoundError) as ex:
|
|
119
|
+
print(fr"❌ Failed to import `{pyfile}` as a module: {ex} ")
|
|
120
|
+
print("⚠️ Attempting import with ad-hoc `$PATH` manipulation. DO NOT pickle any objects in this session as correct deserialization cannot be guaranteed.")
|
|
121
|
+
import sys
|
|
122
|
+
from pathlib import Path
|
|
123
|
+
sys.path.append(str(Path(pyfile).parent))
|
|
124
|
+
if repo_root is not None:
|
|
125
|
+
sys.path.append(repo_root)
|
|
126
|
+
exec(f"from {Path(pyfile).stem} import *")
|
|
127
|
+
print(fr"✅ Successfully imported `{pyfile}`")
|
|
@@ -22,7 +22,7 @@ def choose_function_or_lines(choice_file: PathExtended, kwargs_dict: dict[str, o
|
|
|
22
22
|
choice_function: Optional[str] = None
|
|
23
23
|
|
|
24
24
|
if choice_file.suffix == ".py":
|
|
25
|
-
from machineconfig.scripts.python.
|
|
25
|
+
from machineconfig.scripts.python.helpers_fire_command.file_wrangler import parse_pyfile
|
|
26
26
|
options, func_args = parse_pyfile(file_path=str(choice_file))
|
|
27
27
|
choice_function_tmp = choose_from_options(msg="Choose a function to run", options=options, fzf=True, multi=False)
|
|
28
28
|
assert isinstance(choice_function_tmp, str), f"choice_function must be a string. Got {type(choice_function_tmp)}"
|
|
@@ -21,7 +21,7 @@ def create_from_function(
|
|
|
21
21
|
suffixes = {".py"}
|
|
22
22
|
choice_file = match_file_name(sub_string=path, search_root=PathExtended.cwd(), suffixes=suffixes)
|
|
23
23
|
elif path_obj.is_dir():
|
|
24
|
-
from machineconfig.scripts.python.
|
|
24
|
+
from machineconfig.scripts.python.helpers_fire_command.file_wrangler import search_for_files_of_interest
|
|
25
25
|
print(f"🔍 Searching recursively for Python, PowerShell and Shell scripts in directory `{path_obj}`")
|
|
26
26
|
files = search_for_files_of_interest(path_obj)
|
|
27
27
|
print(f"🔍 Got #{len(files)} results.")
|
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
# mkdir ~/data/local
|
|
6
6
|
# sudo mount -o nolock,noatime,nodiratime,proto=tcp,timeo=600,retrans=2,noac alex-p51s-5:/home/alex/data/local ./data/local
|
|
7
7
|
|
|
8
|
-
uv run --python 3.14 --with "machineconfig>=6.
|
|
8
|
+
uv run --python 3.14 --with "machineconfig>=6.86" python -m machineconfig.scripts.python.mount_nfs
|
|
9
9
|
# Check if remote server is reachable and share folder exists
|
|
10
10
|
if ! ping -c 1 "$remote_server" &> /dev/null; then
|
|
11
11
|
echo "💥 Error: Remote server $remote_server is not reachable."
|
|
@@ -28,8 +28,6 @@ Usage examples:
|
|
|
28
28
|
|
|
29
29
|
"""
|
|
30
30
|
|
|
31
|
-
from typing import Annotated
|
|
32
|
-
import typer
|
|
33
31
|
import configparser
|
|
34
32
|
from pathlib import Path
|
|
35
33
|
import os
|
|
@@ -38,8 +36,7 @@ import subprocess
|
|
|
38
36
|
import getpass
|
|
39
37
|
from typing import List, Dict, Optional
|
|
40
38
|
from rich.console import Console
|
|
41
|
-
from rich.
|
|
42
|
-
from rich.prompt import Prompt, Confirm
|
|
39
|
+
from rich.prompt import Prompt
|
|
43
40
|
from rich.table import Table
|
|
44
41
|
|
|
45
42
|
console = Console()
|
|
@@ -263,51 +260,6 @@ def manual_network_selection() -> bool:
|
|
|
263
260
|
return False
|
|
264
261
|
|
|
265
262
|
|
|
266
|
-
def main(
|
|
267
|
-
ssid: Annotated[str, typer.Option("-n", "--ssid", help="🔗 SSID of WiFi (from config)")] = "MyPhoneHotSpot",
|
|
268
|
-
manual: Annotated[bool, typer.Option("-m", "--manual", help="🔍 Manual network selection mode")] = False,
|
|
269
|
-
list_: Annotated[bool, typer.Option("-l", "--list", help="📡 List available networks only")] = False,
|
|
270
|
-
) -> None:
|
|
271
|
-
"""Main function with fallback network selection"""
|
|
272
|
-
console.print(Panel("📶 Welcome to the WiFi Connector Tool", title="[bold blue]WiFi Connection[/bold blue]", border_style="blue"))
|
|
273
|
-
|
|
274
|
-
# If user just wants to list networks
|
|
275
|
-
if list_:
|
|
276
|
-
display_available_networks()
|
|
277
|
-
return
|
|
278
|
-
|
|
279
|
-
# If user wants manual mode, skip config and go straight to selection
|
|
280
|
-
if manual:
|
|
281
|
-
console.print("[blue]🔍 Manual network selection mode[/blue]")
|
|
282
|
-
if manual_network_selection():
|
|
283
|
-
console.print("[green]🎉 Successfully connected![/green]")
|
|
284
|
-
else:
|
|
285
|
-
console.print("[red]❌ Failed to connect[/red]")
|
|
286
|
-
return
|
|
287
|
-
|
|
288
|
-
# Try to connect using configuration first
|
|
289
|
-
console.print(f"[blue]🔍 Attempting to connect to configured network: {ssid}[/blue]")
|
|
290
|
-
|
|
291
|
-
if try_config_connection(ssid):
|
|
292
|
-
console.print("[green]🎉 Successfully connected using configuration![/green]")
|
|
293
|
-
return
|
|
294
|
-
|
|
295
|
-
# Configuration failed, offer fallback options
|
|
296
|
-
console.print("\n[yellow]⚠️ Configuration connection failed or not available[/yellow]")
|
|
297
|
-
|
|
298
|
-
if Confirm.ask("[blue]Would you like to manually select a network?[/blue]", default=True):
|
|
299
|
-
if manual_network_selection():
|
|
300
|
-
console.print("[green]🎉 Successfully connected![/green]")
|
|
301
|
-
else:
|
|
302
|
-
console.print("[red]❌ Failed to connect[/red]")
|
|
303
|
-
else:
|
|
304
|
-
console.print("[blue]👋 Goodbye![/blue]")
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
def arg_parser() -> None:
|
|
308
|
-
typer.run(main)
|
|
309
|
-
|
|
310
|
-
|
|
311
263
|
def get_current_wifi_name() -> str:
|
|
312
264
|
"""Get the name of the currently connected WiFi network"""
|
|
313
265
|
console.print("\n[blue]🔍 Checking current WiFi connection...[/blue]")
|
|
@@ -412,7 +364,3 @@ def create_new_connection(name: str, ssid: str, password: str):
|
|
|
412
364
|
except Exception as e:
|
|
413
365
|
console.print(f"[red]❌ Unexpected error: {e}[/red]")
|
|
414
366
|
raise
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
if __name__ == "__main__":
|
|
418
|
-
arg_parser()
|
|
@@ -51,7 +51,7 @@ def select_layout(layouts_json_file: Path, selected_layouts_names: Optional[list
|
|
|
51
51
|
|
|
52
52
|
def find_layout_file(layout_path: str, ) -> Path:
|
|
53
53
|
from machineconfig.utils.path_extended import PathExtended
|
|
54
|
-
from machineconfig.scripts.python.
|
|
54
|
+
from machineconfig.scripts.python.helpers_fire_command.file_wrangler import search_for_files_of_interest
|
|
55
55
|
from machineconfig.utils.options import choose_from_options
|
|
56
56
|
from machineconfig.utils.path_helper import match_file_name, sanitize_path
|
|
57
57
|
path_obj = sanitize_path(layout_path)
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import subprocess
|
|
2
|
+
# from machineconfig.utils.schemas.layouts.layout_types import LayoutConfig
|
|
2
3
|
import typer
|
|
3
4
|
from typing import Annotated
|
|
4
5
|
|
|
@@ -9,7 +10,21 @@ def strip_ansi_codes(text: str) -> str:
|
|
|
9
10
|
return re.sub(r'\x1b\[[0-9;]*[a-zA-Z]', '', text)
|
|
10
11
|
|
|
11
12
|
|
|
12
|
-
def choose_zellij_session(
|
|
13
|
+
def choose_zellij_session(
|
|
14
|
+
new_session: Annotated[bool, typer.Option("--new-session", "-n", help="Create a new Zellij session instead of attaching to an existing one.", show_default=True)] = False,
|
|
15
|
+
kill_all: Annotated[bool, typer.Option("--kill-all", "-k", help="Kill all existing Zellij sessions before creating a new one.", show_default=True)] = False):
|
|
16
|
+
|
|
17
|
+
if new_session:
|
|
18
|
+
cmd = """
|
|
19
|
+
zellij --layout st2
|
|
20
|
+
"""
|
|
21
|
+
if kill_all:
|
|
22
|
+
cmd = f"""zellij kill-sessions
|
|
23
|
+
{cmd}"""
|
|
24
|
+
from machineconfig.utils.code import exit_then_run_shell_script
|
|
25
|
+
exit_then_run_shell_script(cmd, strict=True)
|
|
26
|
+
typer.Exit()
|
|
27
|
+
return
|
|
13
28
|
cmd = "zellij list-sessions"
|
|
14
29
|
sessions: list[str] = subprocess.check_output(cmd, shell=True).decode().strip().split("\n")
|
|
15
30
|
sessions.sort(key=lambda s: "EXITED" in s)
|
|
@@ -32,16 +47,6 @@ def choose_zellij_session():
|
|
|
32
47
|
exit_then_run_shell_script(result, strict=True)
|
|
33
48
|
|
|
34
49
|
|
|
35
|
-
def new_zellij_session(kill_all: Annotated[bool, typer.Option("--kill-all", "-k", help="Kill all existing Zellij sessions before creating a new one.", show_default=True)] = False):
|
|
36
|
-
cmd = """
|
|
37
|
-
zellij --layout st2
|
|
38
|
-
"""
|
|
39
|
-
if kill_all:
|
|
40
|
-
cmd = f"""zellij kill-sessions
|
|
41
|
-
{cmd}"""
|
|
42
|
-
from machineconfig.utils.code import exit_then_run_shell_script
|
|
43
|
-
exit_then_run_shell_script(cmd, strict=True)
|
|
44
|
-
|
|
45
50
|
|
|
46
51
|
def get_session_tabs() -> list[tuple[str, str]]:
|
|
47
52
|
cmd = "zellij list-sessions"
|
|
@@ -64,16 +69,40 @@ def get_session_tabs() -> list[tuple[str, str]]:
|
|
|
64
69
|
print(result)
|
|
65
70
|
return result
|
|
66
71
|
|
|
72
|
+
def start_wt(layout_name: Annotated[str, typer.Argument(help="Layout name to start.")]):
|
|
73
|
+
from pathlib import Path
|
|
74
|
+
layouts_file = Path.home().joinpath("dotfiles/machineconfig/layouts.json")
|
|
75
|
+
if not layouts_file.exists():
|
|
76
|
+
typer.echo(f"❌ Layouts file not found: {layouts_file}")
|
|
77
|
+
# available
|
|
78
|
+
raise typer.Exit(code=1)
|
|
79
|
+
import json
|
|
80
|
+
from machineconfig.utils.schemas.layouts.layout_types import LayoutsFile
|
|
81
|
+
layouts_data: LayoutsFile = json.loads(layouts_file.read_text(encoding="utf-8"))
|
|
82
|
+
chosen_layout = next((a_layout for a_layout in layouts_data["layouts"] if a_layout["layoutName"] == layout_name), None)
|
|
83
|
+
if not chosen_layout:
|
|
84
|
+
typer.echo(f"❌ Layout '{layout_name}' not found in layouts file.")
|
|
85
|
+
available_layouts = [a_layout["layoutName"] for a_layout in layouts_data["layouts"]]
|
|
86
|
+
typer.echo(f"Available layouts: {', '.join(available_layouts)}")
|
|
87
|
+
raise typer.Exit(code=1)
|
|
88
|
+
from machineconfig.cluster.sessions_managers.wt_local import run_wt_layout
|
|
89
|
+
run_wt_layout(layout_config=chosen_layout)
|
|
90
|
+
|
|
91
|
+
# cmd = f'powershell -ExecutionPolicy Bypass -File "./{layout_name}_layout.ps1"'
|
|
92
|
+
# from machineconfig.utils.code import exit_then_run_shell_script
|
|
93
|
+
# exit_then_run_shell_script(cmd, strict=True)
|
|
94
|
+
|
|
67
95
|
|
|
68
96
|
def main():
|
|
69
97
|
app = typer.Typer(help="🖥️ Terminal utilities", no_args_is_help=True, add_help_option=False)
|
|
70
|
-
app.command(name="
|
|
71
|
-
app.command(name="
|
|
72
|
-
|
|
73
|
-
app.command(name="
|
|
98
|
+
app.command(name="attach-to-zellij", no_args_is_help=False, help="[z] Choose a Zellij session to attach to")(choose_zellij_session)
|
|
99
|
+
app.command(name="z", hidden=True, no_args_is_help=False, help="[z] Choose a Zellij session to attach to")(choose_zellij_session)
|
|
100
|
+
|
|
101
|
+
app.command(name="start-wt", no_args_is_help=True, help="[w] Start a Windows Terminal layout by name.")(start_wt)
|
|
102
|
+
app.command(name="w", hidden=True, no_args_is_help=True, help="[w] Start a Windows Terminal layout by name.")(start_wt)
|
|
74
103
|
|
|
75
|
-
app.command(name="get-session-tabs", no_args_is_help=False, help="Get all Zellij session tabs.")(get_session_tabs)
|
|
76
|
-
app.command(name="
|
|
104
|
+
app.command(name="get-session-tabs", no_args_is_help=False, help="[zt] Get all Zellij session tabs.")(get_session_tabs)
|
|
105
|
+
app.command(name="zt", hidden=True, no_args_is_help=False, help="[zt] Get all Zellij session tabs.")(get_session_tabs)
|
|
77
106
|
app()
|
|
78
107
|
|
|
79
108
|
|
|
@@ -2,9 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
from machineconfig.scripts.python.helpers_devops.cli_utils import download, merge_pdfs, get_machine_specs, init_project, compress_pdf
|
|
4
4
|
import typer
|
|
5
|
-
from typing import Annotated
|
|
6
|
-
from pathlib import Path
|
|
7
|
-
|
|
5
|
+
from typing import Annotated
|
|
8
6
|
|
|
9
7
|
def kill_process(
|
|
10
8
|
# name: Annotated[Optional[str], typer.Option(..., "--name", "-n", help="Name of the process to kill")],
|
|
@@ -21,30 +19,20 @@ def kill_process(
|
|
|
21
19
|
# )
|
|
22
20
|
|
|
23
21
|
|
|
24
|
-
def
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
r_dir = Path(repo_dir).resolve()
|
|
29
|
-
if not r_dir.exists() or not r_dir.is_dir() or not (r_dir / "pyproject.toml").exists():
|
|
30
|
-
typer.echo(f"❌ The provided repo directory `{r_dir}` is not valid or does not contain a `pyproject.toml` file.")
|
|
31
|
-
raise typer.Exit(code=1)
|
|
32
|
-
command = f"""
|
|
33
|
-
cd "{r_dir}" || exit 1
|
|
34
|
-
uv add nbformat ipdb ipykernel ipython pylint pyright mypy pyrefly ty pytest
|
|
35
|
-
"""
|
|
36
|
-
from machineconfig.utils.code import run_shell_script
|
|
37
|
-
typer.echo(f"➡️ Installing dev packages in repo at `{r_dir}`...")
|
|
38
|
-
run_shell_script(command)
|
|
39
|
-
typer.echo(f"✅ Dev packages installed successfully in repo at `{r_dir}`.")
|
|
40
|
-
# TODO: see upgrade packages.
|
|
41
|
-
|
|
22
|
+
def upgrade_packages():
|
|
23
|
+
from machineconfig.utils.upgrade_packages import generate_uv_add_commands
|
|
24
|
+
from pathlib import Path
|
|
25
|
+
generate_uv_add_commands(pyproject_path=Path.cwd() / "pyproject.toml", output_path=Path.cwd() / "pyproject_init.sh")
|
|
42
26
|
|
|
43
27
|
|
|
44
28
|
def get_app() -> typer.Typer:
|
|
45
29
|
app = typer.Typer(help="🛠️ utilities operations", no_args_is_help=True, add_help_option=False, add_completion=False)
|
|
46
30
|
app.command(name="kill-process", no_args_is_help=False, help="[k] Choose a process to kill")(kill_process)
|
|
47
31
|
app.command(name="k", no_args_is_help=False, help="Choose a process to kill", hidden=True)(kill_process)
|
|
32
|
+
|
|
33
|
+
app.command(name="upgrade-packages", no_args_is_help=False, help="[up] Upgrade project dependencies.")(upgrade_packages)
|
|
34
|
+
app.command(name="up", no_args_is_help=False, hidden=True)(upgrade_packages)
|
|
35
|
+
|
|
48
36
|
app.command(name="download", no_args_is_help=True, help="[d] Download a file from a URL and optionally decompress it.")(download)
|
|
49
37
|
app.command(name="d", no_args_is_help=True, hidden=True)(download)
|
|
50
38
|
app.command(name="get-machine-specs", no_args_is_help=False, help="[g] Get machine specifications.")(get_machine_specs)
|
|
@@ -56,6 +44,7 @@ def get_app() -> typer.Typer:
|
|
|
56
44
|
app.command(name="pm", no_args_is_help=True, hidden=True)(merge_pdfs)
|
|
57
45
|
app.command(name="pdf-compress", no_args_is_help=True, help="[pc] Compress a PDF file.")(compress_pdf)
|
|
58
46
|
app.command(name="pc", no_args_is_help=True, hidden=True)(compress_pdf)
|
|
47
|
+
|
|
59
48
|
return app
|
|
60
49
|
|
|
61
50
|
# def func():
|
|
@@ -7,7 +7,7 @@ $user = ''
|
|
|
7
7
|
$sharePath = ''
|
|
8
8
|
$driveLetter = ''
|
|
9
9
|
|
|
10
|
-
uv run --python 3.14 --with "machineconfig>=6.
|
|
10
|
+
uv run --python 3.14 --with "machineconfig>=6.86" python -m machineconfig.scripts.python.mount_ssh
|
|
11
11
|
|
|
12
12
|
net use T: \\sshfs.kr\$user@$host.local
|
|
13
13
|
# this worked: net use T: \\sshfs\alex@alex-p51s-5.local
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
# Equivalent PowerShell script for term.ps1
|
|
2
|
+
|
|
3
|
+
Set-StrictMode -Version Latest
|
|
4
|
+
$ErrorActionPreference = 'Stop'
|
|
5
|
+
|
|
6
|
+
# Generate random name using timestamp and SHA256 hash
|
|
7
|
+
$timestampNs = [DateTimeOffset]::Now.ToUnixTimeMilliseconds() * 1000000
|
|
8
|
+
$hashInput = [System.Text.Encoding]::UTF8.GetBytes($timestampNs.ToString())
|
|
9
|
+
$sha256 = [System.Security.Cryptography.SHA256]::Create()
|
|
10
|
+
$hashBytes = $sha256.ComputeHash($hashInput)
|
|
11
|
+
$hashString = -join ($hashBytes | ForEach-Object { $_.ToString('x2') })
|
|
12
|
+
$randomName = $hashString.Substring(0, 16)
|
|
13
|
+
|
|
14
|
+
$opDir = "$env:USERPROFILE\tmp_results\tmp_scripts\machineconfig"
|
|
15
|
+
$opProgramPath = "$opDir\$randomName.ps1"
|
|
16
|
+
$global:OP_PROGRAM_PATH = $opProgramPath
|
|
17
|
+
|
|
18
|
+
# ANSI color/style codes (using Write-Host colors)
|
|
19
|
+
$bold = [char]27 + '[1m'
|
|
20
|
+
$reset = [char]27 + '[0m'
|
|
21
|
+
$green = [char]27 + '[32m'
|
|
22
|
+
$yellow = [char]27 + '[33m'
|
|
23
|
+
$blue = [char]27 + '[34m'
|
|
24
|
+
$red = [char]27 + '[31m'
|
|
25
|
+
|
|
26
|
+
$timestamp = Get-Date -Format 'u'
|
|
27
|
+
|
|
28
|
+
Write-Host "${bold}${blue}🛠️ terminal — running term${reset}"
|
|
29
|
+
Write-Host "${blue}Timestamp:${reset} ${timestamp}"
|
|
30
|
+
Write-Host "${blue}Op program path:${reset} ${opProgramPath}"
|
|
31
|
+
|
|
32
|
+
terminal $args
|
|
33
|
+
|
|
34
|
+
if (Test-Path $opProgramPath) {
|
|
35
|
+
Write-Host "${green}✅ Found op program:${reset} ${opProgramPath}"
|
|
36
|
+
# Assuming bat is available; otherwise, use Get-Content
|
|
37
|
+
& bat --style=plain --paging=never $opProgramPath
|
|
38
|
+
Write-Host "${green}▶ Running...${reset}"
|
|
39
|
+
. $opProgramPath
|
|
40
|
+
$status = $LASTEXITCODE
|
|
41
|
+
if ($status -eq 0) {
|
|
42
|
+
Write-Host "${green}✅ Completed successfully (exit ${status})${reset}"
|
|
43
|
+
} else {
|
|
44
|
+
Write-Host "${yellow}⚠️ Program exited with status ${status}${reset}"
|
|
45
|
+
}
|
|
46
|
+
} else {
|
|
47
|
+
Write-Host "${yellow}⚠️ No op program found at: ${opProgramPath}${reset}"
|
|
48
|
+
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
#!/bin/bash
|
|
2
2
|
. <( curl -sSL "https://raw.githubusercontent.com/thisismygitrepo/machineconfig/main/src/machineconfig/setup_linux/uv.sh")
|
|
3
3
|
mcfg() {
|
|
4
|
-
"$HOME/.local/bin/uv" run --python 3.14 --with "machineconfig>=6.
|
|
4
|
+
"$HOME/.local/bin/uv" run --python 3.14 --with "machineconfig>=6.86" mcfg "$@"
|
|
5
5
|
}
|
|
6
6
|
alias d="mcfg devops"
|
|
7
7
|
alias c="mcfg cloud"
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
iex (iwr "https://raw.githubusercontent.com/thisismygitrepo/machineconfig/main/src/machineconfig/setup_windows/uv.ps1").Content
|
|
4
4
|
function mcfg {
|
|
5
|
-
& "$HOME\.local\bin\uv.exe" run --python 3.14 --with "machineconfig>=6.
|
|
5
|
+
& "$HOME\.local\bin\uv.exe" run --python 3.14 --with "machineconfig>=6.86" mcfg $args
|
|
6
6
|
}
|
|
7
7
|
function d { mcfg devops @args }
|
|
8
8
|
function c { mcfg cloud @args }
|
machineconfig/utils/code.py
CHANGED
|
@@ -7,18 +7,23 @@ from pathlib import Path
|
|
|
7
7
|
|
|
8
8
|
def print_code(code: str, lexer: str, desc: str, subtitle: str = ""):
|
|
9
9
|
import platform
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
if
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
10
|
+
try:
|
|
11
|
+
from rich.console import Console
|
|
12
|
+
from rich.panel import Panel
|
|
13
|
+
from rich.syntax import Syntax
|
|
14
|
+
if lexer == "shell":
|
|
15
|
+
if platform.system() == "Windows":
|
|
16
|
+
lexer = "powershell"
|
|
17
|
+
elif platform.system() in ["Linux", "Darwin"]:
|
|
18
|
+
lexer = "sh"
|
|
19
|
+
else:
|
|
20
|
+
raise NotImplementedError(f"Platform {platform.system()} not supported for lexer {lexer}")
|
|
21
|
+
console = Console()
|
|
22
|
+
console.print(Panel(Syntax(code=code, lexer=lexer), title=f"📄 {desc}", subtitle=subtitle), style="bold red")
|
|
23
|
+
except ImportError:
|
|
24
|
+
print(f"--- {desc} ---")
|
|
25
|
+
print(code)
|
|
26
|
+
print(f"--- End of {desc} ---")
|
|
22
27
|
|
|
23
28
|
|
|
24
29
|
def get_uv_command_executing_python_script(python_script: str, uv_with: Optional[list[str]], uv_project_dir: Optional[str]) -> tuple[str, Path]:
|
|
@@ -51,7 +56,7 @@ def run_python_script_in_marimo(py_script: str, uv_project_with: Optional[str]):
|
|
|
51
56
|
if uv_project_with is not None:
|
|
52
57
|
requirements = f"""--with "marimo" --project {uv_project_with} """
|
|
53
58
|
else:
|
|
54
|
-
requirements =
|
|
59
|
+
requirements = """--with "marimo" """
|
|
55
60
|
fire_line = f"""
|
|
56
61
|
cd {tmp_dir}
|
|
57
62
|
uv run {requirements} marimo convert {pyfile.name} -o marimo_nb.py
|
machineconfig/utils/installer.py
CHANGED
machineconfig/utils/meta.py
CHANGED
|
@@ -5,7 +5,7 @@ from typing import Any
|
|
|
5
5
|
|
|
6
6
|
|
|
7
7
|
def get_import_module_string(py_file: str) -> str:
|
|
8
|
-
from machineconfig.scripts.python.
|
|
8
|
+
from machineconfig.scripts.python.helpers_fire_command.file_wrangler import get_import_module_code
|
|
9
9
|
from machineconfig.utils.accessories import get_repo_root
|
|
10
10
|
from pathlib import Path
|
|
11
11
|
repo_root = get_repo_root(Path(py_file))
|
|
@@ -230,8 +230,9 @@ def lambda_to_python_script(lmb: Callable[[], Any], in_global: bool, import_modu
|
|
|
230
230
|
if lines[-1].startswith("return "):
|
|
231
231
|
lines[-1] = lines[-1].replace("return ", "# return ", 1)
|
|
232
232
|
result_text = "\n".join(lines)
|
|
233
|
-
|
|
234
|
-
|
|
233
|
+
|
|
234
|
+
if "Optional" in result_text or "Any" in result_text or "Union" in result_text or "Literal" in result_text:
|
|
235
|
+
result_text = "from typing import Optional, Any, Union, Literal\n\n" + result_text
|
|
235
236
|
|
|
236
237
|
if import_prefix:
|
|
237
238
|
result_text = f"{import_prefix}{result_text}"
|
|
@@ -77,7 +77,7 @@ def match_file_name(sub_string: str, search_root: PathExtended, suffixes: set[st
|
|
|
77
77
|
if len(filename_matches) < 20:
|
|
78
78
|
print("\n".join([a_potential_match.as_posix() for a_potential_match in filename_matches]))
|
|
79
79
|
if len(filename_matches) > 1:
|
|
80
|
-
print("Try to narrow down filename_matches search by case-sensitivity.")
|
|
80
|
+
print(f"Try to narrow down filename_matches search by case-sensitivity, found {len(filename_matches)} results. First @ {filename_matches[0].as_posix()}")
|
|
81
81
|
# let's see if avoiding .lower() helps narrowing down to one result
|
|
82
82
|
reduced_scripts = [a_potential_match for a_potential_match in filename_matches if sub_string in a_potential_match.name]
|
|
83
83
|
if len(reduced_scripts) == 1:
|
|
@@ -6,7 +6,7 @@ capturing all user inputs collected during interactive execution.
|
|
|
6
6
|
|
|
7
7
|
from pathlib import Path
|
|
8
8
|
from typing import TypedDict, Literal, NotRequired
|
|
9
|
-
from machineconfig.scripts.python.
|
|
9
|
+
from machineconfig.scripts.python.helpers_agents.fire_agents_help_launch import AGENTS
|
|
10
10
|
|
|
11
11
|
SEARCH_STRATEGIES = Literal["file_path", "keyword_search", "filename_pattern"]
|
|
12
12
|
|
machineconfig/utils/ssh.py
CHANGED
|
@@ -8,7 +8,7 @@ from machineconfig.utils.terminal import Response
|
|
|
8
8
|
from machineconfig.utils.accessories import pprint, randstr
|
|
9
9
|
from machineconfig.utils.meta import lambda_to_python_script
|
|
10
10
|
UV_RUN_CMD = "$HOME/.local/bin/uv run" if platform.system() != "Windows" else """& "$env:USERPROFILE/.local/bin/uv" run"""
|
|
11
|
-
MACHINECONFIG_VERSION = "machineconfig>=6.
|
|
11
|
+
MACHINECONFIG_VERSION = "machineconfig>=6.86"
|
|
12
12
|
DEFAULT_PICKLE_SUBDIR = "tmp_results/tmp_scripts/ssh"
|
|
13
13
|
|
|
14
14
|
class SSH:
|
|
@@ -115,7 +115,7 @@ class SSH:
|
|
|
115
115
|
self.tqdm_wrap = RichProgressWrapper
|
|
116
116
|
from machineconfig.scripts.python.helpers_devops.cli_utils import get_machine_specs
|
|
117
117
|
self.local_specs: MachineSpecs = get_machine_specs()
|
|
118
|
-
resp = self.run_shell(command=
|
|
118
|
+
resp = self.run_shell(command="""~/.local/bin/utils get-machine-specs """, verbose_output=False, description="Getting remote machine specs", strict_stderr=False, strict_return_code=False)
|
|
119
119
|
json_str = resp.op
|
|
120
120
|
import ast
|
|
121
121
|
self.remote_specs: MachineSpecs = cast(MachineSpecs, ast.literal_eval(json_str))
|