diff --git a/backend/plugin/tools.py b/backend/plugin/tools.py index ff29cde7..53a2eb77 100644 --- a/backend/plugin/tools.py +++ b/backend/plugin/tools.py @@ -1,9 +1,14 @@ #!/usr/bin/env python3 # -*- coding: utf-8 -*- +import asyncio import inspect import os +import subprocess +import sys import warnings +from asyncio import subprocess as async_subprocess + import rtoml from fastapi import APIRouter @@ -119,3 +124,42 @@ def plugin_router_inject() -> None: # 将插件路由注入到目标 router 中 target_router.include_router(plugin_router) + + +def install_requirements() -> None: + """安装插件依赖""" + plugins = get_plugins() + for plugin in plugins: + requirements_file = os.path.join(PLUGIN_DIR, plugin, 'requirements.txt') + if not os.path.exists(requirements_file): + continue + else: + try: + subprocess.run([sys.executable, '-m', 'ensurepip', '--upgrade']) + subprocess.check_call([sys.executable, '-m', 'pip', 'install', '-r', requirements_file]) + except subprocess.CalledProcessError as e: + raise EnvironmentError(f'插件 {plugin} 依赖安装失败:{e}') from e + + +async def install_requirements_async() -> None: + """异步安装插件依赖""" + plugins = get_plugins() + for plugin in plugins: + requirements_file = os.path.join(PLUGIN_DIR, plugin, 'requirements.txt') + if not os.path.exists(requirements_file): + continue + else: + await async_subprocess.create_subprocess_exec(sys.executable, '-m', 'ensurepip', '--upgrade') + res = await async_subprocess.create_subprocess_exec( + sys.executable, + '-m', + 'pip', + 'install', + '-r', + requirements_file, + stdout=asyncio.subprocess.PIPE, + stderr=asyncio.subprocess.PIPE, + ) + _, stderr = await res.communicate() + if res.returncode != 0: + raise EnvironmentError(f'插件 {plugin} 依赖包安装失败:{stderr}') diff --git a/backend/scripts/init_data.py b/backend/scripts/init_data.py index 9da8ddff..72b11267 100644 --- a/backend/scripts/init_data.py +++ b/backend/scripts/init_data.py @@ -1,23 +1,15 @@ #!/usr/bin/env python3 # -*- coding: utf-8 -*- # ruff: noqa: I001 -from backend.database.db import create_table -import logging -import sys - from anyio import run -sys.path.append('../') - - -logging.basicConfig(level=logging.INFO) -logger = logging.getLogger(__name__) +from backend.database.db import create_table async def init() -> None: - logger.info('Creating initial data') + print('Creating initial data') await create_table() - logger.info('Initial data created') + print('Initial data created') if __name__ == '__main__': diff --git a/backend/scripts/init_plugin.py b/backend/scripts/init_plugin.py new file mode 100644 index 00000000..70cb001a --- /dev/null +++ b/backend/scripts/init_plugin.py @@ -0,0 +1,16 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- +# ruff: noqa: I001 +from anyio import run + +from backend.plugin.tools import install_requirements_async + + +async def init() -> None: + print('Starting initial plugin') + await install_requirements_async() + print('Plugin successfully installed') + + +if __name__ == '__main__': + run(init) # type: ignore