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
@@ -0,0 +1,216 @@
1
+ {
2
+ "$schema": "https://charm.land/crush.json",
3
+ "providers": {
4
+ "openai": {
5
+ "id": "openai",
6
+ "name": "OpenAI",
7
+ "base_url": "https://api.openai.com/v1",
8
+ "type": "openai",
9
+ "api_key": "$OPENAI_API_KEY",
10
+ "extra_headers": {
11
+ "OpenAI-Beta": "assistants=v2"
12
+ },
13
+ "models": [
14
+ {
15
+ "id": "gpt-4o",
16
+ "name": "GPT-4o",
17
+ "cost_per_1m_in": 5,
18
+ "cost_per_1m_out": 15,
19
+ "cost_per_1m_in_cached": 1,
20
+ "cost_per_1m_out_cached": 3,
21
+ "context_window": 128000,
22
+ "default_max_tokens": 16384,
23
+ "can_reason": false,
24
+ "has_reasoning_efforts": false,
25
+ "supports_attachments": true
26
+ },
27
+ {
28
+ "id": "gpt-4o-mini",
29
+ "name": "GPT-4o mini",
30
+ "cost_per_1m_in": 0.15,
31
+ "cost_per_1m_out": 0.6,
32
+ "cost_per_1m_in_cached": 0.05,
33
+ "cost_per_1m_out_cached": 0.2,
34
+ "context_window": 128000,
35
+ "default_max_tokens": 8192,
36
+ "can_reason": false,
37
+ "has_reasoning_efforts": false,
38
+ "supports_attachments": true
39
+ }
40
+ ]
41
+ },
42
+ "anthropic": {
43
+ "id": "anthropic",
44
+ "name": "Anthropic",
45
+ "base_url": "https://api.anthropic.com/v1",
46
+ "type": "anthropic",
47
+ "api_key": "$ANTHROPIC_API_KEY",
48
+ "extra_headers": {
49
+ "anthropic-version": "2023-06-01"
50
+ },
51
+ "models": [
52
+ {
53
+ "id": "claude-3-5-sonnet-20240620",
54
+ "name": "Claude 3.5 Sonnet",
55
+ "cost_per_1m_in": 3,
56
+ "cost_per_1m_out": 15,
57
+ "cost_per_1m_in_cached": 3.75,
58
+ "cost_per_1m_out_cached": 0.3,
59
+ "context_window": 200000,
60
+ "default_max_tokens": 8000,
61
+ "can_reason": true,
62
+ "has_reasoning_efforts": true,
63
+ "default_reasoning_effort": "medium",
64
+ "supports_attachments": true
65
+ },
66
+ {
67
+ "id": "claude-3-haiku-20240307",
68
+ "name": "Claude 3 Haiku",
69
+ "cost_per_1m_in": 0.25,
70
+ "cost_per_1m_out": 1.25,
71
+ "cost_per_1m_in_cached": 0.05,
72
+ "cost_per_1m_out_cached": 0.1,
73
+ "context_window": 200000,
74
+ "default_max_tokens": 4000,
75
+ "can_reason": true,
76
+ "has_reasoning_efforts": true,
77
+ "default_reasoning_effort": "low",
78
+ "supports_attachments": true
79
+ }
80
+ ]
81
+ },
82
+ "openrouter": {
83
+ "id": "openrouter",
84
+ "name": "OpenRouter",
85
+ "base_url": "https://openrouter.ai/api/v1",
86
+ "type": "openai",
87
+ "api_key": "$OPENROUTER_API_KEY",
88
+ "models": [
89
+ {
90
+ "id": "deepseek/deepseek-chat",
91
+ "name": "Deepseek V3",
92
+ "cost_per_1m_in": 0.27,
93
+ "cost_per_1m_out": 1.1,
94
+ "cost_per_1m_in_cached": 0.07,
95
+ "cost_per_1m_out_cached": 0.3,
96
+ "context_window": 64000,
97
+ "default_max_tokens": 5000,
98
+ "can_reason": true,
99
+ "has_reasoning_efforts": false,
100
+ "supports_attachments": false
101
+ }
102
+ ]
103
+ },
104
+ "ollama": {
105
+ "id": "ollama",
106
+ "name": "Ollama",
107
+ "base_url": "http://localhost:11434/v1/",
108
+ "type": "openai",
109
+ "models": [
110
+ {
111
+ "id": "qwen2.5-coder:14b",
112
+ "name": "Qwen2.5 Coder 14B",
113
+ "cost_per_1m_in": 0,
114
+ "cost_per_1m_out": 0,
115
+ "cost_per_1m_in_cached": 0,
116
+ "cost_per_1m_out_cached": 0,
117
+ "context_window": 32768,
118
+ "default_max_tokens": 4096,
119
+ "can_reason": false,
120
+ "has_reasoning_efforts": false,
121
+ "supports_attachments": false
122
+ }
123
+ ]
124
+ }
125
+ },
126
+ "models": {
127
+ "large": {
128
+ "provider": "anthropic",
129
+ "model": "claude-3-5-sonnet-20240620",
130
+ "think": true,
131
+ "max_tokens": 6000
132
+ },
133
+ "small": {
134
+ "provider": "openai",
135
+ "model": "gpt-4o-mini",
136
+ "max_tokens": 4096
137
+ }
138
+ },
139
+ "lsp": {
140
+ "python": {
141
+ "command": "pyright-langserver",
142
+ "args": ["--stdio"],
143
+ "filetypes": ["py"],
144
+ "env": {
145
+ "PYRIGHT_PYTHON_FORCE_VERSION": "3.13"
146
+ }
147
+ },
148
+ "ruff": {
149
+ "command": "ruff",
150
+ "args": ["server"],
151
+ "filetypes": ["py"]
152
+ },
153
+ "json": {
154
+ "command": "vscode-json-languageserver",
155
+ "args": ["--stdio"]
156
+ }
157
+ },
158
+ "mcp": {
159
+ "filesystem": {
160
+ "type": "stdio",
161
+ "command": "uv",
162
+ "args": [
163
+ "run",
164
+ "python",
165
+ "-m",
166
+ "machineconfig.scripts.python.ai.solutions._shared"
167
+ ],
168
+ "timeout": 120,
169
+ "env": {
170
+ "UV_PROJECT_ENV": "$(pwd)"
171
+ }
172
+ },
173
+ "github-docs": {
174
+ "type": "http",
175
+ "url": "https://api.github.com/mcp/",
176
+ "timeout": 90,
177
+ "headers": {
178
+ "Authorization": "$(echo Bearer $GITHUB_MCP_TOKEN)",
179
+ "X-Crush-Client": "machineconfig"
180
+ }
181
+ },
182
+ "architect": {
183
+ "type": "sse",
184
+ "url": "https://architect.mcp.machineconfig.local/stream",
185
+ "timeout": 120,
186
+ "headers": {
187
+ "Authorization": "$(echo Bearer $ARCHITECT_MCP_TOKEN)"
188
+ }
189
+ }
190
+ },
191
+ "options": {
192
+ "context_paths": [
193
+ "CRUSH.md",
194
+ "src/machineconfig/scripts/python/ai/solutions/crush/privacy.md",
195
+ ".github/copilot-instructions.md",
196
+ "src/machineconfig/scripts/python/ai/solutions/_shared.py"
197
+ ],
198
+ "tui": {
199
+ "compact_mode": true,
200
+ "diff_mode": "unified"
201
+ },
202
+ "debug": false,
203
+ "debug_lsp": false,
204
+ "disable_auto_summarize": false,
205
+ "data_directory": ".crush"
206
+ },
207
+ "permissions": {
208
+ "allowed_tools": [
209
+ "view",
210
+ "ls",
211
+ "glob",
212
+ "grep",
213
+ "write"
214
+ ]
215
+ }
216
+ }
@@ -0,0 +1,25 @@
1
+
2
+
3
+ """
4
+ ref: https://github.com/charmbracelet/crush
5
+
6
+ """
7
+
8
+ from pathlib import Path
9
+ import platform
10
+ from machineconfig.scripts.python.ai.solutions._shared import get_generic_instructions_path
11
+
12
+
13
+
14
+ def build_configuration(repo_root: Path) -> None:
15
+ instructions_path = get_generic_instructions_path()
16
+ repo_root.joinpath("CRUSH.md").write_text(data=instructions_path.read_text(encoding="utf-8"), encoding="utf-8")
17
+
18
+ repo_settings = repo_root.joinpath(".crush.json")
19
+ ignore_settings = repo_root.joinpath(".crushignore")
20
+ if platform.system() == "Windows":
21
+ global_settings = Path.home().joinpath("AppData/Local/crush/crush.json")
22
+ else:
23
+ global_settings = Path.home().joinpath(".config/crush/crush.json")
24
+
25
+ _ = repo_settings, ignore_settings, global_settings # to avoid unused variable warnings
@@ -0,0 +1,2 @@
1
+
2
+ docs don't mention at all anything about user code privacy, data collection or telemetry or any reporting.
@@ -0,0 +1,10 @@
1
+ from pathlib import Path
2
+
3
+ from machineconfig.scripts.python.ai.solutions._shared import get_generic_instructions_path
4
+
5
+
6
+ def build_configuration(repo_root: Path) -> None:
7
+ instructions_path = get_generic_instructions_path()
8
+ cursor_rules_path = repo_root.joinpath(".cursor/rules/python_dev.mdc")
9
+ cursor_rules_path.parent.mkdir(parents=True, exist_ok=True)
10
+ cursor_rules_path.write_text(data=instructions_path.read_text(encoding="utf-8"), encoding="utf-8")
@@ -0,0 +1,14 @@
1
+ from pathlib import Path
2
+
3
+ from machineconfig.scripts.python.ai.solutions._shared import get_generic_instructions_path
4
+ from machineconfig.utils.source_of_truth import LIBRARY_ROOT
5
+
6
+ def build_configuration(repo_root: Path) -> None:
7
+ instructions_path = get_generic_instructions_path()
8
+ repo_root.joinpath("GEMINI.md").write_text(data=instructions_path.read_text(encoding="utf-8"), encoding="utf-8")
9
+
10
+ gemini_dir = repo_root.joinpath(".gemini")
11
+ settings_source_path = LIBRARY_ROOT.joinpath("scripts/python/ai/solutions/gemini/settings.json")
12
+ gemini_dir.mkdir(parents=True, exist_ok=True)
13
+
14
+ settings_source_path.write_text(data=settings_source_path.read_text(encoding="utf-8"), encoding="utf-8")
@@ -0,0 +1,41 @@
1
+ from pathlib import Path
2
+
3
+ from machineconfig.utils.source_of_truth import LIBRARY_ROOT
4
+
5
+
6
+ def create_dot_scripts(repo_root: Path) -> None:
7
+ scripts_dir = LIBRARY_ROOT.joinpath("scripts/python/ai/scripts")
8
+ target_dir = repo_root.joinpath(".scripts")
9
+ target_dir.mkdir(parents=True, exist_ok=True)
10
+ for script_path in scripts_dir.iterdir():
11
+ target_dir.joinpath(script_path.name).write_text(data=script_path.read_text(encoding="utf-8"), encoding="utf-8")
12
+
13
+
14
+ def adjust_gitignore(repo_root: Path) -> None:
15
+ dot_git_ignore_path = repo_root.joinpath(".gitignore")
16
+ if dot_git_ignore_path.exists() is False:
17
+ return
18
+
19
+ dot_git_ignore_content = dot_git_ignore_path.read_text(encoding="utf-8")
20
+ entries_to_add: list[str] = []
21
+ required_entries: list[str] = [
22
+ ".links",
23
+ "notebooks",
24
+ ".ai",
25
+ ".scripts",
26
+ "GEMINI.md",
27
+ "CLAUDE.md",
28
+ ".cursor",
29
+ ".github/instructions",
30
+ ".github/chatmodes",
31
+ ".github/prompts",
32
+ ]
33
+
34
+ for entry in required_entries:
35
+ if entry not in dot_git_ignore_content:
36
+ entries_to_add.append(entry)
37
+
38
+ if len(entries_to_add) == 0:
39
+ return
40
+
41
+ dot_git_ignore_path.write_text(data=dot_git_ignore_content + "\n" + "\n".join(entries_to_add), encoding="utf-8")
@@ -0,0 +1,3 @@
1
+
2
+ # disable usage and erroror reports to kilocode in About/Export page.
3
+ # Disable model api provider data collection.
@@ -0,0 +1,4 @@
1
+ {
2
+ "$schema": "https://opencode.ai/config.json",
3
+ "instructions": [".github/instructions/*.md"]
4
+ }
@@ -2,8 +2,8 @@
2
2
  Choose a theme for Wezterm
