machineconfig 5.13__py3-none-any.whl → 5.15__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/scripts/python/count_lines_frontend.py +4 -4
- machineconfig/scripts/python/croshell.py +20 -67
- machineconfig/scripts/python/fire_jobs.py +2 -2
- machineconfig/scripts/python/interactive.py +26 -42
- machineconfig/scripts/python/share_terminal.py +2 -2
- machineconfig/setup_windows/web_shortcuts/interactive.ps1 +1 -0
- machineconfig/utils/code.py +1 -1
- machineconfig/utils/files/ascii_art.py +118 -0
- machineconfig/utils/files/headers.py +71 -0
- machineconfig/utils/files/read.py +103 -0
- machineconfig/utils/installer_utils/installer.py +2 -2
- machineconfig/utils/installer_utils/installer_abc.py +7 -0
- machineconfig/utils/options.py +0 -25
- machineconfig/utils/terminal.py +1 -1
- {machineconfig-5.13.dist-info → machineconfig-5.15.dist-info}/METADATA +1 -1
- {machineconfig-5.13.dist-info → machineconfig-5.15.dist-info}/RECORD +19 -16
- {machineconfig-5.13.dist-info → machineconfig-5.15.dist-info}/WHEEL +0 -0
- {machineconfig-5.13.dist-info → machineconfig-5.15.dist-info}/entry_points.txt +0 -0
- {machineconfig-5.13.dist-info → machineconfig-5.15.dist-info}/top_level.txt +0 -0
|
@@ -5,11 +5,11 @@ import typer
|
|
|
5
5
|
def analyze_repo_development(repo_path: str = typer.Argument(..., help="Path to the git repository")):
|
|
6
6
|
from machineconfig.scripts.python import count_lines
|
|
7
7
|
from pathlib import Path
|
|
8
|
-
count_lines_path = Path(count_lines.__file__)
|
|
8
|
+
count_lines_path = Path(count_lines.__file__)
|
|
9
9
|
# --project $HOME/code/machineconfig
|
|
10
|
-
cmd = f"""uv run --python 3.13 --with machineconfig
|
|
11
|
-
from machineconfig.utils.code import
|
|
12
|
-
|
|
10
|
+
cmd = f"""uv run --python 3.13 --with machineconfig[plot] {count_lines_path} analyze-over-time {repo_path}"""
|
|
11
|
+
from machineconfig.utils.code import run_shell_script
|
|
12
|
+
run_shell_script(cmd)
|
|
13
13
|
|
|
14
14
|
|
|
15
15
|
if __name__ == "__main__":
|
|
@@ -40,8 +40,6 @@ except Exception: print(pycode)
|
|
|
40
40
|
|
|
41
41
|
|
|
42
42
|
def get_read_data_pycode(path: str):
|
|
43
|
-
# We need to be careful here since we're generating Python code as a string
|
|
44
|
-
# that will use f-strings itself
|
|
45
43
|
return f"""
|
|
46
44
|
from rich.panel import Panel
|
|
47
45
|
from rich.text import Text
|
|
@@ -49,7 +47,8 @@ from rich.console import Console
|
|
|
49
47
|
console = Console()
|
|
50
48
|
p = PathExtended(r'{path}').absolute()
|
|
51
49
|
try:
|
|
52
|
-
|
|
50
|
+
from machineconfig.utils.files.read import Read
|
|
51
|
+
dat = Read.read(p)
|
|
53
52
|
if isinstance(dat, dict):
|
|
54
53
|
panel_title = f"📄 File Data: {{p.name}}"
|
|
55
54
|
console.print(Panel(Text(str(dat), justify="left"), title=panel_title, expand=False))
|
|
@@ -63,53 +62,25 @@ except Exception as e:
|
|
|
63
62
|
"""
|
|
64
63
|
|
|
65
64
|
|
|
66
|
-
def get_read_pyfile_pycode(path: PathExtended, as_module: bool, cmd: str = ""):
|
|
67
|
-
if as_module:
|
|
68
|
-
pycode = rf"""
|
|
69
|
-
import sys
|
|
70
|
-
sys.path.append(r'{path.parent}')
|
|
71
|
-
from {path.stem} import *
|
|
72
|
-
{cmd}
|
|
73
|
-
"""
|
|
74
|
-
else:
|
|
75
|
-
pycode = f"""
|
|
76
|
-
__file__ = PathExtended(r'{path}')
|
|
77
|
-
{path.read_text(encoding="utf-8")}
|
|
78
|
-
"""
|
|
79
|
-
return pycode
|
|
80
|
-
|
|
81
65
|
|
|
82
66
|
def main(
|
|
83
|
-
module: Annotated[bool, typer.Option("--module", "-m", help="flag to run the file as a module as opposed to main.")] = False,
|
|
84
|
-
newWindow: Annotated[bool, typer.Option("--newWindow", "-w", help="flag for running in new window.")] = False,
|
|
85
|
-
nonInteratctive: Annotated[bool, typer.Option("--nonInteratctive", "-N", help="flag for a non-interactive session.")] = False,
|
|
86
67
|
python: Annotated[bool, typer.Option("--python", "-p", help="flag to use python over IPython.")] = False,
|
|
87
68
|
fzf: Annotated[bool, typer.Option("--fzf", "-F", help="search with fuzzy finder for python scripts and run them")] = False,
|
|
88
69
|
ve: Annotated[Optional[str], typer.Option("--ve", "-v", help="virtual enviroment to use, defaults to activated ve, if existed, else ve.")] = None,
|
|
89
70
|
profile: Annotated[Optional[str], typer.Option("--profile", "-P", help="ipython profile to use, defaults to default profile.")] = None,
|
|
90
71
|
read: Annotated[str, typer.Option("--read", "-r", help="read a binary file.")] = "",
|
|
91
|
-
file: Annotated[str, typer.Option("--file", "-f", help="python file path to interpret")] = "",
|
|
92
|
-
cmd: Annotated[str, typer.Option("--cmd", "-c", help="python command to interpret")] = "",
|
|
93
|
-
terminal: Annotated[str, typer.Option("--terminal", "-t", help="specify which terminal to be used. Default console host.")] = "",
|
|
94
|
-
shell: Annotated[str, typer.Option("--shell", "-S", help="specify which shell to be used. Defaults to CMD.")] = "",
|
|
95
72
|
jupyter: Annotated[bool, typer.Option("--jupyter", "-j", help="run in jupyter interactive console")] = False,
|
|
96
73
|
streamlit_viewer: Annotated[bool, typer.Option("--stViewer", "-s", help="view in streamlit app")] = False,
|
|
74
|
+
visidata: Annotated[bool, typer.Option("--visidata", "-V", help="open data file in visidata")] = False,
|
|
97
75
|
) -> None:
|
|
98
76
|
# ==================================================================================
|
|
99
77
|
# flags processing
|
|
100
|
-
interactivity = "
|
|
78
|
+
interactivity = "-i"
|
|
101
79
|
interpreter = "python" if python else "ipython"
|
|
102
80
|
ipython_profile: Optional[str] = profile
|
|
103
81
|
file_obj = PathExtended.cwd() # initialization value, could be modified according to args.
|
|
104
82
|
|
|
105
|
-
if
|
|
106
|
-
text = "🖥️ Executing command from CLI argument"
|
|
107
|
-
console.print(Panel(text, title="[bold blue]Info[/bold blue]"))
|
|
108
|
-
import textwrap
|
|
109
|
-
|
|
110
|
-
program = textwrap.dedent(cmd)
|
|
111
|
-
|
|
112
|
-
elif fzf:
|
|
83
|
+
if fzf:
|
|
113
84
|
text = "🔍 Searching for Python files..."
|
|
114
85
|
console.print(Panel(text, title="[bold blue]Info[/bold blue]"))
|
|
115
86
|
options = [str(item) for item in PathExtended.cwd().search("*.py", r=True)]
|
|
@@ -119,13 +90,6 @@ def main(
|
|
|
119
90
|
text = f"📄 Selected file: {PathExtended(file_selected).name}"
|
|
120
91
|
console.print(Panel(text, title="[bold blue]Info[/bold blue]"))
|
|
121
92
|
|
|
122
|
-
elif file != "":
|
|
123
|
-
file_obj = PathExtended(file.lstrip()).expanduser().absolute()
|
|
124
|
-
program = get_read_pyfile_pycode(file_obj, as_module=module, cmd=cmd)
|
|
125
|
-
text1 = f"📄 Loading file: {file_obj.name}"
|
|
126
|
-
text2 = f"🔄 Mode: {'Module' if module else 'Script'}"
|
|
127
|
-
console.print(Panel(f"{text1}\n{text2}", title="[bold blue]Info[/bold blue]"))
|
|
128
|
-
|
|
129
93
|
elif read != "":
|
|
130
94
|
if streamlit_viewer:
|
|
131
95
|
# text = "📊 STARTING STREAMLIT VIEWER"
|
|
@@ -154,46 +118,35 @@ def main(
|
|
|
154
118
|
preprogram = """
|
|
155
119
|
|
|
156
120
|
#%%
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
except ImportError:
|
|
162
|
-
print("Crocodile not found, skipping import.")
|
|
121
|
+
|
|
122
|
+
from machineconfig.utils.files.headers import print_header, print_logo
|
|
123
|
+
print_header()
|
|
124
|
+
print_logo("CROCODILE")
|
|
163
125
|
from pathlib import Path
|
|
164
|
-
|
|
126
|
+
|
|
165
127
|
"""
|
|
166
128
|
|
|
167
129
|
pyfile = PathExtended.tmp().joinpath(f"tmp_scripts/python/croshell/{randstr()}.py")
|
|
168
130
|
pyfile.parent.mkdir(parents=True, exist_ok=True)
|
|
169
131
|
|
|
170
|
-
|
|
171
|
-
title = "Reading Data"
|
|
172
|
-
elif file != "":
|
|
173
|
-
title = "Running Python File"
|
|
174
|
-
else:
|
|
175
|
-
title = "Executed code"
|
|
132
|
+
title = "Reading Data"
|
|
176
133
|
python_program = preprogram + add_print_header_pycode(str(pyfile), title=title) + program
|
|
177
134
|
pyfile.write_text(python_program, encoding="utf-8")
|
|
178
135
|
# ve_root_from_file, ipython_profile = get_ve_path_and_ipython_profile(PathExtended(file))
|
|
179
136
|
ipython_profile = ipython_profile if ipython_profile is not None else "default"
|
|
180
137
|
# ve_activateion_line = get_ve_activate_line(ve_name=args.ve or ve_profile_suggested, a_path=str(PathExtended.cwd()))
|
|
181
|
-
shell_program = """
|
|
182
|
-
#!/bin/bash
|
|
183
138
|
|
|
184
|
-
|
|
185
|
-
|
|
139
|
+
if visidata:
|
|
140
|
+
fire_line = f"uv run --with visidata,pyarrow vd {str(file_obj)}"
|
|
141
|
+
elif jupyter:
|
|
186
142
|
fire_line = f"code --new-window {str(pyfile)}"
|
|
187
143
|
else:
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
fire_line
|
|
191
|
-
|
|
192
|
-
from
|
|
193
|
-
|
|
194
|
-
print()
|
|
195
|
-
import subprocess
|
|
196
|
-
subprocess.run(shell_program, shell=True, check=True)
|
|
144
|
+
if interpreter == "ipython": profile = f" --profile {ipython_profile} --no-banner"
|
|
145
|
+
else: profile = ""
|
|
146
|
+
fire_line = f"uv run --python 3.13 --with machineconfig[plot] {interpreter} {interactivity} {profile} {str(pyfile)}"
|
|
147
|
+
|
|
148
|
+
from machineconfig.utils.code import run_shell_script
|
|
149
|
+
run_shell_script(fire_line)
|
|
197
150
|
|
|
198
151
|
|
|
199
152
|
def arg_parser() -> None:
|
|
@@ -221,8 +221,8 @@ python -m machineconfig.cluster.templates.cli_click --file {choice_file} """
|
|
|
221
221
|
command = "$ErrorActionPreference = 'SilentlyContinue';\n" + command + "\nStart-Sleep -Seconds 0.5"
|
|
222
222
|
else:
|
|
223
223
|
raise NotImplementedError(f"Platform {platform.system()} not supported.")
|
|
224
|
-
from machineconfig.utils.code import
|
|
225
|
-
|
|
224
|
+
from machineconfig.utils.code import run_shell_script
|
|
225
|
+
run_shell_script(command)
|
|
226
226
|
|
|
227
227
|
|
|
228
228
|
def main(
|
|
@@ -27,27 +27,23 @@ from questionary import Choice
|
|
|
27
27
|
from rich.console import Console
|
|
28
28
|
from rich.panel import Panel
|
|
29
29
|
from rich.text import Text
|
|
30
|
-
from machineconfig.utils.code import
|
|
30
|
+
from machineconfig.utils.code import run_shell_script
|
|
31
31
|
|
|
32
32
|
_ = cast
|
|
33
33
|
console = Console()
|
|
34
34
|
|
|
35
35
|
|
|
36
36
|
def display_header() -> None:
|
|
37
|
-
"""Display the script header."""
|
|
38
37
|
header_text = Text("MACHINE CONFIGURATION", style="bold magenta")
|
|
39
38
|
subtitle_text = Text("Interactive Installation Script", style="italic cyan")
|
|
40
39
|
console.print(Panel(f"📦 {header_text}\n{subtitle_text}", border_style="blue", padding=(1, 2)))
|
|
41
40
|
def display_completion_message() -> None:
|
|
42
|
-
"""Display completion message."""
|
|
43
41
|
completion_text = Text("INSTALLATION COMPLETE", style="bold green")
|
|
44
42
|
subtitle_text = Text("System setup finished successfully", style="italic green")
|
|
45
43
|
console.print(Panel(f"✨ {completion_text}\n{subtitle_text}\n\n🎉 Your system has been configured successfully!\n🔄 You may need to reboot to apply all changes.", border_style="green", padding=(1, 2)))
|
|
46
44
|
def display_dotfiles_instructions() -> None:
|
|
47
|
-
"""Display instructions for dotfiles migration."""
|
|
48
45
|
header_text = Text("DOTFILES MIGRATION", style="bold yellow")
|
|
49
46
|
subtitle_text = Text("Configuration transfer options", style="italic yellow")
|
|
50
|
-
|
|
51
47
|
instructions = """
|
|
52
48
|
🖱️ [bold blue]Method 1: USING MOUSE WITHOUT KB OR BROWSER SHARE[/bold blue]
|
|
53
49
|
On original machine, run:
|
|
@@ -65,32 +61,9 @@ def display_dotfiles_instructions() -> None:
|
|
|
65
61
|
[dim]cd ~
|
|
66
62
|
cloud_copy SHARE_URL . --config ss[/dim]
|
|
67
63
|
(requires symlinks to be created first)"""
|
|
68
|
-
|
|
69
64
|
console.print(Panel(f"📂 {header_text}\n{subtitle_text}\n\n{instructions}", border_style="yellow", padding=(1, 2)))
|
|
70
65
|
|
|
71
66
|
|
|
72
|
-
def install_windows_desktop_apps() -> bool:
|
|
73
|
-
"""Install Windows desktop applications using winget."""
|
|
74
|
-
if system() != "Windows":
|
|
75
|
-
console.print("❌ This function is only available on Windows systems.", style="bold red")
|
|
76
|
-
return False
|
|
77
|
-
console.print("🔧 Installing Nerd Fonts", style="bold cyan")
|
|
78
|
-
try:
|
|
79
|
-
from machineconfig.jobs.installer.custom_dev.nerfont_windows_helper import install_nerd_fonts
|
|
80
|
-
install_nerd_fonts()
|
|
81
|
-
console.print("✅ Nerd Fonts installed successfully", style="bold green")
|
|
82
|
-
except Exception as e:
|
|
83
|
-
console.print(f"❌ Error installing Nerd Fonts: {e}", style="bold red")
|
|
84
|
-
console.print("🔧 Setting Windows Terminal settings", style="bold cyan")
|
|
85
|
-
try:
|
|
86
|
-
from machineconfig.setup_windows.wt_and_pwsh.set_wt_settings import main as set_wt_settings_main
|
|
87
|
-
set_wt_settings_main()
|
|
88
|
-
console.print("✅ Windows Terminal settings configured successfully", style="bold green")
|
|
89
|
-
except Exception as e:
|
|
90
|
-
console.print(f"❌ Error setting Windows Terminal settings: {e}", style="bold red")
|
|
91
|
-
return True
|
|
92
|
-
|
|
93
|
-
|
|
94
67
|
def get_installation_choices() -> list[str]:
|
|
95
68
|
"""Get user choices for installation options."""
|
|
96
69
|
choices = [
|
|
@@ -114,11 +87,15 @@ def get_installation_choices() -> list[str]:
|
|
|
114
87
|
|
|
115
88
|
|
|
116
89
|
def execute_installations(selected_options: list[str]) -> None:
|
|
117
|
-
"""Execute the selected installation options."""
|
|
118
90
|
if system() == "Windows":
|
|
119
|
-
|
|
91
|
+
from machineconfig import setup_windows as module
|
|
92
|
+
script_path = Path(module.__file__).parent / "ve.ps1"
|
|
93
|
+
run_shell_script(script_path.read_text(encoding="utf-8"))
|
|
120
94
|
else:
|
|
121
|
-
|
|
95
|
+
from machineconfig import setup_linux as module
|
|
96
|
+
script_path = Path(module.__file__).parent / "ve.sh"
|
|
97
|
+
run_shell_script(script_path.read_text(encoding="utf-8"))
|
|
98
|
+
|
|
122
99
|
for maybe_a_group in selected_options:
|
|
123
100
|
if maybe_a_group in ("ESSENTIAL", "DEV", "ESSENTIAL_SYSTEM", "DEV_SYSTEM", "TerminalEyeCandy"):
|
|
124
101
|
console.print(Panel("⚡ [bold bright_yellow]CLI APPLICATIONS[/bold bright_yellow]\n[italic]Command-line tools installation[/italic]", border_style="bright_yellow"))
|
|
@@ -129,21 +106,25 @@ def execute_installations(selected_options: list[str]) -> None:
|
|
|
129
106
|
console.print("✅ CLI applications installed successfully", style="bold green")
|
|
130
107
|
except Exception as e:
|
|
131
108
|
console.print(f"❌ Error installing CLI applications: {e}", style="bold red")
|
|
132
|
-
|
|
109
|
+
run_shell_script(". $HOME/.bashrc")
|
|
133
110
|
|
|
134
111
|
if "upgrade_system" in selected_options:
|
|
135
112
|
if system() == "Windows":
|
|
136
113
|
console.print("❌ System upgrade is not applicable on Windows via this script.", style="bold red")
|
|
137
114
|
elif system() == "Linux":
|
|
138
115
|
console.print(Panel("🔄 [bold magenta]SYSTEM UPDATE[/bold magenta]\n[italic]Package management[/italic]", border_style="magenta"))
|
|
139
|
-
|
|
116
|
+
run_shell_script("sudo nala upgrade -y")
|
|
140
117
|
else:
|
|
141
118
|
console.print(f"❌ System upgrade not supported on {system()}.", style="bold red")
|
|
142
119
|
if "install_repos" in selected_options:
|
|
143
120
|
console.print(Panel("🐍 [bold green]PYTHON ENVIRONMENT[/bold green]\n[italic]Virtual environment setup[/italic]", border_style="green"))
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
121
|
+
if system() == "Windows":
|
|
122
|
+
from machineconfig import setup_windows as module
|
|
123
|
+
script_path = Path(module.__file__).parent / "repos.ps1"
|
|
124
|
+
else:
|
|
125
|
+
from machineconfig import setup_linux as module
|
|
126
|
+
script_path = Path(module.__file__).parent / "repos.sh"
|
|
127
|
+
run_shell_script(script_path.read_text(encoding="utf-8"))
|
|
147
128
|
|
|
148
129
|
if "install_ssh_server" in selected_options:
|
|
149
130
|
console.print(Panel("🔒 [bold red]SSH SERVER[/bold red]\n[italic]Remote access setup[/italic]", border_style="red"))
|
|
@@ -152,9 +133,9 @@ def execute_installations(selected_options: list[str]) -> None:
|
|
|
152
133
|
Add-WindowsCapability -Online -Name OpenSSH.Server~~~~0.0.1.0
|
|
153
134
|
Start-Service sshd
|
|
154
135
|
Set-Service -Name sshd -StartupType 'Automatic'"""
|
|
155
|
-
|
|
136
|
+
run_shell_script(f'powershell -Command "{powershell_script}"')
|
|
156
137
|
else:
|
|
157
|
-
|
|
138
|
+
run_shell_script("sudo nala install openssh-server -y")
|
|
158
139
|
|
|
159
140
|
if "install_shell_profile" in selected_options:
|
|
160
141
|
console.print(Panel("🐚 [bold green]SHELL PROFILE[/bold green]\n[italic]Shell configuration setup[/italic]", border_style="green"))
|
|
@@ -179,8 +160,8 @@ Set-Service -Name sshd -StartupType 'Automatic'"""
|
|
|
179
160
|
console.print("✅ Symlinks created successfully", style="bold green")
|
|
180
161
|
except Exception as e:
|
|
181
162
|
console.print(f"❌ Error creating symlinks: {e}", style="bold red")
|
|
182
|
-
|
|
183
|
-
|
|
163
|
+
run_shell_script("sudo chmod 600 $HOME/.ssh/*")
|
|
164
|
+
run_shell_script("sudo chmod 700 $HOME/.ssh")
|
|
184
165
|
else:
|
|
185
166
|
console.print("⏭️ Skipping symlink creation - finish dotfiles transfer first", style="yellow")
|
|
186
167
|
|
|
@@ -200,7 +181,10 @@ Set-Service -Name sshd -StartupType 'Automatic'"""
|
|
|
200
181
|
console.print(f"❌ Error retrieving backup data: {e}", style="bold red")
|
|
201
182
|
|
|
202
183
|
if "install_windows_desktop" in selected_options:
|
|
203
|
-
|
|
184
|
+
from machineconfig.jobs.installer.custom_dev.nerfont_windows_helper import install_nerd_fonts
|
|
185
|
+
install_nerd_fonts()
|
|
186
|
+
from machineconfig.setup_windows.wt_and_pwsh.set_wt_settings import main as set_wt_settings_main
|
|
187
|
+
set_wt_settings_main()
|
|
204
188
|
|
|
205
189
|
|
|
206
190
|
def main() -> None:
|
|
@@ -210,7 +194,7 @@ def main() -> None:
|
|
|
210
194
|
if not selected_options:
|
|
211
195
|
console.print("❌ No options selected. Exiting...", style="bold red")
|
|
212
196
|
sys.exit(0)
|
|
213
|
-
console.print(f"\n✅ Selected options: {'
|
|
197
|
+
console.print(f"\n✅ Selected options: {'\n'.join(selected_options)}", style="bold green")
|
|
214
198
|
proceed = questionary.confirm("🚀 Proceed with installation?", default=True).ask()
|
|
215
199
|
if not proceed:
|
|
216
200
|
console.print("❌ Installation cancelled.", style="bold red")
|
|
@@ -132,8 +132,8 @@ def main(
|
|
|
132
132
|
#!/bin/bash
|
|
133
133
|
ttyd --writable -t enableSixel=true {ssl_args} --port {port} --credential "{username}:{password}" -t 'theme={{"background": "black"}}' {start_command}
|
|
134
134
|
"""
|
|
135
|
-
from machineconfig.utils.code import
|
|
136
|
-
|
|
135
|
+
from machineconfig.utils.code import run_shell_script
|
|
136
|
+
run_shell_script(code)
|
|
137
137
|
|
|
138
138
|
|
|
139
139
|
def main_with_parser():
|
|
@@ -10,3 +10,4 @@ Invoke-WebRequest -Uri "https://raw.githubusercontent.com/thisismygitrepo/machin
|
|
|
10
10
|
rm ve.ps1
|
|
11
11
|
|
|
12
12
|
uv run --python 3.13 --with machineconfig devops interactive
|
|
13
|
+
# uv run --python 3.13 --with machineconfig https://raw.githubusercontent.com/thisismygitrepo/machineconfig/ee4f69e838e1acbb275bfb5a3d3faee23345f2a8/src/machineconfig/scripts/python/devops.py
|
machineconfig/utils/code.py
CHANGED
|
@@ -98,7 +98,7 @@ def print_code(code: str, lexer: str, desc: str, subtitle: str = ""):
|
|
|
98
98
|
console.print(Panel(Syntax(code=code, lexer=lexer), title=f"📄 {desc}", subtitle=subtitle), style="bold red")
|
|
99
99
|
|
|
100
100
|
|
|
101
|
-
def
|
|
101
|
+
def run_shell_script(program: str):
|
|
102
102
|
import tempfile
|
|
103
103
|
if platform.system() == "Windows":
|
|
104
104
|
suffix = ".ps1"
|
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
"""Ascii art
|
|
2
|
+
"""
|
|
3
|
+
|
|
4
|
+
import os
|
|
5
|
+
import random
|
|
6
|
+
import textwrap
|
|
7
|
+
import subprocess
|
|
8
|
+
from pathlib import Path
|
|
9
|
+
import tempfile
|
|
10
|
+
import platform
|
|
11
|
+
from typing import Optional, Literal
|
|
12
|
+
|
|
13
|
+
# https://github.com/sepandhaghighi/art
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
BOX_OR_CHAR = Literal['boxes', 'cowsay']
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
class ArtLib:
|
|
20
|
+
@staticmethod
|
|
21
|
+
def cowsay(text: str):
|
|
22
|
+
import cowsay
|
|
23
|
+
char = random.choice(cowsay.char_names)
|
|
24
|
+
return cowsay.get_output_string(char, text=text)
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
class BoxStyles:
|
|
28
|
+
language = ['ada-box', 'caml', 'boxquote', 'stone', 'tex-box', 'shell', 'simple', 'c', 'cc', 'html']
|
|
29
|
+
scene = ['whirly', 'xes', 'columns', 'parchment', 'scroll', 'scroll-akn', 'diamonds', 'headline', 'nuke', 'spring', 'stark1'] # , 'important3'
|
|
30
|
+
character = ['capgirl', 'cat', 'boy', 'girl', 'dog', 'mouse', 'santa', 'face', 'ian_jones', 'peek', 'unicornsay']
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
class CowStyles:
|
|
34
|
+
eyes = ['-b', '-d', '-g', '-h', '-l', '-L', '-n', '-N', '-p', '-s', '-t', '-w', '-y']
|
|
35
|
+
# this one for the package installed with sudo apt install cowsay and is located at /usr/games/cowsay. See cowsay -l
|
|
36
|
+
figures = ['apt', 'bunny', 'cheese', 'cock', 'cower', 'daemon', 'default', 'dragon',
|
|
37
|
+
'dragon-and-cow', 'duck', 'elephant', 'elephant-in-snake', 'eyes', 'fox', 'ghostbusters',
|
|
38
|
+
'gnu', 'kangaroo', 'kiss', 'milk',
|
|
39
|
+
'moose', 'pony', 'pony-smaller', 'sheep', 'skeleton', 'snowman', 'stegosaurus', # 'suse',
|
|
40
|
+
'three-eyes', 'turkey', 'turtle', 'tux', 'unipony', 'unipony-smaller', 'vader', 'vader'] # 'hellokitty' 'mech-and-cow' # 'moofasa', 'stimpy', 'calvin', , 'ren', 'koala', 'flaming-sheep' , 'bud-frogs' , 'kosh' , 'luke-koala'
|
|
41
|
+
|
|
42
|
+
|
|
43
|
+
FIGLET_FONTS = ['banner', 'big', 'standard']
|
|
44
|
+
|
|
45
|
+
FIGJS_FONTS = ['3D Diagonal', '3D-ASCII', '4Max', '5 Line Oblique', 'Acrobatic', 'ANSI Regular', 'ANSI Shadow',
|
|
46
|
+
'Avatar', 'Banner', 'Banner3-D', 'Banner4',
|
|
47
|
+
'Basic', 'Big Money-ne', 'Big Money-nw', 'Big Money-se', 'Big Money-sw', 'Big', 'Bloody', 'Bolger', 'Braced', 'Bright',
|
|
48
|
+
'DOS Rebel',
|
|
49
|
+
'Elite', 'Epic', 'Flower Power',
|
|
50
|
+
'Fraktur', # 'Isometric4'. 'AMC Tubes', 'Banner3', Alligator2
|
|
51
|
+
'Star Wars',
|
|
52
|
+
'Sub-Zero', 'The Edge', 'USA Flag', 'Varsity', "Doom"
|
|
53
|
+
] # too large Crazy 'Sweet', 'Electronic', 'Swamp Land', Crawford, Alligator
|
|
54
|
+
|
|
55
|
+
|
|
56
|
+
def get_art(comment: Optional[str] = None, artlib: Optional[BOX_OR_CHAR] = None, style: Optional[str] = None, super_style: str = 'scene', prefix: str = ' ', file: Optional[str] = None, verbose: bool = True):
|
|
57
|
+
""" takes in a comment and does the following wrangling:
|
|
58
|
+
* text => figlet font => boxes => lolcat
|
|
59
|
+
* text => cowsay => lolcat
|
|
60
|
+
"""
|
|
61
|
+
if comment is None:
|
|
62
|
+
try:
|
|
63
|
+
comment = subprocess.run("fortune", shell=True, capture_output=True, text=True, check=True).stdout
|
|
64
|
+
except Exception:
|
|
65
|
+
comment = "crocodile"
|
|
66
|
+
if artlib is None: artlib = random.choice(['boxes', 'cowsay'])
|
|
67
|
+
to_file = '' if not file else f'> {file}'
|
|
68
|
+
if artlib == 'boxes':
|
|
69
|
+
if style is None: style = random.choice(BoxStyles.__dict__[super_style or random.choice(['language', 'scene', 'character'])])
|
|
70
|
+
fonting = f'figlet -f {random.choice(FIGLET_FONTS)}'
|
|
71
|
+
cmd = f"""echo "{comment}" | {fonting} | boxes -d {style} {to_file}"""
|
|
72
|
+
else:
|
|
73
|
+
if style is None: style = random.choice(CowStyles.figures)
|
|
74
|
+
cmd = f"""echo "{comment}" | /usr/games/cowsay -f {style} {to_file}"""
|
|
75
|
+
try:
|
|
76
|
+
res = subprocess.run(cmd, text=True, capture_output=True, shell=True, check=True).stdout
|
|
77
|
+
except subprocess.CalledProcessError as ex:
|
|
78
|
+
print(ex)
|
|
79
|
+
return ""
|
|
80
|
+
res = textwrap.indent(res, prefix=prefix)
|
|
81
|
+
if verbose:
|
|
82
|
+
print(f'Using style: {style} from {artlib}', '\n' * 3)
|
|
83
|
+
print(f'{cmd=}')
|
|
84
|
+
print('Results:\n', res)
|
|
85
|
+
return res
|
|
86
|
+
|
|
87
|
+
|
|
88
|
+
def font_box_color(logo: str):
|
|
89
|
+
font = random.choice(FIGJS_FONTS)
|
|
90
|
+
# print(f"{font}\n")
|
|
91
|
+
box_style = random.choice(['whirly', 'xes', 'columns', 'parchment', 'scroll', 'scroll-akn', 'diamonds', 'headline', 'nuke', 'spring', 'stark1'])
|
|
92
|
+
_cmd = f'figlet -f "{font}" "{logo}" | boxes -d "{box_style}" | lolcatjs'
|
|
93
|
+
# print(_cmd)
|
|
94
|
+
os.system(_cmd) # | lolcat
|
|
95
|
+
# print("after")
|
|
96
|
+
|
|
97
|
+
|
|
98
|
+
def character_color(logo: str):
|
|
99
|
+
assert platform.system() == 'Windows', 'This function is only for Windows.'
|
|
100
|
+
with tempfile.NamedTemporaryFile(mode='w', suffix='.txt', delete=False) as f:
|
|
101
|
+
f.write(ArtLib.cowsay(logo))
|
|
102
|
+
_new_art = f.name
|
|
103
|
+
os.system(f'type {_new_art} | lolcatjs') # | lolcat
|
|
104
|
+
|
|
105
|
+
|
|
106
|
+
def character_or_box_color(logo: str):
|
|
107
|
+
assert platform.system() in {'Linux', 'Darwin'}, 'This function is only for Linux and macOS.'
|
|
108
|
+
with tempfile.NamedTemporaryFile(mode='w', suffix='.txt', delete=False) as f:
|
|
109
|
+
_new_art = f.name
|
|
110
|
+
get_art(logo, artlib=None, file=_new_art, verbose=False)
|
|
111
|
+
# Prefer bat on mac if available, fallback to cat
|
|
112
|
+
pager = "bat" if (platform.system() == "Darwin" and any((Path(p).joinpath("bat").exists() for p in os.environ.get("PATH", "").split(os.pathsep)))) else "cat"
|
|
113
|
+
command = f"{pager} {_new_art} | lolcat"
|
|
114
|
+
os.system(command)
|
|
115
|
+
|
|
116
|
+
|
|
117
|
+
if __name__ == '__main__':
|
|
118
|
+
pass
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
|
|
2
|
+
import glob
|
|
3
|
+
import os
|
|
4
|
+
import platform
|
|
5
|
+
import random
|
|
6
|
+
from pathlib import Path
|
|
7
|
+
from rich import pretty
|
|
8
|
+
from rich.console import Console
|
|
9
|
+
from typing import Optional
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
def print_header():
|
|
13
|
+
console = Console()
|
|
14
|
+
pretty.install()
|
|
15
|
+
|
|
16
|
+
# Environment Information Panel
|
|
17
|
+
from rich.panel import Panel
|
|
18
|
+
from rich.table import Table
|
|
19
|
+
|
|
20
|
+
table = Table(show_header=False, show_edge=False, pad_edge=False)
|
|
21
|
+
table.add_column("Label", style="cyan", no_wrap=True)
|
|
22
|
+
table.add_column("Value", style="white")
|
|
23
|
+
|
|
24
|
+
table.add_row("Python Version", platform.python_version())
|
|
25
|
+
table.add_row("Operating System", platform.system())
|
|
26
|
+
table.add_row("Virtual Environment", os.getenv('VIRTUAL_ENV', 'None'))
|
|
27
|
+
table.add_row("Running @", str(Path.cwd()))
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
console.print(Panel(table, title="[bold blue]✨ 🐊 Crocodile Shell 14.5 ✨ Made with 🐍 | Built with ❤️[/bold blue]", border_style="blue"))
|
|
31
|
+
def print_logo(logo: str):
|
|
32
|
+
from machineconfig.utils.files.ascii_art import font_box_color, character_color, character_or_box_color
|
|
33
|
+
if platform.system() == "Windows":
|
|
34
|
+
_1x = Path.home().joinpath(r"AppData/Roaming/npm/figlet").exists()
|
|
35
|
+
_2x = Path.home().joinpath(r"AppData/Roaming/npm/lolcatjs").exists()
|
|
36
|
+
_3x = Path.home().joinpath(r"AppData/Local/Microsoft/WindowsApps/boxes.exe").exists()
|
|
37
|
+
if _1x and _2x and _3x:
|
|
38
|
+
if random.choice([True, True, False]): font_box_color(logo)
|
|
39
|
+
else: character_color(logo)
|
|
40
|
+
else:
|
|
41
|
+
print("\n" + "🚫 " + "-" * 70 + " 🚫")
|
|
42
|
+
print("🔍 Missing ASCII art dependencies. Install with: iwr bit.ly/cfgasciiartwindows | iex")
|
|
43
|
+
print("🚫 " + "-" * 70 + " 🚫\n")
|
|
44
|
+
_default_art = Path(random.choice(glob.glob(str(Path(__file__).parent.joinpath("art", "*")))))
|
|
45
|
+
print(_default_art.read_text())
|
|
46
|
+
elif platform.system() in ["Linux", "Darwin"]: # Explicitly handle both Linux and macOS
|
|
47
|
+
def is_executable_in_path(executable_name: str) -> Optional[str]:
|
|
48
|
+
path_dirs = os.environ['PATH'].split(os.pathsep)
|
|
49
|
+
for path_dir in path_dirs:
|
|
50
|
+
path_to_executable = os.path.join(path_dir, executable_name)
|
|
51
|
+
if os.path.isfile(path_to_executable) and os.access(path_to_executable, os.X_OK): return path_to_executable
|
|
52
|
+
return None
|
|
53
|
+
avail_cowsay = is_executable_in_path("cowsay")
|
|
54
|
+
avail_lolcat = is_executable_in_path("lolcat")
|
|
55
|
+
avail_boxes = is_executable_in_path("boxes")
|
|
56
|
+
avail_figlet = is_executable_in_path("figlet")
|
|
57
|
+
if avail_cowsay and avail_lolcat and avail_boxes and avail_figlet:
|
|
58
|
+
_dynamic_art = random.choice([True, True, True, True, False])
|
|
59
|
+
if _dynamic_art: character_or_box_color(logo=logo)
|
|
60
|
+
else: print(Path(random.choice(glob.glob(str(Path(__file__).parent.joinpath("art", "*"))))).read_text())
|
|
61
|
+
else:
|
|
62
|
+
print("\n" + "🚫 " + "-" * 70 + " 🚫")
|
|
63
|
+
install_cmd = "devops install --group TerminalEyeCandy" if platform.system() == "Linux" else "brew install cowsay lolcat boxes figlet"
|
|
64
|
+
print(f"🔍 Missing ASCII art dependencies. Install with: {install_cmd}")
|
|
65
|
+
print("🚫 " + "-" * 70 + " 🚫\n")
|
|
66
|
+
_default_art = Path(random.choice(glob.glob(str(Path(__file__).parent.joinpath("art", "*")))))
|
|
67
|
+
print(_default_art.read_text())
|
|
68
|
+
else:
|
|
69
|
+
print(f"⚠️ Platform {platform.system()} not supported for ASCII art. Using default art.")
|
|
70
|
+
_default_art = Path(random.choice(glob.glob(str(Path(__file__).parent.joinpath("art", "*")))))
|
|
71
|
+
print(_default_art.read_text())
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
from pathlib import Path
|
|
5
|
+
from typing import Any, Optional
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
class Read:
|
|
9
|
+
@staticmethod
|
|
10
|
+
def read(path: 'Path', **kwargs: Any) -> Any:
|
|
11
|
+
if Path(path).is_dir(): raise IsADirectoryError(f"Path is a directory, not a file: {path}")
|
|
12
|
+
suffix = Path(path).suffix[1:]
|
|
13
|
+
if suffix == "": raise ValueError(f"File type could not be inferred from suffix. Suffix is empty. Path: {path}")
|
|
14
|
+
if suffix in ("sqlite", "sqlite3", "db", "duckdb"):
|
|
15
|
+
# from crocodile.database import DBMS
|
|
16
|
+
# if suffix == "duckdb": pass
|
|
17
|
+
# res = DBMS.from_local_db(path=path)
|
|
18
|
+
# print(res.describe_db())
|
|
19
|
+
# return res
|
|
20
|
+
raise NotImplementedError("Reading database files is not implemented yet. Use `crocodile.database.DBMS` to connect to the database file.")
|
|
21
|
+
try: return getattr(Read, suffix)(str(path), **kwargs)
|
|
22
|
+
except AttributeError as err:
|
|
23
|
+
if "type object 'Read' has no attribute" not in str(err): raise AttributeError(err) from err
|
|
24
|
+
if suffix in ('eps', 'jpg', 'jpeg', 'pdf', 'pgf', 'png', 'ps', 'raw', 'rgba', 'svg', 'svgz', 'tif', 'tiff'):
|
|
25
|
+
import matplotlib.pyplot as pyplot
|
|
26
|
+
return pyplot.imread(path, **kwargs) # from: plt.gcf().canvas.get_supported_filetypes().keys():
|
|
27
|
+
if suffix == "parquet":
|
|
28
|
+
import polars as pl
|
|
29
|
+
return pl.read_parquet(path, **kwargs)
|
|
30
|
+
elif suffix == "csv":
|
|
31
|
+
import polars as pl
|
|
32
|
+
return pl.read_csv(path, **kwargs)
|
|
33
|
+
try:
|
|
34
|
+
# guess = install_n_import('magic', 'python-magic').from_file(path)
|
|
35
|
+
guess = "IDKm"
|
|
36
|
+
raise AttributeError(f"Unknown file type. failed to recognize the suffix `{suffix}`. According to libmagic1, the file seems to be: {guess}") from err
|
|
37
|
+
except ImportError as err2:
|
|
38
|
+
print(f"💥 Unknown file type. failed to recognize the suffix `{suffix}` of file {path} ")
|
|
39
|
+
raise ImportError(err) from err2
|
|
40
|
+
@staticmethod
|
|
41
|
+
def json(path: 'Path', r: bool = False, **kwargs: Any) -> Any: # return could be list or dict etc
|
|
42
|
+
import json
|
|
43
|
+
try:
|
|
44
|
+
mydict = json.loads(Path(path).read_text(encoding='utf-8'), **kwargs)
|
|
45
|
+
except Exception:
|
|
46
|
+
import pyjson5
|
|
47
|
+
mydict = pyjson5.loads(Path(path).read_text(encoding='utf-8'), **kwargs) # file has C-style comments.
|
|
48
|
+
_ = r
|
|
49
|
+
return mydict
|
|
50
|
+
@staticmethod
|
|
51
|
+
def yaml(path: 'Path', r: bool = False) -> Any: # return could be list or dict etc
|
|
52
|
+
import yaml # type: ignore
|
|
53
|
+
with open(str(path), "r", encoding="utf-8") as file:
|
|
54
|
+
mydict = yaml.load(file, Loader=yaml.FullLoader)
|
|
55
|
+
_ = r
|
|
56
|
+
return mydict
|
|
57
|
+
@staticmethod
|
|
58
|
+
def ini(path: 'Path', encoding: Optional[str] = None):
|
|
59
|
+
if not Path(path).exists() or Path(path).is_dir(): raise FileNotFoundError(f"File not found or is a directory: {path}")
|
|
60
|
+
import configparser
|
|
61
|
+
res = configparser.ConfigParser()
|
|
62
|
+
res.read(filenames=[str(path)], encoding=encoding)
|
|
63
|
+
return res
|
|
64
|
+
@staticmethod
|
|
65
|
+
def toml(path: 'Path'):
|
|
66
|
+
import toml
|
|
67
|
+
return toml.loads(Path(path).read_text(encoding='utf-8'))
|
|
68
|
+
@staticmethod
|
|
69
|
+
def npy(path: 'Path', **kwargs: Any):
|
|
70
|
+
import numpy as np
|
|
71
|
+
data = np.load(str(path), allow_pickle=True, **kwargs)
|
|
72
|
+
# data = data.item() if data.dtype == np.object else data
|
|
73
|
+
return data
|
|
74
|
+
@staticmethod
|
|
75
|
+
def pickle(path: 'Path', **kwargs: Any):
|
|
76
|
+
import pickle
|
|
77
|
+
try: return pickle.loads(Path(path).read_bytes(), **kwargs)
|
|
78
|
+
except BaseException as ex:
|
|
79
|
+
print(f"💥 Failed to load pickle file `{path}` with error:\n{ex}")
|
|
80
|
+
raise ex
|
|
81
|
+
@staticmethod
|
|
82
|
+
def pkl(path: 'Path', **kwargs: Any): return Read.pickle(path, **kwargs)
|
|
83
|
+
# @staticmethod
|
|
84
|
+
# def dill(path: 'Path', **kwargs: Any) -> Any:
|
|
85
|
+
# """handles imports automatically provided that saved object was from an imported class (not in defined in __main__)"""
|
|
86
|
+
# import dill
|
|
87
|
+
# obj = dill.loads(str=Path(path).read_bytes(), **kwargs)
|
|
88
|
+
# return obj
|
|
89
|
+
@staticmethod
|
|
90
|
+
def py(path: 'Path', init_globals: Optional[dict[str, Any]] = None, run_name: Optional[str] = None):
|
|
91
|
+
import runpy
|
|
92
|
+
return runpy.run_path(str(path), init_globals=init_globals, run_name=run_name)
|
|
93
|
+
@staticmethod
|
|
94
|
+
def txt(path: 'Path', encoding: str = 'utf-8') -> str: return Path(path).read_text(encoding=encoding)
|
|
95
|
+
@staticmethod
|
|
96
|
+
def parquet(path: 'Path', **kwargs: Any):
|
|
97
|
+
import polars as pl
|
|
98
|
+
return pl.read_parquet(path, **kwargs)
|
|
99
|
+
|
|
100
|
+
|
|
101
|
+
|
|
102
|
+
if __name__ == '__main__':
|
|
103
|
+
pass
|
|
@@ -125,12 +125,12 @@ def install_group(package_group: PACKAGE_GROUPS):
|
|
|
125
125
|
else:
|
|
126
126
|
options_system = get_installers_system_groups()
|
|
127
127
|
from machineconfig.utils.schemas.installer.installer_types import get_normalized_arch, get_os_name
|
|
128
|
-
from machineconfig.utils.code import
|
|
128
|
+
from machineconfig.utils.code import run_shell_script
|
|
129
129
|
for an_item in options_system:
|
|
130
130
|
if an_item["appName"] == package_group:
|
|
131
131
|
program = an_item["fileNamePattern"][get_normalized_arch()][get_os_name()]
|
|
132
132
|
if program is not None:
|
|
133
|
-
|
|
133
|
+
run_shell_script(program)
|
|
134
134
|
break
|
|
135
135
|
|
|
136
136
|
|
|
@@ -124,6 +124,13 @@ def check_tool_exists(tool_name: str) -> bool:
|
|
|
124
124
|
return any([Path("/usr/local/bin").joinpath(tool_name).is_file(), Path("/usr/bin").joinpath(tool_name).is_file(), root_path.joinpath(tool_name).is_file()])
|
|
125
125
|
else:
|
|
126
126
|
raise NotImplementedError(f"platform {platform.system()} not implemented")
|
|
127
|
+
def is_executable_in_path(executable_name: str) -> bool:
|
|
128
|
+
import os
|
|
129
|
+
path_dirs = os.environ['PATH'].split(os.pathsep)
|
|
130
|
+
for path_dir in path_dirs:
|
|
131
|
+
path_to_executable = os.path.join(path_dir, executable_name)
|
|
132
|
+
if os.path.isfile(path_to_executable) and os.access(path_to_executable, os.X_OK): return True
|
|
133
|
+
return False
|
|
127
134
|
|
|
128
135
|
|
|
129
136
|
def check_if_installed_already(exe_name: str, version: Optional[str], use_cache: bool) -> tuple[str, str, str]:
|
machineconfig/utils/options.py
CHANGED
|
@@ -6,31 +6,6 @@ from rich.console import Console
|
|
|
6
6
|
import subprocess
|
|
7
7
|
from typing import Optional, Union, Iterable, overload, Literal
|
|
8
8
|
|
|
9
|
-
|
|
10
|
-
# _ = cmd
|
|
11
|
-
# cmd = "where.exe"
|
|
12
|
-
# cmd = "which"
|
|
13
|
-
# try: # talking to terminal is too slow.
|
|
14
|
-
# _tmp = subprocess.check_output([cmd, tool_name], stderr=subprocess.DEVNULL)
|
|
15
|
-
# res: bool = True
|
|
16
|
-
# except (subprocess.CalledProcessError, FileNotFoundError):
|
|
17
|
-
# res = False
|
|
18
|
-
# return res
|
|
19
|
-
# return root_path.joinpath(tool_name).is_file()
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
# 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:
|
|
23
|
-
# 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)
|
|
24
|
-
# assert not isinstance(choice_key, list)
|
|
25
|
-
# return choice_key
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
# 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]:
|
|
29
|
-
# 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)
|
|
30
|
-
# if isinstance(choice_key, list):
|
|
31
|
-
# return choice_key
|
|
32
|
-
# return [choice_key]
|
|
33
|
-
|
|
34
9
|
@overload
|
|
35
10
|
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: ...
|
|
36
11
|
@overload
|
machineconfig/utils/terminal.py
CHANGED
|
@@ -147,7 +147,7 @@ class Terminal:
|
|
|
147
147
|
return os.getuid() == 0 # Check for root on Posix
|
|
148
148
|
'''
|
|
149
149
|
|
|
150
|
-
# def
|
|
150
|
+
# def run_shell_script(self, script: str, shell: SHELLS = "default", verbose: bool = False):
|
|
151
151
|
# if self.machine == "Linux":
|
|
152
152
|
# script = "#!/bin/bash" + "\n" + script # `source` is only available in bash.
|
|
153
153
|
# script_file = PathExtended.tmpfile(name="tmp_shell_script", suffix=".ps1" if self.machine == "Windows" else ".sh", folder="tmp_scripts")
|
|
@@ -143,8 +143,8 @@ machineconfig/scripts/python/cloud_mount.py,sha256=GwcXbd5ohoHGESfX5edtCEl2-umDD
|
|
|
143
143
|
machineconfig/scripts/python/cloud_repo_sync.py,sha256=8dnlHbQqRymPRU0v01pNIuaIvFeY4fReP7ewNSSCt34,9765
|
|
144
144
|
machineconfig/scripts/python/cloud_sync.py,sha256=RWGpAfJ9fnN18yNBSgN44dzA38Hmd4879JL5r2pcyrM,3514
|
|
145
145
|
machineconfig/scripts/python/count_lines.py,sha256=ZexMRsV70pe9fhLbGuens9EP5gCf078EwTDRHRZo5A0,15960
|
|
146
|
-
machineconfig/scripts/python/count_lines_frontend.py,sha256=
|
|
147
|
-
machineconfig/scripts/python/croshell.py,sha256=
|
|
146
|
+
machineconfig/scripts/python/count_lines_frontend.py,sha256=bIha5lKjWxKiO1OJAbt9gKzVyECXFbWKWIy69bdyaJg,533
|
|
147
|
+
machineconfig/scripts/python/croshell.py,sha256=zHUhOqWG81AOTeawZoDkpURnV1fAisY2lyZ0apvlmVY,6547
|
|
148
148
|
machineconfig/scripts/python/devops.py,sha256=JB4_M6S-nO3yqas8wtAlU2r6jsmHu_nlq7aoEOH-54Y,3486
|
|
149
149
|
machineconfig/scripts/python/devops_add_identity.py,sha256=wvjNgqsLmqD2SxbNCW_usqfp0LI-TDvcJJKGOWt2oFw,3775
|
|
150
150
|
machineconfig/scripts/python/devops_add_ssh_key.py,sha256=BXB-9RvuSZO0YTbnM2azeABW2ngLW4SKhhAGAieMzfw,6873
|
|
@@ -155,14 +155,14 @@ machineconfig/scripts/python/fire_agents_help_launch.py,sha256=1ymWiszfjCyPv3ofi
|
|
|
155
155
|
machineconfig/scripts/python/fire_agents_help_search.py,sha256=qIfSS_su2YJ1Gb0_lu4cbjlJlYMBw0v52NTGiSrGjk8,2991
|
|
156
156
|
machineconfig/scripts/python/fire_agents_helper_types.py,sha256=zKu8Vr6iucaGSkCm_Tkt_WrYU7-6Nript3coYyzTXzY,295
|
|
157
157
|
machineconfig/scripts/python/fire_agents_load_balancer.py,sha256=mpqx3uaQdBXYieuvhdK-qsvLepf9oIMo3pwPj9mSEDI,1079
|
|
158
|
-
machineconfig/scripts/python/fire_jobs.py,sha256=
|
|
158
|
+
machineconfig/scripts/python/fire_jobs.py,sha256=VIZZOjnE0u1g7U1jmYN3YUTFsLt8MM4_z67U951oEm4,15907
|
|
159
159
|
machineconfig/scripts/python/fire_jobs_args_helper.py,sha256=-gl5I-26Op12nToIpAA-YEpvn8MMkNlI5XjhUbj50I0,4273
|
|
160
160
|
machineconfig/scripts/python/fire_jobs_route_helper.py,sha256=EFWsg6F9TeSAtYQec57WtPopUbm2euGZTUZv6J4RhNE,3026
|
|
161
161
|
machineconfig/scripts/python/fire_jobs_streamlit_helper.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
162
162
|
machineconfig/scripts/python/ftpx.py,sha256=QfQTp-6jQP6yxfbLc5sKxiMtTgAgc8sjN7d17_uLiZc,9400
|
|
163
163
|
machineconfig/scripts/python/get_zellij_cmd.py,sha256=e35-18hoXM9N3PFbvbizfkNY_-63iMicieWE3TbGcCQ,576
|
|
164
164
|
machineconfig/scripts/python/gh_models.py,sha256=3BLfW25mBRiPO5VKtVm-nMlKLv-PaZDw7mObajq6F6M,5538
|
|
165
|
-
machineconfig/scripts/python/interactive.py,sha256=
|
|
165
|
+
machineconfig/scripts/python/interactive.py,sha256=gxAaVasW37TbSPswiyli-ImNQLU8jQbCb6Csnk5Igdg,11188
|
|
166
166
|
machineconfig/scripts/python/mount_nfs.py,sha256=aECrL64j9g-9rF49sVJAjGmzaoGgcMnl3g9v17kQF4c,3239
|
|
167
167
|
machineconfig/scripts/python/mount_nw_drive.py,sha256=iru6AtnTyvyuk6WxlK5R4lDkuliVpPV5_uBTVVhXtjQ,1550
|
|
168
168
|
machineconfig/scripts/python/mount_ssh.py,sha256=k2fKq3f5dKq_7anrFOlqvJoI_3U4EWNHLRZ1o3Lsy6M,2268
|
|
@@ -176,7 +176,7 @@ machineconfig/scripts/python/repos_helper_record.py,sha256=dtnnInQPn00u1cyr0oOgJ
|
|
|
176
176
|
machineconfig/scripts/python/repos_helper_update.py,sha256=AYyKIB7eQ48yoYmFjydIhRI1lV39TBv_S4_LCa-oKuQ,11042
|
|
177
177
|
machineconfig/scripts/python/scheduler.py,sha256=rKhssuxkD697EY6qaV6CSdNhxpAQLDWO4fE8GMCQ9FA,3061
|
|
178
178
|
machineconfig/scripts/python/sessions.py,sha256=e8gL0fVWOZ5WcJsA3ZWfqJBc5c7g-rMlVf0SF63rIaU,8547
|
|
179
|
-
machineconfig/scripts/python/share_terminal.py,sha256=
|
|
179
|
+
machineconfig/scripts/python/share_terminal.py,sha256=D9zwPZk4cV2ix5f-fHDfp0awtMsI5C5ANlfv1vW-VKE,5336
|
|
180
180
|
machineconfig/scripts/python/snapshot.py,sha256=aDvKeoniZaeTSNv9zWBUajaj2yagAxVdfuvO1_tgq5Y,1026
|
|
181
181
|
machineconfig/scripts/python/start_slidev.py,sha256=FAJ1_WkAQ7KcbRZ3cSN_72NDgV_flRrwxmXv1imyulI,4897
|
|
182
182
|
machineconfig/scripts/python/start_terminals.py,sha256=DRWbMZumhPmL0DvvsCsbRNFL5AVQn1SgaziafTio3YQ,6149
|
|
@@ -370,18 +370,18 @@ machineconfig/setup_windows/others/obs.ps1,sha256=2andchcXpxS3rqZjGaMpY5VShxTAKW
|
|
|
370
370
|
machineconfig/setup_windows/web_shortcuts/all.ps1,sha256=L03JJ4Jua_bzgtF3kuDOkuQ-Nqaj_ZcV3CFEkCHD1WI,908
|
|
371
371
|
machineconfig/setup_windows/web_shortcuts/ascii_art.ps1,sha256=pUVTtgKHOdgaK3hxz7JoMZzTyQ7vm2RfE_OJgB7e4cw,1270
|
|
372
372
|
machineconfig/setup_windows/web_shortcuts/croshell.ps1,sha256=cTQnegGLGYhuFY3YuuAj2ortN__adA2dznk2E737h4A,644
|
|
373
|
-
machineconfig/setup_windows/web_shortcuts/interactive.ps1,sha256
|
|
373
|
+
machineconfig/setup_windows/web_shortcuts/interactive.ps1,sha256=RMUq_GNf0FCD_o4g4BEbBRg098VOyUEh9ezL2rRNEOI,714
|
|
374
374
|
machineconfig/setup_windows/web_shortcuts/ssh.ps1,sha256=Tj9axEugJE7I3AQ0w1eUGLPb8ufME5jvU5S7VUjlLJE,424
|
|
375
375
|
machineconfig/setup_windows/wt_and_pwsh/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
376
376
|
machineconfig/setup_windows/wt_and_pwsh/set_wt_settings.py,sha256=ogxJnwpdcpH7N6dFJu95UCNoGYirZKQho_3X0F_hmXs,6791
|
|
377
377
|
machineconfig/utils/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
378
378
|
machineconfig/utils/accessories.py,sha256=W_9dLzjwNTW5JQk_pe3B2ijQ1nA2-8Kdg2r7VBtzgQs,4340
|
|
379
|
-
machineconfig/utils/code.py,sha256=
|
|
379
|
+
machineconfig/utils/code.py,sha256=Q44GVBgI5wEphGAKsMmXE2wEtzjJngy5pfJV9NCJ8EA,5652
|
|
380
380
|
machineconfig/utils/installer.py,sha256=xYM6tyctqLmr2lLXUKWgobTRufGIua31uspMXP4HGjY,9945
|
|
381
381
|
machineconfig/utils/io.py,sha256=ZXB3aataS1IZ_0WMcCRSmoN1nbkvEO-bWYcs-TpngqU,2872
|
|
382
382
|
machineconfig/utils/links.py,sha256=S0XICdbcFESUqm5RINDrOf3O8G1b7QEADncXXcC8IQc,15520
|
|
383
383
|
machineconfig/utils/notifications.py,sha256=vvdsY5IX6XEiILTnt5lNyHxhCi0ljdGX2T_67VRfrG4,9009
|
|
384
|
-
machineconfig/utils/options.py,sha256=
|
|
384
|
+
machineconfig/utils/options.py,sha256=vUO4Kej-vDOv64wHr2HNDyu6PATURpjd7xp6N8OOoJg,7083
|
|
385
385
|
machineconfig/utils/path_extended.py,sha256=Xjdn2AVnB8p1jfNMNe2kJutVa5zGnFFJVGZbw-Bp_hg,53200
|
|
386
386
|
machineconfig/utils/path_helper.py,sha256=0e3Xh3BAEv27oqcezNeVLHJllGmLEgLH4T1l90m-650,8014
|
|
387
387
|
machineconfig/utils/procs.py,sha256=Bm-yopmj19yiBO9tywJHEcs9rZmeRyJqbgTSe216LTU,11349
|
|
@@ -389,24 +389,27 @@ machineconfig/utils/scheduler.py,sha256=pOzpOowapfC6Fl_k82JbESmLS8eh-zk4FyjJyUX1
|
|
|
389
389
|
machineconfig/utils/scheduling.py,sha256=RF1iXJpqf4Dg18jdZWtBixz97KAHC6VKYqTFSpdLWuc,11188
|
|
390
390
|
machineconfig/utils/source_of_truth.py,sha256=GnjcVkKm11RyZFHGnPbne5YDEBYoZ5yryBNkpfGC7O4,854
|
|
391
391
|
machineconfig/utils/ssh.py,sha256=KTUp42nT4Vuh350_EvArQoR2N5iVXrc2BFld93fRUX4,20919
|
|
392
|
-
machineconfig/utils/terminal.py,sha256=
|
|
392
|
+
machineconfig/utils/terminal.py,sha256=IlmOByfQG-vjhaFFxxzU5rWzP5_qUzmalRfuey3PAmc,11801
|
|
393
393
|
machineconfig/utils/upgrade_packages.py,sha256=H96zVJEWXJW07nh5vhjuSCrPtXGqoUb7xeJsFYYdmCI,3330
|
|
394
394
|
machineconfig/utils/ve.py,sha256=L-6PBXnQGXThiwWgheJMQoisAZOZA6SVCbGw2J-GFnI,2414
|
|
395
395
|
machineconfig/utils/ai/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
396
396
|
machineconfig/utils/ai/generate_file_checklist.py,sha256=ajbmhcBToRugl75c_KZRq2XJumxKgIqQhyf7_YtF5q4,2729
|
|
397
397
|
machineconfig/utils/cloud/onedrive/setup_oauth.py,sha256=ZTVkqgrwbV_EoPvyT8dyOTUE0ur3BW4sa9o6QYtt5Bo,2341
|
|
398
398
|
machineconfig/utils/cloud/onedrive/transaction.py,sha256=m-aNcnWj_gfZVvJOSpkdIqjZxU_3nXx2CA-qKbQgP3I,26232
|
|
399
|
+
machineconfig/utils/files/ascii_art.py,sha256=cNJaJC07vx94fS44-tzgfbfBeCwXVrgpnWGBLUnfC38,5212
|
|
400
|
+
machineconfig/utils/files/headers.py,sha256=L54G11DfLadyZGyQXSQ7y8UI_tNvlld7zqP4qEAWL88,3647
|
|
401
|
+
machineconfig/utils/files/read.py,sha256=dyf-DDkLnCKgwmRH0Af4UtBIZh6iMUaYmjgJtdSGRFg,4744
|
|
399
402
|
machineconfig/utils/installer_utils/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
400
403
|
machineconfig/utils/installer_utils/github_release_bulk.py,sha256=WJf_qZlF02SmIc6C7o1h4Gy4gAaJAfeAS8O9s2Itj-k,6535
|
|
401
|
-
machineconfig/utils/installer_utils/installer.py,sha256=
|
|
402
|
-
machineconfig/utils/installer_utils/installer_abc.py,sha256=
|
|
404
|
+
machineconfig/utils/installer_utils/installer.py,sha256=H9wukQBSZDLlpB6Xn4Sa2hSV8iCUr9UQChcgOa3u-L8,9278
|
|
405
|
+
machineconfig/utils/installer_utils/installer_abc.py,sha256=VTHe5O3jA6k6rnUnXhgnEf6mVvkVQlEuXjzYLEDgEAs,11140
|
|
403
406
|
machineconfig/utils/installer_utils/installer_class.py,sha256=fN4Nfqn4tlSfQGW52A_Ipi6GT6utC30ZuSj5WM_yxIY,20252
|
|
404
407
|
machineconfig/utils/schemas/fire_agents/fire_agents_input.py,sha256=pTxvLzIpD5RF508lUUBBkWcc4V1B10J4ylvVgVGkcM0,2037
|
|
405
408
|
machineconfig/utils/schemas/installer/installer_types.py,sha256=QClRY61QaduBPJoSpdmTIdgS9LS-RvE-QZ-D260tD3o,1214
|
|
406
409
|
machineconfig/utils/schemas/layouts/layout_types.py,sha256=TcqlZdGVoH8htG5fHn1KWXhRdPueAcoyApppZsPAPto,2020
|
|
407
410
|
machineconfig/utils/schemas/repos/repos_types.py,sha256=ECVr-3IVIo8yjmYmVXX2mnDDN1SLSwvQIhx4KDDQHBQ,405
|
|
408
|
-
machineconfig-5.
|
|
409
|
-
machineconfig-5.
|
|
410
|
-
machineconfig-5.
|
|
411
|
-
machineconfig-5.
|
|
412
|
-
machineconfig-5.
|
|
411
|
+
machineconfig-5.15.dist-info/METADATA,sha256=8JyyiMszEzLFyVI_-3rScZA_eBYO8Jd8dPOj3FyGHjQ,8030
|
|
412
|
+
machineconfig-5.15.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
|
413
|
+
machineconfig-5.15.dist-info/entry_points.txt,sha256=2afE1mw-o4MUlfxyX73SV02XaQI4SV_LdL2r6_CzhPU,1074
|
|
414
|
+
machineconfig-5.15.dist-info/top_level.txt,sha256=porRtB8qms8fOIUJgK-tO83_FeH6Bpe12oUVC670teA,14
|
|
415
|
+
machineconfig-5.15.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|