machineconfig 7.64__py3-none-any.whl → 7.79__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of machineconfig might be problematic. Click here for more details.
- machineconfig/cluster/sessions_managers/utils/maker.py +4 -2
- machineconfig/jobs/installer/custom_dev/sysabc.py +26 -0
- machineconfig/jobs/installer/installer_data.json +70 -2
- machineconfig/profile/create_links_export.py +2 -2
- machineconfig/scripts/__init__.py +0 -4
- machineconfig/scripts/python/agents.py +22 -17
- machineconfig/scripts/python/ai/solutions/copilot/instructions/python/dev.instructions.md +3 -0
- machineconfig/scripts/python/croshell.py +22 -17
- machineconfig/scripts/python/devops.py +1 -1
- machineconfig/scripts/python/devops_navigator.py +0 -4
- machineconfig/scripts/python/env_manager/path_manager_tui.py +1 -1
- machineconfig/scripts/python/fire_jobs.py +13 -13
- machineconfig/scripts/python/ftpx.py +36 -12
- machineconfig/scripts/python/helpers/ast_search.py +74 -0
- machineconfig/scripts/python/helpers/qr_code.py +166 -0
- machineconfig/scripts/python/helpers/repo_rag.py +325 -0
- machineconfig/scripts/python/helpers/symantic_search.py +25 -0
- machineconfig/scripts/python/helpers_cloud/cloud_copy.py +28 -21
- machineconfig/scripts/python/helpers_cloud/cloud_helpers.py +1 -1
- machineconfig/scripts/python/helpers_cloud/cloud_mount.py +19 -17
- machineconfig/scripts/python/helpers_cloud/cloud_sync.py +8 -7
- machineconfig/scripts/python/helpers_croshell/start_slidev.py +6 -7
- machineconfig/scripts/python/helpers_devops/cli_nw.py +88 -7
- machineconfig/scripts/python/helpers_devops/cli_self.py +7 -6
- machineconfig/scripts/python/helpers_devops/cli_share_file.py +7 -7
- machineconfig/scripts/python/helpers_devops/cli_share_server.py +12 -11
- machineconfig/scripts/python/helpers_devops/cli_terminal.py +6 -5
- machineconfig/scripts/python/helpers_devops/cli_utils.py +2 -1
- machineconfig/scripts/python/helpers_devops/devops_status.py +7 -19
- machineconfig/scripts/python/helpers_fire_command/fire_jobs_route_helper.py +20 -9
- machineconfig/scripts/python/helpers_navigator/command_tree.py +50 -18
- machineconfig/scripts/python/helpers_repos/cloud_repo_sync.py +5 -3
- machineconfig/scripts/python/helpers_repos/count_lines_frontend.py +1 -1
- machineconfig/scripts/python/helpers_utils/download.py +4 -3
- machineconfig/scripts/python/helpers_utils/path.py +81 -31
- machineconfig/scripts/python/interactive.py +1 -1
- machineconfig/scripts/python/{machineconfig.py → mcfg_entry.py} +4 -0
- machineconfig/scripts/python/msearch.py +21 -2
- machineconfig/scripts/python/nw/address.py +132 -0
- machineconfig/scripts/python/nw/devops_add_ssh_key.py +8 -5
- machineconfig/scripts/python/terminal.py +2 -2
- machineconfig/scripts/python/utils.py +10 -9
- machineconfig/scripts/windows/mounts/mount_ssh.ps1 +1 -1
- machineconfig/settings/lf/windows/lfcd.ps1 +1 -1
- machineconfig/settings/shells/nushell/config.nu +2 -2
- machineconfig/settings/shells/nushell/env.nu +45 -6
- machineconfig/settings/shells/nushell/init.nu +282 -95
- machineconfig/settings/shells/pwsh/init.ps1 +1 -0
- machineconfig/setup_linux/web_shortcuts/interactive.sh +10 -10
- machineconfig/setup_windows/uv.ps1 +8 -1
- machineconfig/setup_windows/web_shortcuts/interactive.ps1 +10 -10
- machineconfig/setup_windows/web_shortcuts/quick_init.ps1 +3 -2
- machineconfig/utils/accessories.py +7 -4
- machineconfig/utils/code.py +4 -2
- machineconfig/utils/installer_utils/install_from_url.py +180 -0
- machineconfig/utils/installer_utils/installer_class.py +18 -10
- machineconfig/utils/installer_utils/installer_cli.py +14 -9
- machineconfig/utils/links.py +2 -2
- machineconfig/utils/meta.py +2 -2
- machineconfig/utils/options.py +3 -3
- machineconfig/utils/path_extended.py +1 -1
- machineconfig/utils/path_helper.py +0 -1
- machineconfig/utils/ssh.py +143 -409
- machineconfig/utils/ssh_utils/abc.py +8 -0
- machineconfig/utils/ssh_utils/copy_from_here.py +110 -0
- machineconfig/utils/ssh_utils/copy_to_here.py +302 -0
- machineconfig/utils/ssh_utils/utils.py +141 -0
- machineconfig/utils/ssh_utils/wsl.py +168 -0
- machineconfig/utils/upgrade_packages.py +2 -1
- machineconfig/utils/ve.py +11 -4
- {machineconfig-7.64.dist-info → machineconfig-7.79.dist-info}/METADATA +1 -1
- {machineconfig-7.64.dist-info → machineconfig-7.79.dist-info}/RECORD +77 -68
- {machineconfig-7.64.dist-info → machineconfig-7.79.dist-info}/entry_points.txt +2 -2
- machineconfig/scripts/python/explore.py +0 -49
- /machineconfig/{settings/shells/pwsh/profile.ps1 → scripts/python/helpers_fire_command/f.py} +0 -0
- /machineconfig/scripts/{Restore-ThunderbirdProfile.ps1 → windows/mounts/Restore-ThunderbirdProfile.ps1} +0 -0
- {machineconfig-7.64.dist-info → machineconfig-7.79.dist-info}/WHEEL +0 -0
- {machineconfig-7.64.dist-info → machineconfig-7.79.dist-info}/top_level.txt +0 -0
|
@@ -0,0 +1,180 @@
|
|
|
1
|
+
|
|
2
|
+
|
|
3
|
+
import platform
|
|
4
|
+
from urllib.parse import urlparse
|
|
5
|
+
|
|
6
|
+
import typer
|
|
7
|
+
from typing import Optional, TypeAlias, cast
|
|
8
|
+
|
|
9
|
+
from machineconfig.utils.installer_utils.installer_class import install_deb_package
|
|
10
|
+
from machineconfig.utils.installer_utils.installer_locator_utils import find_move_delete_linux, find_move_delete_windows
|
|
11
|
+
from machineconfig.utils.path_extended import DECOMPRESS_SUPPORTED_FORMATS, PathExtended
|
|
12
|
+
from machineconfig.utils.source_of_truth import INSTALL_TMP_DIR, INSTALL_VERSION_ROOT
|
|
13
|
+
|
|
14
|
+
SUPPORTED_GITHUB_HOSTS = {"github.com", "www.github.com"}
|
|
15
|
+
|
|
16
|
+
GitHubAsset: TypeAlias = dict[str, object]
|
|
17
|
+
GitHubRelease: TypeAlias = dict[str, object]
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
def _extract_repo_name(github_url: str) -> str:
|
|
21
|
+
parsed = urlparse(github_url)
|
|
22
|
+
parts = [part for part in parsed.path.strip("/").split("/") if part]
|
|
23
|
+
if len(parts) < 2:
|
|
24
|
+
return ""
|
|
25
|
+
owner, repo = parts[0], parts[1]
|
|
26
|
+
if repo == "":
|
|
27
|
+
return ""
|
|
28
|
+
return f"{owner}/{repo}"
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
def _fetch_latest_release(repo_name: str) -> Optional[GitHubRelease]:
|
|
32
|
+
import json
|
|
33
|
+
import requests
|
|
34
|
+
try:
|
|
35
|
+
response = requests.get(f"https://api.github.com/repos/{repo_name}/releases/latest", timeout=30)
|
|
36
|
+
except requests.RequestException:
|
|
37
|
+
return None
|
|
38
|
+
if response.status_code != 200:
|
|
39
|
+
return None
|
|
40
|
+
try:
|
|
41
|
+
data = response.json()
|
|
42
|
+
except json.JSONDecodeError:
|
|
43
|
+
return None
|
|
44
|
+
if not isinstance(data, dict):
|
|
45
|
+
return None
|
|
46
|
+
return cast(GitHubRelease, data)
|
|
47
|
+
|
|
48
|
+
|
|
49
|
+
def _format_size(size_bytes: int) -> str:
|
|
50
|
+
if size_bytes <= 0:
|
|
51
|
+
return "0 B"
|
|
52
|
+
units = ("B", "KiB", "MiB", "GiB", "TiB")
|
|
53
|
+
value = float(size_bytes)
|
|
54
|
+
index = 0
|
|
55
|
+
while value >= 1024 and index < len(units) - 1:
|
|
56
|
+
value /= 1024
|
|
57
|
+
index += 1
|
|
58
|
+
return f"{value:.1f} {units[index]}"
|
|
59
|
+
|
|
60
|
+
|
|
61
|
+
def _derive_tool_name(repo_name: str, asset_name: str) -> str:
|
|
62
|
+
repo_segment = repo_name.split("/", maxsplit=1)[-1]
|
|
63
|
+
repo_clean = repo_segment.replace(".git", "").lower()
|
|
64
|
+
repo_filtered = "".join(char for char in repo_clean if char.isalnum())
|
|
65
|
+
if repo_filtered:
|
|
66
|
+
return repo_filtered
|
|
67
|
+
asset_clean = asset_name.lower()
|
|
68
|
+
asset_filtered = "".join(char for char in asset_clean if char.isalnum())
|
|
69
|
+
if asset_filtered:
|
|
70
|
+
return asset_filtered
|
|
71
|
+
return "githubapp"
|
|
72
|
+
|
|
73
|
+
|
|
74
|
+
def install_from_github_url(github_url: str) -> None:
|
|
75
|
+
from machineconfig.utils.options import choose_from_options
|
|
76
|
+
from rich.console import Console
|
|
77
|
+
from rich.panel import Panel
|
|
78
|
+
|
|
79
|
+
console = Console()
|
|
80
|
+
repo_name = _extract_repo_name(github_url)
|
|
81
|
+
if repo_name == "":
|
|
82
|
+
console.print(Panel(f"Invalid GitHub URL: {github_url}", title="❌ Error", border_style="red"))
|
|
83
|
+
raise typer.Exit(1)
|
|
84
|
+
console.print(Panel(f"Fetching latest release for [green]{repo_name}[/green]", title="🌐 GitHub", border_style="blue"))
|
|
85
|
+
release_raw = _fetch_latest_release(repo_name)
|
|
86
|
+
if not release_raw:
|
|
87
|
+
console.print(Panel("No releases available for this repository.", title="❌ Error", border_style="red"))
|
|
88
|
+
raise typer.Exit(1)
|
|
89
|
+
release = release_raw
|
|
90
|
+
assets_value = release.get("assets", [])
|
|
91
|
+
assets: list[GitHubAsset] = []
|
|
92
|
+
if isinstance(assets_value, list):
|
|
93
|
+
for asset in assets_value:
|
|
94
|
+
if isinstance(asset, dict):
|
|
95
|
+
typed_asset: GitHubAsset = {}
|
|
96
|
+
name_value = asset.get("name")
|
|
97
|
+
url_value = asset.get("browser_download_url")
|
|
98
|
+
size_value = asset.get("size")
|
|
99
|
+
content_value = asset.get("content_type")
|
|
100
|
+
if isinstance(name_value, str):
|
|
101
|
+
typed_asset["name"] = name_value
|
|
102
|
+
if isinstance(url_value, str):
|
|
103
|
+
typed_asset["browser_download_url"] = url_value
|
|
104
|
+
if isinstance(size_value, int):
|
|
105
|
+
typed_asset["size"] = size_value
|
|
106
|
+
if isinstance(content_value, str):
|
|
107
|
+
typed_asset["content_type"] = content_value
|
|
108
|
+
assets.append(typed_asset)
|
|
109
|
+
if not assets:
|
|
110
|
+
console.print(Panel("No downloadable assets found in the latest release.", title="❌ Error", border_style="red"))
|
|
111
|
+
raise typer.Exit(1)
|
|
112
|
+
binary_assets = assets
|
|
113
|
+
selection_pool = binary_assets if binary_assets else assets
|
|
114
|
+
if not selection_pool:
|
|
115
|
+
console.print(Panel("No assets available for installation.", title="❌ Error", border_style="red"))
|
|
116
|
+
raise typer.Exit(1)
|
|
117
|
+
options_map: dict[str, GitHubAsset] = {}
|
|
118
|
+
for asset in selection_pool:
|
|
119
|
+
name = asset.get("name")
|
|
120
|
+
download_url = asset.get("browser_download_url")
|
|
121
|
+
if not isinstance(name, str) or not isinstance(download_url, str) or name == "" or download_url == "":
|
|
122
|
+
continue
|
|
123
|
+
size_value = asset.get("size")
|
|
124
|
+
size = size_value if isinstance(size_value, int) else 0
|
|
125
|
+
label = f"{name} [{_format_size(size)}]"
|
|
126
|
+
options_map[label] = asset
|
|
127
|
+
if not options_map:
|
|
128
|
+
console.print(Panel("Release assets lack download URLs.", title="❌ Error", border_style="red"))
|
|
129
|
+
raise typer.Exit(1)
|
|
130
|
+
selection_label = choose_from_options(options=list(options_map.keys()), msg="Select a release asset", multi=False, header="📦 GitHub Release Assets", fzf=True)
|
|
131
|
+
selected_asset = options_map[selection_label]
|
|
132
|
+
download_url_value = selected_asset.get("browser_download_url")
|
|
133
|
+
asset_name_value = selected_asset.get("name")
|
|
134
|
+
if not isinstance(download_url_value, str) or download_url_value == "":
|
|
135
|
+
console.print(Panel("Selected asset lacks a download URL.", title="❌ Error", border_style="red"))
|
|
136
|
+
raise typer.Exit(1)
|
|
137
|
+
asset_name = asset_name_value if isinstance(asset_name_value, str) else "github_binary"
|
|
138
|
+
version_value = release.get("tag_name")
|
|
139
|
+
version = version_value if isinstance(version_value, str) and version_value != "" else "latest"
|
|
140
|
+
console.print(Panel(f"Downloading [cyan]{asset_name}[/cyan]", title="⬇️ Download", border_style="magenta"))
|
|
141
|
+
archive_path = PathExtended(download_url_value).download(folder=INSTALL_TMP_DIR)
|
|
142
|
+
extracted_path = archive_path
|
|
143
|
+
if extracted_path.suffix in DECOMPRESS_SUPPORTED_FORMATS:
|
|
144
|
+
extracted_path = archive_path.decompress()
|
|
145
|
+
archive_path.delete(sure=True)
|
|
146
|
+
if extracted_path.is_dir():
|
|
147
|
+
nested_items = list(extracted_path.glob("*"))
|
|
148
|
+
if len(nested_items) == 1:
|
|
149
|
+
nested_path = PathExtended(nested_items[0])
|
|
150
|
+
if nested_path.suffix in DECOMPRESS_SUPPORTED_FORMATS:
|
|
151
|
+
extracted_path = nested_path.decompress()
|
|
152
|
+
nested_path.delete(sure=True)
|
|
153
|
+
if extracted_path.suffix == ".deb":
|
|
154
|
+
install_deb_package(extracted_path)
|
|
155
|
+
tool_name_deb = _derive_tool_name(repo_name, asset_name)
|
|
156
|
+
INSTALL_VERSION_ROOT.joinpath(tool_name_deb).parent.mkdir(parents=True, exist_ok=True)
|
|
157
|
+
INSTALL_VERSION_ROOT.joinpath(tool_name_deb).write_text(version, encoding="utf-8")
|
|
158
|
+
console.print(Panel(f"Installed Debian package for [green]{tool_name_deb}[/green]", title="✅ Complete", border_style="green"))
|
|
159
|
+
return
|
|
160
|
+
system_name = platform.system()
|
|
161
|
+
tool_name = _derive_tool_name(repo_name, asset_name)
|
|
162
|
+
rename_target = f"{tool_name}.exe" if system_name == "Windows" else tool_name
|
|
163
|
+
try:
|
|
164
|
+
if system_name == "Windows":
|
|
165
|
+
installed_path = find_move_delete_windows(downloaded_file_path=extracted_path, exe_name=tool_name, delete=True, rename_to=rename_target)
|
|
166
|
+
elif system_name in {"Linux", "Darwin"}:
|
|
167
|
+
installed_path = find_move_delete_linux(downloaded=extracted_path, tool_name=tool_name, delete=True, rename_to=rename_target)
|
|
168
|
+
else:
|
|
169
|
+
console.print(Panel(f"Unsupported operating system: {system_name}", title="❌ Error", border_style="red"))
|
|
170
|
+
raise typer.Exit(1)
|
|
171
|
+
except IndexError:
|
|
172
|
+
if system_name == "Windows":
|
|
173
|
+
installed_path = find_move_delete_windows(downloaded_file_path=extracted_path, exe_name=None, delete=True, rename_to=rename_target)
|
|
174
|
+
elif system_name in {"Linux", "Darwin"}:
|
|
175
|
+
installed_path = find_move_delete_linux(downloaded=extracted_path, tool_name="", delete=True, rename_to=rename_target)
|
|
176
|
+
else:
|
|
177
|
+
raise
|
|
178
|
+
INSTALL_VERSION_ROOT.joinpath(tool_name).parent.mkdir(parents=True, exist_ok=True)
|
|
179
|
+
INSTALL_VERSION_ROOT.joinpath(tool_name).write_text(version, encoding="utf-8")
|
|
180
|
+
console.print(Panel(f"Installed [green]{tool_name}[/green] to {installed_path}\nVersion: {version}", title="✅ Complete", border_style="green"))
|
|
@@ -12,18 +12,22 @@ from urllib.parse import urlparse
|
|
|
12
12
|
|
|
13
13
|
|
|
14
14
|
def install_deb_package(downloaded: PathExtended) -> None:
|
|
15
|
+
from rich import print as rprint
|
|
16
|
+
from rich.panel import Panel
|
|
15
17
|
print(f"📦 Installing .deb package: {downloaded}")
|
|
16
18
|
assert platform.system() == "Linux"
|
|
17
19
|
result = subprocess.run(f"sudo nala install -y {downloaded}", shell=True, capture_output=True, text=True)
|
|
18
20
|
success = result.returncode == 0 and result.stderr == ""
|
|
19
21
|
if not success:
|
|
22
|
+
from rich.console import Group
|
|
20
23
|
desc = "Installing .deb"
|
|
21
|
-
|
|
24
|
+
sub_panels = []
|
|
22
25
|
if result.stdout:
|
|
23
|
-
|
|
26
|
+
sub_panels.append(Panel(result.stdout, title="STDOUT", style="blue"))
|
|
24
27
|
if result.stderr:
|
|
25
|
-
|
|
26
|
-
|
|
28
|
+
sub_panels.append(Panel(result.stderr, title="STDERR", style="red"))
|
|
29
|
+
group_content = Group(f"❌ {desc} failed\nReturn code: {result.returncode}", *sub_panels)
|
|
30
|
+
rprint(Panel(group_content, title=desc, style="red"))
|
|
27
31
|
print("🗑️ Cleaning up .deb package...")
|
|
28
32
|
downloaded.delete(sure=True)
|
|
29
33
|
|
|
@@ -79,19 +83,23 @@ class Installer:
|
|
|
79
83
|
version_to_be_installed: str = "unknown" # Initialize to ensure it's always bound
|
|
80
84
|
if repo_url == "CMD":
|
|
81
85
|
if any(pm in installer_arch_os for pm in ["npm ", "pip ", "winget ", "brew ", "curl "]):
|
|
86
|
+
from rich import print as rprint
|
|
87
|
+
from rich.panel import Panel
|
|
88
|
+
from rich.console import Group
|
|
82
89
|
package_manager = installer_arch_os.split(" ", maxsplit=1)[0]
|
|
83
90
|
print(f"📦 Using package manager: {installer_arch_os}")
|
|
84
91
|
desc = package_manager + " installation"
|
|
85
92
|
version_to_be_installed = package_manager + "Latest"
|
|
86
|
-
result = subprocess.run(installer_arch_os, shell=True, capture_output=
|
|
87
|
-
success = result.returncode == 0 and result.stderr == ""
|
|
93
|
+
result = subprocess.run(installer_arch_os, shell=True, capture_output=False, text=True)
|
|
94
|
+
success = result.returncode == 0 and result.stderr == ""
|
|
88
95
|
if not success:
|
|
89
|
-
|
|
96
|
+
sub_panels = []
|
|
90
97
|
if result.stdout:
|
|
91
|
-
|
|
98
|
+
sub_panels.append(Panel(result.stdout, title="STDOUT", style="blue"))
|
|
92
99
|
if result.stderr:
|
|
93
|
-
|
|
94
|
-
|
|
100
|
+
sub_panels.append(Panel(result.stderr, title="STDERR", style="red"))
|
|
101
|
+
group_content = Group(f"❌ {desc} failed\nReturn code: {result.returncode}", *sub_panels)
|
|
102
|
+
rprint(Panel(group_content, title=desc, style="red"))
|
|
95
103
|
elif installer_arch_os.endswith((".sh", ".py", ".ps1")):
|
|
96
104
|
import machineconfig.jobs.installer as module
|
|
97
105
|
from pathlib import Path
|
|
@@ -1,11 +1,13 @@
|
|
|
1
1
|
"""Devops Devapps Install"""
|
|
2
2
|
|
|
3
3
|
import typer
|
|
4
|
-
from typing import
|
|
4
|
+
from typing import Annotated, Optional
|
|
5
5
|
from machineconfig.jobs.installer.package_groups import PACKAGE_GROUP2NAMES
|
|
6
|
+
from machineconfig.utils.installer_utils.installer_class import Installer
|
|
6
7
|
|
|
7
8
|
|
|
8
|
-
|
|
9
|
+
|
|
10
|
+
def main_installer_cli(
|
|
9
11
|
which: Annotated[Optional[str], typer.Argument(..., help="Comma-separated list of program/groups names to install (if --group flag is set).")] = None,
|
|
10
12
|
group: Annotated[bool, typer.Option(..., "--group", "-g", help="Treat 'which' as a group name. A group is bundle of apps.")] = False,
|
|
11
13
|
interactive: Annotated[bool, typer.Option(..., "--interactive", "-i", help="Interactive selection of programs to install.")] = False,
|
|
@@ -142,17 +144,21 @@ def install_clis(clis_names: list[str]):
|
|
|
142
144
|
from machineconfig.utils.installer_utils.installer_runner import get_installers
|
|
143
145
|
from machineconfig.utils.installer_utils.installer_class import Installer
|
|
144
146
|
from rich.console import Console
|
|
147
|
+
all_installers = get_installers(os=get_os_name(), arch=get_normalized_arch(), which_cats=None)
|
|
145
148
|
total_messages: list[str] = []
|
|
146
|
-
for
|
|
147
|
-
|
|
149
|
+
for a_cli_name in clis_names:
|
|
150
|
+
if "github.com" in a_cli_name.lower():
|
|
151
|
+
from machineconfig.utils.installer_utils.install_from_url import install_from_github_url
|
|
152
|
+
install_from_github_url(github_url=a_cli_name)
|
|
153
|
+
continue
|
|
148
154
|
selected_installer = None
|
|
149
155
|
for installer in all_installers:
|
|
150
156
|
app_name = installer["appName"]
|
|
151
|
-
if app_name.lower() ==
|
|
157
|
+
if app_name.lower() == a_cli_name.lower():
|
|
152
158
|
selected_installer = installer
|
|
153
159
|
break
|
|
154
160
|
if selected_installer is None:
|
|
155
|
-
_handle_installer_not_found(
|
|
161
|
+
_handle_installer_not_found(a_cli_name, all_names=[inst["appName"] for inst in all_installers])
|
|
156
162
|
return None
|
|
157
163
|
message = Installer(selected_installer).install_robust(version=None) # finish the task
|
|
158
164
|
total_messages.append(message)
|
|
@@ -169,13 +175,12 @@ def install_if_missing(which: str):
|
|
|
169
175
|
print(f"✅ {which} is already installed.")
|
|
170
176
|
return
|
|
171
177
|
print(f"⏳ {which} not found. Installing...")
|
|
172
|
-
from machineconfig.utils.installer_utils.installer_cli import
|
|
173
|
-
|
|
178
|
+
from machineconfig.utils.installer_utils.installer_cli import main_installer_cli
|
|
179
|
+
main_installer_cli(which=which, interactive=False)
|
|
174
180
|
|
|
175
181
|
|
|
176
182
|
if __name__ == "__main__":
|
|
177
183
|
from machineconfig.utils.schemas.installer.installer_types import InstallerData
|
|
178
184
|
from machineconfig.utils.installer_utils.installer_class import Installer
|
|
179
|
-
|
|
180
185
|
_ = InstallerData, Installer
|
|
181
186
|
pass
|
machineconfig/utils/links.py
CHANGED
|
@@ -164,7 +164,7 @@ def symlink_map(config_file_default_path: PathExtended, self_managed_config_file
|
|
|
164
164
|
else:
|
|
165
165
|
# Files are different, use on_conflict strategy
|
|
166
166
|
import subprocess
|
|
167
|
-
command = f"""delta --side-by-side "{config_file_default_path}" "{self_managed_config_file_path}" """
|
|
167
|
+
command = f"""delta --paging never --side-by-side "{config_file_default_path}" "{self_managed_config_file_path}" """
|
|
168
168
|
try:
|
|
169
169
|
console.print(Panel(f"🆘 CONFLICT DETECTED | Showing diff between {config_file_default_path} and {self_managed_config_file_path}", title="Conflict Detected", expand=False))
|
|
170
170
|
subprocess.run(command, shell=True, check=True)
|
|
@@ -293,7 +293,7 @@ def copy_map(config_file_default_path: PathExtended, self_managed_config_file_pa
|
|
|
293
293
|
else:
|
|
294
294
|
# Files are different, use on_conflict strategy
|
|
295
295
|
import subprocess
|
|
296
|
-
command = f"""delta --side-by-side "{config_file_default_path}" "{self_managed_config_file_path}" """
|
|
296
|
+
command = f"""delta --paging never --side-by-side "{config_file_default_path}" "{self_managed_config_file_path}" """
|
|
297
297
|
try:
|
|
298
298
|
console.print(Panel(f"🆘 CONFLICT DETECTED | Showing diff between {config_file_default_path} and {self_managed_config_file_path}", title="Conflict Detected", expand=False))
|
|
299
299
|
subprocess.run(command, shell=True, check=True)
|
machineconfig/utils/meta.py
CHANGED
|
@@ -29,7 +29,8 @@ except (ImportError, ModuleNotFoundError) as ex:
|
|
|
29
29
|
return txt
|
|
30
30
|
|
|
31
31
|
|
|
32
|
-
def lambda_to_python_script(lmb: Callable[[], Any],
|
|
32
|
+
def lambda_to_python_script(lmb: Callable[[], Any],
|
|
33
|
+
in_global: bool, import_module: bool) -> str:
|
|
33
34
|
"""
|
|
34
35
|
caveats: always use keyword arguments in the lambda call for best results.
|
|
35
36
|
return statement not allowed in the wrapped function (otherwise it can be put in the global space)
|
|
@@ -250,7 +251,6 @@ if __name__ == "__main__":
|
|
|
250
251
|
import_code_robust = "<import_code_robust>"
|
|
251
252
|
res = lambda_to_python_script(
|
|
252
253
|
lambda: print_code(code=import_code_robust, lexer="python", desc="import as module code"),
|
|
253
|
-
# in_global=True, import_module=False
|
|
254
254
|
in_global=True, import_module=False
|
|
255
255
|
)
|
|
256
256
|
print(res)
|
machineconfig/utils/options.py
CHANGED
|
@@ -14,10 +14,10 @@ from typing import Optional, Union, Iterable, overload, Literal, cast
|
|
|
14
14
|
|
|
15
15
|
|
|
16
16
|
@overload
|
|
17
|
-
def choose_from_options[T](
|
|
17
|
+
def choose_from_options[T](options: Iterable[T], msg: str, multi: Literal[False], custom_input: bool = False, header: str = "", tail: str = "", prompt: str = "", default: Optional[T] = None, fzf: bool = False) -> T: ...
|
|
18
18
|
@overload
|
|
19
|
-
def choose_from_options[T](
|
|
20
|
-
def choose_from_options[T](
|
|
19
|
+
def choose_from_options[T](options: Iterable[T], msg: str, multi: Literal[True], custom_input: bool = True, header: str = "", tail: str = "", prompt: str = "", default: Optional[T] = None, fzf: bool = False, ) -> list[T]: ...
|
|
20
|
+
def choose_from_options[T](options: Iterable[T], msg: str, multi: bool, custom_input: bool = True, header: str = "", tail: str = "", prompt: str = "", default: Optional[T] = None, fzf: bool = False, ) -> Union[T, list[T]]:
|
|
21
21
|
# TODO: replace with https://github.com/tmbo/questionary
|
|
22
22
|
# # also see https://github.com/charmbracelet/gum
|
|
23
23
|
options_strings: list[str] = [str(x) for x in options]
|
|
@@ -711,7 +711,7 @@ class PathExtended(type(Path()), Path): # type: ignore # pylint: disable=E0241
|
|
|
711
711
|
:return: pathlib.Path pointing to the destination directory where contents were extracted
|
|
712
712
|
:raises: FileNotFoundError if archive does not exist; py7zr.Bad7zFile or other error if extraction fails
|
|
713
713
|
"""
|
|
714
|
-
import py7zr
|
|
714
|
+
import py7zr # type: ignore
|
|
715
715
|
import tempfile
|
|
716
716
|
from pathlib import Path
|
|
717
717
|
archive_path_obj = Path(archive_path)
|