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.

Files changed (95) hide show
  1. machineconfig/cluster/remote/cloud_manager.py +1 -1
  2. machineconfig/cluster/sessions_managers/wt_local_manager.py +1 -1
  3. machineconfig/cluster/sessions_managers/wt_remote_manager.py +1 -1
  4. machineconfig/cluster/sessions_managers/zellij_local_manager.py +1 -1
  5. machineconfig/cluster/sessions_managers/zellij_remote_manager.py +1 -1
  6. machineconfig/cluster/templates/utils.py +1 -1
  7. machineconfig/jobs/linux/msc/cli_agents.sh +18 -2
  8. machineconfig/jobs/python/python_ve_symlink.py +2 -2
  9. machineconfig/jobs/python/vscode/api.py +1 -1
  10. machineconfig/jobs/python/vscode/select_interpreter.py +2 -2
  11. machineconfig/jobs/python/vscode/sync_code.py +1 -1
  12. machineconfig/jobs/python_custom_installers/dev/bypass_paywall.py +1 -1
  13. machineconfig/jobs/python_custom_installers/dev/espanso.py +1 -1
  14. machineconfig/jobs/python_custom_installers/hx.py +1 -1
  15. machineconfig/jobs/python_generic_installers/config.json +0 -11
  16. machineconfig/profile/create.py +6 -6
  17. machineconfig/profile/shell.py +3 -3
  18. machineconfig/scripts/python/ai/mcinit.py +23 -67
  19. machineconfig/scripts/python/ai/solutions/__init__.py +0 -0
  20. machineconfig/scripts/python/ai/solutions/_shared.py +5 -0
  21. machineconfig/scripts/python/ai/solutions/claude/claude.py +8 -0
  22. machineconfig/scripts/python/ai/solutions/cline/cline.py +10 -0
  23. machineconfig/scripts/python/ai/solutions/copilot/github_copilot.py +35 -0
  24. machineconfig/scripts/python/ai/solutions/copilot/privacy.md +4 -0
  25. machineconfig/scripts/python/ai/solutions/crush/crush.json +216 -0
  26. machineconfig/scripts/python/ai/solutions/crush/crush.py +25 -0
  27. machineconfig/scripts/python/ai/solutions/crush/privacy.md +2 -0
  28. machineconfig/scripts/python/ai/solutions/cursor/cursors.py +10 -0
  29. machineconfig/scripts/python/ai/solutions/gemini/gemini.py +14 -0
  30. machineconfig/scripts/python/ai/solutions/generic.py +41 -0
  31. machineconfig/scripts/python/ai/solutions/kilocode/privacy.md +3 -0
  32. machineconfig/scripts/python/ai/solutions/opencode/opencode.json +4 -0
  33. machineconfig/scripts/python/ai/solutions/opencode/opencode.py +1 -0
  34. machineconfig/scripts/python/choose_wezterm_theme.py +3 -3
  35. machineconfig/scripts/python/cloud_copy.py +2 -2
  36. machineconfig/scripts/python/cloud_mount.py +4 -4
  37. machineconfig/scripts/python/cloud_repo_sync.py +5 -4
  38. machineconfig/scripts/python/croshell.py +14 -9
  39. machineconfig/scripts/python/devops.py +2 -2
  40. machineconfig/scripts/python/devops_add_identity.py +4 -9
  41. machineconfig/scripts/python/devops_add_ssh_key.py +3 -5
  42. machineconfig/scripts/python/devops_backup_retrieve.py +6 -5
  43. machineconfig/scripts/python/devops_devapps_install.py +4 -4
  44. machineconfig/scripts/python/devops_update_repos.py +2 -2
  45. machineconfig/scripts/python/dotfile.py +1 -1
  46. machineconfig/scripts/python/fire_agents.py +7 -7
  47. machineconfig/scripts/python/fire_agents_help_launch.py +2 -2
  48. machineconfig/scripts/python/fire_jobs.py +13 -13
  49. machineconfig/scripts/python/fire_jobs_layout_helper.py +6 -6
  50. machineconfig/scripts/python/ftpx.py +2 -2
  51. machineconfig/scripts/python/helpers/cloud_helpers.py +2 -1
  52. machineconfig/scripts/python/helpers/helpers2.py +4 -3
  53. machineconfig/scripts/python/helpers/helpers4.py +1 -1
  54. machineconfig/scripts/python/helpers/repo_sync_helpers.py +2 -2
  55. machineconfig/scripts/python/mount_nfs.py +4 -4
  56. machineconfig/scripts/python/mount_ssh.py +1 -1
  57. machineconfig/scripts/python/repos.py +6 -3
  58. machineconfig/scripts/python/repos_helper_clone.py +121 -0
  59. machineconfig/scripts/python/repos_helper_record.py +2 -2
  60. machineconfig/scripts/python/start_slidev.py +1 -1
  61. machineconfig/scripts/python/start_terminals.py +2 -2
  62. machineconfig/scripts/python/wsl_windows_transfer.py +1 -1
  63. machineconfig/settings/shells/ipy/profiles/default/startup/playext.py +2 -2
  64. machineconfig/setup_windows/wt_and_pwsh/install_nerd_fonts.py +1 -1
  65. machineconfig/setup_windows/wt_and_pwsh/set_wt_settings.py +3 -3
  66. machineconfig/utils/{utils2.py → accessories.py} +13 -29
  67. machineconfig/utils/code.py +2 -2
  68. machineconfig/utils/installer.py +2 -2
  69. machineconfig/utils/installer_utils/installer_abc.py +1 -1
  70. machineconfig/utils/installer_utils/installer_class.py +5 -5
  71. machineconfig/utils/io.py +94 -0
  72. machineconfig/utils/links.py +2 -2
  73. machineconfig/utils/notifications.py +0 -9
  74. machineconfig/utils/options.py +25 -18
  75. machineconfig/utils/{path_reduced.py → path_extended.py} +1 -1
  76. machineconfig/utils/{path.py → path_helper.py} +3 -3
  77. machineconfig/utils/procs.py +3 -3
  78. machineconfig/utils/{utils5.py → scheduler.py} +3 -8
  79. machineconfig/utils/scheduling.py +2 -2
  80. machineconfig/utils/ssh.py +2 -2
  81. machineconfig/utils/terminal.py +12 -2
  82. machineconfig/utils/ve.py +2 -16
  83. {machineconfig-3.3.dist-info → machineconfig-3.7.dist-info}/METADATA +1 -4
  84. {machineconfig-3.3.dist-info → machineconfig-3.7.dist-info}/RECORD +94 -78
  85. machineconfig/utils/io_save.py +0 -95
  86. /machineconfig/scripts/python/ai/{chatmodes → solutions/copilot/chatmodes}/Thinking-Beast-Mode.chatmode.md +0 -0
  87. /machineconfig/scripts/python/ai/{chatmodes → solutions/copilot/chatmodes}/Ultimate-Transparent-Thinking-Beast-Mode.chatmode.md +0 -0
  88. /machineconfig/scripts/python/ai/{chatmodes → solutions/copilot/chatmodes}/deepResearch.chatmode.md +0 -0
  89. /machineconfig/scripts/python/ai/{instructions → solutions/copilot/instructions}/python/dev.instructions.md +0 -0
  90. /machineconfig/scripts/python/ai/{prompts → solutions/copilot/prompts}/allLintersAndTypeCheckers.prompt.md +0 -0
  91. /machineconfig/scripts/python/ai/{prompts → solutions/copilot/prompts}/research-report-skeleton.prompt.md +0 -0
  92. /machineconfig/scripts/python/ai/{configs/.gemini → solutions/gemini}/settings.json +0 -0
  93. {machineconfig-3.3.dist-info → machineconfig-3.7.dist-info}/WHEEL +0 -0
  94. {machineconfig-3.3.dist-info → machineconfig-3.7.dist-info}/entry_points.txt +0 -0
  95. {machineconfig-3.3.dist-info → machineconfig-3.7.dist-info}/top_level.txt +0 -0
