|
1 | 1 | from pathlib import Path |
| 2 | +from subprocess import CompletedProcess |
2 | 3 |
|
3 | 4 | import typer |
4 | 5 | from rich.console import Console |
@@ -105,27 +106,53 @@ def _remove_plugin_from_config(config_path: Path, plugin_name: str) -> bool: |
105 | 106 | return False |
106 | 107 |
|
107 | 108 |
|
| 109 | +def _run_package_command(*, action: str, package: str) -> CompletedProcess[str]: |
| 110 | + import subprocess |
| 111 | + import sys |
| 112 | + |
| 113 | + if action == "install": |
| 114 | + commands = [ |
| 115 | + ["uv", "pip", "install", "--python", sys.executable, "--", package], |
| 116 | + [sys.executable, "-m", "pip", "install", package], |
| 117 | + ] |
| 118 | + elif action == "uninstall": |
| 119 | + commands = [ |
| 120 | + ["uv", "pip", "uninstall", "--python", sys.executable, package], |
| 121 | + [sys.executable, "-m", "pip", "uninstall", "-y", package], |
| 122 | + ] |
| 123 | + else: |
| 124 | + raise ValueError(f"Unsupported package action: {action}") |
| 125 | + |
| 126 | + last_error: OSError | None = None |
| 127 | + for command in commands: |
| 128 | + try: |
| 129 | + return subprocess.run( |
| 130 | + command, |
| 131 | + capture_output=True, |
| 132 | + text=True, |
| 133 | + ) |
| 134 | + except OSError as e: |
| 135 | + last_error = e |
| 136 | + |
| 137 | + if last_error is not None: |
| 138 | + raise last_error |
| 139 | + |
| 140 | + raise RuntimeError("No package command was attempted") |
| 141 | + |
| 142 | + |
108 | 143 | def plugin_add_command( |
109 | 144 | *, |
110 | 145 | package: str, |
111 | 146 | no_setup: bool, |
112 | 147 | config_path: Path, |
113 | 148 | ) -> None: |
114 | | - import subprocess |
115 | | - import sys |
116 | | - |
117 | 149 | typer.echo(f"Installing {package}...") |
118 | 150 | installed_before = get_installed_plugin_names() |
119 | | - install_cmd = ["uv", "pip", "install", "--python", sys.executable, "--", package] |
120 | 151 |
|
121 | 152 | try: |
122 | | - result = subprocess.run( |
123 | | - install_cmd, |
124 | | - capture_output=True, |
125 | | - text=True, |
126 | | - ) |
| 153 | + result = _run_package_command(action="install", package=package) |
127 | 154 | except OSError as e: |
128 | | - typer.echo(f"Installation failed: could not execute '{install_cmd[0]}': {e}") |
| 155 | + typer.echo(f"Installation failed: could not execute a package installer: {e}") |
129 | 156 | raise typer.Exit(1) from e |
130 | 157 |
|
131 | 158 | if result.returncode != 0: |
@@ -165,21 +192,13 @@ def plugin_remove_command( |
165 | 192 | package: str, |
166 | 193 | config_path: Path, |
167 | 194 | ) -> None: |
168 | | - import subprocess |
169 | | - import sys |
170 | | - |
171 | 195 | typer.echo(f"Removing {package}...") |
172 | 196 | installed_before = get_installed_plugin_names() |
173 | | - uninstall_cmd = ["uv", "pip", "uninstall", "--python", sys.executable, package] |
174 | 197 |
|
175 | 198 | try: |
176 | | - result = subprocess.run( |
177 | | - uninstall_cmd, |
178 | | - capture_output=True, |
179 | | - text=True, |
180 | | - ) |
| 199 | + result = _run_package_command(action="uninstall", package=package) |
181 | 200 | except OSError as e: |
182 | | - typer.echo(f"Removal failed: could not execute '{uninstall_cmd[0]}': {e}") |
| 201 | + typer.echo(f"Removal failed: could not execute a package installer: {e}") |
183 | 202 | raise typer.Exit(1) from e |
184 | 203 |
|
185 | 204 | if result.returncode != 0: |
@@ -248,7 +267,7 @@ def plugin_list_command( |
248 | 267 | config_path: Path, |
249 | 268 | console: Console, |
250 | 269 | ) -> None: |
251 | | - discovered = discover_plugins() |
| 270 | + discovered = discover_plugins(rules_path=config_path.parent.resolve() / "rules.toml") |
252 | 271 | discovered_names = {name for name, _ in discovered} |
253 | 272 |
|
254 | 273 | config_plugins = {} |
|
0 commit comments