94bf3b8195
* Initial plan * Fix type annotation errors in cmd_conf, cmd_init, and version_comparator Co-authored-by: LIghtJUNction <106986785+LIghtJUNction@users.noreply.github.com> * Changes before error encountered Co-authored-by: LIghtJUNction <106986785+LIghtJUNction@users.noreply.github.com> * Fix more type annotation errors: change `= None` to `| None = None` Co-authored-by: LIghtJUNction <106986785+LIghtJUNction@users.noreply.github.com> * Fix final batch of type annotation errors Co-authored-by: LIghtJUNction <106986785+LIghtJUNction@users.noreply.github.com> --------- Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com> Co-authored-by: LIghtJUNction <106986785+LIghtJUNction@users.noreply.github.com> Co-authored-by: LIghtJUNction <lightjunction.me@gmail.com>
63 lines
1.9 KiB
Python
63 lines
1.9 KiB
Python
import asyncio
|
|
import logging
|
|
import sys
|
|
|
|
logger = logging.getLogger("astrbot")
|
|
|
|
|
|
class PipInstaller:
|
|
def __init__(self, pip_install_arg: str, pypi_index_url: str | None = None):
|
|
self.pip_install_arg = pip_install_arg
|
|
self.pypi_index_url = pypi_index_url
|
|
|
|
async def install(
|
|
self,
|
|
package_name: str | None = None,
|
|
requirements_path: str | None = None,
|
|
mirror: str | None = None,
|
|
):
|
|
args = ["install"]
|
|
if package_name:
|
|
args.append(package_name)
|
|
elif requirements_path:
|
|
args.extend(["-r", requirements_path])
|
|
|
|
index_url = mirror or self.pypi_index_url or "https://pypi.org/simple"
|
|
|
|
args.extend(["--trusted-host", "mirrors.aliyun.com", "-i", index_url])
|
|
|
|
if self.pip_install_arg:
|
|
args.extend(self.pip_install_arg.split())
|
|
|
|
logger.info(f"Pip 包管理器: pip {' '.join(args)}")
|
|
try:
|
|
process = await asyncio.create_subprocess_exec(
|
|
sys.executable,
|
|
"-m",
|
|
"pip",
|
|
*args,
|
|
stdout=asyncio.subprocess.PIPE,
|
|
stderr=asyncio.subprocess.STDOUT,
|
|
)
|
|
|
|
assert process.stdout is not None
|
|
async for line in process.stdout:
|
|
logger.info(line.decode().strip())
|
|
|
|
await process.wait()
|
|
|
|
if process.returncode != 0:
|
|
raise Exception(f"安装失败,错误码:{process.returncode}")
|
|
except FileNotFoundError:
|
|
# 没有 pip
|
|
from pip import main as pip_main
|
|
|
|
result_code = await asyncio.to_thread(pip_main, args)
|
|
|
|
# 清除 pip.main 导致的多余的 logging handlers
|
|
for handler in logging.root.handlers[:]:
|
|
logging.root.removeHandler(handler)
|
|
|
|
if result_code != 0:
|
|
raise Exception(f"安装失败,错误码:{result_code}")
|