✨ feat: 实现部分aide
This commit is contained in:
1
aide-program/aide/env/__init__.py
vendored
Normal file
1
aide-program/aide/env/__init__.py
vendored
Normal file
@@ -0,0 +1 @@
|
||||
# 环境检测相关模块
|
||||
119
aide-program/aide/env/ensure.py
vendored
Normal file
119
aide-program/aide/env/ensure.py
vendored
Normal file
@@ -0,0 +1,119 @@
|
||||
"""环境检测与修复逻辑。"""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import platform
|
||||
import subprocess
|
||||
import sys
|
||||
from pathlib import Path
|
||||
|
||||
from aide.core import output
|
||||
from aide.core.config import ConfigManager
|
||||
|
||||
|
||||
class EnvManager:
|
||||
def __init__(self, root: Path):
|
||||
self.root = root
|
||||
|
||||
def ensure(self, runtime_only: bool, cfg: ConfigManager) -> bool:
|
||||
"""运行环境检测入口。"""
|
||||
required_py = self._get_required_python(cfg, runtime_only)
|
||||
if not self._check_python_version(required_py):
|
||||
return False
|
||||
uv_version = self._check_uv()
|
||||
if uv_version is None:
|
||||
return False
|
||||
|
||||
if runtime_only:
|
||||
output.ok(f"运行时环境就绪 (python:{platform.python_version()}, uv:{uv_version})")
|
||||
return True
|
||||
|
||||
config = cfg.ensure_config()
|
||||
cfg.ensure_gitignore()
|
||||
|
||||
env_config = config.get("env", {})
|
||||
venv_path = self.root / env_config.get("venv", ".venv")
|
||||
req_path = self.root / env_config.get("requirements", "requirements.txt")
|
||||
|
||||
self._ensure_requirements_file(req_path)
|
||||
if not self._ensure_venv(venv_path):
|
||||
return False
|
||||
if not self._install_requirements(venv_path, req_path):
|
||||
return False
|
||||
|
||||
task_config = config.get("task", {})
|
||||
output.info(f"任务原文档: {task_config.get('source', 'task-now.md')}")
|
||||
output.info(f"任务细则文档: {task_config.get('spec', 'task-spec.md')}")
|
||||
output.ok(f"环境就绪 (python:{platform.python_version()}, uv:{uv_version}, venv:{venv_path})")
|
||||
return True
|
||||
|
||||
@staticmethod
|
||||
def _get_required_python(cfg: ConfigManager, runtime_only: bool) -> str:
|
||||
if runtime_only:
|
||||
return "3.11"
|
||||
data = cfg.load_config()
|
||||
runtime = data.get("runtime", {})
|
||||
return str(runtime.get("python_min", "3.11"))
|
||||
|
||||
@staticmethod
|
||||
def _parse_version(version: str) -> tuple[int, ...]:
|
||||
parts = []
|
||||
for part in version.split("."):
|
||||
try:
|
||||
parts.append(int(part))
|
||||
except ValueError:
|
||||
break
|
||||
return tuple(parts)
|
||||
|
||||
def _check_python_version(self, required: str) -> bool:
|
||||
current = self._parse_version(platform.python_version())
|
||||
target = self._parse_version(required)
|
||||
if current >= target:
|
||||
return True
|
||||
output.err(f"Python 版本不足,要求>={required},当前 {platform.python_version()}")
|
||||
return False
|
||||
|
||||
def _check_uv(self) -> str | None:
|
||||
try:
|
||||
result = subprocess.run(
|
||||
["uv", "--version"],
|
||||
check=True,
|
||||
capture_output=True,
|
||||
text=True,
|
||||
)
|
||||
return result.stdout.strip()
|
||||
except (subprocess.CalledProcessError, FileNotFoundError) as exc:
|
||||
output.err(f"未检测到 uv,请先安装({exc})")
|
||||
return None
|
||||
|
||||
def _ensure_venv(self, venv_path: Path) -> bool:
|
||||
if venv_path.exists():
|
||||
return True
|
||||
output.info(f"创建虚拟环境: {venv_path}")
|
||||
try:
|
||||
subprocess.run(["uv", "venv", str(venv_path)], check=True)
|
||||
output.ok("已创建虚拟环境")
|
||||
return True
|
||||
except subprocess.CalledProcessError as exc:
|
||||
output.err(f"创建虚拟环境失败: {exc}")
|
||||
return False
|
||||
|
||||
@staticmethod
|
||||
def _ensure_requirements_file(req_path: Path) -> None:
|
||||
if req_path.exists():
|
||||
return
|
||||
req_path.write_text("# 在此添加依赖\n", encoding="utf-8")
|
||||
output.warn(f"未找到 {req_path.name},已创建空文件")
|
||||
|
||||
def _install_requirements(self, venv_path: Path, req_path: Path) -> bool:
|
||||
if not req_path.exists():
|
||||
output.err(f"缺少 {req_path}")
|
||||
return False
|
||||
cmd = ["uv", "pip", "install", "-r", str(req_path), "--python", str(venv_path)]
|
||||
output.info("安装依赖(uv pip install -r requirements.txt)")
|
||||
try:
|
||||
subprocess.run(cmd, check=True, stdout=subprocess.DEVNULL, stderr=subprocess.STDOUT)
|
||||
return True
|
||||
except subprocess.CalledProcessError as exc:
|
||||
output.err(f"安装依赖失败: {exc}")
|
||||
return False
|
||||
Reference in New Issue
Block a user