Files
NyaHome/src/nyahome/cli/cli_check.py
T
MangoFanFanw ad3bafcd35 feat(cli): 实现 nyahome config 命令
允许通过 nyahome 终端命令修改设置
同时再次调整数据库有关的内部常量的位置
2026-06-06 10:04:26 +08:00

170 lines
5.6 KiB
Python

import json
from importlib.metadata import distribution
from importlib.util import find_spec
from pathlib import Path
from typing import Mapping
from nyahome.cli.cli import console
from nyahome.data import db_type_allowlist, db_driver_available
class CliWarning:
def __init__(self) -> None:
self.counter = 0
def info(self, description: str) -> None:
console.print(f"INFO - {description}")
def warning(self, description: str) -> None:
self.counter += 1
console.print(f"[yellow]WARNING {self.counter}[/yellow] - {description}")
cw = CliWarning()
def check_database_connector() -> dict[str, str]:
"""
检查是否安装用于数据库连接的各种驱动库。只有安装对应的驱动库之后才可以连接到对应的数据库。
Returns:
{驱动库: 可用状态描述}
"""
def _(value: bool, description: str) -> str:
return f"{'[green]可用[/green]' if value else '[yellow]不可用[/yellow]'} - {description}"
result: dict[str, str] = {
"sqlite3": _(bool(find_spec("sqlite3")), "Python 标准库,支持 sqlite"),
"pymysql": _(bool(find_spec("pymysql")), "社区维护的 MySQL 驱动库"),
"psycopg": _(bool(find_spec("psycopg")), "更先进的 PostgreSQL 驱动库"),
}
return result
def check_database_type(environ: Mapping[str, str | None]) -> None:
db_type = environ.get("NYAHOME_DB_TYPE")
db_driver = environ.get("NYAHOME_DB_DRIVER")
db_name = environ.get("NYAHOME_DB_NAME")
db_user = environ.get("NYAHOME_DB_USER")
db_password = environ.get("NYAHOME_DB_PASSWORD")
db_host = environ.get("NYAHOME_DB_HOST")
db_port = environ.get("NYAHOME_DB_PORT")
if not db_type:
cw.warning("NYAHOME_DB_TYPE 未设置,将回退到默认数据库 sqlite。")
elif db_type not in db_type_allowlist:
cw.warning(f"NYAHOME_DB_TYPE 的值 {db_type} 不受 NyaHome 官方支持。")
if not db_driver:
cw.warning("NYAHOME_DB_DRIVER 未设置,将使用 SQLModel 的默认驱动库。")
elif not find_spec(db_driver):
cw.warning(f"NYAHOME_DB_DRIVER 的值 {db_driver} 未在当前 NyaHome 中安装。")
elif db_type and (db_driver not in db_driver_available.get(db_type, [])):
cw.warning(f"NYAHOME_DB_DRIVER 的值 {db_driver} 是为数据库 {db_type} 准备的吗?")
if db_driver and db_type != "sqlite": # 对于 sqlite 数据库,不需要设置凭证
if not db_name:
cw.warning("NYAHOME_DB_NAME 未设置,将使用 [cyan]nyahome[/cyan] 作为默认值。")
if not db_user:
cw.warning("NYAHOME_DB_USER 未设置,将使用 [cyan]nyahome[/cyan] 作为默认值。")
if not db_password:
cw.warning("NYAHOME_DB_PASSWORD 未设置,将使用 [cyan]nyahome[/cyan] 作为默认值。")
if not db_host:
cw.warning("NYAHOME_DB_HOST 未设置,将使用 [cyan]localhost[/cyan] 作为默认值。")
if not db_port:
cw.warning("NYAHOME_DB_PORT 未设置,将使用 [cyan]3306[/cyan] 作为默认值。")
cw.info("自检未检查数据库状态是否可用。")
else:
cw.info("使用 sqlite 数据库,跳过数据库凭证检查。")
def check_uvicorn(environ: Mapping[str, str | None]) -> None:
un_host = environ.get("NYAHOME_UVICORN_HOST")
un_port = environ.get("NYAHOME_UVICORN_PORT")
un_reload = environ.get("NYAHOME_UVICORN_RELOAD")
if not un_host:
cw.warning("NYAHOME_UVICORN_HOST 未设置,将使用 [cyan]0.0.0.0[/cyan] 作为默认值。")
if not un_port:
cw.warning("NYAHOME_UVICORN_PORT 未设置,将使用 [cyan]9000[/cyan] 作为默认值。")
if not un_reload:
cw.warning("NYAHOME_UVICORN_RELOAD 未设置,将使用 [cyan]false[/cyan] 作为默认值。")
else:
if un_reload in ["True", "true", "1"]:
cw.warning("NYAHOME_UVICORN_RELOAD 设置为 [cyan]true[/cyan],在生产环境中不应如此。")
def check_nyahome_status() -> None:
# 检查是否以可编辑模式安装 NyaHome
dist = distribution("nyahome")
try:
f = dist.read_text("direct_url.json")
if f:
data = json.loads(f)
if data.get("dir_info", {}).get("editable", False):
cw.warning("当前 NyaHome 以可编辑模式安装。在生产环境中不应如此。")
except Exception:
pass
# 检查 NyaHome 是否受 git 管理
git_dir = Path.cwd() / ".git"
if git_dir.is_dir():
cw.warning("当前 NyaHome 受版本控制系统管理。在生产环境中不应如此。")
LOGGING_YAML_CONTENT = """version: 1
disable_existing_loggers: false
formatters:
default:
"()": uvicorn.logging.DefaultFormatter
fmt: "%(asctime)s | %(levelprefix)s %(name)s | %(message)s"
use_colors: true
access:
"()": uvicorn.logging.AccessFormatter
fmt: '%(asctime)s | %(client_addr)s - "%(request_line)s" %(status_code)s'
use_colors: true
handlers:
default:
formatter: default
class: logging.StreamHandler
stream: ext://sys.stderr
access:
formatter: access
class: logging.StreamHandler
stream: ext://sys.stdout
file:
formatter: default
class: logging.handlers.RotatingFileHandler
filename: .nyahome/app.log
maxBytes: 10485760
backupCount: 5
encoding: utf8
loggers:
uvicorn:
handlers: [ default, file ]
level: INFO
propagate: false
uvicorn.error:
handlers: [ default, file ]
level: INFO
propagate: false
uvicorn.access:
handlers: [ access, file ]
level: INFO
propagate: false
nyahome:
handlers: [ default, file ]
level: DEBUG
propagate: false"""