machineconfig 6.48__py3-none-any.whl → 6.51__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/utils/maker.py +1 -1
- machineconfig/scripts/python/croshell.py +28 -29
- machineconfig/scripts/python/env_manager/path_manager_tui.py +1 -1
- machineconfig/scripts/python/helpers_croshell/crosh.py +34 -38
- machineconfig/scripts/python/helpers_devops/cli_config.py +1 -1
- machineconfig/scripts/python/helpers_devops/cli_self.py +3 -3
- machineconfig/scripts/python/helpers_repos/cloud_repo_sync.py +9 -4
- machineconfig/scripts/python/helpers_repos/count_lines_frontend.py +1 -1
- machineconfig/scripts/python/nw/mount_nfs +1 -1
- machineconfig/scripts/windows/mounts/mount_ssh.ps1 +1 -1
- machineconfig/setup_linux/web_shortcuts/interactive.sh +1 -1
- machineconfig/setup_windows/web_shortcuts/interactive.ps1 +1 -1
- machineconfig/utils/code.py +1 -1
- machineconfig/utils/meta.py +243 -8
- machineconfig/utils/scheduler.py +6 -19
- machineconfig/utils/ssh.py +1 -1
- {machineconfig-6.48.dist-info → machineconfig-6.51.dist-info}/METADATA +1 -1
- {machineconfig-6.48.dist-info → machineconfig-6.51.dist-info}/RECORD +21 -21
- {machineconfig-6.48.dist-info → machineconfig-6.51.dist-info}/WHEEL +0 -0
- {machineconfig-6.48.dist-info → machineconfig-6.51.dist-info}/entry_points.txt +0 -0
- {machineconfig-6.48.dist-info → machineconfig-6.51.dist-info}/top_level.txt +0 -0
|
@@ -6,7 +6,7 @@ from pathlib import Path
|
|
|
6
6
|
|
|
7
7
|
def get_fire_command_and_artifact_files(func: FunctionType):
|
|
8
8
|
from machineconfig.utils.meta import function_to_script
|
|
9
|
-
py_script = function_to_script(func)
|
|
9
|
+
py_script = function_to_script(func, call_with_kwargs=None)
|
|
10
10
|
from machineconfig.utils.accessories import randstr
|
|
11
11
|
py_script_path = Path.home().joinpath("tmp_results", "tmp_py_scripts", f"tmp_{randstr(10)}.py")
|
|
12
12
|
py_script_path.parent.mkdir(parents=True, exist_ok=True)
|
|
@@ -5,8 +5,8 @@ croshell
|
|
|
5
5
|
"""
|
|
6
6
|
|
|
7
7
|
from typing import Annotated, Optional
|
|
8
|
-
from machineconfig.scripts.python.helpers_croshell.crosh import
|
|
9
|
-
from machineconfig.
|
|
8
|
+
from machineconfig.scripts.python.helpers_croshell.crosh import code, get_read_data_pycode
|
|
9
|
+
from machineconfig.utils.meta import lambda_to_defstring
|
|
10
10
|
import typer
|
|
11
11
|
from machineconfig.utils.path_extended import PathExtended
|
|
12
12
|
from pathlib import Path
|
|
@@ -26,10 +26,9 @@ def croshell(
|
|
|
26
26
|
profile: Annotated[Optional[str], typer.Option("--profile", "-P", help="ipython profile to use, defaults to default profile.")] = None,
|
|
27
27
|
jupyter: Annotated[bool, typer.Option("--jupyter", "-j", help="run in jupyter interactive console")] = False,
|
|
28
28
|
vscode: Annotated[bool, typer.Option("--vscode", "-c", help="open the script in vscode")] = False,
|
|
29
|
-
streamlit_viewer: Annotated[bool, typer.Option("--
|
|
30
|
-
visidata: Annotated[bool, typer.Option("--visidata", "-
|
|
29
|
+
streamlit_viewer: Annotated[bool, typer.Option("--streamlit", "-s", help="view in streamlit app")] = False,
|
|
30
|
+
visidata: Annotated[bool, typer.Option("--visidata", "-v", help="open data file in visidata")] = False,
|
|
31
31
|
marimo: Annotated[bool, typer.Option("--marimo", "-m", help="open the notebook using marimo if available")] = False,
|
|
32
|
-
local: Annotated[bool, typer.Option("--local", "-l", help="run in local mode, not in virtual env.")]= False,
|
|
33
32
|
) -> None:
|
|
34
33
|
# ==================================================================================
|
|
35
34
|
# flags processing
|
|
@@ -59,9 +58,10 @@ def croshell(
|
|
|
59
58
|
# streamlit run {py_file_path}
|
|
60
59
|
# """
|
|
61
60
|
# PROGRAM_PATH.write_text(data=final_program, encoding="utf-8")
|
|
61
|
+
print("Streamlit viewer is not yet implemented in this version.")
|
|
62
62
|
return None
|
|
63
63
|
file_obj = PathExtended(str(path).lstrip()).expanduser().absolute()
|
|
64
|
-
program = get_read_data_pycode(str(file_obj))
|
|
64
|
+
program = lambda_to_defstring(lambda: get_read_data_pycode(path=str(file_obj)), in_global=True)
|
|
65
65
|
text = f"📄 Reading data from: {file_obj.name}"
|
|
66
66
|
console.print(Panel(text, title="[bold blue]Info[/bold blue]"))
|
|
67
67
|
else: # if nothing is specified, then run in interactive mode.
|
|
@@ -71,23 +71,29 @@ def croshell(
|
|
|
71
71
|
# InteractiveShell().run()
|
|
72
72
|
# return None
|
|
73
73
|
program = ""
|
|
74
|
-
|
|
75
74
|
preprogram = """
|
|
76
|
-
|
|
77
75
|
#%%
|
|
78
|
-
|
|
79
|
-
from machineconfig.utils.files.headers import print_header, print_logo
|
|
80
|
-
print_header()
|
|
81
|
-
print_logo("CROCODILE")
|
|
82
|
-
from pathlib import Path
|
|
83
|
-
|
|
84
76
|
"""
|
|
77
|
+
def preprogram_func():
|
|
78
|
+
from machineconfig.utils.files.headers import print_header, print_logo
|
|
79
|
+
print_header()
|
|
80
|
+
print_logo("CROCODILE")
|
|
81
|
+
from pathlib import Path
|
|
82
|
+
from machineconfig.utils.path_extended import PathExtended
|
|
83
|
+
_ = Path, PathExtended # avoid unused import warnings
|
|
84
|
+
import inspect, textwrap
|
|
85
|
+
from types import FunctionType
|
|
86
|
+
def get_body_simple_function_no_args(f: FunctionType):
|
|
87
|
+
return textwrap.dedent("\n".join(inspect.getsource(f).splitlines()[1:]))
|
|
88
|
+
preprogram += get_body_simple_function_no_args(preprogram_func)
|
|
85
89
|
|
|
86
90
|
pyfile = PathExtended.tmp().joinpath(f"tmp_scripts/python/croshell/{randstr()}/script.py")
|
|
87
91
|
pyfile.parent.mkdir(parents=True, exist_ok=True)
|
|
88
92
|
|
|
89
93
|
title = "Reading Data"
|
|
90
|
-
|
|
94
|
+
def_code = lambda_to_defstring(lambda: code(path=str(pyfile), title=title))
|
|
95
|
+
# print(def_code)
|
|
96
|
+
python_program = preprogram + "\n\n" + def_code + program
|
|
91
97
|
pyfile.write_text(python_program, encoding="utf-8")
|
|
92
98
|
# ve_root_from_file, ipython_profile = get_ve_path_and_ipython_profile(PathExtended(file))
|
|
93
99
|
ipython_profile = ipython_profile if ipython_profile is not None else "default"
|
|
@@ -120,38 +126,31 @@ from pathlib import Path
|
|
|
120
126
|
if visidata:
|
|
121
127
|
fire_line = f"uv run --with visidata,pyarrow vd {str(file_obj)}"
|
|
122
128
|
elif marimo:
|
|
123
|
-
if Path.home().joinpath("code/machineconfig").exists(): requirements = f"""--project "{str(Path.home().joinpath("code/machineconfig"))}" """
|
|
124
|
-
else: requirements = """--with "marimo,machineconfig[plot]>=6.
|
|
129
|
+
if Path.home().joinpath("code/machineconfig").exists(): requirements = f"""--with marimo --project "{str(Path.home().joinpath("code/machineconfig"))}" """
|
|
130
|
+
else: requirements = """--with "marimo,machineconfig[plot]>=6.51" """
|
|
125
131
|
fire_line = f"""
|
|
126
132
|
cd {str(pyfile.parent)}
|
|
127
133
|
uv run --with "marimo" marimo convert {pyfile.name} -o marimo_nb.py
|
|
128
134
|
uv run {requirements} marimo edit --host 0.0.0.0 marimo_nb.py
|
|
129
135
|
"""
|
|
130
136
|
elif jupyter:
|
|
131
|
-
if Path.home().joinpath("code/machineconfig").exists(): requirements = f"""--project "{str(Path.home().joinpath("code/machineconfig"))}" """
|
|
132
|
-
else: requirements = """--with "machineconfig[plot]>=6.
|
|
137
|
+
if Path.home().joinpath("code/machineconfig").exists(): requirements = f"""--project "{str(Path.home().joinpath("code/machineconfig"))}" --with jupyterlab """
|
|
138
|
+
else: requirements = """--with "machineconfig[plot]>=6.51" """
|
|
133
139
|
fire_line = f"uv run {requirements} jupyter-lab {str(nb_target)}"
|
|
134
140
|
elif vscode:
|
|
135
141
|
fire_line = f"""
|
|
136
142
|
cd {str(pyfile.parent)}
|
|
137
143
|
uv init --python 3.14
|
|
138
144
|
uv venv
|
|
139
|
-
uv add "machineconfig[plot]>=6.
|
|
145
|
+
uv add "machineconfig[plot]>=6.51"
|
|
140
146
|
# code serve-web
|
|
141
147
|
code --new-window {str(pyfile)}
|
|
142
148
|
"""
|
|
143
149
|
else:
|
|
144
150
|
if interpreter == "ipython": profile = f" --profile {ipython_profile} --no-banner"
|
|
145
151
|
else: profile = ""
|
|
146
|
-
if
|
|
147
|
-
|
|
148
|
-
repo_root = LIBRARY_ROOT.parent.parent
|
|
149
|
-
if repo_root.parent.name == "code" and repo_root.name == "machineconfig" and repo_root.exists() and repo_root.is_dir():
|
|
150
|
-
ve_line = f"--project {str(repo_root)}"
|
|
151
|
-
else:
|
|
152
|
-
console.print(Panel("❌ Could not determine the local machineconfig repo root. Please ensure the `REPO_ROOT` in `source_of_truth.py` is correctly set to the local path of the machineconfig repo, or do not use the `--local` flag.", title="Error", border_style="red"))
|
|
153
|
-
return
|
|
154
|
-
else: ve_line = """--with "machineconfig[plot]>=6.48" """
|
|
152
|
+
if Path.home().joinpath("code/machineconfig").exists(): ve_line = f"""--project "{str(Path.home().joinpath("code/machineconfig"))}" """
|
|
153
|
+
else: ve_line = """--with "machineconfig[plot]>=6.51" """
|
|
155
154
|
# ve_path_maybe, ipython_profile_maybe = get_ve_path_and_ipython_profile(Path.cwd())
|
|
156
155
|
# --python 3.14
|
|
157
156
|
fire_line = f"uv run {ve_line} {interpreter} {interactivity} {profile} {str(pyfile)}"
|
|
@@ -1,43 +1,39 @@
|
|
|
1
|
-
def add_print_header_pycode(path: str, title: str):
|
|
2
|
-
return f"""
|
|
3
1
|
|
|
4
|
-
from machineconfig.utils.path_extended import PathExtended
|
|
5
|
-
pycode = PathExtended(r'{path}').read_text(encoding="utf-8")
|
|
6
|
-
pycode = pycode.split("except Exception: print(pycode)")[2]
|
|
7
2
|
|
|
8
|
-
|
|
9
|
-
from
|
|
10
|
-
from
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
3
|
+
def code(path: str, title: str):
|
|
4
|
+
from pathlib import Path
|
|
5
|
+
print("Reading code from path:", path)
|
|
6
|
+
pycode = Path(path).read_text(encoding="utf-8")
|
|
7
|
+
pycode = pycode.split("except Exception: print(pycode)")[2]
|
|
8
|
+
try:
|
|
9
|
+
# from rich.text import Text
|
|
10
|
+
from rich.panel import Panel
|
|
11
|
+
from rich.console import Console
|
|
12
|
+
from rich.syntax import Syntax
|
|
13
|
+
console = Console()
|
|
14
|
+
if pycode.strip() != "":
|
|
15
|
+
console.print(Panel(Syntax(pycode, lexer="python"), title=title), style="bold red")
|
|
16
|
+
except Exception: print(pycode)
|
|
18
17
|
|
|
19
18
|
|
|
20
19
|
def get_read_data_pycode(path: str):
|
|
21
|
-
|
|
22
|
-
from rich.
|
|
23
|
-
from rich.
|
|
24
|
-
from
|
|
25
|
-
console = Console()
|
|
26
|
-
p = PathExtended(
|
|
27
|
-
try:
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
except Exception as e:
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
"""
|
|
42
|
-
|
|
43
|
-
|
|
20
|
+
from rich.panel import Panel
|
|
21
|
+
from rich.text import Text
|
|
22
|
+
from rich.console import Console
|
|
23
|
+
from machineconfig.utils.path_extended import PathExtended
|
|
24
|
+
console = Console()
|
|
25
|
+
p = PathExtended(path).absolute()
|
|
26
|
+
try:
|
|
27
|
+
from machineconfig.utils.files.read import Read
|
|
28
|
+
from machineconfig.utils.accessories import pprint
|
|
29
|
+
dat = Read.read(p)
|
|
30
|
+
if isinstance(dat, dict):
|
|
31
|
+
panel_title = f"📄 File Data: {p.name}"
|
|
32
|
+
console.print(Panel(Text(str(dat), justify="left"), title=panel_title, expand=False))
|
|
33
|
+
pprint(dat, p.name)
|
|
34
|
+
else:
|
|
35
|
+
panel_title = f"📄 Successfully read the file: {p.name}"
|
|
36
|
+
console.print(Panel(Text(str(dat), justify="left"), title=panel_title, expand=False))
|
|
37
|
+
except Exception as e:
|
|
38
|
+
error_message = f'''❌ ERROR READING FILE\nFile: {p.name}\nError: {e}'''
|
|
39
|
+
console.print(Panel(Text(error_message, justify="left"), title="Error", expand=False, border_style="red"))
|
|
@@ -42,7 +42,7 @@ def path():
|
|
|
42
42
|
from pathlib import Path
|
|
43
43
|
path = Path(navigator.__file__).resolve().parent.joinpath("path_manager_tui.py")
|
|
44
44
|
from machineconfig.utils.code import run_shell_script
|
|
45
|
-
if not Path.home().joinpath("code/machineconfig").exists(): executable = """--with "machineconfig>=6.
|
|
45
|
+
if not Path.home().joinpath("code/machineconfig").exists(): executable = """--with "machineconfig>=6.51,textual" """
|
|
46
46
|
else: executable = f"""--project "{str(Path.home().joinpath("code/machineconfig"))}" --with textual"""
|
|
47
47
|
run_shell_script(f"""uv run {executable} {path}""")
|
|
48
48
|
|
|
@@ -40,9 +40,9 @@ def install(no_copy_assets: Annotated[bool, typer.Option("--no-assets-copy", "-n
|
|
|
40
40
|
else:
|
|
41
41
|
import platform
|
|
42
42
|
if platform.system() == "Windows":
|
|
43
|
-
run_shell_script(r"""$HOME\.local\bin\uv.exe tool install --upgrade "machineconfig>=6.
|
|
43
|
+
run_shell_script(r"""$HOME\.local\bin\uv.exe tool install --upgrade "machineconfig>=6.51" """)
|
|
44
44
|
else:
|
|
45
|
-
run_shell_script("""$HOME/.local/bin/uv tool install --upgrade "machineconfig>=6.
|
|
45
|
+
run_shell_script("""$HOME/.local/bin/uv tool install --upgrade "machineconfig>=6.51" """)
|
|
46
46
|
from machineconfig.profile.create_shell_profile import create_default_shell_profile
|
|
47
47
|
if not no_copy_assets:
|
|
48
48
|
create_default_shell_profile() # involves copying assets too
|
|
@@ -67,7 +67,7 @@ def navigate():
|
|
|
67
67
|
path = Path(navigator.__file__).resolve().parent.joinpath("devops_navigator.py")
|
|
68
68
|
from machineconfig.utils.code import run_shell_script
|
|
69
69
|
if Path.home().joinpath("code/machineconfig").exists(): executable = f"""--project "{str(Path.home().joinpath("code/machineconfig"))}" --with textual"""
|
|
70
|
-
else: executable = """--with "machineconfig>=6.
|
|
70
|
+
else: executable = """--with "machineconfig>=6.51,textual" """
|
|
71
71
|
run_shell_script(f"""uv run {executable} {path}""")
|
|
72
72
|
|
|
73
73
|
|
|
@@ -77,7 +77,7 @@ git pull originEnc master
|
|
|
77
77
|
"""
|
|
78
78
|
|
|
79
79
|
if Path.home().joinpath("code/machineconfig").exists(): executable = f"""uv run --project "{str(Path.home().joinpath("code/machineconfig"))}" """
|
|
80
|
-
else: executable = """uv run --with "machineconfig>=6.
|
|
80
|
+
else: executable = """uv run --with "machineconfig>=6.51" """
|
|
81
81
|
|
|
82
82
|
shell_path = write_shell_script_to_file(shell_script=script)
|
|
83
83
|
command = f". {shell_path}"
|
|
@@ -100,12 +100,17 @@ git pull originEnc master
|
|
|
100
100
|
|
|
101
101
|
# ================================================================================
|
|
102
102
|
option1 = "Delete remote copy and push local:"
|
|
103
|
+
from machineconfig.utils.meta import function_to_script
|
|
103
104
|
def func2(remote_repo: str, local_repo: str, cloud: str):
|
|
104
105
|
from machineconfig.scripts.python.helpers_repos.sync import delete_remote_repo_copy_and_push_local
|
|
105
106
|
delete_remote_repo_copy_and_push_local(remote_repo=remote_repo, local_repo=local_repo, cloud=cloud)
|
|
106
107
|
return "done"
|
|
107
|
-
|
|
108
|
-
|
|
108
|
+
# def func2(remote_repo: str=str(repo_remote_root), local_repo: str=str(repo_local_root), cloud: str=str(cloud_resolved)):
|
|
109
|
+
# from machineconfig.scripts.python.helpers_repos.sync import delete_remote_repo_copy_and_push_local
|
|
110
|
+
# delete_remote_repo_copy_and_push_local(remote_repo=remote_repo, local_repo=local_repo, cloud=cloud)
|
|
111
|
+
# return "done"
|
|
112
|
+
# program_1_py = function_to_script(func=func2, call_with_kwargs=None)
|
|
113
|
+
program_1_py = function_to_script(func=func2, call_with_kwargs={"remote_repo": str(repo_remote_root), "local_repo": str(repo_local_root), "cloud": cloud_resolved})
|
|
109
114
|
|
|
110
115
|
|
|
111
116
|
shell_file_1 = get_shell_file_executing_python_script(python_script=program_1_py, ve_path=None, executable=executable)
|
|
@@ -128,7 +133,7 @@ sudo chmod +x $HOME/dotfiles/scripts/linux -R
|
|
|
128
133
|
from machineconfig.scripts.python.helpers_repos.sync import inspect_repos
|
|
129
134
|
inspect_repos(repo_local_root=repo_local_root, repo_remote_root=repo_remote_root)
|
|
130
135
|
return "done"
|
|
131
|
-
program_3_py = function_to_script(func=func,
|
|
136
|
+
program_3_py = function_to_script(func=func, call_with_kwargs={"repo_local_root": str(repo_local_root), "repo_remote_root": str(repo_remote_root)})
|
|
132
137
|
shell_file_3 = get_shell_file_executing_python_script(python_script=program_3_py, ve_path=None, executable=executable)
|
|
133
138
|
# ================================================================================
|
|
134
139
|
|
|
@@ -8,7 +8,7 @@ def analyze_repo_development(repo_path: Annotated[str, typer.Argument(..., help=
|
|
|
8
8
|
from pathlib import Path
|
|
9
9
|
count_lines_path = Path(count_lines.__file__)
|
|
10
10
|
# --project $HOME/code/ machineconfig --group plot
|
|
11
|
-
cmd = f"""uv run --python 3.14 --with "machineconfig[plot]>=6.
|
|
11
|
+
cmd = f"""uv run --python 3.14 --with "machineconfig[plot]>=6.51" {count_lines_path} analyze-over-time {repo_path}"""
|
|
12
12
|
from machineconfig.utils.code import run_shell_script
|
|
13
13
|
run_shell_script(cmd)
|
|
14
14
|
|
|
@@ -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.51" 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."
|
|
@@ -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.51" 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
|
|
@@ -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.51" 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.51" mcfg $args
|
|
6
6
|
}
|
|
7
7
|
function d { mcfg devops @args }
|
|
8
8
|
function c { mcfg cloud @args }
|
machineconfig/utils/code.py
CHANGED
|
@@ -19,7 +19,7 @@ def get_shell_script_executing_python_file(python_file: str, func: Optional[str]
|
|
|
19
19
|
if ve_path is None: ve_activate_line = ""
|
|
20
20
|
else: ve_activate_line = get_ve_activate_line(ve_path)
|
|
21
21
|
shell_script = f"""
|
|
22
|
-
echo "Executing
|
|
22
|
+
echo "Executing {exec_line}"
|
|
23
23
|
{ve_activate_line}
|
|
24
24
|
{exec_line}
|
|
25
25
|
deactivate || true
|
machineconfig/utils/meta.py
CHANGED
|
@@ -5,7 +5,7 @@ import inspect
|
|
|
5
5
|
import textwrap
|
|
6
6
|
from collections.abc import Callable, Mapping
|
|
7
7
|
from types import FunctionType, ModuleType
|
|
8
|
-
from typing import ParamSpec
|
|
8
|
+
from typing import Any, ParamSpec
|
|
9
9
|
|
|
10
10
|
P = ParamSpec("P")
|
|
11
11
|
|
|
@@ -90,6 +90,17 @@ def _extract_imports(func: FunctionType) -> str:
|
|
|
90
90
|
if isinstance(node.value, ast.Name):
|
|
91
91
|
used_names.add(node.value.id)
|
|
92
92
|
|
|
93
|
+
for node in ast.walk(tree):
|
|
94
|
+
if isinstance(node, ast.FunctionDef):
|
|
95
|
+
for default in node.args.defaults + node.args.kw_defaults:
|
|
96
|
+
if default is not None:
|
|
97
|
+
for subnode in ast.walk(default):
|
|
98
|
+
if isinstance(subnode, ast.Name):
|
|
99
|
+
used_names.add(subnode.id)
|
|
100
|
+
elif isinstance(subnode, ast.Attribute):
|
|
101
|
+
if isinstance(subnode.value, ast.Name):
|
|
102
|
+
used_names.add(subnode.value.id)
|
|
103
|
+
|
|
93
104
|
for name in used_names:
|
|
94
105
|
if name in func_globals:
|
|
95
106
|
obj = func_globals[name]
|
|
@@ -101,7 +112,20 @@ def _extract_imports(func: FunctionType) -> str:
|
|
|
101
112
|
else:
|
|
102
113
|
import_statements.add(f"import {module_name} as {name}")
|
|
103
114
|
|
|
104
|
-
elif hasattr(obj, '__module__') and obj.__module__ != '__main__':
|
|
115
|
+
elif isinstance(obj, type) and hasattr(obj, '__module__') and obj.__module__ != '__main__':
|
|
116
|
+
try:
|
|
117
|
+
module_name = obj.__module__
|
|
118
|
+
obj_name = obj.__name__ if hasattr(obj, '__name__') else name
|
|
119
|
+
|
|
120
|
+
if module_name and module_name != 'builtins':
|
|
121
|
+
if obj_name == name:
|
|
122
|
+
import_statements.add(f"from {module_name} import {obj_name}")
|
|
123
|
+
else:
|
|
124
|
+
import_statements.add(f"from {module_name} import {obj_name} as {name}")
|
|
125
|
+
except AttributeError:
|
|
126
|
+
pass
|
|
127
|
+
|
|
128
|
+
elif callable(obj) and not isinstance(obj, type) and hasattr(obj, '__module__') and obj.__module__ != '__main__':
|
|
105
129
|
try:
|
|
106
130
|
module_name = obj.__module__
|
|
107
131
|
obj_name = obj.__name__ if hasattr(obj, '__name__') else name
|
|
@@ -120,6 +144,7 @@ def _extract_imports(func: FunctionType) -> str:
|
|
|
120
144
|
def _extract_globals(func: FunctionType) -> str:
|
|
121
145
|
"""Extract global variables needed by the function."""
|
|
122
146
|
global_assignments: list[str] = []
|
|
147
|
+
needed_types: set[type] = set()
|
|
123
148
|
|
|
124
149
|
source = _get_function_source(func)
|
|
125
150
|
func_globals = func.__globals__
|
|
@@ -137,6 +162,17 @@ def _extract_globals(func: FunctionType) -> str:
|
|
|
137
162
|
if isinstance(node.value, ast.Name):
|
|
138
163
|
used_names.add(node.value.id)
|
|
139
164
|
|
|
165
|
+
for node in ast.walk(tree):
|
|
166
|
+
if isinstance(node, ast.FunctionDef):
|
|
167
|
+
for default in node.args.defaults + node.args.kw_defaults:
|
|
168
|
+
if default is not None:
|
|
169
|
+
for subnode in ast.walk(default):
|
|
170
|
+
if isinstance(subnode, ast.Name):
|
|
171
|
+
used_names.add(subnode.id)
|
|
172
|
+
elif isinstance(subnode, ast.Attribute):
|
|
173
|
+
if isinstance(subnode.value, ast.Name):
|
|
174
|
+
used_names.add(subnode.value.id)
|
|
175
|
+
|
|
140
176
|
for name in used_names:
|
|
141
177
|
if name in func_globals:
|
|
142
178
|
obj = func_globals[name]
|
|
@@ -144,13 +180,35 @@ def _extract_globals(func: FunctionType) -> str:
|
|
|
144
180
|
if not isinstance(obj, (ModuleType, FunctionType, type)):
|
|
145
181
|
if not (hasattr(obj, '__module__') and hasattr(obj, '__name__')):
|
|
146
182
|
try:
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
183
|
+
obj_type = type(obj)
|
|
184
|
+
|
|
185
|
+
if obj_type.__name__ == 'PathExtended' and obj_type.__module__ == 'machineconfig.utils.path_extended':
|
|
186
|
+
global_assignments.append(f"{name} = PathExtended('{str(obj)}')")
|
|
187
|
+
if obj_type.__module__ not in ['builtins', '__main__']:
|
|
188
|
+
needed_types.add(obj_type)
|
|
189
|
+
else:
|
|
190
|
+
repr_str = repr(obj)
|
|
191
|
+
if len(repr_str) < 1000 and '\n' not in repr_str and all(ord(c) < 128 or c in [' ', '\n', '\t'] for c in repr_str):
|
|
192
|
+
global_assignments.append(f"{name} = {repr_str}")
|
|
193
|
+
if obj_type.__module__ not in ['builtins', '__main__']:
|
|
194
|
+
needed_types.add(obj_type)
|
|
195
|
+
else:
|
|
196
|
+
global_assignments.append(f"# Warning: Could not serialize global variable '{name}' (repr too complex or contains non-ASCII)")
|
|
197
|
+
except Exception as e:
|
|
198
|
+
global_assignments.append(f"# Warning: Could not serialize global variable '{name}': {e}")
|
|
199
|
+
|
|
200
|
+
result_parts: list[str] = []
|
|
152
201
|
|
|
153
|
-
|
|
202
|
+
if needed_types:
|
|
203
|
+
for obj_type in sorted(needed_types, key=lambda t: (t.__module__, t.__name__)):
|
|
204
|
+
module_name = obj_type.__module__
|
|
205
|
+
type_name = obj_type.__name__
|
|
206
|
+
result_parts.append(f"from {module_name} import {type_name}")
|
|
207
|
+
result_parts.append("")
|
|
208
|
+
|
|
209
|
+
result_parts.extend(global_assignments)
|
|
210
|
+
|
|
211
|
+
return "\n".join(result_parts)
|
|
154
212
|
|
|
155
213
|
|
|
156
214
|
def _prepare_call_kwargs(func: FunctionType, call_with_kwargs: Mapping[str, object] | None) -> dict[str, object] | None:
|
|
@@ -187,6 +245,183 @@ def _generate_call_statement(func: FunctionType, kwargs: dict[str, object]) -> s
|
|
|
187
245
|
return f"{func.__name__}({args_str})"
|
|
188
246
|
|
|
189
247
|
|
|
248
|
+
def lambda_to_defstring(lmb: Callable[[], Any], in_global: bool = False) -> str:
|
|
249
|
+
"""
|
|
250
|
+
Given a no-arg lambda like `lambda: func(a=var1, b=var2)`,
|
|
251
|
+
return a string containing the full function definition of `func`
|
|
252
|
+
but with the defaults for the parameters provided in the call replaced
|
|
253
|
+
by the *actual* values (repr) taken from the lambda's globals.
|
|
254
|
+
|
|
255
|
+
All imports are local to this function.
|
|
256
|
+
|
|
257
|
+
Args:
|
|
258
|
+
lmb: A lambda function with no arguments
|
|
259
|
+
in_global: If True, return kwargs as global variable assignments followed by dedented body.
|
|
260
|
+
If False (default), return the full function definition with updated defaults.
|
|
261
|
+
"""
|
|
262
|
+
# local imports
|
|
263
|
+
import inspect as _inspect
|
|
264
|
+
import ast as _ast
|
|
265
|
+
import textwrap as _textwrap
|
|
266
|
+
import types as _types
|
|
267
|
+
|
|
268
|
+
# sanity checks
|
|
269
|
+
if not (callable(lmb) and isinstance(lmb, _types.LambdaType)):
|
|
270
|
+
raise TypeError("Expected a lambda function object")
|
|
271
|
+
|
|
272
|
+
src = _inspect.getsource(lmb)
|
|
273
|
+
src = _textwrap.dedent(src)
|
|
274
|
+
tree = _ast.parse(src)
|
|
275
|
+
|
|
276
|
+
# find first Lambda node
|
|
277
|
+
lambda_node = None
|
|
278
|
+
for n in _ast.walk(tree):
|
|
279
|
+
if isinstance(n, _ast.Lambda):
|
|
280
|
+
lambda_node = n
|
|
281
|
+
break
|
|
282
|
+
if lambda_node is None:
|
|
283
|
+
raise ValueError("Could not find a lambda expression in source")
|
|
284
|
+
|
|
285
|
+
body = lambda_node.body
|
|
286
|
+
if not isinstance(body, _ast.Call):
|
|
287
|
+
raise ValueError("Lambda body is not a call expression")
|
|
288
|
+
|
|
289
|
+
globals_dict = getattr(lmb, "__globals__", {})
|
|
290
|
+
|
|
291
|
+
# Also capture closure variables from the lambda
|
|
292
|
+
closure_dict: dict[str, Any] = {}
|
|
293
|
+
if lmb.__closure__:
|
|
294
|
+
code_obj = lmb.__code__
|
|
295
|
+
freevars = code_obj.co_freevars
|
|
296
|
+
for i, var_name in enumerate(freevars):
|
|
297
|
+
closure_dict[var_name] = lmb.__closure__[i].cell_contents
|
|
298
|
+
|
|
299
|
+
# Merge globals and closures (closures take precedence for shadowing)
|
|
300
|
+
eval_namespace = {**globals_dict, **closure_dict}
|
|
301
|
+
|
|
302
|
+
# resolve the function object being called
|
|
303
|
+
try:
|
|
304
|
+
func_ref_src = _ast.unparse(body.func)
|
|
305
|
+
except AttributeError:
|
|
306
|
+
func_ref_src = _ast.get_source_segment(src, body.func) or ""
|
|
307
|
+
try:
|
|
308
|
+
func_obj = eval(func_ref_src, eval_namespace)
|
|
309
|
+
except Exception as e:
|
|
310
|
+
raise RuntimeError(f"Could not resolve function reference '{func_ref_src}': {e}")
|
|
311
|
+
|
|
312
|
+
if not callable(func_obj):
|
|
313
|
+
raise TypeError("Resolved object is not callable")
|
|
314
|
+
|
|
315
|
+
func_name = getattr(func_obj, "__name__", "<unknown>")
|
|
316
|
+
|
|
317
|
+
# Evaluate each keyword argument value in the lambda's globals to get real Python objects
|
|
318
|
+
call_kwargs = {}
|
|
319
|
+
for kw in body.keywords:
|
|
320
|
+
if kw.arg is None:
|
|
321
|
+
# **kwargs in call — evaluate to dict and merge
|
|
322
|
+
try:
|
|
323
|
+
val = eval(compile(_ast.Expression(kw.value), "<lambda_eval>", "eval"), eval_namespace)
|
|
324
|
+
if isinstance(val, dict):
|
|
325
|
+
call_kwargs.update(val)
|
|
326
|
+
else:
|
|
327
|
+
raise ValueError("Keyword expansion did not evaluate to a dict")
|
|
328
|
+
except Exception as e:
|
|
329
|
+
raise RuntimeError(f"Failed to evaluate **kwargs expression: {e}")
|
|
330
|
+
else:
|
|
331
|
+
try:
|
|
332
|
+
val = eval(compile(_ast.Expression(kw.value), "<lambda_eval>", "eval"), eval_namespace)
|
|
333
|
+
call_kwargs[kw.arg] = val
|
|
334
|
+
except Exception as e:
|
|
335
|
+
raise RuntimeError(f"Failed to evaluate value for kw '{kw.arg}': {e}")
|
|
336
|
+
|
|
337
|
+
# Try to get original source and dedent it for body extraction
|
|
338
|
+
try:
|
|
339
|
+
orig_src = _inspect.getsource(func_obj)
|
|
340
|
+
ded = _textwrap.dedent(orig_src)
|
|
341
|
+
lines = ded.splitlines()
|
|
342
|
+
# find the line that starts with def <name>(
|
|
343
|
+
def_index = None
|
|
344
|
+
for i, ln in enumerate(lines):
|
|
345
|
+
if ln.lstrip().startswith(f"def {func_name}("):
|
|
346
|
+
def_index = i
|
|
347
|
+
break
|
|
348
|
+
if def_index is None:
|
|
349
|
+
body_lines = ded.splitlines()
|
|
350
|
+
else:
|
|
351
|
+
body_lines = lines[def_index + 1 :]
|
|
352
|
+
# ensure we have a body, otherwise use pass
|
|
353
|
+
if not any(line.strip() for line in body_lines):
|
|
354
|
+
body_text = " pass\n"
|
|
355
|
+
else:
|
|
356
|
+
# keep the dedented body lines exactly as-is (they should be indented)
|
|
357
|
+
body_text = "\n".join(body_lines) + ("\n" if not body_lines[-1].endswith("\n") else "")
|
|
358
|
+
except (OSError, IOError, TypeError):
|
|
359
|
+
body_text = " pass\n"
|
|
360
|
+
|
|
361
|
+
# Build a replaced signature using inspect.signature
|
|
362
|
+
sig = _inspect.signature(func_obj)
|
|
363
|
+
new_params = []
|
|
364
|
+
for name, param in sig.parameters.items():
|
|
365
|
+
# If the call provided a value for this parameter, replace default
|
|
366
|
+
if name in call_kwargs:
|
|
367
|
+
new_default = call_kwargs[name]
|
|
368
|
+
else:
|
|
369
|
+
new_default = param.default
|
|
370
|
+
|
|
371
|
+
# Recreate the Parameter (keeping annotation and kind)
|
|
372
|
+
if new_default is _inspect.Parameter.empty:
|
|
373
|
+
new_param = _inspect.Parameter(name, param.kind, annotation=param.annotation)
|
|
374
|
+
else:
|
|
375
|
+
new_param = _inspect.Parameter(
|
|
376
|
+
name, param.kind, default=new_default, annotation=param.annotation
|
|
377
|
+
)
|
|
378
|
+
new_params.append(new_param)
|
|
379
|
+
|
|
380
|
+
new_sig = _inspect.Signature(parameters=new_params, return_annotation=sig.return_annotation)
|
|
381
|
+
|
|
382
|
+
# If in_global mode, return kwargs as global assignments + dedented body
|
|
383
|
+
if in_global:
|
|
384
|
+
global_assignments: list[str] = []
|
|
385
|
+
for name, param in sig.parameters.items():
|
|
386
|
+
# Get the value from call_kwargs if provided, else use original default
|
|
387
|
+
if name in call_kwargs:
|
|
388
|
+
value = call_kwargs[name]
|
|
389
|
+
elif param.default is not _inspect.Parameter.empty:
|
|
390
|
+
value = param.default
|
|
391
|
+
else:
|
|
392
|
+
# No value provided and no default - skip this parameter
|
|
393
|
+
continue
|
|
394
|
+
|
|
395
|
+
# Build type annotation string if available
|
|
396
|
+
if param.annotation is not _inspect.Parameter.empty:
|
|
397
|
+
# Try to get a nice string representation of the annotation
|
|
398
|
+
try:
|
|
399
|
+
if hasattr(param.annotation, "__name__"):
|
|
400
|
+
type_str = param.annotation.__name__
|
|
401
|
+
else:
|
|
402
|
+
type_str = str(param.annotation)
|
|
403
|
+
except Exception:
|
|
404
|
+
type_str = str(param.annotation)
|
|
405
|
+
global_assignments.append(f"{name}: {type_str} = {repr(value)}")
|
|
406
|
+
else:
|
|
407
|
+
global_assignments.append(f"{name} = {repr(value)}")
|
|
408
|
+
|
|
409
|
+
# Dedent the body text to remove function indentation
|
|
410
|
+
dedented_body = _textwrap.dedent(body_text).rstrip()
|
|
411
|
+
|
|
412
|
+
# Combine global assignments and body
|
|
413
|
+
if global_assignments:
|
|
414
|
+
result_parts = ["\n".join(global_assignments), "", dedented_body]
|
|
415
|
+
return "\n".join(result_parts)
|
|
416
|
+
else:
|
|
417
|
+
return dedented_body
|
|
418
|
+
|
|
419
|
+
# Compose final function definition text
|
|
420
|
+
header = f"def {func_name}{new_sig}:\n"
|
|
421
|
+
final_src = header + body_text
|
|
422
|
+
return final_src
|
|
423
|
+
|
|
424
|
+
|
|
190
425
|
if __name__ == "__main__":
|
|
191
426
|
# Example usage
|
|
192
427
|
a = True
|
machineconfig/utils/scheduler.py
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
|
+
|
|
1
2
|
from pathlib import Path
|
|
2
3
|
from typing import Callable, Optional, Union, Any, Protocol, List, TypeVar
|
|
3
4
|
import logging
|
|
4
5
|
import time
|
|
5
6
|
from datetime import datetime, timezone, timedelta
|
|
6
7
|
from machineconfig.utils.io import from_pickle
|
|
7
|
-
from machineconfig.utils.path_extended import PathExtended
|
|
8
8
|
|
|
9
9
|
|
|
10
10
|
class LoggerTemplate(Protocol):
|
|
@@ -147,7 +147,6 @@ class Scheduler:
|
|
|
147
147
|
T2 = TypeVar("T2")
|
|
148
148
|
def to_pickle(obj: Any, path: Path) -> None:
|
|
149
149
|
import pickle
|
|
150
|
-
path.parent.mkdir(parents=True, exist_ok=True)
|
|
151
150
|
path.write_bytes(pickle.dumps(obj))
|
|
152
151
|
|
|
153
152
|
|
|
@@ -160,15 +159,12 @@ class CacheMemory[T]():
|
|
|
160
159
|
self.time_produced = datetime.now()
|
|
161
160
|
self.logger = logger
|
|
162
161
|
self.expire = expire
|
|
163
|
-
self.name = name if isinstance(name, str) else
|
|
164
|
-
self.last_call_is_fresh = False
|
|
165
|
-
|
|
162
|
+
self.name = name if isinstance(name, str) else self.source_func.__name__
|
|
166
163
|
@property
|
|
167
164
|
def age(self) -> timedelta:
|
|
168
165
|
return datetime.now() - self.time_produced
|
|
169
166
|
|
|
170
167
|
def __call__(self, fresh: bool = False) -> T:
|
|
171
|
-
self.last_call_is_fresh = False
|
|
172
168
|
if fresh or not hasattr(self, "cache"):
|
|
173
169
|
why = "There was an explicit fresh order." if fresh else "Previous cache never existed."
|
|
174
170
|
t0 = time.time()
|
|
@@ -177,7 +173,6 @@ class CacheMemory[T]():
|
|
|
177
173
|
ℹ️ Reason: {why}""")
|
|
178
174
|
self.cache = self.source_func()
|
|
179
175
|
self.logger.warning(f"⏱️ Cache population took {time.time() - t0:.2f} seconds.")
|
|
180
|
-
self.last_call_is_fresh = True
|
|
181
176
|
self.time_produced = datetime.now()
|
|
182
177
|
else:
|
|
183
178
|
age = self.age
|
|
@@ -189,7 +184,6 @@ class CacheMemory[T]():
|
|
|
189
184
|
t0 = time.time()
|
|
190
185
|
self.cache = self.source_func()
|
|
191
186
|
self.logger.warning(f"⏱️ Cache population took {time.time() - t0:.2f} seconds.")
|
|
192
|
-
self.last_call_is_fresh = True
|
|
193
187
|
self.time_produced = datetime.now()
|
|
194
188
|
else:
|
|
195
189
|
self.logger.warning(f"""
|
|
@@ -212,21 +206,19 @@ class Cache[T](): # This class helps to accelrate access to latest data coming
|
|
|
212
206
|
) -> None:
|
|
213
207
|
self.cache: T
|
|
214
208
|
self.source_func = source_func # function which when called returns a fresh object to be frozen.
|
|
215
|
-
self.path:
|
|
209
|
+
self.path: Path = path
|
|
210
|
+
_ = self.path.parent.mkdir(parents=True, exist_ok=True)
|
|
216
211
|
self.time_produced = datetime.now() # if path is None else
|
|
217
212
|
self.save = saver
|
|
218
213
|
self.reader = reader
|
|
219
214
|
self.logger = logger
|
|
220
215
|
self.expire = expire
|
|
221
|
-
self.name = name if isinstance(name, str) else
|
|
222
|
-
self.last_call_is_fresh = False
|
|
223
|
-
|
|
216
|
+
self.name = name if isinstance(name, str) else self.source_func.__name__
|
|
224
217
|
@property
|
|
225
218
|
def age(self):
|
|
226
219
|
"""Throws AttributeError if called before cache is populated and path doesn't exists"""
|
|
227
220
|
return datetime.now() - self.time_produced
|
|
228
221
|
def __call__(self, fresh: bool = False) -> T:
|
|
229
|
-
self.last_call_is_fresh = False
|
|
230
222
|
if fresh or not hasattr(self, "cache"): # populate cache for the first time
|
|
231
223
|
if not fresh and self.path.exists():
|
|
232
224
|
age = datetime.now() - datetime.fromtimestamp(self.path.stat().st_mtime)
|
|
@@ -245,10 +237,8 @@ class Cache[T](): # This class helps to accelrate access to latest data coming
|
|
|
245
237
|
t0 = time.time()
|
|
246
238
|
self.cache = self.source_func()
|
|
247
239
|
self.logger.warning(f"⏱️ Cache population took {time.time() - t0:.2f} seconds.")
|
|
248
|
-
self.last_call_is_fresh = True
|
|
249
240
|
self.time_produced = datetime.now()
|
|
250
|
-
|
|
251
|
-
# self.save(self.cache, self.path)
|
|
241
|
+
self.save(self.cache, self.path)
|
|
252
242
|
return self.cache
|
|
253
243
|
return self(fresh=False) # may be the cache is old ==> check that by passing it through the logic again.
|
|
254
244
|
else:
|
|
@@ -261,7 +251,6 @@ class Cache[T](): # This class helps to accelrate access to latest data coming
|
|
|
261
251
|
t0 = time.time()
|
|
262
252
|
self.cache = self.source_func() # fresh data.
|
|
263
253
|
self.logger.warning(f"⏱️ Cache population took {time.time() - t0:.2f} seconds.")
|
|
264
|
-
self.last_call_is_fresh = True
|
|
265
254
|
self.time_produced = datetime.now()
|
|
266
255
|
self.save(self.cache, self.path)
|
|
267
256
|
else: # cache exists
|
|
@@ -277,7 +266,6 @@ class Cache[T](): # This class helps to accelrate access to latest data coming
|
|
|
277
266
|
t0 = time.time()
|
|
278
267
|
self.cache = self.source_func()
|
|
279
268
|
self.logger.warning(f"⏱️ Cache population took {time.time() - t0:.2f} seconds.")
|
|
280
|
-
self.last_call_is_fresh = True
|
|
281
269
|
self.time_produced = datetime.now()
|
|
282
270
|
self.save(self.cache, self.path)
|
|
283
271
|
else:
|
|
@@ -294,5 +282,4 @@ class Cache[T](): # This class helps to accelrate access to latest data coming
|
|
|
294
282
|
def decorator(source_func: Callable[[], T2]) -> Cache["T2"]:
|
|
295
283
|
res = Cache(source_func=source_func, expire=expire, logger=logger, path=path, name=name, reader=reader, saver=saver)
|
|
296
284
|
return res
|
|
297
|
-
|
|
298
285
|
return decorator
|
machineconfig/utils/ssh.py
CHANGED
|
@@ -6,7 +6,7 @@ from machineconfig.utils.terminal import Response, MACHINE
|
|
|
6
6
|
from machineconfig.utils.accessories import pprint
|
|
7
7
|
|
|
8
8
|
UV_RUN_CMD = "$HOME/.local/bin/uv run"
|
|
9
|
-
MACHINECONFIG_VERSION = "machineconfig>=6.
|
|
9
|
+
MACHINECONFIG_VERSION = "machineconfig>=6.51"
|
|
10
10
|
DEFAULT_PICKLE_SUBDIR = "tmp_results/tmp_scripts/ssh"
|
|
11
11
|
|
|
12
12
|
|
|
@@ -25,7 +25,7 @@ machineconfig/cluster/sessions_managers/zellij_remote_manager.py,sha256=xzih0y8_
|
|
|
25
25
|
machineconfig/cluster/sessions_managers/helpers/enhanced_command_runner.py,sha256=3vcQVg-HHa_WTxBGPtKMAdoSqJVa2EO5KAtrY8a6I3c,5264
|
|
26
26
|
machineconfig/cluster/sessions_managers/helpers/load_balancer_helper.py,sha256=i5TRittC1IWTgMZNyG8AR5qq-3WrGp3xgIx2m5ktT7g,7526
|
|
27
27
|
machineconfig/cluster/sessions_managers/utils/load_balancer.py,sha256=Y4RQmhROY6o7JXSJXRrBTkoAuEmu1gvmvN_7JKPw5sc,3178
|
|
28
|
-
machineconfig/cluster/sessions_managers/utils/maker.py,sha256=
|
|
28
|
+
machineconfig/cluster/sessions_managers/utils/maker.py,sha256=kUJLOctqRR_jumdDIssxBI65pBhBEHxDOOq_RohnoeU,2133
|
|
29
29
|
machineconfig/cluster/sessions_managers/wt_utils/layout_generator.py,sha256=OA50j16uUS9ZTjL38TLuR3jufIOln_EszMZpbWyejTo,6972
|
|
30
30
|
machineconfig/cluster/sessions_managers/wt_utils/process_monitor.py,sha256=Mitm7mKiKl5lT0OiEUHAqVg2Q21RjsKO1-hpJTHJ5lM,15196
|
|
31
31
|
machineconfig/cluster/sessions_managers/wt_utils/remote_executor.py,sha256=lApUy67_WhfaBXqt0meZSx_QvwiXjN0YLdyE3c7kP_s,6744
|
|
@@ -122,7 +122,7 @@ machineconfig/scripts/linux/other/switch_ip,sha256=NQfeKMBSbFY3eP6M-BadD-TQo5qMP
|
|
|
122
122
|
machineconfig/scripts/python/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
123
123
|
machineconfig/scripts/python/agents.py,sha256=gGeeWCI0AN_DyDJ3G5KR9qSsXv8zkUd5dBRRWqz-dQE,10722
|
|
124
124
|
machineconfig/scripts/python/cloud.py,sha256=yAD6ciKiEtv2CH3g2NScDK5cpCZQi7Vu8yyeehw_cU8,1263
|
|
125
|
-
machineconfig/scripts/python/croshell.py,sha256=
|
|
125
|
+
machineconfig/scripts/python/croshell.py,sha256=SRubnCMUdgi0yAdQ3maHPbSzoWLJIl3gLA04nEFO0Fo,8046
|
|
126
126
|
machineconfig/scripts/python/devops.py,sha256=LGra1YiLEQYjaRevNjJB51Bia81IgjrvUQkA6z8wq8I,2440
|
|
127
127
|
machineconfig/scripts/python/devops_navigator.py,sha256=5Cm384D4S8_GsvMzTwr0C16D0ktf8_5Mk5bEJncwDO8,237
|
|
128
128
|
machineconfig/scripts/python/entry.py,sha256=a0Zk_3RnIFTQ55zSQrvOOiKom_SaoxElPMmWQgGy4V0,2221
|
|
@@ -162,7 +162,7 @@ machineconfig/scripts/python/ai/solutions/opencode/opencode.json,sha256=nahHKRw1
|
|
|
162
162
|
machineconfig/scripts/python/ai/solutions/opencode/opencode.py,sha256=AbpHGcgLb-kRsJGnwFEktk7uzpZOCcBY74-YBdrKVGs,1
|
|
163
163
|
machineconfig/scripts/python/env_manager/__init__.py,sha256=E4LAHbU1wo2dLjE36ntv8U7QNTe8TasujUAYK9SLvWk,6
|
|
164
164
|
machineconfig/scripts/python/env_manager/path_manager_backend.py,sha256=ZVGlGJALhg7zNABDdwXxL7MFbL2BXPebObipXSLGbic,1552
|
|
165
|
-
machineconfig/scripts/python/env_manager/path_manager_tui.py,sha256=
|
|
165
|
+
machineconfig/scripts/python/env_manager/path_manager_tui.py,sha256=jVIpEwvRbkaqw7HXl0Ufy_m4tBGhxhfC8gKrC4fTTds,6932
|
|
166
166
|
machineconfig/scripts/python/helpers_cloud/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
167
167
|
machineconfig/scripts/python/helpers_cloud/cloud_copy.py,sha256=OV1w3ajFVFs6FJytjIPOntYB_aW2ywGohKi73V4Dm2Y,8691
|
|
168
168
|
machineconfig/scripts/python/helpers_cloud/cloud_helpers.py,sha256=GA-bxXouUmknk9fyQAsPT-Xl3RG9-yBed71a2tu9Pig,4914
|
|
@@ -171,19 +171,19 @@ machineconfig/scripts/python/helpers_cloud/cloud_sync.py,sha256=ThfI4rvKG6IPzAo3
|
|
|
171
171
|
machineconfig/scripts/python/helpers_cloud/helpers2.py,sha256=3fXDiDlz5EDk_04YtPd-bjZcjUjmGTpgiQ1YMaGbD8g,7310
|
|
172
172
|
machineconfig/scripts/python/helpers_cloud/helpers5.py,sha256=dPBvA9Tcyx9TMgM6On49A1CueGMhBdRzikDnlJGf3J0,1123
|
|
173
173
|
machineconfig/scripts/python/helpers_croshell/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
174
|
-
machineconfig/scripts/python/helpers_croshell/crosh.py,sha256=
|
|
174
|
+
machineconfig/scripts/python/helpers_croshell/crosh.py,sha256=FlK3qyMsbacM27Hq83JpXNOSlC4QSsF8B2665BEFs34,1620
|
|
175
175
|
machineconfig/scripts/python/helpers_croshell/pomodoro.py,sha256=SPkfeoZGv8rylGiOyzQ7UK3aXZ3G2FIOuGkSuBUggOI,2019
|
|
176
176
|
machineconfig/scripts/python/helpers_croshell/scheduler.py,sha256=rKhssuxkD697EY6qaV6CSdNhxpAQLDWO4fE8GMCQ9FA,3061
|
|
177
177
|
machineconfig/scripts/python/helpers_croshell/start_slidev.py,sha256=HfJReOusTPhwcbAvCyJyTBd2iumJB5wmPdcTXz_Yvh8,4897
|
|
178
178
|
machineconfig/scripts/python/helpers_croshell/viewer.py,sha256=heQNjB9fwn3xxbPgMofhv1Lp6Vtkl76YjjexWWBM0pM,2041
|
|
179
179
|
machineconfig/scripts/python/helpers_croshell/viewer_template.py,sha256=ve3Q1-iKhCLc0VJijKvAeOYp2xaFOeIOC_XW956GWCc,3944
|
|
180
180
|
machineconfig/scripts/python/helpers_devops/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
181
|
-
machineconfig/scripts/python/helpers_devops/cli_config.py,sha256=
|
|
181
|
+
machineconfig/scripts/python/helpers_devops/cli_config.py,sha256=YB97BaIgxT9VPWYoVc0rk_pzL2BjBn5v6-VccreS8J4,5652
|
|
182
182
|
machineconfig/scripts/python/helpers_devops/cli_config_dotfile.py,sha256=rjTys4FNf9_feP9flWM7Zvq17dxWmetSiGaHPxp25nk,2737
|
|
183
183
|
machineconfig/scripts/python/helpers_devops/cli_data.py,sha256=79Xvx7YnbueruEnl69hrDg2AhVxf_zCUdlVcKfeMGyQ,1774
|
|
184
184
|
machineconfig/scripts/python/helpers_devops/cli_nw.py,sha256=B5Xa9pV5MdC4vPo3EmKaHvNMlThsY3c5F92YPE5j3rI,4176
|
|
185
185
|
machineconfig/scripts/python/helpers_devops/cli_repos.py,sha256=Xwkv1adqHZvTfRSPWiqSK3PZ1XADyx3llw_YkbxaKyE,12505
|
|
186
|
-
machineconfig/scripts/python/helpers_devops/cli_self.py,sha256=
|
|
186
|
+
machineconfig/scripts/python/helpers_devops/cli_self.py,sha256=zcEeQsgbR7OgPkvzAuHPKntT-YMVXYmRJU5cE7kkbes,6167
|
|
187
187
|
machineconfig/scripts/python/helpers_devops/cli_share_server.py,sha256=q9pFJ6AxPuygMr3onMNOKEuuQHbVE_6Qoyo7xRT5FX0,4196
|
|
188
188
|
machineconfig/scripts/python/helpers_devops/cli_terminal.py,sha256=k_PzXaiGyE0vXr0Ii1XcJz2A7UvyPJrR31TRWt4RKRI,6019
|
|
189
189
|
machineconfig/scripts/python/helpers_devops/cli_utils.py,sha256=G2RHnOvNfEWjxETZjXVu688xyLL-c0Zq22p24kXLLQ8,3487
|
|
@@ -222,9 +222,9 @@ machineconfig/scripts/python/helpers_navigator/main_app.py,sha256=R1vOBMUKaiFHOg
|
|
|
222
222
|
machineconfig/scripts/python/helpers_navigator/search_bar.py,sha256=kDi8Jhxap8wdm7YpDBtfhwcPnSqDPFrV2LqbcSBWMT4,414
|
|
223
223
|
machineconfig/scripts/python/helpers_repos/action.py,sha256=9AxWy8mB9HFeV5t11-qD_l-KA5jkUmm0pXVKT1L6-Qk,14894
|
|
224
224
|
machineconfig/scripts/python/helpers_repos/clone.py,sha256=UULEG5xJuXlPGU0nqXH6U45jA9DOFqLw8B4iPytCwOQ,5471
|
|
225
|
-
machineconfig/scripts/python/helpers_repos/cloud_repo_sync.py,sha256=
|
|
225
|
+
machineconfig/scripts/python/helpers_repos/cloud_repo_sync.py,sha256=wWlO5-3yT70R8FSU254f4LUMCIaGzrqZexmgzI2ddAU,10412
|
|
226
226
|
machineconfig/scripts/python/helpers_repos/count_lines.py,sha256=Q5c7b-DxvTlQmljoic7niTuiAVyFlwYvkVQ7uRJHiTo,16009
|
|
227
|
-
machineconfig/scripts/python/helpers_repos/count_lines_frontend.py,sha256=
|
|
227
|
+
machineconfig/scripts/python/helpers_repos/count_lines_frontend.py,sha256=iOPc9iLfgMwMFwCguiutfPHHPfpNDYCqHj0W4pFkm-k,607
|
|
228
228
|
machineconfig/scripts/python/helpers_repos/entrypoint.py,sha256=WYEFGUJp9HWImlFjbs_hiFZrUqM_KEYm5VvSUjWd04I,2810
|
|
229
229
|
machineconfig/scripts/python/helpers_repos/grource.py,sha256=oJj1-gqlkV3Z_BrIOXRmtzoXcuBl0xTYfulJ5D0srOc,14656
|
|
230
230
|
machineconfig/scripts/python/helpers_repos/record.py,sha256=FQo0swuJZOp0I2XGK-t1OQU4zJHmQ2z9zTpDD30Tmg4,11001
|
|
@@ -238,7 +238,7 @@ machineconfig/scripts/python/nw/add_ssh_key.py,sha256=9JLmWu8pE7PAL5VuCFd19iVEdC
|
|
|
238
238
|
machineconfig/scripts/python/nw/devops_add_identity.py,sha256=aPjcHbTLhxYwWYcandyAHdwuO15ZBu3fB82u6bI0tMQ,3773
|
|
239
239
|
machineconfig/scripts/python/nw/devops_add_ssh_key.py,sha256=CkIl85hZLtG9k7yXLSzqi88YrilHV4hIUWHAPBwxWjw,8922
|
|
240
240
|
machineconfig/scripts/python/nw/mount_drive,sha256=zemKofv7hOmRN_V3qK0q580GkfWw3VdikyVVQyiu8j8,3514
|
|
241
|
-
machineconfig/scripts/python/nw/mount_nfs,sha256=
|
|
241
|
+
machineconfig/scripts/python/nw/mount_nfs,sha256=q75al-z70gQhjUwtZzM-hu-U3cATaDrGtEyjgbegQrI,1855
|
|
242
242
|
machineconfig/scripts/python/nw/mount_nfs.py,sha256=lOMDY4RS7tx8gsCazVR5tNNwFbaRyO2PJlnwBCDQgCM,3573
|
|
243
243
|
machineconfig/scripts/python/nw/mount_nw_drive,sha256=BqjGBCbwe5ZAsZDO3L0zHhh_gJfZy1CYOcqXA4Y-WkQ,2262
|
|
244
244
|
machineconfig/scripts/python/nw/mount_nw_drive.py,sha256=iru6AtnTyvyuk6WxlK5R4lDkuliVpPV5_uBTVVhXtjQ,1550
|
|
@@ -255,7 +255,7 @@ machineconfig/scripts/windows/fzfrga.bat,sha256=rU_KBMO6ii2EZ0akMnmDk9vpuhKSUZqk
|
|
|
255
255
|
machineconfig/scripts/windows/mounts/mount_nfs.ps1,sha256=XrAdzpxE6a4OccSmWJ7YWHJTnsZK8uXnFE5j9GOPA20,2026
|
|
256
256
|
machineconfig/scripts/windows/mounts/mount_nw.ps1,sha256=puxcfZc3ZCJerm8pj8OZGVoTYkhzp-h7oV-MrksSqIE,454
|
|
257
257
|
machineconfig/scripts/windows/mounts/mount_smb.ps1,sha256=PzYWpIO9BpwXjdWlUQL9pnMRnOGNSkxfh4bHukJFme8,69
|
|
258
|
-
machineconfig/scripts/windows/mounts/mount_ssh.ps1,sha256=
|
|
258
|
+
machineconfig/scripts/windows/mounts/mount_ssh.ps1,sha256=EJ7EzPIesIMmpvReVpu5tJGZBcBqzH4EgNfhUnO4vLg,322
|
|
259
259
|
machineconfig/scripts/windows/mounts/share_cloud.cmd,sha256=exD7JCdxw2LqVjw2MKCYHbVZlEqmelXtwnATng-dhJ4,1028
|
|
260
260
|
machineconfig/scripts/windows/mounts/share_smb.ps1,sha256=U7x8ULYSjbgzTtiHNSKQuTaZ_apilDvkGV5Xm5hXk5M,384
|
|
261
261
|
machineconfig/scripts/windows/mounts/unlock_bitlocker.ps1,sha256=Wv-SLscdckV-1mG3p82VXKPY9zW3hgkRmcLUXIZ1daE,253
|
|
@@ -371,7 +371,7 @@ machineconfig/setup_linux/others/mint_keyboard_shortcuts.sh,sha256=F5dbg0n9RHsKG
|
|
|
371
371
|
machineconfig/setup_linux/ssh/openssh_all.sh,sha256=3dg6HEUFbHQOzLfSAtzK_D_GB8rGCCp_aBnxNdnidVc,824
|
|
372
372
|
machineconfig/setup_linux/ssh/openssh_wsl.sh,sha256=1eeRGrloVB34K5z8yWVUMG5b9pV-WBfHgV9jqXiYgCQ,1398
|
|
373
373
|
machineconfig/setup_linux/web_shortcuts/android.sh,sha256=gzep6bBhK7FCBvGcXK0fdJCtkSfBOftt0aFyDZq_eMs,68
|
|
374
|
-
machineconfig/setup_linux/web_shortcuts/interactive.sh,sha256
|
|
374
|
+
machineconfig/setup_linux/web_shortcuts/interactive.sh,sha256=-33Rd_a52za-bO_OVIRXS4AhNvcG7uzOGjlWAOfRdDU,441
|
|
375
375
|
machineconfig/setup_windows/__init__.py,sha256=NnSVZkIBoxoMgkj-_KAqGonH3YziBIWXOKDEcmNAGTY,386
|
|
376
376
|
machineconfig/setup_windows/apps.ps1,sha256=dmZQZD4ZlNZo9jYkjIS3ag4qDAYZvaLysjmo9ELwBA4,11218
|
|
377
377
|
machineconfig/setup_windows/uv.ps1,sha256=ukk1Abh-q-RfpoEqI2XTE2dcQJmHk0VFF6WqkK3TW8Q,350
|
|
@@ -381,25 +381,25 @@ machineconfig/setup_windows/others/power_options.ps1,sha256=c7Hn94jBD5GWF29CxMhm
|
|
|
381
381
|
machineconfig/setup_windows/ssh/add-sshkey.ps1,sha256=qfPdqCpd9KP3VhH4ifsUm1Xvec7c0QVl4Wt8JIAm9HQ,1653
|
|
382
382
|
machineconfig/setup_windows/ssh/add_identity.ps1,sha256=b8ZXpmNUSw3IMYvqSY7ClpdWPG39FS7MefoWnRhWN2U,506
|
|
383
383
|
machineconfig/setup_windows/ssh/openssh-server.ps1,sha256=OMlYQdvuJQNxF5EILLPizB6BZAT3jAmDsv1WcVVxpFQ,2529
|
|
384
|
-
machineconfig/setup_windows/web_shortcuts/interactive.ps1,sha256=
|
|
384
|
+
machineconfig/setup_windows/web_shortcuts/interactive.ps1,sha256=cO6kEXDbTCufPuBeksWtf728owbTK6pXmp8RLZ54fz8,547
|
|
385
385
|
machineconfig/setup_windows/wt_and_pwsh/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
386
386
|
machineconfig/setup_windows/wt_and_pwsh/set_wt_settings.py,sha256=ogxJnwpdcpH7N6dFJu95UCNoGYirZKQho_3X0F_hmXs,6791
|
|
387
387
|
machineconfig/utils/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
388
388
|
machineconfig/utils/accessories.py,sha256=W_9dLzjwNTW5JQk_pe3B2ijQ1nA2-8Kdg2r7VBtzgQs,4340
|
|
389
|
-
machineconfig/utils/code.py,sha256=
|
|
389
|
+
machineconfig/utils/code.py,sha256=W0JFDF1ynJJIYtrAP6IqCcmrhvS-_zyDz43etnWW7_4,7543
|
|
390
390
|
machineconfig/utils/installer.py,sha256=wNkX2r6dlZD9zmuIkBKj5AliNPfI9zVWgtu8XqgUVIg,10204
|
|
391
391
|
machineconfig/utils/io.py,sha256=4dSieoqZO8Vvi4vW8lLoITDHBvmFp4dtl3kyeZHQ6Co,2528
|
|
392
392
|
machineconfig/utils/links.py,sha256=KM6vIn3hag9FYEzLSHP5MAM9tU_RStw2mCq2_OvmmZA,23672
|
|
393
|
-
machineconfig/utils/meta.py,sha256=
|
|
393
|
+
machineconfig/utils/meta.py,sha256=r557UPqgNLXzQpk8Umeujj9RnRBeIz3RwOwjZ7hWsw0,17309
|
|
394
394
|
machineconfig/utils/notifications.py,sha256=tuXIudcip0tEioG-bm8BbLr3FMDve4f6BktlznBhKxM,9013
|
|
395
395
|
machineconfig/utils/options.py,sha256=vUO4Kej-vDOv64wHr2HNDyu6PATURpjd7xp6N8OOoJg,7083
|
|
396
396
|
machineconfig/utils/path_extended.py,sha256=WyJwoHnXdvSQQJ-yrxTX78FpqYmgVeKDYpNEB9UsRck,53223
|
|
397
397
|
machineconfig/utils/path_helper.py,sha256=0e3Xh3BAEv27oqcezNeVLHJllGmLEgLH4T1l90m-650,8014
|
|
398
398
|
machineconfig/utils/procs.py,sha256=YPA_vEYQGwPd_o_Lc6nOTBo5BrB1tSs8PJ42XiGpenM,10957
|
|
399
|
-
machineconfig/utils/scheduler.py,sha256
|
|
399
|
+
machineconfig/utils/scheduler.py,sha256=44CASABJg3epccxhAwv2CX7TVgZh6zVy3K4vqHKTuf4,14228
|
|
400
400
|
machineconfig/utils/scheduling.py,sha256=RF1iXJpqf4Dg18jdZWtBixz97KAHC6VKYqTFSpdLWuc,11188
|
|
401
401
|
machineconfig/utils/source_of_truth.py,sha256=ZAnCRltiM07ig--P6g9_6nEAvNFC4X4ERFTVcvpIYsE,764
|
|
402
|
-
machineconfig/utils/ssh.py,sha256=
|
|
402
|
+
machineconfig/utils/ssh.py,sha256=QDY3ti-V8PwZlAlNIw_4mPbPrRznJQjqb9ohN1x4HTM,39079
|
|
403
403
|
machineconfig/utils/terminal.py,sha256=IlmOByfQG-vjhaFFxxzU5rWzP5_qUzmalRfuey3PAmc,11801
|
|
404
404
|
machineconfig/utils/tst.py,sha256=6u1GI49NdcpxH2BYGAusNfY5q9G_ytCGVzFM5b6HYpM,674
|
|
405
405
|
machineconfig/utils/upgrade_packages.py,sha256=mSFyKvB3JhHte_x1dtmEgrJZCAXgTUQoaJUSx1OXQ3Y,4145
|
|
@@ -428,8 +428,8 @@ machineconfig/utils/schemas/installer/installer_types.py,sha256=QClRY61QaduBPJoS
|
|
|
428
428
|
machineconfig/utils/schemas/layouts/layout_types.py,sha256=TcqlZdGVoH8htG5fHn1KWXhRdPueAcoyApppZsPAPto,2020
|
|
429
429
|
machineconfig/utils/schemas/repos/repos_types.py,sha256=ECVr-3IVIo8yjmYmVXX2mnDDN1SLSwvQIhx4KDDQHBQ,405
|
|
430
430
|
machineconfig/utils/ssh_utils/utils.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
431
|
-
machineconfig-6.
|
|
432
|
-
machineconfig-6.
|
|
433
|
-
machineconfig-6.
|
|
434
|
-
machineconfig-6.
|
|
435
|
-
machineconfig-6.
|
|
431
|
+
machineconfig-6.51.dist-info/METADATA,sha256=gDZDg13wSRXMkH_JmCW_3OPQdHyWfRSK7S2SaS2VsYU,2928
|
|
432
|
+
machineconfig-6.51.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
|
433
|
+
machineconfig-6.51.dist-info/entry_points.txt,sha256=M0jwN_brZdXWhmNVeXLvdKxfkv8WhhXFZYcuKBA9qnk,418
|
|
434
|
+
machineconfig-6.51.dist-info/top_level.txt,sha256=porRtB8qms8fOIUJgK-tO83_FeH6Bpe12oUVC670teA,14
|
|
435
|
+
machineconfig-6.51.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|