3
3
  """
4
4
 
5
- from machineconfig.utils.options import choose_one_option
6
- from machineconfig.utils.path_reduced import PathExtended
5
+ from machineconfig.utils.options import choose_from_options
6
+ from machineconfig.utils.path_extended import PathExtended
7
7
  from typing import Any
8
8
  import time
9
9
  from rich.panel import Panel
@@ -45,7 +45,7 @@ schemes_list = [
45
45
 
46
46
  def main2():
47
47
  console.print(Panel("🎨 WezTerm Theme Selector", title_align="left", border_style="green"))
48
- option = choose_one_option(options=schemes_list, header="Choose a theme for Wezterm", fzf=True)
48
+ option = choose_from_options(multi=False, options=schemes_list, header="Choose a theme for Wezterm", fzf=True, msg="Use arrow keys to navigate, Enter to select a theme")
49
49
  set_theme(option)
50
50
  print(f"✅ Theme set to: {option}")
51
51
 
@@ -2,7 +2,7 @@
2
2
  CC
3
3
  """
4
4
 
5
- from machineconfig.utils.path_reduced import PathExtended as PathExtended
5
+ from machineconfig.utils.path_extended import PathExtended as PathExtended
6
6
  from tenacity import retry, stop_after_attempt, wait_chain, wait_fixed
