mirror of
https://github.com/fastapi-practices/fastapi-best-architecture.git
synced 2026-09-21 13:12:24 +00:00
Update the plugin dependency install method (#1007)
This commit is contained in:
@@ -1,6 +1,5 @@
|
||||
import os
|
||||
import subprocess
|
||||
import sys
|
||||
|
||||
from importlib.metadata import PackageNotFoundError, distribution
|
||||
|
||||
@@ -15,61 +14,6 @@ class PluginInstallError(Exception):
|
||||
"""插件安装错误"""
|
||||
|
||||
|
||||
def _ensure_pip_available() -> bool:
|
||||
"""确保 pip 在虚拟环境中可用"""
|
||||
try:
|
||||
result = subprocess.run([sys.executable, '-m', 'pip', '--version'], capture_output=True, text=True)
|
||||
if result.returncode == 0:
|
||||
return True
|
||||
except (subprocess.TimeoutExpired, subprocess.SubprocessError, FileNotFoundError):
|
||||
pass
|
||||
|
||||
# 尝试使用 ensurepip
|
||||
try:
|
||||
subprocess.check_call(
|
||||
[sys.executable, '-m', 'ensurepip', '--default-pip'],
|
||||
stdout=subprocess.DEVNULL,
|
||||
stderr=subprocess.DEVNULL,
|
||||
)
|
||||
result = subprocess.run([sys.executable, '-m', 'pip', '--version'], capture_output=True, text=True)
|
||||
if result.returncode == 0:
|
||||
return True
|
||||
except (subprocess.CalledProcessError, subprocess.TimeoutExpired, subprocess.SubprocessError, FileNotFoundError):
|
||||
pass
|
||||
|
||||
# 尝试下载并安装
|
||||
try:
|
||||
import os
|
||||
import tempfile
|
||||
|
||||
import httpx
|
||||
|
||||
try:
|
||||
with tempfile.NamedTemporaryFile(mode='w', suffix='.py', delete=False) as f:
|
||||
with httpx.Client(timeout=3) as client:
|
||||
get_pip_url = 'https://bootstrap.pypa.io/get-pip.py'
|
||||
response = client.get(get_pip_url)
|
||||
response.raise_for_status()
|
||||
f.write(response.text)
|
||||
temp_file = f.name
|
||||
except Exception: # noqa: ignore
|
||||
return False
|
||||
|
||||
try:
|
||||
subprocess.check_call([sys.executable, temp_file], stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)
|
||||
result = subprocess.run([sys.executable, '-m', 'pip', '--version'], capture_output=True, text=True)
|
||||
return result.returncode == 0
|
||||
finally:
|
||||
try:
|
||||
os.unlink(temp_file)
|
||||
except OSError:
|
||||
pass
|
||||
except Exception: # noqa: ignore
|
||||
pass
|
||||
|
||||
return False
|
||||
|
||||
|
||||
def get_plugins() -> list[str]:
|
||||
"""
|
||||
获取插件列表
|
||||
@@ -111,10 +55,7 @@ def install_requirements(plugin: str | None) -> None: # noqa: C901
|
||||
|
||||
if missing_dependencies:
|
||||
try:
|
||||
if not _ensure_pip_available():
|
||||
raise PluginInstallError(f'pip 安装失败,无法继续安装插件 {plugin} 依赖')
|
||||
|
||||
pip_install = [sys.executable, '-m', 'pip', 'install', '-r', requirements_file]
|
||||
pip_install = ['uv', 'pip', 'install', '-r', requirements_file]
|
||||
if settings.PLUGIN_PIP_CHINA:
|
||||
pip_install.extend(['-i', settings.PLUGIN_PIP_INDEX_URL])
|
||||
|
||||
@@ -149,7 +90,7 @@ def uninstall_requirements(plugin: str) -> None:
|
||||
requirements_file = PLUGIN_DIR / plugin / 'requirements.txt'
|
||||
if os.path.exists(requirements_file):
|
||||
try:
|
||||
pip_uninstall = [sys.executable, '-m', 'pip', 'uninstall', '-r', requirements_file, '-y']
|
||||
pip_uninstall = ['uv', 'pip', 'uninstall', '-r', str(requirements_file), '-y']
|
||||
subprocess.check_call(pip_uninstall, stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)
|
||||
except subprocess.CalledProcessError as e:
|
||||
raise PluginInstallError(f'插件 {plugin} 依赖卸载失败:{e}') from e
|
||||
|
||||
Reference in New Issue
Block a user