@@ -1,8 +1,8 @@
1
- from machineconfig.utils.path_reduced import PathExtended as PathExtended
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.utils2 import read_json
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 choose_one_option
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 = choose_one_option(options=config_paths)
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 = choose_one_option(options=app_names, fzf=True)
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())
@@ -1,5 +1,5 @@
1
- from machineconfig.utils.path_reduced import PathExtended as PathExtended, PLike
2
- from machineconfig.utils.utils2 import randstr
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 ""
@@ -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 choose_one_option[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 = display_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
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 choose_multiple_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 = display_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]
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 display_options[T](msg: str, options: Iterable[T], header: str = "", tail: str = "", prompt: str = "", default: Optional[T] = None, fzf: bool = False, multi: bool = False, custom_input: bool = False) -> Union[T, list[T]]:
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 display_options(msg=msg, options=options, header=header, tail=tail, prompt=prompt, default=default, fzf=fzf, multi=multi, custom_input=custom_input)
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 display_options(msg=msg, options=options, header=header, tail=tail, prompt=prompt, default=default, fzf=fzf, multi=multi, custom_input=custom_input)
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 display_options(msg=msg, options=options, header=header, tail=tail, prompt=prompt, default=default, fzf=fzf, multi=multi, custom_input=custom_input)
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 = choose_one_option(msg="WHICH CLOUD?", options=list(remotes), default=remotes[0], fzf=True)
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
- def choose_ssh_host(multi: bool = True):
155
- return display_options(msg="", options=get_ssh_hosts(), multi=multi, fzf=True)
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,4 +1,4 @@
1
- from machineconfig.utils.utils2 import randstr
1
+ from machineconfig.utils.accessories import randstr
2
2
 
3
3
  from datetime import datetime
4
4
  import time
@@ -1,5 +1,5 @@
1
- from machineconfig.utils.path_reduced import PathExtended as PathExtended
2
- from machineconfig.utils.options import choose_one_option
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 = choose_one_option(msg="Multiple matches found", options=reduced_scripts, fzf=True)
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:
@@ -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 display_options
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.utils2 import pprint
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 = display_options(options=formatted_data.split("\n"), msg="📋 Select processes to manage:", fzf=True, multi=True)
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.path_reduced import PathExtended as PathExtended
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.utils2 import get_repr
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 choose_multiple_options
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 = choose_multiple_options(task_display.splitlines(), "📋 Choose tasks to run")
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"""
@@ -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.path_reduced import PathExtended, PLike, OPLike
7
- from machineconfig.utils.utils2 import pprint
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
 
@@ -1,4 +1,4 @@
1
- from machineconfig.utils.path_reduced import PathExtended, OPLike
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
- {"from crocodile.toolbox import *" if toolbox else "# No toolbox import."}
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.path_reduced import PathExtended as PathExtended
2
- from machineconfig.utils.utils2 import read_ini
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
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