feat(cli): 部分完成 nyahome init 和 check 命令
This commit is contained in:
+10
-1
@@ -4,4 +4,13 @@ from rich.console import Console
|
||||
|
||||
console = Console()
|
||||
|
||||
ENV_PATH = Path.cwd() / ".nyahome" / ".env"
|
||||
DATA_DIR = Path.cwd() / ".nyahome"
|
||||
ENV_PATH = DATA_DIR / ".env"
|
||||
LOGGING_YAML = DATA_DIR / "logging.yaml"
|
||||
|
||||
db_driver_available = {
|
||||
"sqlite": ["sqlite3"],
|
||||
"mysql": ["pymysql"],
|
||||
"postgresql": ["psycopg"],
|
||||
}
|
||||
db_type_allowlist = ["sqlite", "mysql", "postgresql"]
|
||||
|
||||
@@ -0,0 +1,168 @@
|
||||
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, db_driver_available, db_type_allowlist
|
||||
|
||||
|
||||
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]3006[/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"""
|
||||
Reference in New Issue
Block a user