88import warnings
99
1010from functools import lru_cache
11+ from importlib .metadata import PackageNotFoundError , distribution
1112from typing import Any
1213
1314import rtoml
1415
1516from fastapi import APIRouter , Depends , Request
17+ from packaging .requirements import Requirement
1618from starlette .concurrency import run_in_threadpool
1719
1820from backend .common .enums import StatusType
@@ -33,6 +35,10 @@ class PluginInjectError(Exception):
3335 """插件注入错误"""
3436
3537
38+ class PluginInstallError (Exception ):
39+ """插件安装错误"""
40+
41+
3642@lru_cache
3743def get_plugins () -> list [str ]:
3844 """获取插件列表"""
@@ -262,7 +268,24 @@ def install_requirements(plugin: str | None) -> None:
262268
263269 for plugin in plugins :
264270 requirements_file = os .path .join (PLUGIN_DIR , plugin , 'requirements.txt' )
271+ missing_dependencies = False
265272 if os .path .exists (requirements_file ):
273+ with open (requirements_file , 'r' , encoding = 'utf-8' ) as f :
274+ for line in f :
275+ line = line .strip ()
276+ if not line or line .startswith ('#' ):
277+ continue
278+ try :
279+ req = Requirement (line )
280+ dependency = req .name .lower ()
281+ except Exception as e :
282+ raise PluginInstallError (f'插件 { plugin } 依赖 { line } 格式错误: { str (e )} ' ) from e
283+ try :
284+ distribution (dependency )
285+ except PackageNotFoundError :
286+ missing_dependencies = True
287+
288+ if missing_dependencies :
266289 try :
267290 ensurepip_install = [sys .executable , '-m' , 'ensurepip' , '--upgrade' ]
268291 pip_install = [sys .executable , '-m' , 'pip' , 'install' , '-r' , requirements_file ]
@@ -271,7 +294,7 @@ def install_requirements(plugin: str | None) -> None:
271294 subprocess .check_call (ensurepip_install , stdout = subprocess .DEVNULL , stderr = subprocess .DEVNULL )
272295 subprocess .check_call (pip_install , stdout = subprocess .DEVNULL , stderr = subprocess .DEVNULL )
273296 except subprocess .CalledProcessError as e :
274- raise PluginInjectError (f'插件 { plugin } 依赖安装失败:{ e . stderr } ' ) from e
297+ raise PluginInstallError (f'插件 { plugin } 依赖安装失败:{ e } ' ) from e
275298
276299
277300def uninstall_requirements (plugin : str ) -> None :
@@ -285,9 +308,9 @@ def uninstall_requirements(plugin: str) -> None:
285308 if os .path .exists (requirements_file ):
286309 try :
287310 pip_uninstall = [sys .executable , '-m' , 'pip' , 'uninstall' , '-r' , requirements_file , '-y' ]
288- subprocess .check_call (pip_uninstall )
311+ subprocess .check_call (pip_uninstall , stdout = subprocess . DEVNULL , stderr = subprocess . DEVNULL )
289312 except subprocess .CalledProcessError as e :
290- raise PluginInjectError (f'插件 { plugin } 依赖卸载失败:{ e . stderr } ' ) from e
313+ raise PluginInstallError (f'插件 { plugin } 依赖卸载失败:{ e } ' ) from e
291314
292315
293316async def install_requirements_async (plugin : str | None = None ) -> None :
0 commit comments