7
7
  import getpass
8
8
  import argparse
@@ -14,7 +14,7 @@ from machineconfig.scripts.python.helpers.cloud_helpers import ArgsDefaults, Arg
14
14
  from rich.console import Console
15
15
  from rich.panel import Panel
16
16
  from rich.progress import Progress
17
- from machineconfig.utils.utils2 import pprint
17
+ from machineconfig.utils.accessories import pprint
18
18
 
19
19
  console = Console()
20
20
 
@@ -1,8 +1,8 @@
1
1
  """Cloud mount script"""
2
2
 
3
- from machineconfig.utils.options import choose_one_option
4
- from machineconfig.utils.utils2 import read_ini
5
- from machineconfig.utils.path_reduced import PathExtended as PathExtended
3
+ from machineconfig.utils.options import choose_from_options
4
+ from machineconfig.utils.io import read_ini
5
+ from machineconfig.utils.path_extended import PathExtended as PathExtended
6
6
 
7
7
  import platform
8
8
  import argparse
@@ -59,7 +59,7 @@ def mount(cloud: Optional[str], network: Optional[str], destination: Optional[st
59
59
 
60
60
  config = get_rclone_config()
61
61
  if cloud is None:
62
- res = choose_one_option(msg="which cloud", options=config.sections(), header="CLOUD MOUNT", default=None)
62
+ res = choose_from_options(multi=False, msg="which cloud", options=config.sections(), header="CLOUD MOUNT", default=None)
63
63
  if type(res) is str:
64
64
  cloud = res
65
65
  else:
@@ -2,13 +2,14 @@
2
2
 
3
3
  from pathlib import Path
4
4
  import git
5
- from machineconfig.utils.path_reduced import PathExtended as PathExtended
5
+ from machineconfig.utils.io import read_ini
6
+ from machineconfig.utils.path_extended import PathExtended as PathExtended
6
7
  from machineconfig.utils.terminal import Terminal
7
- from machineconfig.utils.utils2 import randstr, read_ini
8
+ from machineconfig.utils.accessories import randstr
8
9
 
9
10
  from machineconfig.scripts.python.helpers.repo_sync_helpers import fetch_dotfiles
10
11
  from machineconfig.utils.source_of_truth import CONFIG_PATH, DEFAULTS_PATH
11
- from machineconfig.utils.options import choose_one_option
12
+ from machineconfig.utils.options import choose_from_options
12
13
  from machineconfig.utils.code import get_shell_file_executing_python_script, write_shell_script_to_file
13
14
  import platform
14
15
  import argparse
@@ -140,7 +141,7 @@ git commit -am "finished merging"
140
141
  program_content = None
141
142
  match action:
142
143
  case "ask":
143
- choice = choose_one_option(options=[option1, option2, option3, option4], fzf=False)
144
+ choice = choose_from_options(multi=False, msg="Choose one option", options=[option1, option2, option3, option4], fzf=False)
144
145
  if choice == option1:
145
146
  program_content = shell_file_1.read_text(encoding="utf-8")
146
147
  elif choice == option2:
@@ -5,10 +5,10 @@ croshell
5
5
  """
6
6
 
7
7
  import argparse
8
- from machineconfig.utils.path_reduced import PathExtended as PathExtended
9
- from machineconfig.utils.utils2 import randstr
8
+ from machineconfig.utils.path_extended import PathExtended as PathExtended
9
+ from machineconfig.utils.accessories import randstr
10
10
 
11
- from machineconfig.utils.options import display_options
11
+ from machineconfig.utils.options import choose_from_options
12
12
  from machineconfig.utils.ve import get_ve_activate_line
13
13
  from typing import Optional
14
14
  from rich.console import Console
@@ -21,8 +21,10 @@ console = Console()
21
21
 
22
22
  def add_print_header_pycode(path: str, title: str):
23
23
  return f"""
24
- # from machineconfig.utils.path_reduced import P as PathExtended
25
- from crocodile.file_management import P as PathExtended
24
+ try:
25
+ from crocodile.file_management import P as PathExtended
26
+ except ImportError:
27
+ from machineconfig.utils.path_reduced import PathExtended
26
28
  pycode = PathExtended(r'{path}').read_text(encoding="utf-8")
27
29
  pycode = pycode.split("except Exception: print(pycode)")[2]
28
30
 
@@ -119,7 +121,7 @@ def build_parser():
119
121
  text = "🔍 Searching for Python files..."
120
122
  console.print(Panel(text, title="[bold blue]Info[/bold blue]"))
121
123
  options = [str(item) for item in PathExtended.cwd().search("*.py", r=True)]
122
- file = display_options(msg="Choose a python file to run", options=options, fzf=True, multi=False)
124
+ file = choose_from_options(msg="Choose a python file to run", options=options, fzf=True, multi=False)
123
125
  assert isinstance(file, str)
124
126
  program = PathExtended(file).read_text(encoding="utf-8")
125
127
  text = f"📄 Selected file: {PathExtended(file).name}"
@@ -160,10 +162,13 @@ def build_parser():
160
162
  preprogram = """
161
163
 
162
164
  #%%
163
- from crocodile.croshell import *
165
+ try:
166
+ from crocodile.croshell import *
167
+ print_header()
168
+ print_logo(logo="crocodile")
169
+ except ImportError:
170
+ print("Crocodile not found, skipping import.")
164
171
  from pathlib import Path
165
- print_header()
166
- print_logo(logo="crocodile")
167
172
  print(f"🐊 Crocodile Shell | Running @ {Path.cwd()}")
168
173
  """
169
174
 
@@ -1,6 +1,6 @@
1
1
  """devops with emojis"""
2
2
 
3
- from machineconfig.utils.options import display_options
3
+ from machineconfig.utils.options import choose_from_options
4
4
 
5
5
  from platform import system
6
6
  from enum import Enum
@@ -45,7 +45,7 @@ def main(which: Optional[str] = None):
45
45
  options = [op.value for op in Options]
46
46
  if which is None:
47
47
  try:
48
- choice_key = display_options(msg="", options=options, header="🛠️ DEVOPS", default=options[0])
48
+ choice_key = choose_from_options(msg="", options=options, header="🛠️ DEVOPS", default=options[0], multi=False)
49
49
  except KeyboardInterrupt:
50
50
  console.print(Panel("❌ Operation cancelled by user", title_align="left", border_style="red", width=BOX_WIDTH))
51
51
  return
@@ -1,8 +1,8 @@
1
1
  """ID"""
2
2
 
3
3
  # from platform import system
4
- from machineconfig.utils.path_reduced import PathExtended as PathExtended
5
- from machineconfig.utils.options import display_options
4
+ from machineconfig.utils.path_extended import PathExtended as PathExtended
5
+ from machineconfig.utils.options import choose_from_options
6
6
  from rich.panel import Panel
7
7
  from rich.text import Text
8
8
 
@@ -22,7 +22,7 @@ def main() -> None:
22
22
  else:
23
23
  print(Panel("⚠️ No SSH private keys found", expand=False))
24
24
 
25
- choice = display_options(msg="Path to private key to be used when ssh'ing: ", options=[str(x) for x in private_keys] + ["I have the path to the key file", "I want to paste the key itself"])
25
+ choice = choose_from_options(msg="Path to private key to be used when ssh'ing: ", options=[str(x) for x in private_keys] + ["I have the path to the key file", "I want to paste the key itself"], multi=False)
26
26
 
27
27
  if choice == "I have the path to the key file":
28
28
  print(Panel("📄 Please enter the path to your private key file", expand=False))
@@ -37,15 +37,10 @@ def main() -> None:
37
37
  path_to_key.write_text(input("🔑 Paste the private key here: "), encoding="utf-8")
38
38
  print(Panel(f"💾 Key saved to: {path_to_key}", expand=False))
39
39
 
40
- elif isinstance(choice, str):
40
+ else:
41
41
  path_to_key = PathExtended(choice)
42
42
  print(Panel(f"🔑 Using selected key: {path_to_key.name}", expand=False))
43
43
 
44
- else:
45
- error_message = f"❌ ERROR: Invalid choice\nThe selected option is not supported: {choice}"
46
- print(Panel(Text(error_message, justify="center"), expand=False, border_style="red"))
47
- raise NotImplementedError(f"Choice {choice} not supported")
48
-
49
44
  txt = f"IdentityFile {path_to_key.collapseuser().as_posix()}" # adds this id for all connections, no host specified.
50
45
  config_path = PathExtended.home().joinpath(".ssh/config")
51
46
 
@@ -2,8 +2,8 @@
2
2
 
3
3
  from platform import system
4
4
  from machineconfig.utils.source_of_truth import LIBRARY_ROOT
5
- from machineconfig.utils.options import display_options
6
- from machineconfig.utils.path_reduced import PathExtended as PathExtended
5
+ from machineconfig.utils.options import choose_from_options
6
+ from machineconfig.utils.path_extended import PathExtended as PathExtended
7
7
  from rich.console import Console
8
8
  from rich.panel import Panel
9
9
  from rich import box # Import box
@@ -84,9 +84,7 @@ def main() -> None:
84
84
  i_have_path_option = "I have the path to the key file"
85
85
  i_paste_option = "I want to paste the key itself"
86
86
 
87
- res = display_options("Which public key to add? ", options=[str(x) for x in pub_keys] + [all_keys_option, i_have_path_option, i_paste_option])
88
- assert isinstance(res, str), f"Got {res} of type {type(res)} instead of str."
89
-
87
+ res = choose_from_options("Which public key to add? ", options=[str(x) for x in pub_keys] + [all_keys_option, i_have_path_option, i_paste_option], multi=False)
90
88
  if res == all_keys_option:
91
89
  console.print(Panel(f"🔄 Processing all {len(pub_keys)} public keys...", title="[bold blue]Processing[/bold blue]", border_style="blue"))
92
90
  program = "\n\n\n".join([get_add_ssh_key_script(key) for key in pub_keys])
@@ -1,16 +1,17 @@
1
1
  """BR: Backup and Retrieve"""
2
2
 
3
3
  # import subprocess
4
- from machineconfig.utils.path_reduced import PathExtended as PathExtended
5
- from machineconfig.utils.utils2 import read_ini, read_toml
4
+ from machineconfig.utils.io import read_ini
5
+ from machineconfig.utils.path_extended import PathExtended as PathExtended
6
6
  from machineconfig.utils.source_of_truth import LIBRARY_ROOT, DEFAULTS_PATH
7
7
  from machineconfig.utils.code import print_code
8
- from machineconfig.utils.options import choose_cloud_interactively, choose_multiple_options
8
+ from machineconfig.utils.options import choose_cloud_interactively, choose_from_options
9
9
  from machineconfig.scripts.python.helpers.helpers2 import ES
10
10
  from platform import system
11
11
  from typing import Any, Literal, Optional
12
12
  from rich.console import Console
13
13
  from rich.panel import Panel
14
+ import tomllib
14
15
 
15
16
 
16
17
  OPTIONS = Literal["BACKUP", "RETRIEVE"]
@@ -26,7 +27,7 @@ def main_backup_retrieve(direction: OPTIONS, which: Optional[str] = None) -> Non
26
27
  console.print(Panel("🔍 DEFAULT CLOUD NOT FOUND\n🔄 Please select a cloud configuration from the options below", title="[bold red]Error: Cloud Not Found[/bold red]", border_style="red"))
27
28
  cloud = choose_cloud_interactively()
28
29
 
29
- bu_file: dict[str, Any] = read_toml(LIBRARY_ROOT.joinpath("profile/backup.toml"))
30
+ bu_file: dict[str, Any] = tomllib.loads(LIBRARY_ROOT.joinpath("profile/backup.toml").read_text(encoding="utf-8"))
30
31
 
31
32
  console.print(Panel(f"🧰 LOADING BACKUP CONFIGURATION\n📄 File: {LIBRARY_ROOT.joinpath('profile/backup.toml')}", title="[bold blue]Backup Configuration[/bold blue]", border_style="blue"))
32
33
 
@@ -39,7 +40,7 @@ def main_backup_retrieve(direction: OPTIONS, which: Optional[str] = None) -> Non
39
40
 
40
41
  if which is None:
41
42
  console.print(Panel(f"🔍 SELECT {direction} ITEMS\n📋 Choose which configuration entries to process", title="[bold blue]Select Items[/bold blue]", border_style="blue"))
42
- choices = choose_multiple_options(msg=f"WHICH FILE of the following do you want to {direction}?", options=["all"] + list(bu_file.keys()))
43
+ choices = choose_from_options(multi=True, msg=f"WHICH FILE of the following do you want to {direction}?", options=["all"] + list(bu_file.keys()))
43
44
  else:
44
45
  choices = which.split(",") if which else []
45
46
  console.print(Panel(f"🔖 PRE-SELECTED ITEMS\n📝 Using: {', '.join(choices)}", title="[bold blue]Pre-selected Items[/bold blue]", border_style="blue"))
@@ -3,7 +3,7 @@
3
3
  # import subprocess
4
4
  from rich.progress import Progress, SpinnerColumn, TextColumn
5
5
  from machineconfig.utils.source_of_truth import LIBRARY_ROOT
6
- from machineconfig.utils.options import choose_multiple_options
6
+ from machineconfig.utils.options import choose_from_options
7
7
  from machineconfig.utils.installer import get_installers, install_all
8
8
  from platform import system
9
9
  from typing import Any, Optional, Literal, TypeAlias, get_args
@@ -59,7 +59,7 @@ def main(which: Optional[WHICH_CAT | str]) -> None:
59
59
 
60
60
  options += list(get_args(WHICH_CAT))
61
61
  # print("s"*1000)
62
- program_names = choose_multiple_options(msg="", options=options, header="🚀 CHOOSE DEV APP", default="AllEssentials")
62
+ program_names = choose_from_options(multi=True, msg="", options=options, header="🚀 CHOOSE DEV APP", default="AllEssentials")
63
63
 
64
64
  total_commands = ""
65
65
  installation_messages: list[str] = []
@@ -112,7 +112,7 @@ def get_programs_by_category(program_name: WHICH_CAT):
112
112
  options_system = {**options_system_1, **options_system_2}
113
113
  else:
114
114
  raise NotImplementedError(f"❌ System {system()} not supported")
115
- program_names = choose_multiple_options(msg="", options=sorted(list(options_system.keys())), header="🚀 CHOOSE DEV APP")
115
+ program_names = choose_from_options(multi=True, msg="", options=sorted(list(options_system.keys())), header="🚀 CHOOSE DEV APP")
116
116
  program = ""
117
117
  for name in program_names:
118
118
  print(f"""
@@ -127,7 +127,7 @@ def get_programs_by_category(program_name: WHICH_CAT):
127
127
  # case "OtherDevApps":
128
128
  # installers = get_installers(dev=True, system=system())
129
129
  # options__: list[str] = [x.get_description() for x in tqdm(installers, desc="Checking installed programs")]
130
- # program_names = choose_multiple_options(msg="", options=sorted(options__) + ["all"], header="CHOOSE DEV APP")
130
+ # program_names = choose_from_options(multi=True, msg="", options=sorted(options__) + ["all"], header="CHOOSE DEV APP")
131
131
  # if "all" in program_names: program_names = options__
132
132
  # program = ""
133
133
  # print("Installing:")
@@ -3,9 +3,9 @@
3
3
  import git
4
4
  from pathlib import Path
5
5
  from machineconfig.scripts.python.repos_helper_update import RepositoryUpdateResult, run_uv_sync, update_repository
6
- from machineconfig.utils.path_reduced import PathExtended as PathExtended
6
+ from machineconfig.utils.path_extended import PathExtended as PathExtended
7
7
  from machineconfig.utils.source_of_truth import DEFAULTS_PATH
8
- from machineconfig.utils.utils2 import read_ini
8
+ from machineconfig.utils.io import read_ini
9
9
 
10
10
 
11
11
  def _display_summary(results: list[RepositoryUpdateResult]) -> None:
@@ -1,6 +1,6 @@
1
1
  """Like yadm and dotter."""
2
2
 
3
- from machineconfig.utils.path_reduced import PathExtended as PathExtended
3
+ from machineconfig.utils.path_extended import PathExtended as PathExtended
4
4
  from machineconfig.utils.links import symlink_func
5
5
  from machineconfig.utils.source_of_truth import LIBRARY_ROOT, REPO_ROOT
6
6
  import argparse