Files
nocobase-mcp/scripts/agent_installer/common.py
T

90 lines
1.9 KiB
Python

from __future__ import annotations
import argparse
import json
import os
import re
import shutil
import subprocess
import sys
import tempfile
from collections.abc import Callable, Sequence
from dataclasses import asdict, dataclass
from pathlib import Path
from typing import Any
from urllib.parse import urlsplit, urlunsplit
MIN_PYTHON = (3, 12)
DEFAULT_ENV_NAME = "nb-mcp"
SERVER_NAME = "nocobase-crm"
REQUIRED_PROJECT_FILES = ("pyproject.toml", "uv.lock", "config.example.json")
ENV_NAME_PATTERN = re.compile(r"^[A-Za-z0-9][A-Za-z0-9._-]{0,63}$")
ANSI_ESCAPE_PATTERN = re.compile(r"\x1b\[[0-?]*[ -/]*[@-~]")
Which = Callable[[str], str | None]
Runner = Callable[..., subprocess.CompletedProcess[str]]
class InstallerError(RuntimeError):
"""Raised when a deterministic installation step cannot finish safely."""
@dataclass(frozen=True)
class Check:
name: str
ok: bool
required: bool
detail: str
def _project_root(path: str | Path | None) -> Path:
candidate = Path(path) if path is not None else Path(__file__).resolve().parent.parent
return candidate.expanduser().resolve()
def _load_json_object(path: Path) -> dict[str, Any]:
try:
value = json.loads(path.read_text(encoding="utf-8"))
except (OSError, json.JSONDecodeError) as error:
raise InstallerError(f"Could not read valid JSON from {path}: {error}") from error
if not isinstance(value, dict):
raise InstallerError(f"Expected a JSON object in {path}")
return value
__all__ = [
"ANSI_ESCAPE_PATTERN",
"Any",
"Callable",
"Check",
"DEFAULT_ENV_NAME",
"ENV_NAME_PATTERN",
"InstallerError",
"MIN_PYTHON",
"Path",
"REQUIRED_PROJECT_FILES",
"Runner",
"SERVER_NAME",
"Sequence",
"Which",
"_load_json_object",
"_project_root",
"argparse",
"asdict",
"json",
"os",
"re",
"shutil",
"subprocess",
"sys",
"tempfile",
"urlsplit",
"urlunsplit",
]