machineconfig 7.49__py3-none-any.whl → 7.64__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 +21 -11
- machineconfig/jobs/installer/custom/boxes.py +2 -2
- machineconfig/jobs/installer/custom/hx.py +16 -12
- machineconfig/jobs/installer/custom_dev/brave.py +1 -1
- machineconfig/jobs/installer/custom_dev/cloudflare_warp_cli.py +23 -0
- machineconfig/jobs/installer/custom_dev/code.py +4 -1
- machineconfig/jobs/installer/custom_dev/dubdb_adbc.py +1 -1
- machineconfig/jobs/installer/custom_dev/nerfont_windows_helper.py +1 -10
- machineconfig/jobs/installer/custom_dev/sysabc.py +119 -0
- machineconfig/jobs/installer/custom_dev/wezterm.py +2 -19
- machineconfig/jobs/installer/installer_data.json +739 -25
- machineconfig/jobs/installer/linux_scripts/redis.sh +1 -0
- machineconfig/jobs/installer/package_groups.py +49 -83
- machineconfig/logger.py +0 -1
- machineconfig/profile/create_links_export.py +21 -7
- machineconfig/profile/mapper.toml +1 -4
- machineconfig/scripts/linux/wrap_mcfg +1 -1
- machineconfig/scripts/python/croshell.py +20 -43
- machineconfig/scripts/python/devops.py +3 -4
- machineconfig/scripts/python/env_manager/path_manager_tui.py +1 -1
- machineconfig/scripts/python/fire_jobs.py +53 -39
- machineconfig/scripts/python/ftpx.py +4 -2
- machineconfig/scripts/python/helpers_agents/agentic_frameworks/fire_qwen.py +0 -12
- machineconfig/scripts/python/helpers_croshell/crosh.py +3 -3
- machineconfig/scripts/python/helpers_devops/cli_config.py +3 -19
- machineconfig/scripts/python/helpers_devops/cli_config_dotfile.py +22 -13
- machineconfig/scripts/python/helpers_devops/cli_self.py +12 -6
- machineconfig/scripts/python/helpers_devops/cli_share_file.py +2 -2
- machineconfig/scripts/python/helpers_devops/cli_share_server.py +1 -1
- machineconfig/scripts/python/helpers_devops/cli_terminal.py +1 -1
- machineconfig/scripts/python/helpers_devops/cli_utils.py +1 -152
- machineconfig/scripts/python/helpers_devops/devops_backup_retrieve.py +4 -4
- machineconfig/scripts/python/helpers_fire_command/file_wrangler.py +2 -20
- machineconfig/scripts/python/helpers_fire_command/fire_jobs_route_helper.py +3 -4
- machineconfig/scripts/python/helpers_msearch/scripts_linux/fzfg +1 -1
- machineconfig/scripts/python/helpers_repos/clone.py +0 -1
- machineconfig/scripts/python/helpers_repos/cloud_repo_sync.py +9 -3
- machineconfig/scripts/python/helpers_repos/count_lines_frontend.py +1 -1
- machineconfig/scripts/python/helpers_repos/entrypoint.py +2 -1
- machineconfig/scripts/python/helpers_repos/record.py +2 -1
- machineconfig/scripts/python/helpers_sessions/sessions_multiprocess.py +7 -7
- machineconfig/scripts/python/helpers_utils/download.py +151 -0
- machineconfig/scripts/python/helpers_utils/path.py +106 -0
- machineconfig/scripts/python/interactive.py +17 -26
- machineconfig/scripts/python/nw/devops_add_ssh_key.py +21 -5
- machineconfig/scripts/python/nw/ssh_debug_linux.py +7 -7
- machineconfig/scripts/python/nw/ssh_debug_windows.py +4 -4
- machineconfig/scripts/python/nw/wsl_windows_transfer.py +3 -2
- machineconfig/scripts/python/sessions.py +37 -22
- machineconfig/scripts/python/utils.py +8 -3
- machineconfig/scripts/windows/mounts/mount_ssh.ps1 +1 -1
- machineconfig/settings/shells/nushell/init.nu +2 -2
- machineconfig/settings/shells/wezterm/wezterm.lua +2 -0
- machineconfig/settings/shells/zsh/init.sh +1 -8
- machineconfig/settings/yazi/init.lua +45 -24
- machineconfig/settings/yazi/keymap_windows.toml +1 -2
- machineconfig/settings/yazi/shell/yazi_cd.ps1 +29 -5
- machineconfig/setup_linux/__init__.py +0 -1
- machineconfig/setup_linux/web_shortcuts/interactive.sh +12 -10
- machineconfig/setup_mac/__init__.py +2 -3
- machineconfig/setup_windows/__init__.py +0 -3
- machineconfig/setup_windows/web_shortcuts/interactive.ps1 +12 -10
- machineconfig/setup_windows/web_shortcuts/quick_init.ps1 +16 -0
- machineconfig/utils/code.py +2 -2
- machineconfig/utils/files/headers.py +2 -2
- machineconfig/utils/installer_utils/installer_class.py +42 -40
- machineconfig/utils/installer_utils/{installer.py → installer_cli.py} +61 -101
- machineconfig/utils/installer_utils/{installer_abc.py → installer_locator_utils.py} +0 -68
- machineconfig/utils/{installer.py → installer_utils/installer_runner.py} +11 -51
- machineconfig/utils/io.py +0 -1
- machineconfig/utils/meta.py +29 -15
- machineconfig/utils/options.py +1 -1
- machineconfig/utils/path_extended.py +40 -19
- machineconfig/utils/path_helper.py +75 -21
- machineconfig/utils/schemas/layouts/layout_types.py +1 -1
- machineconfig/utils/ssh.py +3 -3
- machineconfig-7.64.dist-info/METADATA +124 -0
- {machineconfig-7.49.dist-info → machineconfig-7.64.dist-info}/RECORD +84 -87
- machineconfig/jobs/installer/linux_scripts/pgsql.sh +0 -41
- machineconfig/jobs/installer/linux_scripts/timescaledb.sh +0 -71
- machineconfig/jobs/installer/powershell_scripts/archive_pygraphviz.ps1 +0 -12
- machineconfig/scripts/python/nw/add_ssh_key.py +0 -148
- machineconfig/settings/lf/linux/exe/fzf_nano.sh +0 -16
- machineconfig/setup_linux/apps.sh +0 -66
- machineconfig/setup_mac/apps.sh +0 -73
- machineconfig/setup_windows/apps.ps1 +0 -62
- machineconfig-7.49.dist-info/METADATA +0 -92
- /machineconfig/jobs/installer/linux_scripts/{warp-cli.sh → cloudflare_warp_cli.sh} +0 -0
- /machineconfig/{jobs/installer/powershell_scripts → setup_windows/ssh}/openssh-server_add_key.ps1 +0 -0
- /machineconfig/{jobs/installer/powershell_scripts → setup_windows/ssh}/openssh-server_copy-ssh-id.ps1 +0 -0
- {machineconfig-7.49.dist-info → machineconfig-7.64.dist-info}/WHEEL +0 -0
- {machineconfig-7.49.dist-info → machineconfig-7.64.dist-info}/entry_points.txt +0 -0
- {machineconfig-7.49.dist-info → machineconfig-7.64.dist-info}/top_level.txt +0 -0
|
@@ -8,11 +8,9 @@ fire
|
|
|
8
8
|
"""
|
|
9
9
|
|
|
10
10
|
from machineconfig.utils.ve import get_ve_path_and_ipython_profile
|
|
11
|
-
from machineconfig.utils.options import choose_from_options
|
|
12
|
-
from machineconfig.utils.path_helper import match_file_name, sanitize_path
|
|
13
|
-
from machineconfig.utils.path_extended import PathExtended
|
|
14
11
|
from machineconfig.utils.accessories import get_repo_root, randstr
|
|
15
12
|
from machineconfig.scripts.python.helpers_fire_command.fire_jobs_args_helper import FireJobArgs, extract_kwargs, parse_fire_args_from_context
|
|
13
|
+
from machineconfig.utils.path_helper import get_choice_file
|
|
16
14
|
|
|
17
15
|
import platform
|
|
18
16
|
from typing import Optional, Annotated
|
|
@@ -21,25 +19,12 @@ import typer
|
|
|
21
19
|
|
|
22
20
|
|
|
23
21
|
def route(args: FireJobArgs, fire_args: str = "") -> None:
|
|
24
|
-
|
|
25
|
-
if not path_obj.exists():
|
|
26
|
-
suffixes = {".py", ".sh", ".ps1"}
|
|
27
|
-
choice_file = match_file_name(sub_string=args.path, search_root=PathExtended.cwd(), suffixes=suffixes)
|
|
28
|
-
elif path_obj.is_dir():
|
|
29
|
-
from machineconfig.scripts.python.helpers_fire_command.file_wrangler import search_for_files_of_interest
|
|
30
|
-
print(f"🔍 Searching recursively for Python, PowerShell and Shell scripts in directory `{path_obj}`")
|
|
31
|
-
files = search_for_files_of_interest(path_obj)
|
|
32
|
-
print(f"🔍 Got #{len(files)} results.")
|
|
33
|
-
choice_file = choose_from_options(multi=False, options=files, fzf=True, msg="Choose one option")
|
|
34
|
-
choice_file = PathExtended(choice_file)
|
|
35
|
-
else:
|
|
36
|
-
choice_file = path_obj
|
|
37
|
-
|
|
22
|
+
choice_file = get_choice_file(args.path, suffixes=None)
|
|
38
23
|
repo_root = get_repo_root(Path(choice_file))
|
|
39
24
|
print(f"💾 Selected file: {choice_file}.\nRepo root: {repo_root}")
|
|
40
25
|
if args.marimo:
|
|
41
26
|
print(f"🧽 Preparing to launch Marimo notebook for `{choice_file}`...")
|
|
42
|
-
tmp_dir =
|
|
27
|
+
tmp_dir = Path.home().joinpath(f"tmp_results/tmp_scripts/marimo/{choice_file.stem}_{randstr()}")
|
|
43
28
|
tmp_dir.mkdir(parents=True, exist_ok=True)
|
|
44
29
|
script = f"""
|
|
45
30
|
cd {tmp_dir}
|
|
@@ -53,7 +38,6 @@ uv run --project {repo_root} --with marimo marimo edit --host 0.0.0.0 marimo_nb.
|
|
|
53
38
|
|
|
54
39
|
# ========================= preparing kwargs_dict
|
|
55
40
|
if choice_file.suffix == ".py":
|
|
56
|
-
|
|
57
41
|
kwargs_dict = extract_kwargs(args) # This now returns empty dict, but kept for compatibility
|
|
58
42
|
else:
|
|
59
43
|
kwargs_dict = {}
|
|
@@ -62,17 +46,20 @@ uv run --project {repo_root} --with marimo marimo edit --host 0.0.0.0 marimo_nb.
|
|
|
62
46
|
choice_function: Optional[str] = None # Initialize to avoid unbound variable
|
|
63
47
|
if args.choose_function:
|
|
64
48
|
from machineconfig.scripts.python.helpers_fire_command.fire_jobs_route_helper import choose_function_or_lines
|
|
49
|
+
|
|
65
50
|
choice_function, choice_file, kwargs_dict = choose_function_or_lines(choice_file, kwargs_dict)
|
|
66
51
|
else:
|
|
67
52
|
choice_function = args.function
|
|
68
53
|
|
|
69
54
|
if choice_file.suffix == ".py":
|
|
70
55
|
from machineconfig.scripts.python.helpers_fire_command.fire_jobs_route_helper import get_command_streamlit
|
|
56
|
+
|
|
71
57
|
with_project = f"--project {repo_root} " if repo_root is not None else ""
|
|
72
58
|
if args.streamlit:
|
|
73
59
|
exe = get_command_streamlit(choice_file=choice_file, environment=args.environment, repo_root=repo_root)
|
|
74
60
|
exe = f"uv run {with_project} {exe} "
|
|
75
|
-
elif args.jupyter:
|
|
61
|
+
elif args.jupyter:
|
|
62
|
+
exe = f"uv run {with_project} jupyter-lab"
|
|
76
63
|
else:
|
|
77
64
|
if args.interactive:
|
|
78
65
|
_ve_root_from_file, ipy_profile = get_ve_path_and_ipython_profile(choice_file)
|
|
@@ -81,20 +68,38 @@ uv run --project {repo_root} --with marimo marimo edit --host 0.0.0.0 marimo_nb.
|
|
|
81
68
|
exe = f"uv run {with_project} ipython -i --no-banner --profile {ipy_profile} "
|
|
82
69
|
else:
|
|
83
70
|
exe = f"uv run {with_project} python "
|
|
84
|
-
elif choice_file.suffix == ".ps1" or choice_file.suffix == ".sh":
|
|
85
|
-
|
|
86
|
-
|
|
71
|
+
elif choice_file.suffix == ".ps1" or choice_file.suffix == ".sh":
|
|
72
|
+
exe = "."
|
|
73
|
+
elif choice_file.suffix == "":
|
|
74
|
+
exe = ""
|
|
75
|
+
else:
|
|
76
|
+
raise NotImplementedError(f"File type {choice_file.suffix} not supported, in the sense that I don't know how to fire it.")
|
|
87
77
|
|
|
88
|
-
if args.module or (args.debug and args.choose_function):
|
|
78
|
+
if args.module or (args.debug and args.choose_function):
|
|
79
|
+
# because debugging tools do not support choosing functions and don't interplay with fire module. So the only way to have debugging and choose function options is to import the file as a module into a new script and run the function of interest there and debug the new script.
|
|
89
80
|
assert choice_file.suffix == ".py", f"File must be a python file to be imported as a module. Got {choice_file}"
|
|
90
81
|
from machineconfig.scripts.python.helpers_fire_command.file_wrangler import get_import_module_code, wrap_import_in_try_except
|
|
91
82
|
from machineconfig.utils.meta import lambda_to_python_script
|
|
92
83
|
from machineconfig.utils.code import print_code
|
|
84
|
+
|
|
93
85
|
import_code = get_import_module_code(str(choice_file))
|
|
94
|
-
import_code_robust = lambda_to_python_script(
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
86
|
+
import_code_robust = lambda_to_python_script(
|
|
87
|
+
lambda: wrap_import_in_try_except(
|
|
88
|
+
import_line=import_code, pyfile=str(choice_file), repo_root=str(repo_root) if repo_root is not None else None
|
|
89
|
+
),
|
|
90
|
+
in_global=True,
|
|
91
|
+
import_module=False,
|
|
92
|
+
)
|
|
93
|
+
# print(f"🧩 Preparing import code for module import:\n{import_code}")
|
|
94
|
+
code_printing = lambda_to_python_script(
|
|
95
|
+
lambda: print_code(code=import_code_robust, lexer="python", desc="import as module code"),
|
|
96
|
+
in_global=True, import_module=False
|
|
97
|
+
)
|
|
98
|
+
print(f"🧩 Preparing import code for module import:\n{import_code}")
|
|
99
|
+
if choice_function is not None:
|
|
100
|
+
calling = f"""res = {choice_function}({("**" + str(kwargs_dict)) if kwargs_dict else ""})"""
|
|
101
|
+
else:
|
|
102
|
+
calling = """# No function selected to call. You can add your code here."""
|
|
98
103
|
choice_file = Path.home().joinpath(f"tmp_results/tmp_scripts/python/{Path(choice_file).parent.name}_{Path(choice_file).stem}_{randstr()}.py")
|
|
99
104
|
choice_file.parent.mkdir(parents=True, exist_ok=True)
|
|
100
105
|
choice_file.write_text(import_code_robust + "\n" + code_printing + "\n" + calling, encoding="utf-8")
|
|
@@ -117,15 +122,17 @@ uv run --project {repo_root} --with marimo marimo edit --host 0.0.0.0 marimo_nb.
|
|
|
117
122
|
if args.holdDirectory:
|
|
118
123
|
command = f"{exe} {choice_file}"
|
|
119
124
|
else:
|
|
120
|
-
command = f"cd {choice_file.parent}\n{exe} {choice_file.name}\ncd {
|
|
125
|
+
command = f"cd {choice_file.parent}\n{exe} {choice_file.name}\ncd {Path.cwd()}"
|
|
121
126
|
elif args.cmd:
|
|
122
127
|
command = rf""" cd /d {choice_file.parent} & {exe} {choice_file.name} """
|
|
123
128
|
else:
|
|
124
|
-
if choice_file.suffix == "":
|
|
125
|
-
|
|
126
|
-
|
|
129
|
+
if choice_file.suffix == "":
|
|
130
|
+
command = f"{exe} {choice_file} {fire_args}"
|
|
131
|
+
else:
|
|
132
|
+
command = f"{exe} {choice_file} "
|
|
127
133
|
|
|
128
|
-
if not args.cmd:
|
|
134
|
+
if not args.cmd:
|
|
135
|
+
pass
|
|
129
136
|
else:
|
|
130
137
|
new_line = "\n"
|
|
131
138
|
command = rf"""start cmd -Argument "/k {command.replace(new_line, " & ")} " """ # this works from powershell
|
|
@@ -134,23 +141,27 @@ uv run --project {repo_root} --with marimo marimo edit --host 0.0.0.0 marimo_nb.
|
|
|
134
141
|
if choice_function is not None:
|
|
135
142
|
command += f"--function {choice_function} "
|
|
136
143
|
|
|
137
|
-
if args.optimized:
|
|
144
|
+
if args.optimized:
|
|
145
|
+
command = command.replace("python ", "python -OO ")
|
|
138
146
|
|
|
139
147
|
from rich.panel import Panel
|
|
140
148
|
from rich.console import Console
|
|
141
149
|
from rich.syntax import Syntax
|
|
150
|
+
|
|
142
151
|
console = Console()
|
|
143
152
|
if args.zellij_tab is not None:
|
|
144
|
-
comman_path__ =
|
|
153
|
+
comman_path__ = Path.home().joinpath(f"tmp_results/tmp_scripts/zellij_commands/{choice_file.stem}_{randstr()}.sh")
|
|
145
154
|
comman_path__.parent.mkdir(parents=True, exist_ok=True)
|
|
146
155
|
comman_path__.write_text(command, encoding="utf-8")
|
|
147
156
|
console.print(Panel(Syntax(command, lexer="shell"), title=f"🔥 fire command @ {comman_path__}: "), style="bold red")
|
|
148
157
|
import subprocess
|
|
158
|
+
|
|
149
159
|
existing_tab_names = subprocess.run(["zellij", "action", "query-tab-names"], capture_output=True, text=True, check=True).stdout.splitlines()
|
|
150
160
|
if args.zellij_tab in existing_tab_names:
|
|
151
161
|
print(f"⚠️ Tab name `{args.zellij_tab}` already exists. Please choose a different name.")
|
|
152
162
|
args.zellij_tab += f"_{randstr(3)}"
|
|
153
163
|
from machineconfig.cluster.sessions_managers.zellij_local import run_command_in_zellij_tab
|
|
164
|
+
|
|
154
165
|
command = run_command_in_zellij_tab(command=str(comman_path__), tab_name=args.zellij_tab, cwd=None)
|
|
155
166
|
if args.watch:
|
|
156
167
|
command = "watchexec --restart --exts py,sh,ps1 " + command
|
|
@@ -158,6 +169,7 @@ uv run --project {repo_root} --with marimo marimo edit --host 0.0.0.0 marimo_nb.
|
|
|
158
169
|
command = f"\ngit -C {choice_file.parent} pull\n" + command
|
|
159
170
|
if args.PathExport:
|
|
160
171
|
from machineconfig.scripts.python.helpers_fire_command.file_wrangler import add_to_path
|
|
172
|
+
|
|
161
173
|
export_line = add_to_path(path_variable="PYTHONPATH", directory=str(repo_root))
|
|
162
174
|
command = export_line + "\n" + command
|
|
163
175
|
if args.loop:
|
|
@@ -169,6 +181,7 @@ uv run --project {repo_root} --with marimo marimo edit --host 0.0.0.0 marimo_nb.
|
|
|
169
181
|
raise NotImplementedError(f"Platform {platform.system()} not supported.")
|
|
170
182
|
|
|
171
183
|
from machineconfig.utils.code import exit_then_run_shell_script
|
|
184
|
+
|
|
172
185
|
exit_then_run_shell_script(script=command, strict=False)
|
|
173
186
|
|
|
174
187
|
|
|
@@ -187,15 +200,14 @@ def fire(
|
|
|
187
200
|
module: Annotated[bool, typer.Option("--module", "-m", help="Launch the main file")] = False,
|
|
188
201
|
optimized: Annotated[bool, typer.Option("--optimized", "-O", help="Run the optimized version of the function")] = False,
|
|
189
202
|
zellij_tab: Annotated[Optional[str], typer.Option("--zellij-tab", "-z", help="Open in a new zellij tab")] = None,
|
|
190
|
-
|
|
191
203
|
submit_to_cloud: Annotated[bool, typer.Option("--submit-to-cloud", "-C", help="Submit to cloud compute")] = False,
|
|
192
204
|
remote: Annotated[bool, typer.Option("--remote", "-r", help="Launch on a remote machine")] = False,
|
|
193
|
-
|
|
194
205
|
streamlit: Annotated[bool, typer.Option("--streamlit", "-S", help="Run as streamlit app")] = False,
|
|
195
206
|
environment: Annotated[str, typer.Option("--environment", "-E", help="Choose ip, localhost, hostname or arbitrary url")] = "",
|
|
196
|
-
holdDirectory: Annotated[
|
|
207
|
+
holdDirectory: Annotated[
|
|
208
|
+
bool, typer.Option("--holdDirectory", "-D", help="Hold current directory and avoid cd'ing to the script directory")
|
|
209
|
+
] = False,
|
|
197
210
|
PathExport: Annotated[bool, typer.Option("--PathExport", "-P", help="Augment the PYTHONPATH with repo root")] = False,
|
|
198
|
-
|
|
199
211
|
git_pull: Annotated[bool, typer.Option("--git-pull", "-g", help="Start by pulling the git repo")] = False,
|
|
200
212
|
watch: Annotated[bool, typer.Option("--watch", "-w", help="Watch the file for changes")] = False,
|
|
201
213
|
) -> None:
|
|
@@ -235,12 +247,14 @@ def fire(
|
|
|
235
247
|
except Exception as e:
|
|
236
248
|
# For other exceptions, print clean error message and exit
|
|
237
249
|
import sys
|
|
250
|
+
|
|
238
251
|
print(f"❌ Error: {e}", file=sys.stderr)
|
|
239
252
|
sys.exit(1)
|
|
240
253
|
|
|
241
254
|
|
|
242
255
|
def get_app():
|
|
243
256
|
from typer import Typer
|
|
257
|
+
|
|
244
258
|
app = Typer(add_completion=False)
|
|
245
259
|
app.command(context_settings={"allow_extra_args": True, "allow_interspersed_args": False})(fire)
|
|
246
260
|
return app
|
|
@@ -145,8 +145,10 @@ def ftpx(
|
|
|
145
145
|
received_file = PathExtended(resolved_target) # type: ignore
|
|
146
146
|
else:
|
|
147
147
|
if source_is_remote:
|
|
148
|
-
|
|
149
|
-
❌ Path Error: Source must be a remote path (machine:path)"""
|
|
148
|
+
if resolved_source is None:
|
|
149
|
+
typer.echo("""❌ Path Error: Source must be a remote path (machine:path)""")
|
|
150
|
+
typer.Exit(code=1)
|
|
151
|
+
return
|
|
150
152
|
target_display = resolved_target or "<auto>"
|
|
151
153
|
console.print(
|
|
152
154
|
Panel(
|
|
@@ -5,22 +5,10 @@ from machineconfig.scripts.python.helpers_agents.fire_agents_helper_types import
|
|
|
5
5
|
|
|
6
6
|
|
|
7
7
|
def fire_qwen(ai_spec: AI_SPEC, prompt_path: Path, repo_root: Path, config_dir: str | None) -> str:
|
|
8
|
-
# assert model == "qwen", "Only qwen is supported currently."
|
|
9
|
-
# assert provider == "qwen", "Only qwen is supported currently."
|
|
10
|
-
# model = "qwen"
|
|
11
|
-
# model = "gemini-2.5-flash-lite"
|
|
12
|
-
# model = None # auto-select
|
|
13
|
-
# if model is None:
|
|
14
|
-
# model_arg = ""
|
|
15
|
-
# else:
|
|
16
8
|
_ = ai_spec["provider"]
|
|
17
|
-
# model_arg = f"--model {shlex.quote(model)}"
|
|
18
|
-
# Need a real shell for the pipeline; otherwise '| gemini ...' is passed as args to 'cat'
|
|
19
9
|
safe_path = shlex.quote(str(prompt_path))
|
|
20
|
-
|
|
21
10
|
match ai_spec["machine"]:
|
|
22
11
|
case "local":
|
|
23
|
-
# Export the environment variable so it's available to subshells
|
|
24
12
|
cmd = f"""
|
|
25
13
|
qwen --yolo --prompt {safe_path}
|
|
26
14
|
"""
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
|
|
2
2
|
|
|
3
|
-
def
|
|
3
|
+
def get_read_python_file_pycode(path: str, title: str):
|
|
4
4
|
from pathlib import Path
|
|
5
5
|
print("Reading code from path:", path)
|
|
6
6
|
pycode = Path(path).read_text(encoding="utf-8")
|
|
@@ -20,9 +20,9 @@ def get_read_data_pycode(path: str):
|
|
|
20
20
|
from rich.panel import Panel
|
|
21
21
|
from rich.text import Text
|
|
22
22
|
from rich.console import Console
|
|
23
|
-
from
|
|
23
|
+
from pathlib import Path
|
|
24
24
|
console = Console()
|
|
25
|
-
p =
|
|
25
|
+
p = Path(path).absolute()
|
|
26
26
|
try:
|
|
27
27
|
from machineconfig.utils.files.read import Read
|
|
28
28
|
from machineconfig.utils.accessories import pprint
|
|
@@ -7,7 +7,7 @@ import machineconfig.scripts.python.helpers_devops.cli_config_dotfile as dotfile
|
|
|
7
7
|
import machineconfig.profile.create_links_export as create_links_export
|
|
8
8
|
|
|
9
9
|
|
|
10
|
-
def
|
|
10
|
+
def configure_shell_profile(which: Annotated[Literal["default", "d", "nushell", "n"], typer.Option(..., "--which", "-w", help="Which shell profile to create/configure")]="default"):
|
|
11
11
|
"""🔗 Configure your shell profile."""
|
|
12
12
|
from machineconfig.profile.create_shell_profile import create_default_shell_profile, create_nu_shell_profile
|
|
13
13
|
match which:
|
|
@@ -20,20 +20,6 @@ def shell(which: Annotated[Literal["default", "d", "nushell", "n"], typer.Option
|
|
|
20
20
|
typer.echo(f"[red]Error:[/] Unknown shell profile type: {which}")
|
|
21
21
|
|
|
22
22
|
|
|
23
|
-
def path():
|
|
24
|
-
"""📚 NAVIGATE PATH variable with TUI"""
|
|
25
|
-
from machineconfig.scripts.python import env_manager as navigator
|
|
26
|
-
from pathlib import Path
|
|
27
|
-
path = Path(navigator.__file__).resolve().parent.joinpath("path_manager_tui.py")
|
|
28
|
-
from machineconfig.utils.code import run_shell_script, get_uv_command_executing_python_script
|
|
29
|
-
uv_with = ["textual"]
|
|
30
|
-
uv_project_dir = None
|
|
31
|
-
if not Path.home().joinpath("code/machineconfig").exists():
|
|
32
|
-
uv_with.append("machineconfig>=7.49")
|
|
33
|
-
else:
|
|
34
|
-
uv_project_dir = str(Path.home().joinpath("code/machineconfig"))
|
|
35
|
-
run_shell_script(get_uv_command_executing_python_script(python_script=path.read_text(encoding="utf-8"), uv_with=uv_with, uv_project_dir=uv_project_dir)[0])
|
|
36
|
-
|
|
37
23
|
|
|
38
24
|
def pwsh_theme():
|
|
39
25
|
"""🔗 Select powershell prompt theme."""
|
|
@@ -97,10 +83,8 @@ def get_app():
|
|
|
97
83
|
config_apps.command("b", no_args_is_help=True, help="Manage public configuration files.", hidden=True)(create_links_export.main_public_from_parser)
|
|
98
84
|
config_apps.command("dotfile", no_args_is_help=True, help="🔗 [d] Manage dotfiles.")(dotfile_module.main)
|
|
99
85
|
config_apps.command("d", no_args_is_help=True, hidden=True)(dotfile_module.main)
|
|
100
|
-
config_apps.command("shell", no_args_is_help=False, help="🔗 [s] Configure your shell profile.")(
|
|
101
|
-
config_apps.command("s", no_args_is_help=False, help="Configure your shell profile.", hidden=True)(
|
|
102
|
-
config_apps.command("path", no_args_is_help=False, help="📚 [p] NAVIGATE PATH variable with TUI")(path)
|
|
103
|
-
config_apps.command("p", no_args_is_help=False, help="NAVIGATE PATH variable with TUI", hidden=True)(path)
|
|
86
|
+
config_apps.command("shell", no_args_is_help=False, help="🔗 [s] Configure your shell profile.")(configure_shell_profile)
|
|
87
|
+
config_apps.command("s", no_args_is_help=False, help="Configure your shell profile.", hidden=True)(configure_shell_profile)
|
|
104
88
|
config_apps.command("starship-theme", no_args_is_help=False, help="🔗 [t] Select starship prompt theme.")(starship_theme)
|
|
105
89
|
config_apps.command("t", no_args_is_help=False, help="Select starship prompt theme.", hidden=True)(starship_theme)
|
|
106
90
|
config_apps.command("pwsh-theme", no_args_is_help=False, help="🔗 [T] Select powershell prompt theme.")(pwsh_theme)
|
|
@@ -12,7 +12,9 @@ def main(
|
|
|
12
12
|
method: Annotated[Literal["symlink", "s", "copy", "c"], typer.Option(..., "--method", "-m", help="Method to use for linking files")] = "copy",
|
|
13
13
|
on_conflict: Annotated[ON_CONFLICT_LOOSE, typer.Option(..., "--on-conflict", "-o", help="Action to take on conflict")] = "throw-error",
|
|
14
14
|
sensitivity: Annotated[Literal["private", "v", "public", "b"], typer.Option(..., "--sensitivity", "-s", help="Sensitivity of the config file.")] = "private",
|
|
15
|
-
destination: Annotated[str, typer.Option("--destination", "-d", help="destination folder (override the default, use at your own risk)")] = "",
|
|
15
|
+
destination: Annotated[str, typer.Option("--destination", "-d", help="destination folder (override the default, use at your own risk)")] = "",
|
|
16
|
+
shared: Annotated[bool, typer.Option("--shared", "-sh", help="Whether the config file is shared across destinations directory.")] = False,
|
|
17
|
+
) -> None:
|
|
16
18
|
from rich.console import Console
|
|
17
19
|
from rich.panel import Panel
|
|
18
20
|
from machineconfig.utils.links import symlink_map, copy_map
|
|
@@ -27,26 +29,33 @@ def main(
|
|
|
27
29
|
console = Console()
|
|
28
30
|
orig_path = Path(file).expanduser().absolute()
|
|
29
31
|
if destination == "":
|
|
30
|
-
|
|
31
|
-
|
|
32
|
+
if shared:
|
|
33
|
+
new_path = backup_root.joinpath("shared").joinpath(orig_path.name)
|
|
34
|
+
new_path.parent.mkdir(parents=True, exist_ok=True)
|
|
35
|
+
else:
|
|
36
|
+
new_path = backup_root.joinpath(orig_path.relative_to(Path.home()))
|
|
37
|
+
new_path.parent.mkdir(parents=True, exist_ok=True)
|
|
32
38
|
else:
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
+
if shared:
|
|
40
|
+
dest_path = Path(destination).expanduser().absolute()
|
|
41
|
+
dest_path.mkdir(parents=True, exist_ok=True)
|
|
42
|
+
new_path = dest_path.joinpath("shared").joinpath(orig_path.name)
|
|
43
|
+
new_path.parent.mkdir(parents=True, exist_ok=True)
|
|
44
|
+
else:
|
|
45
|
+
dest_path = Path(destination).expanduser().absolute()
|
|
46
|
+
dest_path.mkdir(parents=True, exist_ok=True)
|
|
47
|
+
new_path = dest_path.joinpath(orig_path.name)
|
|
39
48
|
match method:
|
|
40
49
|
case "copy" | "c":
|
|
41
50
|
try:
|
|
42
|
-
copy_map(config_file_default_path=
|
|
51
|
+
copy_map(config_file_default_path=orig_path, self_managed_config_file_path=new_path, on_conflict=ON_CONFLICT_MAPPER[on_conflict]) # type: ignore[arg-type]
|
|
43
52
|
except Exception as e:
|
|
44
53
|
typer.echo(f"[red]Error:[/] {e}")
|
|
45
54
|
typer.Exit(code=1)
|
|
46
55
|
return
|
|
47
56
|
case "symlink" | "s":
|
|
48
57
|
try:
|
|
49
|
-
symlink_map(config_file_default_path=
|
|
58
|
+
symlink_map(config_file_default_path=orig_path, self_managed_config_file_path=new_path, on_conflict=ON_CONFLICT_MAPPER[on_conflict]) # type: ignore[arg-type]
|
|
50
59
|
except Exception as e:
|
|
51
60
|
typer.echo(f"[red]Error:[/] {e}")
|
|
52
61
|
typer.Exit(code=1)
|
|
@@ -56,10 +65,10 @@ def main(
|
|
|
56
65
|
|
|
57
66
|
# mapper_snippet = "\n".join(
|
|
58
67
|
# [
|
|
59
|
-
# f"[bold]📝 Edit configuration file:[/] [cyan]nano {
|
|
68
|
+
# f"[bold]📝 Edit configuration file:[/] [cyan]nano {Path(CONFIG_ROOT)}/symlinks/mapper.toml[/cyan]",
|
|
60
69
|
# "",
|
|
61
70
|
# f"[{new_path.parent.name}]",
|
|
62
|
-
# f"{orig_path.name.split('.')[0]} = {{ this = '{orig_path.
|
|
71
|
+
# f"{orig_path.name.split('.')[0]} = {{ this = '{orig_path.as_posix()}', to_this = '{new_path.as_posix()}' }}",
|
|
63
72
|
# ]
|
|
64
73
|
# )
|
|
65
74
|
# console.print(
|
|
@@ -9,7 +9,9 @@ def copy_both_assets():
|
|
|
9
9
|
create_helper.copy_assets_to_machine(which="settings")
|
|
10
10
|
|
|
11
11
|
|
|
12
|
-
def update(copy_assets: Annotated[bool, typer.Option("--assets-copy/--no-assets-copy", "-a/-na", help="Copy (overwrite) assets to the machine after the update")] = True
|
|
12
|
+
def update(copy_assets: Annotated[bool, typer.Option("--assets-copy/--no-assets-copy", "-a/-na", help="Copy (overwrite) assets to the machine after the update")] = True,
|
|
13
|
+
link_public_configs: Annotated[bool, typer.Option("--link-public-configs/--no-link-public-configs", "-b/-nb", help="Link public configs after update (overwrites your configs!)")] = False,
|
|
14
|
+
):
|
|
13
15
|
"""🔄 UPDATE uv and machineconfig"""
|
|
14
16
|
from pathlib import Path
|
|
15
17
|
if Path.home().joinpath("code", "machineconfig").exists():
|
|
@@ -34,8 +36,12 @@ uv tool install --upgrade machineconfig
|
|
|
34
36
|
else:
|
|
35
37
|
from machineconfig.utils.code import run_shell_script
|
|
36
38
|
run_shell_script(shell_script)
|
|
37
|
-
|
|
38
|
-
|
|
39
|
+
if copy_assets:
|
|
40
|
+
copy_both_assets()
|
|
41
|
+
if link_public_configs:
|
|
42
|
+
import machineconfig.profile.create_links_export as create_links_export
|
|
43
|
+
create_links_export.main_public_from_parser(method="copy", on_conflict="overwrite-default-path", which="all", interactive=False)
|
|
44
|
+
|
|
39
45
|
|
|
40
46
|
def install(no_copy_assets: Annotated[bool, typer.Option("--no-assets-copy", "-na", help="Copy (overwrite) assets to the machine after the update")] = False):
|
|
41
47
|
"""📋 CLONE machienconfig locally and incorporate to shell profile for faster execution and nightly updates."""
|
|
@@ -46,9 +52,9 @@ def install(no_copy_assets: Annotated[bool, typer.Option("--no-assets-copy", "-n
|
|
|
46
52
|
else:
|
|
47
53
|
import platform
|
|
48
54
|
if platform.system() == "Windows":
|
|
49
|
-
run_shell_script(r"""& "$HOME\.local\bin\uv.exe" tool install --upgrade "machineconfig>=7.
|
|
55
|
+
run_shell_script(r"""& "$HOME\.local\bin\uv.exe" tool install --upgrade "machineconfig>=7.64" """)
|
|
50
56
|
else:
|
|
51
|
-
run_shell_script("""$HOME/.local/bin/uv tool install --upgrade "machineconfig>=7.
|
|
57
|
+
run_shell_script("""$HOME/.local/bin/uv tool install --upgrade "machineconfig>=7.64" """)
|
|
52
58
|
from machineconfig.profile.create_shell_profile import create_default_shell_profile
|
|
53
59
|
if not no_copy_assets:
|
|
54
60
|
create_default_shell_profile() # involves copying assets too
|
|
@@ -73,7 +79,7 @@ def navigate():
|
|
|
73
79
|
path = Path(navigator.__file__).resolve().parent.joinpath("devops_navigator.py")
|
|
74
80
|
from machineconfig.utils.code import run_shell_script
|
|
75
81
|
if Path.home().joinpath("code/machineconfig").exists(): executable = f"""--project "{str(Path.home().joinpath("code/machineconfig"))}" --with textual"""
|
|
76
|
-
else: executable = """--with "machineconfig>=7.
|
|
82
|
+
else: executable = """--with "machineconfig>=7.64,textual" """
|
|
77
83
|
run_shell_script(f"""uv run {executable} {path}""")
|
|
78
84
|
|
|
79
85
|
|
|
@@ -12,7 +12,7 @@ Usage examples:
|
|
|
12
12
|
devops network receive -- --relay 10.17.62.206:443 7121-donor-olympic-bicycle
|
|
13
13
|
devops network receive -- croc --relay 10.17.62.206:443 7121-donor-olympic-bicycle
|
|
14
14
|
"""
|
|
15
|
-
from machineconfig.utils.installer_utils.
|
|
15
|
+
from machineconfig.utils.installer_utils.installer_cli import install_if_missing
|
|
16
16
|
install_if_missing(which="croc")
|
|
17
17
|
import platform
|
|
18
18
|
import sys
|
|
@@ -100,7 +100,7 @@ def share_file_send(path: Annotated[str, typer.Argument(help="Path to the file o
|
|
|
100
100
|
qrcode: Annotated[bool, typer.Option("--qrcode", "--qr", help="Show receive code as a qrcode")] = False,
|
|
101
101
|
) -> None:
|
|
102
102
|
"""Send a file using croc with relay server."""
|
|
103
|
-
from machineconfig.utils.installer_utils.
|
|
103
|
+
from machineconfig.utils.installer_utils.installer_cli import install_if_missing
|
|
104
104
|
install_if_missing(which="croc")
|
|
105
105
|
# Get relay server IP from environment or use default
|
|
106
106
|
import socket
|
|
@@ -40,7 +40,7 @@ def web_file_explorer(
|
|
|
40
40
|
over_internet: Annotated[bool, typer.Option("--over-internet", "-i", help="Expose the share server over the internet using ngrok")] = False,
|
|
41
41
|
backend: Annotated[str, typer.Option("--backend", "-b", help="Backend to use: filebrowser (default), miniserve, or easy-sharing")] = "filebrowser"
|
|
42
42
|
) -> None:
|
|
43
|
-
from machineconfig.utils.installer_utils.
|
|
43
|
+
from machineconfig.utils.installer_utils.installer_cli import install_if_missing
|
|
44
44
|
|
|
45
45
|
if backend not in ["filebrowser", "miniserve", "easy-sharing"]:
|
|
46
46
|
typer.echo(f"❌ ERROR: Invalid backend '{backend}'. Must be one of: filebrowser, miniserve, easy-sharing", err=True)
|
|
@@ -60,7 +60,7 @@ def main(
|
|
|
60
60
|
ssl_ca: Annotated[Optional[str], typer.Option("--ssl-ca", "-A", help="SSL CA file path for client certificate verification")] = None,
|
|
61
61
|
over_internet: Annotated[bool, typer.Option("--over-internet", "-i", help="Expose the terminal over the internet using ngrok")] = False
|
|
62
62
|
) -> None:
|
|
63
|
-
from machineconfig.utils.installer_utils.
|
|
63
|
+
from machineconfig.utils.installer_utils.installer_cli import install_if_missing
|
|
64
64
|
install_if_missing("ttyd")
|
|
65
65
|
if over_internet: install_if_missing("ngrok")
|
|
66
66
|
|
|
@@ -1,79 +1,7 @@
|
|
|
1
1
|
|
|
2
2
|
|
|
3
3
|
import typer
|
|
4
|
-
from typing import Annotated,
|
|
5
|
-
from pathlib import Path
|
|
6
|
-
|
|
7
|
-
def download(
|
|
8
|
-
url: Annotated[Optional[str], typer.Argument(..., help="The URL to download the file from.")] = None,
|
|
9
|
-
decompress: Annotated[bool, typer.Option("--decompress", "-d", help="Decompress the file if it's an archive.")] = False,
|
|
10
|
-
output: Annotated[Optional[str], typer.Option("--output", "-o", help="The output file path.")] = None,
|
|
11
|
-
) -> None:
|
|
12
|
-
if url is None:
|
|
13
|
-
typer.echo("❌ Error: URL is required.", err=True)
|
|
14
|
-
raise typer.Exit(code=1)
|
|
15
|
-
typer.echo(f"📥 Downloading from: {url}")
|
|
16
|
-
download_path = Path(output) if output else Path(url.split("/")[-1])
|
|
17
|
-
import requests
|
|
18
|
-
import subprocess
|
|
19
|
-
try:
|
|
20
|
-
response = requests.get(url, allow_redirects=True, stream=True, timeout=60)
|
|
21
|
-
response.raise_for_status()
|
|
22
|
-
|
|
23
|
-
total_size = int(response.headers.get('content-length', 0))
|
|
24
|
-
|
|
25
|
-
with open(download_path, 'wb') as f:
|
|
26
|
-
if total_size == 0:
|
|
27
|
-
f.write(response.content)
|
|
28
|
-
else:
|
|
29
|
-
downloaded = 0
|
|
30
|
-
chunk_size = 8192
|
|
31
|
-
for chunk in response.iter_content(chunk_size=chunk_size):
|
|
32
|
-
if chunk:
|
|
33
|
-
f.write(chunk)
|
|
34
|
-
downloaded += len(chunk)
|
|
35
|
-
progress = (downloaded / total_size) * 100
|
|
36
|
-
typer.echo(f"\r⏬ Progress: {progress:.1f}% ({downloaded}/{total_size} bytes)", nl=False)
|
|
37
|
-
typer.echo()
|
|
38
|
-
|
|
39
|
-
typer.echo(f"✅ Downloaded to: {download_path}")
|
|
40
|
-
except requests.exceptions.RequestException as e:
|
|
41
|
-
typer.echo(f"❌ Download failed: {e}", err=True)
|
|
42
|
-
raise typer.Exit(code=1)
|
|
43
|
-
except OSError as e:
|
|
44
|
-
typer.echo(f"❌ File write error: {e}", err=True)
|
|
45
|
-
raise typer.Exit(code=1)
|
|
46
|
-
|
|
47
|
-
if decompress:
|
|
48
|
-
typer.echo(f"📦 Decompressing: {download_path}")
|
|
49
|
-
|
|
50
|
-
base_name = download_path.name
|
|
51
|
-
parts = base_name.split('.')
|
|
52
|
-
base_name = parts[0] if parts else download_path.stem
|
|
53
|
-
|
|
54
|
-
extract_dir = download_path.parent / base_name
|
|
55
|
-
extract_dir.mkdir(parents=True, exist_ok=True)
|
|
56
|
-
|
|
57
|
-
try:
|
|
58
|
-
subprocess.run(
|
|
59
|
-
["ouch", "decompress", str(download_path), "--dir", str(extract_dir)],
|
|
60
|
-
check=True,
|
|
61
|
-
capture_output=True,
|
|
62
|
-
text=True
|
|
63
|
-
)
|
|
64
|
-
typer.echo(f"✅ Decompressed to: {extract_dir}")
|
|
65
|
-
|
|
66
|
-
if download_path.exists():
|
|
67
|
-
download_path.unlink()
|
|
68
|
-
typer.echo(f"🗑️ Removed archive: {download_path}")
|
|
69
|
-
|
|
70
|
-
except subprocess.CalledProcessError as e:
|
|
71
|
-
typer.echo(f"❌ Decompression failed: {e.stderr}", err=True)
|
|
72
|
-
raise typer.Exit(code=1)
|
|
73
|
-
except FileNotFoundError:
|
|
74
|
-
typer.echo("❌ Error: ouch command not found. Please install ouch.", err=True)
|
|
75
|
-
typer.echo("💡 Install with: cargo install ouch", err=True)
|
|
76
|
-
raise typer.Exit(code=1)
|
|
4
|
+
from typing import Annotated, Optional
|
|
77
5
|
|
|
78
6
|
|
|
79
7
|
def merge_pdfs(
|
|
@@ -165,82 +93,3 @@ def compress_pdf(
|
|
|
165
93
|
uv_command, _py_file = get_uv_command_executing_python_script(python_script=code, uv_with=["pymupdf"], uv_project_dir=None)
|
|
166
94
|
run_shell_script(uv_command)
|
|
167
95
|
|
|
168
|
-
|
|
169
|
-
class MachineSpecs(TypedDict):
|
|
170
|
-
system: str
|
|
171
|
-
distro: str
|
|
172
|
-
home_dir: str
|
|
173
|
-
def get_machine_specs() -> MachineSpecs:
|
|
174
|
-
"""Write print and return the local machine specs."""
|
|
175
|
-
import platform
|
|
176
|
-
UV_RUN_CMD = "$HOME/.local/bin/uv run" if platform.system() != "Windows" else """& "$env:USERPROFILE/.local/bin/uv" run"""
|
|
177
|
-
command = f"""{UV_RUN_CMD} --with distro python -c "import distro; print(distro.name(pretty=True))" """
|
|
178
|
-
import subprocess
|
|
179
|
-
distro = subprocess.run(command, shell=True, capture_output=True, text=True).stdout.strip()
|
|
180
|
-
specs: MachineSpecs = {
|
|
181
|
-
"system": platform.system(),
|
|
182
|
-
"distro": distro,
|
|
183
|
-
"home_dir": str(Path.home()),
|
|
184
|
-
}
|
|
185
|
-
print(specs)
|
|
186
|
-
from machineconfig.utils.source_of_truth import CONFIG_ROOT
|
|
187
|
-
path = CONFIG_ROOT.joinpath("machine_specs.json")
|
|
188
|
-
CONFIG_ROOT.mkdir(parents=True, exist_ok=True)
|
|
189
|
-
import json
|
|
190
|
-
path.write_text(json.dumps(specs, indent=4), encoding="utf-8")
|
|
191
|
-
return specs
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
def init_project(python: Annotated[Literal["3.13", "3.14"], typer.Option("--python", "-p", help="Python version for the uv virtual environment.")]= "3.13") -> None:
|
|
195
|
-
_ = python
|
|
196
|
-
repo_root = Path.cwd()
|
|
197
|
-
if not (repo_root / "pyproject.toml").exists():
|
|
198
|
-
typer.echo("❌ Error: pyproject.toml not found.", err=True)
|
|
199
|
-
raise typer.Exit(code=1)
|
|
200
|
-
print("Adding group `plot` with common data science and plotting packages...")
|
|
201
|
-
script = """
|
|
202
|
-
uv add --group plot \
|
|
203
|
-
# Data & computation
|
|
204
|
-
numpy pandas polars duckdb-engine python-magic \
|
|
205
|
-
# Plotting / visualization
|
|
206
|
-
matplotlib plotly kaleido \
|
|
207
|
-
# Notebooks / interactive
|
|
208
|
-
ipython ipykernel jupyterlab nbformat marimo \
|
|
209
|
-
# Code analysis / type checking / linting
|
|
210
|
-
mypy pyright ruff pylint pyrefly \
|
|
211
|
-
# Packaging / build / dev
|
|
212
|
-
cleanpy \
|
|
213
|
-
# CLI / debugging / utilities
|
|
214
|
-
ipdb pudb \
|
|
215
|
-
# Type hints for packages
|
|
216
|
-
types-python-dateutil types-pyyaml types-requests types-tqdm \
|
|
217
|
-
types-mysqlclient types-paramiko types-pytz types-sqlalchemy types-toml types-urllib3 \
|
|
218
|
-
|
|
219
|
-
"""
|
|
220
|
-
from machineconfig.utils.code import run_shell_script
|
|
221
|
-
run_shell_script(script)
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
def edit(path: Annotated[Optional[str], typer.Argument(..., help="The root directory of the project to edit, or a file path.")] = None) -> None:
|
|
225
|
-
if path is None:
|
|
226
|
-
root_path = Path.cwd()
|
|
227
|
-
print(f"No path provided. Using current working directory: {root_path}")
|
|
228
|
-
else:
|
|
229
|
-
root_path = Path(path).expanduser().resolve()
|
|
230
|
-
print(f"Using provided path: {root_path}")
|
|
231
|
-
from machineconfig.utils.accessories import get_repo_root
|
|
232
|
-
repo_root = get_repo_root(root_path)
|
|
233
|
-
if repo_root is not None and repo_root.joinpath("pyproject.toml").exists():
|
|
234
|
-
code = f"""
|
|
235
|
-
cd {repo_root}
|
|
236
|
-
uv add --dev pylsp-mypy python-lsp-server[all] pyright ruff-lsp # for helix editor.
|
|
237
|
-
source ./.venv/bin/activate
|
|
238
|
-
"""
|
|
239
|
-
else:
|
|
240
|
-
code = ""
|
|
241
|
-
if root_path.is_file():
|
|
242
|
-
code += f"hx {root_path}"
|
|
243
|
-
else:
|
|
244
|
-
code += "hx"
|
|
245
|
-
from machineconfig.utils.code import exit_then_run_shell_script
|
|
246
|
-
exit_then_run_shell_script(code)
|