machineconfig 3.3__py3-none-any.whl → 3.7__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/remote/cloud_manager.py +1 -1
- machineconfig/cluster/sessions_managers/wt_local_manager.py +1 -1
- machineconfig/cluster/sessions_managers/wt_remote_manager.py +1 -1
- machineconfig/cluster/sessions_managers/zellij_local_manager.py +1 -1
- machineconfig/cluster/sessions_managers/zellij_remote_manager.py +1 -1
- machineconfig/cluster/templates/utils.py +1 -1
- machineconfig/jobs/linux/msc/cli_agents.sh +18 -2
- machineconfig/jobs/python/python_ve_symlink.py +2 -2
- machineconfig/jobs/python/vscode/api.py +1 -1
- machineconfig/jobs/python/vscode/select_interpreter.py +2 -2
- machineconfig/jobs/python/vscode/sync_code.py +1 -1
- machineconfig/jobs/python_custom_installers/dev/bypass_paywall.py +1 -1
- machineconfig/jobs/python_custom_installers/dev/espanso.py +1 -1
- machineconfig/jobs/python_custom_installers/hx.py +1 -1
- machineconfig/jobs/python_generic_installers/config.json +0 -11
- machineconfig/profile/create.py +6 -6
- machineconfig/profile/shell.py +3 -3
- machineconfig/scripts/python/ai/mcinit.py +23 -67
- machineconfig/scripts/python/ai/solutions/__init__.py +0 -0
- machineconfig/scripts/python/ai/solutions/_shared.py +5 -0
- machineconfig/scripts/python/ai/solutions/claude/claude.py +8 -0
- machineconfig/scripts/python/ai/solutions/cline/cline.py +10 -0
- machineconfig/scripts/python/ai/solutions/copilot/github_copilot.py +35 -0
- machineconfig/scripts/python/ai/solutions/copilot/privacy.md +4 -0
- machineconfig/scripts/python/ai/solutions/crush/crush.json +216 -0
- machineconfig/scripts/python/ai/solutions/crush/crush.py +25 -0
- machineconfig/scripts/python/ai/solutions/crush/privacy.md +2 -0
- machineconfig/scripts/python/ai/solutions/cursor/cursors.py +10 -0
- machineconfig/scripts/python/ai/solutions/gemini/gemini.py +14 -0
- machineconfig/scripts/python/ai/solutions/generic.py +41 -0
- machineconfig/scripts/python/ai/solutions/kilocode/privacy.md +3 -0
- machineconfig/scripts/python/ai/solutions/opencode/opencode.json +4 -0
- machineconfig/scripts/python/ai/solutions/opencode/opencode.py +1 -0
- machineconfig/scripts/python/choose_wezterm_theme.py +3 -3
- machineconfig/scripts/python/cloud_copy.py +2 -2
- machineconfig/scripts/python/cloud_mount.py +4 -4
- machineconfig/scripts/python/cloud_repo_sync.py +5 -4
- machineconfig/scripts/python/croshell.py +14 -9
- machineconfig/scripts/python/devops.py +2 -2
- machineconfig/scripts/python/devops_add_identity.py +4 -9
- machineconfig/scripts/python/devops_add_ssh_key.py +3 -5
- machineconfig/scripts/python/devops_backup_retrieve.py +6 -5
- machineconfig/scripts/python/devops_devapps_install.py +4 -4
- machineconfig/scripts/python/devops_update_repos.py +2 -2
- machineconfig/scripts/python/dotfile.py +1 -1
- machineconfig/scripts/python/fire_agents.py +7 -7
- machineconfig/scripts/python/fire_agents_help_launch.py +2 -2
- machineconfig/scripts/python/fire_jobs.py +13 -13
- machineconfig/scripts/python/fire_jobs_layout_helper.py +6 -6
- machineconfig/scripts/python/ftpx.py +2 -2
- machineconfig/scripts/python/helpers/cloud_helpers.py +2 -1
- machineconfig/scripts/python/helpers/helpers2.py +4 -3
- machineconfig/scripts/python/helpers/helpers4.py +1 -1
- machineconfig/scripts/python/helpers/repo_sync_helpers.py +2 -2
- machineconfig/scripts/python/mount_nfs.py +4 -4
- machineconfig/scripts/python/mount_ssh.py +1 -1
- machineconfig/scripts/python/repos.py +6 -3
- machineconfig/scripts/python/repos_helper_clone.py +121 -0
- machineconfig/scripts/python/repos_helper_record.py +2 -2
- machineconfig/scripts/python/start_slidev.py +1 -1
- machineconfig/scripts/python/start_terminals.py +2 -2
- machineconfig/scripts/python/wsl_windows_transfer.py +1 -1
- machineconfig/settings/shells/ipy/profiles/default/startup/playext.py +2 -2
- machineconfig/setup_windows/wt_and_pwsh/install_nerd_fonts.py +1 -1
- machineconfig/setup_windows/wt_and_pwsh/set_wt_settings.py +3 -3
- machineconfig/utils/{utils2.py → accessories.py} +13 -29
- machineconfig/utils/code.py +2 -2
- machineconfig/utils/installer.py +2 -2
- machineconfig/utils/installer_utils/installer_abc.py +1 -1
- machineconfig/utils/installer_utils/installer_class.py +5 -5
- machineconfig/utils/io.py +94 -0
- machineconfig/utils/links.py +2 -2
- machineconfig/utils/notifications.py +0 -9
- machineconfig/utils/options.py +25 -18
- machineconfig/utils/{path_reduced.py → path_extended.py} +1 -1
- machineconfig/utils/{path.py → path_helper.py} +3 -3
- machineconfig/utils/procs.py +3 -3
- machineconfig/utils/{utils5.py → scheduler.py} +3 -8
- machineconfig/utils/scheduling.py +2 -2
- machineconfig/utils/ssh.py +2 -2
- machineconfig/utils/terminal.py +12 -2
- machineconfig/utils/ve.py +2 -16
- {machineconfig-3.3.dist-info → machineconfig-3.7.dist-info}/METADATA +1 -4
- {machineconfig-3.3.dist-info → machineconfig-3.7.dist-info}/RECORD +94 -78
- machineconfig/utils/io_save.py +0 -95
- /machineconfig/scripts/python/ai/{chatmodes → solutions/copilot/chatmodes}/Thinking-Beast-Mode.chatmode.md +0 -0
- /machineconfig/scripts/python/ai/{chatmodes → solutions/copilot/chatmodes}/Ultimate-Transparent-Thinking-Beast-Mode.chatmode.md +0 -0
- /machineconfig/scripts/python/ai/{chatmodes → solutions/copilot/chatmodes}/deepResearch.chatmode.md +0 -0
- /machineconfig/scripts/python/ai/{instructions → solutions/copilot/instructions}/python/dev.instructions.md +0 -0
- /machineconfig/scripts/python/ai/{prompts → solutions/copilot/prompts}/allLintersAndTypeCheckers.prompt.md +0 -0
- /machineconfig/scripts/python/ai/{prompts → solutions/copilot/prompts}/research-report-skeleton.prompt.md +0 -0
- /machineconfig/scripts/python/ai/{configs/.gemini → solutions/gemini}/settings.json +0 -0
- {machineconfig-3.3.dist-info → machineconfig-3.7.dist-info}/WHEEL +0 -0
- {machineconfig-3.3.dist-info → machineconfig-3.7.dist-info}/entry_points.txt +0 -0
- {machineconfig-3.3.dist-info → machineconfig-3.7.dist-info}/top_level.txt +0 -0
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
from machineconfig.utils.
|
|
1
|
+
from machineconfig.utils.path_extended import PathExtended as PathExtended
|
|
2
2
|
from machineconfig.utils.installer_utils.installer_abc import find_move_delete_linux, find_move_delete_windows
|
|
3
3
|
from machineconfig.utils.source_of_truth import INSTALL_TMP_DIR, INSTALL_VERSION_ROOT, LIBRARY_ROOT
|
|
4
4
|
from machineconfig.utils.options import check_tool_exists
|
|
5
|
-
from machineconfig.utils.
|
|
5
|
+
from machineconfig.utils.io import read_json
|
|
6
6
|
from machineconfig.utils.schemas.installer.installer_types import InstallerData, InstallerDataFiles
|
|
7
7
|
|
|
8
8
|
import platform
|
|
@@ -37,12 +37,12 @@ class Installer:
|
|
|
37
37
|
@staticmethod
|
|
38
38
|
def choose_app_and_install():
|
|
39
39
|
print(f"\n{'=' * 80}\n🔍 SELECT APPLICATION TO INSTALL 🔍\n{'=' * 80}")
|
|
40
|
-
from machineconfig.utils.options import
|
|
40
|
+
from machineconfig.utils.options import choose_from_options
|
|
41
41
|
|
|
42
42
|
print("📂 Searching for configuration files...")
|
|
43
43
|
jobs_dir = Path(LIBRARY_ROOT.joinpath("jobs"))
|
|
44
44
|
config_paths = [Path(p) for p in jobs_dir.rglob("config.json")]
|
|
45
|
-
path =
|
|
45
|
+
path = choose_from_options(multi=False, options=config_paths, msg="Choose one option")
|
|
46
46
|
print(f"📄 Loading configuration from: {path}")
|
|
47
47
|
config_data = read_json(path)
|
|
48
48
|
installer_data_files = InstallerDataFiles(config_data)
|
|
@@ -50,7 +50,7 @@ class Installer:
|
|
|
50
50
|
# Extract app names from the installers
|
|
51
51
|
app_names = [installer["appName"] for installer in installer_data_files["installers"]]
|
|
52
52
|
print("🔍 Select an application to install:")
|
|
53
|
-
app_name =
|
|
53
|
+
app_name = choose_from_options(multi=False, options=app_names, fzf=True, msg="Choose one option")
|
|
54
54
|
|
|
55
55
|
# Find the selected installer data
|
|
56
56
|
selected_installer_data = None
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
from typing import Any, Union, Optional, Mapping
|
|
4
|
+
from pathlib import Path
|
|
5
|
+
import json
|
|
6
|
+
import pickle
|
|
7
|
+
import configparser
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
PathLike = Union[str, Path]
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
def _ensure_parent(path: PathLike) -> Path:
|
|
14
|
+
path_obj = Path(path)
|
|
15
|
+
path_obj.parent.mkdir(parents=True, exist_ok=True)
|
|
16
|
+
return path_obj
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
def save_pickle(obj: Any, path: PathLike, verbose: bool = False) -> Path:
|
|
20
|
+
path_obj = _ensure_parent(path)
|
|
21
|
+
with open(path_obj, "wb") as fh:
|
|
22
|
+
pickle.dump(obj, fh, protocol=pickle.HIGHEST_PROTOCOL)
|
|
23
|
+
if verbose:
|
|
24
|
+
print(f"Saved pickle -> {path_obj}")
|
|
25
|
+
return Path(path_obj)
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
def save_json(obj: Any, path: PathLike, indent: Optional[int] = None, verbose: bool = False) -> Path:
|
|
29
|
+
path_obj = _ensure_parent(path)
|
|
30
|
+
with open(path_obj, "w", encoding="utf-8") as fh:
|
|
31
|
+
json.dump(obj, fh, indent=indent, ensure_ascii=False)
|
|
32
|
+
fh.write("\n")
|
|
33
|
+
if verbose:
|
|
34
|
+
print(f"Saved json -> {path_obj}")
|
|
35
|
+
return Path(path_obj)
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
# def save_toml(obj: Mapping[str, Any], path: PathLike, verbose: bool = False) -> Path:
|
|
39
|
+
# path_obj = _ensure_parent(path)
|
|
40
|
+
# with open(path_obj, "w", encoding="utf-8") as fh:
|
|
41
|
+
# toml.dump(obj, fh)
|
|
42
|
+
# if verbose:
|
|
43
|
+
# print(f"Saved toml -> {path_obj}")
|
|
44
|
+
# return Path(path_obj)
|
|
45
|
+
|
|
46
|
+
|
|
47
|
+
# def save_yaml(obj: Any, path: PathLike, verbose: bool = False) -> Path:
|
|
48
|
+
# path_obj = _ensure_parent(path)
|
|
49
|
+
# with open(path_obj, "w", encoding="utf-8") as fh:
|
|
50
|
+
# yaml.safe_dump(obj, fh, sort_keys=False)
|
|
51
|
+
# if verbose:
|
|
52
|
+
# print(f"Saved yaml -> {path_obj}")
|
|
53
|
+
# return Path(path_obj)
|
|
54
|
+
|
|
55
|
+
|
|
56
|
+
def save_ini(path: PathLike, obj: Mapping[str, Mapping[str, Any]], verbose: bool = False) -> Path:
|
|
57
|
+
cp = configparser.ConfigParser()
|
|
58
|
+
for section, values in obj.items():
|
|
59
|
+
cp[section] = {str(k): str(v) for k, v in values.items()}
|
|
60
|
+
path_obj = _ensure_parent(path)
|
|
61
|
+
with open(path_obj, "w", encoding="utf-8") as fh:
|
|
62
|
+
cp.write(fh)
|
|
63
|
+
if verbose:
|
|
64
|
+
print(f"Saved ini -> {path_obj}")
|
|
65
|
+
return Path(path_obj)
|
|
66
|
+
|
|
67
|
+
|
|
68
|
+
def read_ini(path: "Path", encoding: Optional[str] = None):
|
|
69
|
+
if not Path(path).exists() or Path(path).is_dir():
|
|
70
|
+
raise FileNotFoundError(f"File not found or is a directory: {path}")
|
|
71
|
+
import configparser
|
|
72
|
+
|
|
73
|
+
res = configparser.ConfigParser()
|
|
74
|
+
res.read(filenames=[str(path)], encoding=encoding)
|
|
75
|
+
return res
|
|
76
|
+
|
|
77
|
+
|
|
78
|
+
def read_json(path: "Path", r: bool = False, **kwargs: Any) -> Any: # return could be list or dict etc
|
|
79
|
+
import json
|
|
80
|
+
|
|
81
|
+
try:
|
|
82
|
+
mydict = json.loads(Path(path).read_text(encoding="utf-8"), **kwargs)
|
|
83
|
+
except Exception:
|
|
84
|
+
import pyjson5
|
|
85
|
+
|
|
86
|
+
mydict = pyjson5.loads(Path(path).read_text(encoding="utf-8"), **kwargs) # file has C-style comments.
|
|
87
|
+
_ = r
|
|
88
|
+
return mydict
|
|
89
|
+
|
|
90
|
+
|
|
91
|
+
def from_pickle(path: Path) -> Any:
|
|
92
|
+
import pickle
|
|
93
|
+
|
|
94
|
+
return pickle.loads(path.read_bytes())
|
machineconfig/utils/links.py
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
from machineconfig.utils.
|
|
2
|
-
from machineconfig.utils.
|
|
1
|
+
from machineconfig.utils.path_extended import PathExtended as PathExtended, PLike
|
|
2
|
+
from machineconfig.utils.accessories import randstr
|
|
3
3
|
from rich.console import Console
|
|
4
4
|
from rich.panel import Panel
|
|
5
5
|
|
|
@@ -1,16 +1,8 @@
|
|
|
1
1
|
"""Notifications Module"""
|
|
2
2
|
|
|
3
|
-
# from crocodile.core import install_n_import
|
|
4
|
-
# from crocodile.file_management import P, Read
|
|
5
3
|
from pathlib import Path
|
|
6
|
-
|
|
7
|
-
# from crocodile.meta import RepeatUntilNoException
|
|
8
4
|
import smtplib
|
|
9
5
|
import imaplib
|
|
10
|
-
|
|
11
|
-
# from email import message
|
|
12
|
-
# from email import encoders
|
|
13
|
-
# from email.mime.base import MIMEBase
|
|
14
6
|
from email.mime.text import MIMEText
|
|
15
7
|
from email.mime.multipart import MIMEMultipart
|
|
16
8
|
from typing import Optional, Any, Union
|
|
@@ -192,7 +184,6 @@ encryption = ssl
|
|
|
192
184
|
# else:
|
|
193
185
|
# body_file_path = None
|
|
194
186
|
# assert body is not None, "You must pass either body or body_file."
|
|
195
|
-
# from crocodile.meta import Terminal
|
|
196
187
|
|
|
197
188
|
# to_str = ",".join(to)
|
|
198
189
|
# attachments_str = " ".join([f"--attachment {str(p)}" for p in attachments]) if attachments is not None else ""
|
machineconfig/utils/options.py
CHANGED
|
@@ -4,7 +4,7 @@ from rich.panel import Panel
|
|
|
4
4
|
from rich.console import Console
|
|
5
5
|
import platform
|
|
6
6
|
import subprocess
|
|
7
|
-
from typing import Optional, Union, Iterable
|
|
7
|
+
from typing import Optional, Union, Iterable, overload, Literal
|
|
8
8
|
from machineconfig.utils.source_of_truth import WINDOWS_INSTALL_PATH, LINUX_INSTALL_PATH
|
|
9
9
|
|
|
10
10
|
|
|
@@ -32,20 +32,23 @@ def check_tool_exists(tool_name: str) -> bool:
|
|
|
32
32
|
# return root_path.joinpath(tool_name).is_file()
|
|
33
33
|
|
|
34
34
|
|
|
35
|
-
def
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
35
|
+
# def choose_from_options[T](options: Iterable[T], header: str = "", tail: str = "", prompt: str = "", msg: str = "", default: Optional[T] = None, fzf: bool = False, custom_input: bool = False) -> T:
|
|
36
|
+
# choice_key = choose_from_options(msg=msg, options=options, header=header, tail=tail, prompt=prompt, default=default, fzf=fzf, multi=False, custom_input=custom_input)
|
|
37
|
+
# assert not isinstance(choice_key, list)
|
|
38
|
+
# return choice_key
|
|
39
39
|
|
|
40
40
|
|
|
41
|
-
def
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
41
|
+
# def choose_from_options[T](options: Iterable[T], header: str = "", tail: str = "", prompt: str = "", msg: str = "", default: Optional[T] = None, custom_input: bool = False) -> list[T]:
|
|
42
|
+
# choice_key = choose_from_options(msg=msg, options=options, header=header, tail=tail, prompt=prompt, default=default, fzf=True, multi=True, custom_input=custom_input)
|
|
43
|
+
# if isinstance(choice_key, list):
|
|
44
|
+
# return choice_key
|
|
45
|
+
# return [choice_key]
|
|
46
46
|
|
|
47
|
-
|
|
48
|
-
def
|
|
47
|
+
@overload
|
|
48
|
+
def choose_from_options[T](msg: str, options: Iterable[T], multi: Literal[False], custom_input: bool = False, header: str = "", tail: str = "", prompt: str = "", default: Optional[T] = None, fzf: bool = False) -> T: ...
|
|
49
|
+
@overload
|
|
50
|
+
def choose_from_options[T](msg: str, options: Iterable[T], multi: Literal[True], custom_input: bool = True, header: str = "", tail: str = "", prompt: str = "", default: Optional[T] = None, fzf: bool = False, ) -> list[T]: ...
|
|
51
|
+
def choose_from_options[T](msg: str, options: Iterable[T], multi: bool, custom_input: bool = True, header: str = "", tail: str = "", prompt: str = "", default: Optional[T] = None, fzf: bool = False, ) -> Union[T, list[T]]:
|
|
49
52
|
# TODO: replace with https://github.com/tmbo/questionary
|
|
50
53
|
# # also see https://github.com/charmbracelet/gum
|
|
51
54
|
tool_name = "fzf"
|
|
@@ -90,7 +93,7 @@ def display_options[T](msg: str, options: Iterable[T], header: str = "", tail: s
|
|
|
90
93
|
if choice_string == "":
|
|
91
94
|
if default_string is None:
|
|
92
95
|
console.print(Panel("🧨 Default option not available!", title="Error", expand=False))
|
|
93
|
-
return
|
|
96
|
+
return choose_from_options(msg=msg, options=options, header=header, tail=tail, prompt=prompt, default=default, fzf=fzf, multi=multi, custom_input=custom_input)
|
|
94
97
|
choice_idx = options_strings.index(default_string)
|
|
95
98
|
assert default is not None, "🧨 Default option not available!"
|
|
96
99
|
choice_one: T = default
|
|
@@ -108,7 +111,7 @@ def display_options[T](msg: str, options: Iterable[T], header: str = "", tail: s
|
|
|
108
111
|
_ = ie
|
|
109
112
|
# raise ValueError(f"Unknown choice. {choice_string}") from ie
|
|
110
113
|
console.print(Panel(f"❓ Unknown choice: '{choice_string}'", title="Error", expand=False))
|
|
111
|
-
return
|
|
114
|
+
return choose_from_options(msg=msg, options=options, header=header, tail=tail, prompt=prompt, default=default, fzf=fzf, multi=multi, custom_input=custom_input)
|
|
112
115
|
except TypeError as te: # int(choice_string) failed due to # either the number is invalid, or the input is custom.
|
|
113
116
|
if choice_string in options_strings: # string input
|
|
114
117
|
choice_idx = options_strings.index(choice_one) # type: ignore
|
|
@@ -119,7 +122,7 @@ def display_options[T](msg: str, options: Iterable[T], header: str = "", tail: s
|
|
|
119
122
|
_ = te
|
|
120
123
|
# raise ValueError(f"Unknown choice. {choice_string}") from te
|
|
121
124
|
console.print(Panel(f"❓ Unknown choice: '{choice_string}'", title="Error", expand=False))
|
|
122
|
-
return
|
|
125
|
+
return choose_from_options(msg=msg, options=options, header=header, tail=tail, prompt=prompt, default=default, fzf=fzf, multi=multi, custom_input=custom_input)
|
|
123
126
|
console.print(Panel(f"✅ Selected option {choice_idx}: {choice_one}", title="Selected", expand=False))
|
|
124
127
|
if multi:
|
|
125
128
|
return [choice_one]
|
|
@@ -138,7 +141,7 @@ def choose_cloud_interactively() -> str:
|
|
|
138
141
|
raise ValueError(f"Got {tmp} from rclone listremotes")
|
|
139
142
|
if len(remotes) == 0:
|
|
140
143
|
raise RuntimeError("You don't have remotes. Configure your rclone first to get cloud services access.")
|
|
141
|
-
cloud: str =
|
|
144
|
+
cloud: str = choose_from_options(msg="WHICH CLOUD?", multi=False, options=list(remotes), default=remotes[0], fzf=True)
|
|
142
145
|
console.print(Panel(f"✅ SELECTED CLOUD | {cloud}", border_style="bold blue", expand=False))
|
|
143
146
|
return cloud
|
|
144
147
|
|
|
@@ -151,5 +154,9 @@ def get_ssh_hosts() -> list[str]:
|
|
|
151
154
|
return list(c.get_hostnames())
|
|
152
155
|
|
|
153
156
|
|
|
154
|
-
|
|
155
|
-
|
|
157
|
+
@overload
|
|
158
|
+
def choose_ssh_host(multi: Literal[False]) -> str: ...
|
|
159
|
+
@overload
|
|
160
|
+
def choose_ssh_host(multi: Literal[True]) -> list[str]: ...
|
|
161
|
+
def choose_ssh_host(multi: bool):
|
|
162
|
+
return choose_from_options(msg="", options=get_ssh_hosts(), multi=multi, fzf=True)
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
from machineconfig.utils.
|
|
2
|
-
from machineconfig.utils.options import
|
|
1
|
+
from machineconfig.utils.path_extended import PathExtended as PathExtended
|
|
2
|
+
from machineconfig.utils.options import choose_from_options
|
|
3
3
|
from machineconfig.utils.source_of_truth import EXCLUDE_DIRS
|
|
4
4
|
from rich.console import Console
|
|
5
5
|
from rich.panel import Panel
|
|
@@ -83,7 +83,7 @@ def match_file_name(sub_string: str, search_root: PathExtended, suffixes: set[st
|
|
|
83
83
|
if len(reduced_scripts) == 1:
|
|
84
84
|
return PathExtended(reduced_scripts[0])
|
|
85
85
|
elif len(reduced_scripts) > 1:
|
|
86
|
-
choice =
|
|
86
|
+
choice = choose_from_options(multi=False, msg="Multiple matches found", options=reduced_scripts, fzf=True)
|
|
87
87
|
return PathExtended(choice)
|
|
88
88
|
print(f"Result: This still generated {len(reduced_scripts)} results.")
|
|
89
89
|
if len(reduced_scripts) < 10:
|
machineconfig/utils/procs.py
CHANGED
|
@@ -3,12 +3,12 @@
|
|
|
3
3
|
import psutil
|
|
4
4
|
from rich.progress import Progress, SpinnerColumn, TextColumn
|
|
5
5
|
from zoneinfo import ZoneInfo
|
|
6
|
-
from machineconfig.utils.options import
|
|
6
|
+
from machineconfig.utils.options import choose_from_options
|
|
7
7
|
from typing import Optional, Any
|
|
8
8
|
from rich.console import Console
|
|
9
9
|
from rich.panel import Panel
|
|
10
10
|
from datetime import datetime, timezone
|
|
11
|
-
from machineconfig.utils.
|
|
11
|
+
from machineconfig.utils.accessories import pprint
|
|
12
12
|
|
|
13
13
|
console = Console()
|
|
14
14
|
|
|
@@ -120,7 +120,7 @@ class ProcessManager:
|
|
|
120
120
|
# Format data as table for display
|
|
121
121
|
formatted_data = self._format_process_table()
|
|
122
122
|
options = formatted_data.split("\n")[1:] # Skip header
|
|
123
|
-
res =
|
|
123
|
+
res = choose_from_options(options=formatted_data.split("\n"), msg="📋 Select processes to manage:", fzf=True, multi=True)
|
|
124
124
|
indices = [options.index(val) for val in res]
|
|
125
125
|
selected_processes = [self.data[i] for i in indices]
|
|
126
126
|
|
|
@@ -3,7 +3,8 @@ from typing import Callable, Optional, Union, Any, NoReturn, TypeVar, Protocol,
|
|
|
3
3
|
import logging
|
|
4
4
|
import time
|
|
5
5
|
from datetime import datetime, timezone, timedelta
|
|
6
|
-
from machineconfig.utils.
|
|
6
|
+
from machineconfig.utils.io import from_pickle
|
|
7
|
+
from machineconfig.utils.path_extended import PathExtended as PathExtended
|
|
7
8
|
|
|
8
9
|
|
|
9
10
|
class LoggerTemplate(Protocol):
|
|
@@ -108,7 +109,7 @@ class Scheduler:
|
|
|
108
109
|
# "logfile": self.logger.file_path
|
|
109
110
|
}
|
|
110
111
|
summ.update(sess_stats)
|
|
111
|
-
from machineconfig.utils.
|
|
112
|
+
from machineconfig.utils.accessories import get_repr
|
|
112
113
|
|
|
113
114
|
tmp = get_repr(summ)
|
|
114
115
|
self.logger.critical("\n--> Scheduler has finished running a session. \n" + tmp + "\n" + "-" * 100)
|
|
@@ -157,12 +158,6 @@ def to_pickle(obj: Any, path: Path) -> None:
|
|
|
157
158
|
path.write_bytes(pickle.dumps(obj))
|
|
158
159
|
|
|
159
160
|
|
|
160
|
-
def from_pickle(path: Path) -> Any:
|
|
161
|
-
import pickle
|
|
162
|
-
|
|
163
|
-
return pickle.loads(path.read_bytes())
|
|
164
|
-
|
|
165
|
-
|
|
166
161
|
class Cache(Generic[T]): # This class helps to accelrate access to latest data coming from expensive function. The class has two flavours, memory-based and disk-based variants."""
|
|
167
162
|
# source_func: Callable[[], T]
|
|
168
163
|
def __init__(
|
|
@@ -207,12 +207,12 @@
|
|
|
207
207
|
# for a_dir in tasks_dirs:
|
|
208
208
|
# tasks.append(read_task_from_dir(a_dir))
|
|
209
209
|
|
|
210
|
-
# from machineconfig.utils.utils import
|
|
210
|
+
# from machineconfig.utils.utils import choose_from_options
|
|
211
211
|
|
|
212
212
|
# # Create data for tasks display
|
|
213
213
|
# task_data = [Report.from_path(path=a_task.report_path).__dict__ for a_task in tasks]
|
|
214
214
|
# task_display = format_table_markdown(task_data)
|
|
215
|
-
# tasks_chosen_raw =
|
|
215
|
+
# tasks_chosen_raw = choose_from_options(multi=True, task_display.splitlines(), "📋 Choose tasks to run")
|
|
216
216
|
# tasks_chosen = [tasks[int(a_task_chosen.split("|")[1])] for a_task_chosen in tasks_chosen_raw]
|
|
217
217
|
|
|
218
218
|
# print(f"""
|
machineconfig/utils/ssh.py
CHANGED
|
@@ -3,8 +3,8 @@ import os
|
|
|
3
3
|
from dataclasses import dataclass
|
|
4
4
|
import rich.console
|
|
5
5
|
from machineconfig.utils.terminal import Terminal, Response, MACHINE
|
|
6
|
-
from machineconfig.utils.
|
|
7
|
-
from machineconfig.utils.
|
|
6
|
+
from machineconfig.utils.path_extended import PathExtended, PLike, OPLike
|
|
7
|
+
from machineconfig.utils.accessories import pprint
|
|
8
8
|
# from machineconfig.utils.ve import get_ve_activate_line
|
|
9
9
|
|
|
10
10
|
|
machineconfig/utils/terminal.py
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
from machineconfig.utils.
|
|
1
|
+
from machineconfig.utils.path_extended import PathExtended, OPLike
|
|
2
2
|
import subprocess
|
|
3
3
|
from typing import Any, BinaryIO, Optional, Union
|
|
4
4
|
import platform
|
|
@@ -219,9 +219,19 @@ class Terminal:
|
|
|
219
219
|
|
|
220
220
|
@staticmethod
|
|
221
221
|
def get_header(wdir: OPLike, toolbox: bool):
|
|
222
|
+
if toolbox:
|
|
223
|
+
toobox_code = """
|
|
224
|
+
try:
|
|
225
|
+
from crocodile.toolbox import *
|
|
226
|
+
except ImportError:
|
|
227
|
+
print("Crocodile not found, skipping import.")
|
|
228
|
+
pass
|
|
229
|
+
"""
|
|
230
|
+
else:
|
|
231
|
+
toobox_code = "# No toolbox import."
|
|
222
232
|
return f"""
|
|
223
233
|
# >> Code prepended
|
|
224
|
-
{
|
|
234
|
+
{toobox_code}
|
|
225
235
|
{'''sys.path.insert(0, r'{wdir}') ''' if wdir is not None else "# No path insertion."}
|
|
226
236
|
# >> End of header, start of script passed
|
|
227
237
|
"""
|
machineconfig/utils/ve.py
CHANGED
|
@@ -1,8 +1,7 @@
|
|
|
1
|
-
from machineconfig.utils.
|
|
2
|
-
from machineconfig.utils.
|
|
1
|
+
from machineconfig.utils.path_extended import PathExtended as PathExtended
|
|
2
|
+
from machineconfig.utils.io import read_ini
|
|
3
3
|
import platform
|
|
4
4
|
from typing import Optional
|
|
5
|
-
from pathlib import Path
|
|
6
5
|
|
|
7
6
|
|
|
8
7
|
def get_ve_path_and_ipython_profile(init_path: PathExtended) -> tuple[Optional[str], Optional[str]]:
|
|
@@ -39,19 +38,6 @@ def get_ve_path_and_ipython_profile(init_path: PathExtended) -> tuple[Optional[s
|
|
|
39
38
|
return ve_path, ipy_profile
|
|
40
39
|
|
|
41
40
|
|
|
42
|
-
def get_repo_root(path: Path) -> Optional[Path]:
|
|
43
|
-
from git import Repo, InvalidGitRepositoryError
|
|
44
|
-
|
|
45
|
-
try:
|
|
46
|
-
repo = Repo(str(path), search_parent_directories=True)
|
|
47
|
-
root = repo.working_tree_dir
|
|
48
|
-
if root is not None:
|
|
49
|
-
return Path(root)
|
|
50
|
-
except InvalidGitRepositoryError:
|
|
51
|
-
pass
|
|
52
|
-
return None
|
|
53
|
-
|
|
54
|
-
|
|
55
41
|
def get_ve_activate_line(ve_root: str):
|
|
56
42
|
if platform.system() == "Windows":
|
|
57
43
|
activate_ve_line = f". {ve_root}/Scripts/activate.ps1"
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: machineconfig
|
|
3
|
-
Version: 3.
|
|
3
|
+
Version: 3.7
|
|
4
4
|
Summary: Dotfiles management package
|
|
5
5
|
Author-email: Alex Al-Saffar <programmer@usa.com>
|
|
6
6
|
License: Apache 2.0
|
|
@@ -24,9 +24,6 @@ Requires-Dist: gitpython>=3.1.44
|
|
|
24
24
|
Requires-Dist: pyfzf>=0.3.1
|
|
25
25
|
Requires-Dist: rclone-python>=0.1.23
|
|
26
26
|
Requires-Dist: pyjson5>=1.6.9
|
|
27
|
-
Requires-Dist: pyyaml>=6.0.2
|
|
28
|
-
Requires-Dist: toml>=0.10.2
|
|
29
|
-
Requires-Dist: tomli>=2.2.1
|
|
30
27
|
Provides-Extra: windows
|
|
31
28
|
Requires-Dist: pywin32; extra == "windows"
|
|
32
29
|
Provides-Extra: docs
|