machineconfig 8.51__py3-none-any.whl → 8.61__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.
- machineconfig/jobs/installer/python_scripts/sysabc.py +13 -34
- machineconfig/profile/mapper_dotfiles.toml +3 -3
- machineconfig/scripts/python/devops.py +1 -1
- machineconfig/scripts/python/devops_navigator.py +1 -1
- machineconfig/scripts/python/helper_env/path_manager_tui.py +1 -1
- machineconfig/scripts/python/helpers/helper_env/env_manager_tui.py +1 -1
- machineconfig/scripts/python/helpers/helper_env/path_manager_tui.py +1 -1
- machineconfig/scripts/python/helpers/helpers_croshell/croshell_impl.py +8 -4
- machineconfig/scripts/python/helpers/helpers_devops/cli_config.py +33 -1
- machineconfig/scripts/python/helpers/helpers_devops/cli_config_mount.py +77 -0
- machineconfig/scripts/python/helpers/helpers_devops/cli_data.py +4 -0
- machineconfig/scripts/python/helpers/helpers_devops/cli_nw.py +90 -6
- machineconfig/scripts/python/helpers/helpers_devops/cli_repos.py +3 -3
- machineconfig/scripts/python/helpers/helpers_devops/cli_self.py +41 -15
- machineconfig/scripts/python/helpers/helpers_devops/cli_share_temp.py +69 -0
- machineconfig/scripts/python/helpers/helpers_devops/cli_ssh.py +4 -4
- machineconfig/scripts/python/helpers/helpers_devops/mount_helpers/__init__.py +0 -0
- machineconfig/scripts/python/helpers/helpers_devops/mount_helpers/commands.py +25 -0
- machineconfig/scripts/python/helpers/helpers_devops/mount_helpers/device_entry.py +17 -0
- machineconfig/scripts/python/helpers/helpers_devops/mount_helpers/devices.py +17 -0
- machineconfig/scripts/python/helpers/helpers_devops/mount_helpers/linux.py +103 -0
- machineconfig/scripts/python/helpers/helpers_devops/mount_helpers/macos.py +100 -0
- machineconfig/scripts/python/helpers/helpers_devops/mount_helpers/selection.py +47 -0
- machineconfig/scripts/python/helpers/helpers_devops/mount_helpers/utils.py +28 -0
- machineconfig/scripts/python/helpers/helpers_devops/mount_helpers/windows.py +91 -0
- machineconfig/scripts/python/helpers/helpers_msearch/scripts_windows/fzfg.ps1 +1 -6
- machineconfig/scripts/python/helpers/helpers_network/ssh/__init__.py +0 -0
- machineconfig/scripts/python/helpers/helpers_network/ssh/ssh_add_key_windows.py +23 -0
- machineconfig/scripts/python/helpers/helpers_network/{ssh_add_ssh_key.py → ssh/ssh_add_ssh_key.py} +21 -27
- machineconfig/scripts/python/helpers/helpers_network/ssh/ssh_cloud_init.py +33 -0
- machineconfig/scripts/python/helpers/helpers_network/{ssh_debug_linux.py → ssh/ssh_debug_linux.py} +70 -51
- machineconfig/scripts/python/helpers/helpers_network/ssh/ssh_debug_linux_utils.py +35 -0
- machineconfig/scripts/python/helpers/helpers_network/{ssh_debug_windows.py → ssh/ssh_debug_windows.py} +12 -42
- machineconfig/scripts/python/helpers/helpers_network/ssh/ssh_debug_windows_utils.py +34 -0
- machineconfig/scripts/python/helpers/helpers_repos/cloud_repo_sync.py +2 -3
- machineconfig/scripts/python/helpers/{helpers_terminal/terminal_impl.py → helpers_sessions/attach_impl.py} +16 -25
- machineconfig/scripts/python/helpers/helpers_sessions/sessions_impl.py +57 -129
- machineconfig/scripts/python/helpers/helpers_sessions/utils.py +69 -0
- machineconfig/scripts/python/mcfg_entry.py +0 -7
- machineconfig/scripts/python/sessions.py +95 -14
- machineconfig/scripts/python/utils.py +3 -2
- machineconfig/settings/shells/bash/init.sh +0 -7
- machineconfig/settings/shells/pwsh/init.ps1 +2 -4
- machineconfig/settings/shells/wezterm/wezterm.lua +1 -0
- machineconfig/settings/shells/wt/settings.json +13 -19
- machineconfig/settings/shells/zsh/init.sh +0 -1
- machineconfig/settings/zellij/__init__.py +0 -0
- machineconfig/settings/zellij/config.kdl +0 -295
- machineconfig/settings/zellij/layouts/__init__.py +0 -0
- machineconfig/settings/zellij/layouts/st.kdl +0 -1
- machineconfig/settings/zellij/layouts/st2.kdl +6 -2
- machineconfig/setup_linux/web_shortcuts/interactive.sh +10 -10
- machineconfig/setup_windows/web_shortcuts/interactive.ps1 +10 -10
- machineconfig/utils/installer_utils/installer_cli.py +6 -2
- machineconfig/utils/installer_utils/installer_helper.py +50 -34
- machineconfig/utils/installer_utils/installer_locator_utils.py +3 -13
- machineconfig/utils/options_utils/tv_options.py +1 -1
- machineconfig/utils/procs.py +35 -27
- machineconfig/utils/schemas/layouts/layout_types.py +10 -0
- machineconfig/utils/source_of_truth.py +1 -0
- machineconfig/utils/ssh_utils/abc.py +1 -1
- {machineconfig-8.51.dist-info → machineconfig-8.61.dist-info}/METADATA +2 -3
- {machineconfig-8.51.dist-info → machineconfig-8.61.dist-info}/RECORD +68 -72
- {machineconfig-8.51.dist-info → machineconfig-8.61.dist-info}/entry_points.txt +0 -1
- machineconfig/jobs/scripts/bash_scripts/android.sh +0 -2
- machineconfig/jobs/scripts/bash_scripts/mount_drive +0 -128
- machineconfig/jobs/scripts/bash_scripts/mount_nfs +0 -49
- machineconfig/jobs/scripts/bash_scripts/mount_nw_drive +0 -61
- machineconfig/jobs/scripts/bash_scripts/mount_smb +0 -3
- machineconfig/jobs/scripts/bash_scripts/share_cloud.sh +0 -64
- machineconfig/jobs/scripts/bash_scripts/share_nfs +0 -49
- machineconfig/jobs/scripts/bash_scripts/start_docker +0 -23
- machineconfig/jobs/scripts/powershell_scripts/Restore-ThunderbirdProfile.ps1 +0 -92
- machineconfig/jobs/scripts/powershell_scripts/docker.ps1 +0 -7
- machineconfig/jobs/scripts/powershell_scripts/mount_nfs.ps1 +0 -42
- machineconfig/jobs/scripts/powershell_scripts/mount_nw.ps1 +0 -9
- machineconfig/jobs/scripts/powershell_scripts/mount_smb.ps1 +0 -2
- machineconfig/jobs/scripts/powershell_scripts/mount_ssh.ps1 +0 -13
- machineconfig/jobs/scripts/powershell_scripts/obs.ps1 +0 -4
- machineconfig/jobs/scripts/powershell_scripts/power_options.ps1 +0 -7
- machineconfig/jobs/scripts/powershell_scripts/share_cloud.cmd +0 -34
- machineconfig/jobs/scripts/powershell_scripts/share_smb.ps1 +0 -16
- machineconfig/scripts/python/helpers/helpers_network/mount_nfs.py +0 -85
- machineconfig/scripts/python/helpers/helpers_network/mount_nw_drive.py +0 -48
- machineconfig/scripts/python/helpers/helpers_network/mount_ssh.py +0 -64
- machineconfig/scripts/python/terminal.py +0 -58
- machineconfig/settings/zellij/config.orig.kdl +0 -295
- /machineconfig/{scripts/python/helpers/helpers_terminal → cluster/sessions_managers/wt_utils/examples}/__init__.py +0 -0
- /machineconfig/scripts/python/helpers/helpers_network/{ssh_add_identity.py → ssh/ssh_add_identity.py} +0 -0
- {machineconfig-8.51.dist-info → machineconfig-8.61.dist-info}/WHEEL +0 -0
- {machineconfig-8.51.dist-info → machineconfig-8.61.dist-info}/top_level.txt +0 -0
|
@@ -56,52 +56,31 @@ echo "🔄 Updating Homebrew..."
|
|
|
56
56
|
brew update || true
|
|
57
57
|
|
|
58
58
|
curl -fsSL https://bun.com/install | bash
|
|
59
|
-
|
|
60
|
-
# Note: git and nano are pre-installed on macOS, but we install via Homebrew to ensure latest versions
|
|
61
|
-
# brew install git || true
|
|
62
|
-
# brew install nano || true
|
|
63
|
-
# brew install curl || true
|
|
64
|
-
# nvm install node || true
|
|
65
|
-
# brew install make
|
|
66
|
-
# brew install ffmpeg
|
|
67
|
-
# brew install openssl
|
|
68
|
-
|
|
69
|
-
|
|
59
|
+
# brew install openssl ffmpeg make curl nano git
|
|
70
60
|
echo "✅ Essential tools installation complete."
|
|
71
61
|
"""
|
|
72
62
|
|
|
73
63
|
bash = r"""
|
|
64
|
+
|
|
74
65
|
sudo apt update -y || true
|
|
75
66
|
sudo apt install nala -y || true
|
|
76
|
-
sudo nala install curl wget gpg lsb-release apt-transport-https
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
#
|
|
80
|
-
#
|
|
67
|
+
sudo nala install curl wget gpg lsb-release apt-transport-https \
|
|
68
|
+
samba fuse3 nfs-common \
|
|
69
|
+
git net-tools htop nano \
|
|
70
|
+
build-essential \ # Where it brings gcc, make, etc.,
|
|
71
|
+
python3-dev \ # ensures headers for your Python version.
|
|
72
|
+
unzip \ # bun installer needs this to unzip files.
|
|
73
|
+
pkg-config \
|
|
74
|
+
libssl-dev \ # essential for SSL/TLS support in many applications, compiling rust binaries will need them.
|
|
75
|
+
-y || true
|
|
81
76
|
|
|
82
|
-
# curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.40.3/install.sh | bash
|
|
83
|
-
# source ~/.bashrc || true
|
|
84
|
-
# nvm install node || true
|
|
85
|
-
|
|
86
|
-
sudo nala install unzip -y # required by bun installer
|
|
87
77
|
curl -fsSL https://bun.com/install | bash
|
|
88
78
|
. ~/.bashrc || true
|
|
89
|
-
|
|
90
|
-
sudo ln -s ~/.bun/bin/bun /usr/local/bin/node
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
sudo nala install samba -y || true
|
|
94
|
-
sudo nala install fuse3 -y || true
|
|
95
|
-
sudo nala install nfs-common -y || true
|
|
79
|
+
sudo ln -s ~/.bun/bin/bun /usr/local/bin/node # trick programs that expect node to use bun runtime.
|
|
96
80
|
|
|
97
81
|
# echo 'keyboard-configuration keyboard-configuration/layout select US English' | sudo debconf-set-selections
|
|
98
82
|
# echo 'keyboard-configuration keyboard-configuration/layoutcode string us' | sudo debconf-set-selections
|
|
99
|
-
# sudo DEBIAN_FRONTEND=noninteractive nala install -y
|
|
100
|
-
# sudo nala install hollywood -y || true
|
|
101
|
-
|
|
102
|
-
# sudo nala install ffmpeg -y || true # Required by some dev tools
|
|
103
|
-
# sudo nala install make -y || true # Required by LunarVim and SpaceVim
|
|
104
|
-
# (curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh) || true
|
|
83
|
+
# sudo DEBIAN_FRONTEND=noninteractive nala install cmatrix hollywood ffmpeg -y make || true
|
|
105
84
|
|
|
106
85
|
"""
|
|
107
86
|
|
|
@@ -207,9 +207,9 @@ config = {original = '~/mprocs.yaml', self_managed = 'CONFIG_ROOT/settings/mproc
|
|
|
207
207
|
|
|
208
208
|
|
|
209
209
|
[zellij_linux]
|
|
210
|
-
config = { original = '~/.config/zellij', self_managed = 'CONFIG_ROOT/settings/zellij'
|
|
211
|
-
|
|
212
|
-
|
|
210
|
+
config = { original = '~/.config/zellij', self_managed = 'CONFIG_ROOT/settings/zellij', os = 'linux,darwin'}
|
|
211
|
+
themes = { original = '~/.config/zellij/themes', self_managed = 'CONFIG_ROOT/settings/zellij/themes', os = 'linux,darwin' }
|
|
212
|
+
layouts = { original = '~/.config/zellij/layouts', self_managed = 'CONFIG_ROOT/settings/zellij/layouts', os = 'linux,darwin' }
|
|
213
213
|
|
|
214
214
|
|
|
215
215
|
# ===================== IDEs ============================
|
|
@@ -60,7 +60,7 @@ def get_app() -> typer.Typer:
|
|
|
60
60
|
cli_app = typer.Typer(help="🛠️ DevOps operations", no_args_is_help=True, add_help_option=True, add_completion=False)
|
|
61
61
|
ctx_settings: dict[str, object] = {"allow_extra_args": True, "allow_interspersed_args": True, "ignore_unknown_options": True, "help_option_names": []}
|
|
62
62
|
|
|
63
|
-
cli_app.command("install", no_args_is_help=True, help=install.__doc__, short_help="🛠️
|
|
63
|
+
cli_app.command("install", no_args_is_help=True, help=install.__doc__, short_help="🛠️ [i] Install essential packages")(install)
|
|
64
64
|
cli_app.command("i", no_args_is_help=True, help=install.__doc__, hidden=True)(install)
|
|
65
65
|
|
|
66
66
|
cli_app.command("repos", help="📁 [r] Manage development repositories", context_settings=ctx_settings)(repos)
|
|
@@ -24,12 +24,16 @@ def croshell(
|
|
|
24
24
|
user_uv_with_line = f"--with {uv_with},ipython"
|
|
25
25
|
case "python":
|
|
26
26
|
user_uv_with_line = f"--with {uv_with}"
|
|
27
|
+
case _:
|
|
28
|
+
raise ValueError(f"Unknown interpreter: {interpreter}")
|
|
27
29
|
else:
|
|
28
30
|
match interpreter:
|
|
29
31
|
case "ipython":
|
|
30
32
|
user_uv_with_line = "--with ipython"
|
|
31
33
|
case "python":
|
|
32
34
|
user_uv_with_line = ""
|
|
35
|
+
case _:
|
|
36
|
+
raise ValueError(f"Unknown interpreter: {interpreter}")
|
|
33
37
|
|
|
34
38
|
if project_path is not None:
|
|
35
39
|
uv_project_line = f'--project {project_path}'
|
|
@@ -188,7 +192,7 @@ def _build_fire_line(
|
|
|
188
192
|
if Path.home().joinpath("code/machineconfig").exists():
|
|
189
193
|
requirements = f"""{user_uv_with_line} {uv_project_line} --with marimo,sqlglot """
|
|
190
194
|
else:
|
|
191
|
-
requirements = f"""{uv_python_line} {user_uv_with_line} {uv_project_line} --with "marimo,sqlglot,cowsay,machineconfig[plot]>=8.
|
|
195
|
+
requirements = f"""{uv_python_line} {user_uv_with_line} {uv_project_line} --with "marimo,sqlglot,cowsay,machineconfig[plot]>=8.61" """
|
|
192
196
|
fire_line = f"""
|
|
193
197
|
cd {str(pyfile.parent)}
|
|
194
198
|
uv run {uv_python_line} --with "marimo" marimo convert {pyfile.name} -o marimo_nb.py
|
|
@@ -198,7 +202,7 @@ uv run {requirements} marimo edit --host 0.0.0.0 marimo_nb.py
|
|
|
198
202
|
if Path.home().joinpath("code/machineconfig").exists():
|
|
199
203
|
requirements = f"""{user_uv_with_line} {uv_project_line} --with jupyterlab """
|
|
200
204
|
else:
|
|
201
|
-
requirements = f"""{user_uv_with_line} {uv_project_line} --with "cowsay,machineconfig[plot]>=8.
|
|
205
|
+
requirements = f"""{user_uv_with_line} {uv_project_line} --with "cowsay,machineconfig[plot]>=8.61" """
|
|
202
206
|
fire_line = f"uv run {requirements} {uv_project_line} jupyter-lab {str(nb_target)}"
|
|
203
207
|
elif vscode:
|
|
204
208
|
user_uv_add = f"uv add {uv_with}" if uv_with is not None else ""
|
|
@@ -206,7 +210,7 @@ uv run {requirements} marimo edit --host 0.0.0.0 marimo_nb.py
|
|
|
206
210
|
cd {str(pyfile.parent)}
|
|
207
211
|
uv init {uv_python_line}
|
|
208
212
|
uv venv
|
|
209
|
-
uv add "cowsay,machineconfig[plot]>=8.
|
|
213
|
+
uv add "cowsay,machineconfig[plot]>=8.61"
|
|
210
214
|
uv add {user_uv_add}
|
|
211
215
|
# code serve-web
|
|
212
216
|
code --new-window {str(pyfile)}
|
|
@@ -219,7 +223,7 @@ code --new-window {str(pyfile)}
|
|
|
219
223
|
if Path.home().joinpath("code/machineconfig").exists():
|
|
220
224
|
ve_line = f"""{user_uv_with_line} {uv_project_line} """
|
|
221
225
|
else:
|
|
222
|
-
ve_line = f"""{uv_python_line} {user_uv_with_line} {uv_project_line} --with "cowsay,machineconfig[plot]>=8.
|
|
226
|
+
ve_line = f"""{uv_python_line} {user_uv_with_line} {uv_project_line} --with "cowsay,machineconfig[plot]>=8.61" """
|
|
223
227
|
fire_line = f"uv run {ve_line} {interpreter} {interactivity} {profile} {str(pyfile)}"
|
|
224
228
|
|
|
225
229
|
return fire_line
|
|
@@ -25,7 +25,11 @@ def configure_shell_profile(which: Annotated[Literal["default", "d", "nushell",
|
|
|
25
25
|
def pwsh_theme():
|
|
26
26
|
"""🔗 Select powershell prompt theme."""
|
|
27
27
|
import machineconfig.scripts.python.helpers.helpers_devops.themes as themes
|
|
28
|
-
|
|
28
|
+
file_path = themes.__file__
|
|
29
|
+
# if file_path is None:
|
|
30
|
+
# typer.echo("❌ ERROR: Could not locate themes module file.", err=True)
|
|
31
|
+
# raise typer.Exit(code=1)
|
|
32
|
+
file = Path(file_path).parent / "choose_pwsh_theme.ps1"
|
|
29
33
|
import subprocess
|
|
30
34
|
subprocess.run(["pwsh", "-File", str(file)])
|
|
31
35
|
|
|
@@ -71,6 +75,29 @@ def copy_assets(which: Annotated[Literal["scripts", "s", "settings", "t", "both"
|
|
|
71
75
|
typer.echo(msg)
|
|
72
76
|
|
|
73
77
|
|
|
78
|
+
def list_devices() -> None:
|
|
79
|
+
"""🔗 List available mountable devices."""
|
|
80
|
+
import machineconfig.scripts.python.helpers.helpers_devops.cli_config_mount as mount_module
|
|
81
|
+
mount_module.list_devices()
|
|
82
|
+
|
|
83
|
+
|
|
84
|
+
def mount_device(
|
|
85
|
+
device_query: Annotated[str | None, typer.Option("--device", "-d", help="Device query (path, key, or label).")] = None,
|
|
86
|
+
mount_point: Annotated[str | None, typer.Option("--mount-point", "-p", help="Mount point (use '-' for default on macOS).")] = None,
|
|
87
|
+
interactive: Annotated[bool, typer.Option("--interactive", "-i", help="Pick device and mount point interactively.")] = False,
|
|
88
|
+
) -> None:
|
|
89
|
+
"""🔗 Mount a device to a mount point."""
|
|
90
|
+
import machineconfig.scripts.python.helpers.helpers_devops.cli_config_mount as mount_module
|
|
91
|
+
if interactive:
|
|
92
|
+
mount_module.mount_interactive()
|
|
93
|
+
return
|
|
94
|
+
if device_query is None or mount_point is None:
|
|
95
|
+
msg = typer.style("Error: ", fg=typer.colors.RED) + "--device and --mount-point are required unless --interactive is set"
|
|
96
|
+
typer.echo(msg)
|
|
97
|
+
raise typer.Exit(2)
|
|
98
|
+
mount_module.mount_device(device_query=device_query, mount_point=mount_point)
|
|
99
|
+
|
|
100
|
+
|
|
74
101
|
def get_app():
|
|
75
102
|
config_apps = typer.Typer(help="⚙️ [c] configuration subcommands", no_args_is_help=True, add_help_option=True, add_completion=False)
|
|
76
103
|
config_apps.command("sync", no_args_is_help=True, help="🔗 [s] Sync dotfiles.")(create_links_export.main_from_parser)
|
|
@@ -94,5 +121,10 @@ def get_app():
|
|
|
94
121
|
config_apps.command("copy-assets", no_args_is_help=True, help="🔗 [c] Copy asset files from library to machine.", hidden=False)(copy_assets)
|
|
95
122
|
config_apps.command("c", no_args_is_help=True, help="Copy asset files from library to machine.", hidden=True)(copy_assets)
|
|
96
123
|
|
|
124
|
+
config_apps.command("list-devices", no_args_is_help=False, help="🔗 [l] List available devices for mounting.")(list_devices)
|
|
125
|
+
config_apps.command("l", no_args_is_help=False, help="List available devices for mounting.", hidden=True)(list_devices)
|
|
126
|
+
config_apps.command("mount", no_args_is_help=True, help="🔗 [m] Mount a device to a mount point.")(mount_device)
|
|
127
|
+
config_apps.command("m", no_args_is_help=True, help="Mount a device to a mount point.", hidden=True)(mount_device)
|
|
128
|
+
|
|
97
129
|
|
|
98
130
|
return config_apps
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
|
|
2
|
+
import platform
|
|
3
|
+
from typing import Annotated
|
|
4
|
+
|
|
5
|
+
import typer
|
|
6
|
+
|
|
7
|
+
from machineconfig.scripts.python.helpers.helpers_devops.mount_helpers.devices import list_devices as list_devices_internal
|
|
8
|
+
from machineconfig.scripts.python.helpers.helpers_devops.mount_helpers.linux import mount_linux, select_linux_partition
|
|
9
|
+
from machineconfig.scripts.python.helpers.helpers_devops.mount_helpers.macos import mount_macos
|
|
10
|
+
from machineconfig.scripts.python.helpers.helpers_devops.mount_helpers.selection import pick_device, resolve_device
|
|
11
|
+
from machineconfig.scripts.python.helpers.helpers_devops.mount_helpers.utils import format_device
|
|
12
|
+
from machineconfig.scripts.python.helpers.helpers_devops.mount_helpers.windows import mount_windows
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
def list_devices() -> None:
|
|
16
|
+
entries = list_devices_internal()
|
|
17
|
+
if not entries:
|
|
18
|
+
typer.echo("No devices found")
|
|
19
|
+
return
|
|
20
|
+
for entry in entries:
|
|
21
|
+
typer.echo(format_device(entry))
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
def mount_device(
|
|
25
|
+
device_query: Annotated[str, typer.Argument(...)],
|
|
26
|
+
mount_point: Annotated[str, typer.Argument(...)],
|
|
27
|
+
) -> None:
|
|
28
|
+
try:
|
|
29
|
+
entries = list_devices_internal()
|
|
30
|
+
if not entries:
|
|
31
|
+
typer.echo("No devices found")
|
|
32
|
+
raise typer.Exit(1)
|
|
33
|
+
entry = resolve_device(entries, device_query)
|
|
34
|
+
platform_name = platform.system()
|
|
35
|
+
if platform_name == "Linux":
|
|
36
|
+
selected = select_linux_partition(entries, entry)
|
|
37
|
+
mount_linux(selected, mount_point)
|
|
38
|
+
elif platform_name == "Darwin":
|
|
39
|
+
mount_macos(entry, mount_point)
|
|
40
|
+
elif platform_name == "Windows":
|
|
41
|
+
mount_windows(entry, mount_point)
|
|
42
|
+
else:
|
|
43
|
+
typer.echo(f"Unsupported platform: {platform_name}")
|
|
44
|
+
raise typer.Exit(1)
|
|
45
|
+
typer.echo("Mount completed")
|
|
46
|
+
except RuntimeError as exc:
|
|
47
|
+
typer.echo(f"Mount failed: {exc}")
|
|
48
|
+
raise typer.Exit(1)
|
|
49
|
+
|
|
50
|
+
|
|
51
|
+
def mount_interactive() -> None:
|
|
52
|
+
try:
|
|
53
|
+
entries = list_devices_internal()
|
|
54
|
+
if not entries:
|
|
55
|
+
typer.echo("No devices found")
|
|
56
|
+
raise typer.Exit(1)
|
|
57
|
+
entry = pick_device(entries, header="Available devices")
|
|
58
|
+
platform_name = platform.system()
|
|
59
|
+
if platform_name == "Darwin":
|
|
60
|
+
mount_point = typer.prompt("Mount point (use '-' for default)")
|
|
61
|
+
else:
|
|
62
|
+
mount_point = typer.prompt("Mount point")
|
|
63
|
+
if platform_name == "Linux":
|
|
64
|
+
selected = select_linux_partition(entries, entry)
|
|
65
|
+
mount_linux(selected, mount_point)
|
|
66
|
+
elif platform_name == "Darwin":
|
|
67
|
+
mount_macos(entry, mount_point)
|
|
68
|
+
elif platform_name == "Windows":
|
|
69
|
+
mount_windows(entry, mount_point)
|
|
70
|
+
else:
|
|
71
|
+
typer.echo(f"Unsupported platform: {platform_name}")
|
|
72
|
+
raise typer.Exit(1)
|
|
73
|
+
typer.echo("Mount completed")
|
|
74
|
+
except RuntimeError as exc:
|
|
75
|
+
typer.echo(f"Mount failed: {exc}")
|
|
76
|
+
raise typer.Exit(1)
|
|
77
|
+
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
|
|
1
2
|
import typer
|
|
2
3
|
from typing import Annotated, Optional, Literal
|
|
3
4
|
from machineconfig.profile.create_links_export import REPO_LOOSE
|
|
@@ -18,6 +19,9 @@ def sync(
|
|
|
18
19
|
direction_resolved = "BACKUP"
|
|
19
20
|
case "down" | "d":
|
|
20
21
|
direction_resolved = "RETRIEVE"
|
|
22
|
+
case _:
|
|
23
|
+
typer.echo("Error: Invalid direction. Use 'up' or 'down'.")
|
|
24
|
+
raise typer.Exit(code=1)
|
|
21
25
|
main_backup_retrieve(direction=direction_resolved, which=which, cloud=cloud, repo=repo)
|
|
22
26
|
|
|
23
27
|
|
|
@@ -3,8 +3,9 @@ import machineconfig.scripts.python.helpers.helpers_devops.cli_share_file
|
|
|
3
3
|
import machineconfig.scripts.python.helpers.helpers_devops.cli_share_terminal as cli_share_terminal
|
|
4
4
|
import machineconfig.scripts.python.helpers.helpers_devops.cli_share_server as cli_share_server
|
|
5
5
|
import machineconfig.scripts.python.helpers.helpers_devops.cli_ssh as cli_ssh
|
|
6
|
+
import machineconfig.scripts.python.helpers.helpers_devops.cli_share_temp as cli_share_temp
|
|
6
7
|
import typer
|
|
7
|
-
from typing import Annotated
|
|
8
|
+
from typing import Annotated, Literal
|
|
8
9
|
|
|
9
10
|
|
|
10
11
|
def switch_public_ip_address(
|
|
@@ -124,19 +125,95 @@ def wifi_select(
|
|
|
124
125
|
|
|
125
126
|
|
|
126
127
|
|
|
127
|
-
def reset_cloudflare_tunnel()
|
|
128
|
+
def reset_cloudflare_tunnel(task: Annotated[Literal["oneoff-shell-process", "oneoff-background-process", "as-service"], typer.Option(..., "--task", "-t", help="Task to perform", case_sensitive=False, show_choices=True)],
|
|
129
|
+
tunnel_name: Annotated[str | None, typer.Option("--tunnel-name", "-n", help="Name of the Cloudflare tunnel to run")] = None,
|
|
130
|
+
):
|
|
128
131
|
code = """
|
|
129
132
|
# cloudflared tunnel route dns glenn # creates CNAMES in Cloudflare dashboard
|
|
130
133
|
# sudo systemctl stop cloudflared
|
|
131
|
-
|
|
134
|
+
"""
|
|
135
|
+
match task:
|
|
136
|
+
case "oneoff-shell-process":
|
|
137
|
+
if tunnel_name is None: tunnel_name = ""
|
|
138
|
+
code = f"""cloudflared tunnel run {tunnel_name} # This is running like a normal command """
|
|
139
|
+
case "oneoff-background-process":
|
|
140
|
+
if tunnel_name is None: tunnel_name = ""
|
|
141
|
+
import getpass
|
|
142
|
+
user_name = getpass.getuser()
|
|
143
|
+
code = f"""
|
|
144
|
+
# This verion runs like a deamon, but its not peristent across reboots
|
|
145
|
+
sudo systemd-run \
|
|
146
|
+
--unit=cloudflared-tunnel \
|
|
147
|
+
--description="Cloudflared Tunnel (transient)" \
|
|
148
|
+
--property=Restart=on-failure \
|
|
149
|
+
--property=RestartSec=5 \
|
|
150
|
+
--property=User={user_name} \
|
|
151
|
+
--property=Group={user_name} \
|
|
152
|
+
--property=Environment=HOME=/home/{user_name} \
|
|
153
|
+
--property=WorkingDirectory=/home/{user_name} \
|
|
154
|
+
/home/{user_name}/.local/bin/cloudflared \
|
|
155
|
+
--config /home/{user_name}/.cloudflared/config.yml \
|
|
156
|
+
tunnel run {tunnel_name}
|
|
157
|
+
"""
|
|
158
|
+
case "as-service":
|
|
159
|
+
code = """
|
|
132
160
|
home_dir=$HOME
|
|
133
161
|
cloudflared_path="$home_dir/.local/bin/cloudflared"
|
|
134
162
|
sudo $cloudflared_path service uninstall
|
|
135
163
|
sudo rm /etc/cloudflared/config.yml || true
|
|
136
164
|
sudo $cloudflared_path --config $home_dir/.cloudflared/config.yml service install
|
|
137
165
|
"""
|
|
138
|
-
|
|
139
|
-
|
|
166
|
+
|
|
167
|
+
from machineconfig.utils.code import exit_then_run_shell_script, print_code
|
|
168
|
+
print_code(code, lexer="bash", desc="code to achieve the goal")
|
|
169
|
+
yes = typer.confirm("Do you want to run the above commands now?", default=False)
|
|
170
|
+
if yes:
|
|
171
|
+
exit_then_run_shell_script(code)
|
|
172
|
+
|
|
173
|
+
|
|
174
|
+
|
|
175
|
+
def vscode_share(
|
|
176
|
+
action: Annotated[Literal["run", "install-service", "uninstall-service", "share-local"], typer.Option(..., "--action", "-a", help="Action to perform", case_sensitive=False, show_choices=True)],
|
|
177
|
+
name: Annotated[str | None, typer.Option("--name", "-n", help="Name for the tunnel/service")] = None,
|
|
178
|
+
path: Annotated[str | None, typer.Option("--path", "-p", help="Path to share locally (for share-local)")] = None,
|
|
179
|
+
extra_args: Annotated[str | None, typer.Option("--extra-args", "-e", help="Extra args to append to the code tunnel command")] = None,
|
|
180
|
+
) -> None:
|
|
181
|
+
"""🧑💻 Share workspace using VS Code Tunnels ("code tunnel")
|
|
182
|
+
|
|
183
|
+
Note: this helper prints recommended commands and optionally runs them.
|
|
184
|
+
If you need more functionality, consult VS Code Tunnels docs: https://code.visualstudio.com/docs/remote/tunnels
|
|
185
|
+
"""
|
|
186
|
+
accept = "--accept-server-license-terms"
|
|
187
|
+
name_part = f"--name {name}" if name else ""
|
|
188
|
+
extra = extra_args or ""
|
|
189
|
+
|
|
190
|
+
if action == "run":
|
|
191
|
+
cmd = f"code tunnel {name_part} {accept} {extra}".strip()
|
|
192
|
+
desc = "Run a one-off VS Code tunnel (foreground)"
|
|
193
|
+
elif action == "install-service":
|
|
194
|
+
cmd = f"code tunnel service install {accept} {name_part}".strip()
|
|
195
|
+
desc = "Install code tunnel as a service"
|
|
196
|
+
elif action == "uninstall-service":
|
|
197
|
+
cmd = "code tunnel service uninstall"
|
|
198
|
+
desc = "Uninstall code tunnel service"
|
|
199
|
+
elif action == "share-local":
|
|
200
|
+
p = path or "."
|
|
201
|
+
# Some VS Code CLI integrations prefer starting a tunnel and then using the editor to expose resources.
|
|
202
|
+
cmd = f"code tunnel {name_part} {accept} {extra}".strip()
|
|
203
|
+
desc = f"Start tunnel and then share local path: {p} (use VS Code UI to forward ports / share files)"
|
|
204
|
+
else:
|
|
205
|
+
print(f"Unknown action: {action}")
|
|
206
|
+
return
|
|
207
|
+
|
|
208
|
+
from machineconfig.utils.code import print_code, exit_then_run_shell_script
|
|
209
|
+
print_code(cmd, lexer="bash", desc=desc)
|
|
210
|
+
|
|
211
|
+
if typer.confirm("Do you want to run the above command now?", default=False):
|
|
212
|
+
exit_then_run_shell_script(cmd)
|
|
213
|
+
else:
|
|
214
|
+
print("Command not executed. Use the printed command in your terminal when ready.")
|
|
215
|
+
|
|
216
|
+
|
|
140
217
|
|
|
141
218
|
def add_ip_exclusion_to_warp(ip: Annotated[str, typer.Option(..., "--ip", help="IP address(es) to exclude from WARP (Comma separated)")]):
|
|
142
219
|
ips = ip.split(",")
|
|
@@ -173,6 +250,9 @@ def get_app():
|
|
|
173
250
|
nw_apps.command(name="receive", no_args_is_help=True, hidden=False, help="📁 [rx] receive files to here.")(machineconfig.scripts.python.helpers.helpers_devops.cli_share_file.share_file_receive)
|
|
174
251
|
nw_apps.command(name="rx", no_args_is_help=True, hidden=True, help="📁 [rx] receive files to here.")(machineconfig.scripts.python.helpers.helpers_devops.cli_share_file.share_file_receive)
|
|
175
252
|
|
|
253
|
+
nw_apps.command(name="share-temp-file", help="🌡️ [T] Share a file via temp.sh")(cli_share_temp.upload_file)
|
|
254
|
+
nw_apps.command(name="T", help="Share a file via temp.sh", hidden=True)(cli_share_temp.upload_file)
|
|
255
|
+
|
|
176
256
|
nw_apps.add_typer(cli_ssh.get_app(), name="ssh", help="🔐 [S] SSH subcommands")
|
|
177
257
|
nw_apps.add_typer(cli_ssh.get_app(), name="S", help="SSH subcommands", hidden=True)
|
|
178
258
|
|
|
@@ -193,9 +273,13 @@ def get_app():
|
|
|
193
273
|
nw_apps.command(name="l", no_args_is_help=False, help="Link WSL home and Windows home directories.", hidden=True)(link_wsl_and_windows_home)
|
|
194
274
|
|
|
195
275
|
|
|
196
|
-
nw_apps.command(name="reset-cloudflare-tunnel", help="☁️
|
|
276
|
+
nw_apps.command(name="reset-cloudflare-tunnel", help="☁️ [r] Reset Cloudflare tunnel service")(reset_cloudflare_tunnel)
|
|
197
277
|
nw_apps.command(name="r", help="Reset Cloudflare tunnel service", hidden=True)(reset_cloudflare_tunnel)
|
|
198
278
|
nw_apps.command(name="add-ip-exclusion-to-warp", help="🚫 [p] Add IP exclusion to WARP")(add_ip_exclusion_to_warp)
|
|
199
279
|
nw_apps.command(name="p", help="Add IP exclusion to WARP", hidden=True)(add_ip_exclusion_to_warp)
|
|
200
280
|
|
|
281
|
+
# VS Code Tunnels helper
|
|
282
|
+
nw_apps.command(name="vscode-share", no_args_is_help=True, help="🧑💻 [v] Share workspace via VS Code Tunnels")(vscode_share)
|
|
283
|
+
nw_apps.command(name="v", no_args_is_help=True, hidden=True, help="Share workspace via VS Code Tunnels")(vscode_share)
|
|
284
|
+
|
|
201
285
|
return nw_apps
|
|
@@ -125,7 +125,7 @@ def count_lines_in_repo(repo_path: Annotated[str, typer.Argument(..., help="Path
|
|
|
125
125
|
# from machineconfig.scripts.python.helpers.helpers_repos import repo_analyzer_1
|
|
126
126
|
# repo_analyzer_1.count_historical_line_edits(repo_path=repo_path)
|
|
127
127
|
# from machineconfig.utils.code import run_lambda_function
|
|
128
|
-
# run_lambda_function(lambda: func(repo_path=repo_path), uv_project_dir=None, uv_with=["machineconfig>=8.
|
|
128
|
+
# run_lambda_function(lambda: func(repo_path=repo_path), uv_project_dir=None, uv_with=["machineconfig>=8.61"])
|
|
129
129
|
from machineconfig.scripts.python.helpers.helpers_repos import repo_analyzer_1
|
|
130
130
|
try:
|
|
131
131
|
repo_analyzer_1.count_historical_line_edits(repo_path=repo_path)
|
|
@@ -138,7 +138,7 @@ def print_python_files_by_size(repo_path: Annotated[str, typer.Argument(..., hel
|
|
|
138
138
|
# from machineconfig.scripts.python.helpers.helpers_repos.repo_analyzer_2 import print_python_files_by_size_impl
|
|
139
139
|
# print_python_files_by_size_impl(repo_path=repo_path)
|
|
140
140
|
# from machineconfig.utils.code import run_lambda_function
|
|
141
|
-
# run_lambda_function(lambda: func(repo_path=repo_path), uv_project_dir=None, uv_with=["machineconfig[plot]>=8.
|
|
141
|
+
# run_lambda_function(lambda: func(repo_path=repo_path), uv_project_dir=None, uv_with=["machineconfig[plot]>=8.61"])
|
|
142
142
|
from machineconfig.scripts.python.helpers.helpers_repos.repo_analyzer_2 import print_python_files_by_size_impl
|
|
143
143
|
print_python_files_by_size_impl(repo_path=repo_path)
|
|
144
144
|
|
|
@@ -148,7 +148,7 @@ def analyze_repo_development(repo_path: Annotated[str, typer.Argument(..., help=
|
|
|
148
148
|
# from machineconfig.scripts.python.helpers.helpers_repos.repo_analyzer_2 import analyze_over_time
|
|
149
149
|
# analyze_over_time(repo_path=repo_path)
|
|
150
150
|
# from machineconfig.utils.code import run_lambda_function
|
|
151
|
-
# run_lambda_function(lambda: func(repo_path=repo_path), uv_project_dir=None, uv_with=["machineconfig[plot]>=8.
|
|
151
|
+
# run_lambda_function(lambda: func(repo_path=repo_path), uv_project_dir=None, uv_with=["machineconfig[plot]>=8.61"])
|
|
152
152
|
from machineconfig.scripts.python.helpers.helpers_repos.repo_analyzer_2 import analyze_over_time
|
|
153
153
|
analyze_over_time(repo_path=repo_path)
|
|
154
154
|
|
|
@@ -177,21 +177,47 @@ def readme():
|
|
|
177
177
|
console.print(md)
|
|
178
178
|
|
|
179
179
|
|
|
180
|
+
def buid_docker(
|
|
181
|
+
variant: Annotated[Literal["slim", "ai"], typer.Argument(..., help="Variant to build: 'slim' or 'ai'")] = "slim",
|
|
182
|
+
) -> None:
|
|
183
|
+
"""🧱 `buid_docker` — wrapper for `jobs/shell/docker_build_and_publish.sh`"""
|
|
184
|
+
from pathlib import Path
|
|
185
|
+
import machineconfig
|
|
186
|
+
script_path = Path(machineconfig.__file__).resolve().parent.parent.parent.joinpath("jobs", "shell", "docker_build_and_publish.sh")
|
|
187
|
+
if not script_path.exists():
|
|
188
|
+
typer.echo(f"❌ Script not found: {str(script_path)}")
|
|
189
|
+
raise typer.Exit(code=1)
|
|
190
|
+
|
|
191
|
+
# shell_cmd = f'VARIANT="{variant}" && bash "{str(script_path)}"'\
|
|
192
|
+
from machineconfig.utils.source_of_truth import REPO_ROOT
|
|
193
|
+
shell_cmd = f"""
|
|
194
|
+
export VARIANT="{variant}"
|
|
195
|
+
cd "{str(REPO_ROOT)}"
|
|
196
|
+
bash "{str(script_path)}"
|
|
197
|
+
"""
|
|
198
|
+
# Use exit_then_run_shell_script for interactive runs (keeps tty), otherwise run shell script non-interactively
|
|
199
|
+
from machineconfig.utils.code import exit_then_run_shell_script
|
|
200
|
+
exit_then_run_shell_script(shell_cmd, strict=True)
|
|
201
|
+
|
|
202
|
+
|
|
180
203
|
def get_app():
|
|
181
204
|
cli_app = typer.Typer(help="🔄 [s] self operations subcommands", no_args_is_help=True, add_help_option=True, add_completion=False)
|
|
182
|
-
cli_app.command("update", no_args_is_help=False, help="🔄 [u] UPDATE machineconfig")(update)
|
|
183
|
-
cli_app.command("u", no_args_is_help=False, hidden=True)(update)
|
|
184
|
-
cli_app.command("interactive", no_args_is_help=False, help="🤖 [ia] INTERACTIVE configuration of machine.")(interactive)
|
|
185
|
-
cli_app.command("ia", no_args_is_help=False, help="INTERACTIVE configuration of machine.", hidden=True)(interactive)
|
|
186
|
-
cli_app.command(name="init", no_args_is_help=False, help="🦐 [t] Define and manage configurations")(init)
|
|
187
|
-
cli_app.command(name="t", no_args_is_help=False, hidden=True)(init)
|
|
188
|
-
cli_app.command("status", no_args_is_help=False, help="📊 [s] STATUS of machine, shell profile, apps, symlinks, dotfiles, etc.")(status)
|
|
189
|
-
cli_app.command("s", no_args_is_help=False, help="STATUS of machine, shell profile, apps, symlinks, dotfiles, etc.", hidden=True)(status)
|
|
190
|
-
cli_app.command("install", no_args_is_help=False, help="📋 [i] CLONE machienconfig locally and incorporate to shell profile for faster execution and nightly updates.")(install)
|
|
191
|
-
cli_app.command("i", no_args_is_help=False, help="CLONE machienconfig locally and incorporate to shell profile for faster execution and nightly updates.", hidden=True)(install)
|
|
192
|
-
cli_app.command("navigate", no_args_is_help=False, help="📚 [n] NAVIGATE command structure with TUI")(navigate)
|
|
193
|
-
cli_app.command("n", no_args_is_help=False, help="NAVIGATE command structure with TUI", hidden=True)(navigate)
|
|
194
|
-
|
|
195
|
-
cli_app.command("
|
|
196
|
-
cli_app.command("
|
|
205
|
+
cli_app.command(name= "update", no_args_is_help=False, help="🔄 [u] UPDATE machineconfig")(update)
|
|
206
|
+
cli_app.command(name= "u", no_args_is_help=False, hidden=True)(update)
|
|
207
|
+
cli_app.command(name= "interactive", no_args_is_help=False, help="🤖 [ia] INTERACTIVE configuration of machine.")(interactive)
|
|
208
|
+
cli_app.command(name= "ia", no_args_is_help=False, help="INTERACTIVE configuration of machine.", hidden=True)(interactive)
|
|
209
|
+
cli_app.command(name= "init", no_args_is_help=False, help="🦐 [t] Define and manage configurations")(init)
|
|
210
|
+
cli_app.command(name= "t", no_args_is_help=False, hidden=True)(init)
|
|
211
|
+
cli_app.command(name= "status", no_args_is_help=False, help="📊 [s] STATUS of machine, shell profile, apps, symlinks, dotfiles, etc.")(status)
|
|
212
|
+
cli_app.command(name= "s", no_args_is_help=False, help="STATUS of machine, shell profile, apps, symlinks, dotfiles, etc.", hidden=True)(status)
|
|
213
|
+
cli_app.command(name= "install", no_args_is_help=False, help="📋 [i] CLONE machienconfig locally and incorporate to shell profile for faster execution and nightly updates.")(install)
|
|
214
|
+
cli_app.command(name= "i", no_args_is_help=False, help="CLONE machienconfig locally and incorporate to shell profile for faster execution and nightly updates.", hidden=True)(install)
|
|
215
|
+
cli_app.command(name= "navigate", no_args_is_help=False, help="📚 [n] NAVIGATE command structure with TUI")(navigate)
|
|
216
|
+
cli_app.command(name= "n", no_args_is_help=False, help="NAVIGATE command structure with TUI", hidden=True)(navigate)
|
|
217
|
+
|
|
218
|
+
cli_app.command(name= "buid_docker", no_args_is_help=False, help="🧱 [d] Build docker images (wraps jobs/shell/docker_build_and_publish.sh)")(buid_docker)
|
|
219
|
+
cli_app.command(name= "d", no_args_is_help=False, help="Build docker images (wraps jobs/shell/docker_build_and_publish.sh)", hidden=True)(buid_docker)
|
|
220
|
+
|
|
221
|
+
cli_app.command(name= "readme", no_args_is_help=False, help="📚 [r] render readme markdown in terminal.")(readme)
|
|
222
|
+
cli_app.command(name= "r", no_args_is_help=False, hidden=True)(readme)
|
|
197
223
|
return cli_app
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
|
|
2
|
+
import json
|
|
3
|
+
import sys
|
|
4
|
+
from pathlib import Path
|
|
5
|
+
from typing import Annotated
|
|
6
|
+
|
|
7
|
+
import requests
|
|
8
|
+
import typer
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
TEMP_BASE_URL: str = "https://temp.sh"
|
|
12
|
+
UPLOAD_ENDPOINT: str = f"{TEMP_BASE_URL}/upload"
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
def _extract_url(response: requests.Response) -> str:
|
|
16
|
+
content_type = response.headers.get("content-type", "")
|
|
17
|
+
text = response.text.strip()
|
|
18
|
+
if "application/json" in content_type:
|
|
19
|
+
try:
|
|
20
|
+
data = response.json()
|
|
21
|
+
except (json.JSONDecodeError, ValueError):
|
|
22
|
+
data = None
|
|
23
|
+
if isinstance(data, dict):
|
|
24
|
+
url_value = data.get("url") or data.get("link") or data.get("download")
|
|
25
|
+
if isinstance(url_value, str) and url_value.strip() != "":
|
|
26
|
+
return url_value.strip()
|
|
27
|
+
for token in text.split():
|
|
28
|
+
if token.startswith("https://") or token.startswith("http://"):
|
|
29
|
+
return token
|
|
30
|
+
return text
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
def _upload_file_handle(file_name: str, file_handle: object, content_type: str | None) -> str:
|
|
34
|
+
files: dict[str, tuple[str, object, str] | tuple[str, object]]
|
|
35
|
+
if content_type is None:
|
|
36
|
+
files = {"file": (file_name, file_handle)}
|
|
37
|
+
else:
|
|
38
|
+
files = {"file": (file_name, file_handle, content_type)}
|
|
39
|
+
response = requests.post(UPLOAD_ENDPOINT, files=files) # type: ignore[reportArgumentType]
|
|
40
|
+
response.raise_for_status()
|
|
41
|
+
return _extract_url(response=response)
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
def upload_file(
|
|
45
|
+
file_path: Annotated[Path, typer.Argument(..., exists=True, dir_okay=False, readable=True)],
|
|
46
|
+
) -> None:
|
|
47
|
+
try:
|
|
48
|
+
with file_path.open("rb") as file_handle:
|
|
49
|
+
url = _upload_file_handle(file_name=file_path.name, file_handle=file_handle, content_type=None)
|
|
50
|
+
except requests.RequestException as exc:
|
|
51
|
+
typer.echo(f"Upload failed: {exc}")
|
|
52
|
+
raise typer.Exit(1)
|
|
53
|
+
typer.echo(url)
|
|
54
|
+
|
|
55
|
+
|
|
56
|
+
def upload_text(
|
|
57
|
+
text: Annotated[str, typer.Argument(...)],
|
|
58
|
+
) -> None:
|
|
59
|
+
text_value = text
|
|
60
|
+
if text == "-":
|
|
61
|
+
text_value = sys.stdin.read()
|
|
62
|
+
try:
|
|
63
|
+
payload = text_value.encode("utf-8")
|
|
64
|
+
url = _upload_file_handle(file_name="text.txt", file_handle=payload, content_type="text/plain; charset=utf-8")
|
|
65
|
+
except requests.RequestException as exc:
|
|
66
|
+
typer.echo(f"Upload failed: {exc}")
|
|
67
|
+
raise typer.Exit(1)
|
|
68
|
+
typer.echo(url)
|
|
69
|
+
|