feat(cli): 实现 nyahome config 命令
允许通过 nyahome 终端命令修改设置 同时再次调整数据库有关的内部常量的位置
This commit is contained in:
@@ -5,7 +5,7 @@ from pathlib import Path
|
||||
from typing import Mapping
|
||||
|
||||
from nyahome.cli.cli import console
|
||||
from nyahome.database.engine import db_driver_available, db_type_allowlist
|
||||
from nyahome.data import db_type_allowlist, db_driver_available
|
||||
|
||||
|
||||
class CliWarning:
|
||||
|
||||
@@ -0,0 +1,70 @@
|
||||
from typing import Annotated
|
||||
|
||||
import typer
|
||||
from rich.table import Table
|
||||
|
||||
from nyahome.config import Config, config_manager
|
||||
|
||||
from .cli import console
|
||||
|
||||
config_app = typer.Typer()
|
||||
|
||||
|
||||
@config_app.command(name="list")
|
||||
def list_all_configs() -> None:
|
||||
"""
|
||||
列出所有 NyaHome 定义的设置项。直接输出,可能包含敏感信息。
|
||||
|
||||
同时包含默认值和当前值。在 NyaHome 首次运行时,所有设置项都会以默认值存储。
|
||||
"""
|
||||
config_manager.sync_load_config()
|
||||
ci = Config()
|
||||
|
||||
table = Table(title="NyaHome 设置")
|
||||
table.add_column("设置键名", style="cyan", no_wrap=True)
|
||||
table.add_column("值类型", style="bright_black", no_wrap=True)
|
||||
table.add_column("当前值", style="white")
|
||||
table.add_column("默认值", style="bright_black")
|
||||
|
||||
for key, value in config_manager.get_config().items():
|
||||
default_value = getattr(ci, key)
|
||||
table.add_row(key, type(default_value).__name__, str(value), str(default_value))
|
||||
|
||||
console.print(table)
|
||||
|
||||
|
||||
@config_app.command(name="set")
|
||||
def set_config_item(
|
||||
key: Annotated[str, typer.Argument(help="设置键名")],
|
||||
value: Annotated[list[str], typer.Argument(help="设置键新值,类型会自动转换,多个输入将被视作列表")],
|
||||
) -> None:
|
||||
"""
|
||||
修改一项设置。
|
||||
|
||||
目前,NyaHome 的设置键所支持的值类型包括:str int bool list
|
||||
"""
|
||||
config_manager.sync_load_config()
|
||||
if len(value) == 1:
|
||||
value = value[0]
|
||||
try:
|
||||
config_manager.set(key, value)
|
||||
except AttributeError:
|
||||
console.print(f"[yellow]设置失败,设置键 [cyan]{key}[/cyan] 不存在。[/yellow]")
|
||||
config_manager.sync_save_config()
|
||||
console.print(f"已经将设置项 [cyan]{key}[/cyan] 的值设置为 [cyan]{value}[/cyan]")
|
||||
|
||||
|
||||
@config_app.command(name="reset")
|
||||
def reset_config_item(
|
||||
key: Annotated[str, typer.Argument(help="设置键名")],
|
||||
) -> None:
|
||||
"""
|
||||
重置一项设置至默认值。
|
||||
"""
|
||||
config_manager.sync_load_config()
|
||||
try:
|
||||
config_manager.reset(key)
|
||||
except AttributeError:
|
||||
console.print(f"[yellow]设置失败,设置键 [cyan]{key}[/cyan] 不存在。[/yellow]")
|
||||
config_manager.sync_save_config()
|
||||
console.print(f"已经将设置项 [cyan]{key}[/cyan] 的值重置为默认值。")
|
||||
@@ -1,5 +1,7 @@
|
||||
from .config import Config
|
||||
from .manager import config_manager
|
||||
|
||||
__all__ = [
|
||||
Config,
|
||||
config_manager,
|
||||
]
|
||||
|
||||
@@ -15,6 +15,11 @@ T = TypeVar("T")
|
||||
|
||||
|
||||
class ConfigManager:
|
||||
"""
|
||||
ConfigManager 携带一个初始化的 Config 实例。在 Config 初始化时,所有的默认设置键的值就都已经加载。
|
||||
因此,如果不 load_config,ConfigManager 也将持有一套默认设置。
|
||||
"""
|
||||
|
||||
def __init__(self) -> None:
|
||||
CONFIG_PATH.parent.mkdir(exist_ok=True)
|
||||
self._config = Config()
|
||||
@@ -76,6 +81,47 @@ class ConfigManager:
|
||||
"""
|
||||
return getattr(self._config, key, default) # type: ignore[return-value]
|
||||
|
||||
def set(self, key: str, value: T) -> None:
|
||||
"""
|
||||
设置配置项。
|
||||
|
||||
Args:
|
||||
key: 配置键名
|
||||
value: 配置键的新值,可以是(且仅支持)字符串、整型以及列表。
|
||||
"""
|
||||
try:
|
||||
old_value = self.get(key)
|
||||
except AttributeError as e:
|
||||
raise e
|
||||
|
||||
match old_value:
|
||||
case str():
|
||||
new_value = str(value)
|
||||
case int():
|
||||
new_value = int(value)
|
||||
case bool():
|
||||
new_value = bool(value)
|
||||
case list():
|
||||
new_value = [x for x in value]
|
||||
case _:
|
||||
raise TypeError(f"不支持 {type(old_value).__name__} 类型的设置项。({key})")
|
||||
setattr(self._config, key, new_value)
|
||||
|
||||
def reset(self, key: str) -> None:
|
||||
"""
|
||||
将配置项恢复至默认值。
|
||||
|
||||
Args:
|
||||
key: 配置键名
|
||||
|
||||
"""
|
||||
ci = Config()
|
||||
try:
|
||||
default_value = getattr(ci, key)
|
||||
except AttributeError as e:
|
||||
raise e
|
||||
setattr(self._config, key, default_value)
|
||||
|
||||
def get_config(self) -> dict[str, Any]:
|
||||
config = {}
|
||||
for attr in dir(self._config):
|
||||
|
||||
@@ -0,0 +1,6 @@
|
||||
db_driver_available = {
|
||||
"sqlite": ["sqlite3"],
|
||||
"mysql": ["pymysql"],
|
||||
"postgresql": ["psycopg"],
|
||||
}
|
||||
db_type_allowlist = ["sqlite", "mysql", "postgresql"]
|
||||
@@ -3,12 +3,7 @@ import os
|
||||
from sqlalchemy import Engine
|
||||
from sqlmodel import create_engine
|
||||
|
||||
db_driver_available = {
|
||||
"sqlite": ["sqlite3"],
|
||||
"mysql": ["pymysql"],
|
||||
"postgresql": ["psycopg"],
|
||||
}
|
||||
db_type_allowlist = ["sqlite", "mysql", "postgresql"]
|
||||
from nyahome.data import db_driver_available, db_type_allowlist
|
||||
|
||||
|
||||
def build_engine() -> Engine:
|
||||
|
||||
+17
-4
@@ -12,6 +12,7 @@ from rich.table import Table
|
||||
from nyahome import __version__
|
||||
from nyahome.cli.cli import console
|
||||
from nyahome.cli.cli_aii import aii_app
|
||||
from nyahome.cli.cli_config import config_app
|
||||
from nyahome.cli.cli_env import ENV_PATH, env_app
|
||||
|
||||
app = typer.Typer(
|
||||
@@ -38,7 +39,7 @@ def main(
|
||||
is_eager=True,
|
||||
),
|
||||
) -> None:
|
||||
console.print("[bright_black]NyaHome 仍然处于极早期的阶段。如果遇到任何问题,请告诉芒果帆帆喵![/bright_black]")
|
||||
console.print("(!) [bright_black]NyaHome 仍然处于极早期的阶段。如果遇到任何问题,请告诉芒果帆帆喵![/bright_black]")
|
||||
|
||||
|
||||
@app.command()
|
||||
@@ -91,7 +92,8 @@ def init() -> None:
|
||||
|
||||
from nyahome.cli.cli import DATA_DIR, ENV_PATH, LOGGING_YAML
|
||||
from nyahome.cli.cli_check import LOGGING_YAML_CONTENT
|
||||
from nyahome.database.engine import db_driver_available, db_type_allowlist
|
||||
from nyahome.config import config_manager
|
||||
from nyahome.data import db_driver_available, db_type_allowlist
|
||||
|
||||
console.print("\n准备初始化 NyaHome。")
|
||||
|
||||
@@ -153,6 +155,16 @@ def init() -> None:
|
||||
set_key(ENV_PATH, "NYAHOME_UVICORN_RELOAD", "true" if un_reload else "false")
|
||||
console.print("已设置 uvicorn 启动配置。")
|
||||
|
||||
# 4.NyaHome 设置初始化
|
||||
console.print("\n4. NyaHome 设置初始化")
|
||||
try:
|
||||
config_manager.sync_load_config()
|
||||
except FileNotFoundError:
|
||||
console.print("配置文件 [cyan].nyahome/config.json[/cyan] 不存在,创建默认配置。")
|
||||
config_manager.sync_save_config()
|
||||
else:
|
||||
console.print("配置文件已存在,跳过。")
|
||||
|
||||
|
||||
@app.command()
|
||||
def check() -> None:
|
||||
@@ -203,8 +215,9 @@ def check() -> None:
|
||||
console.print(f"\n[yellow]完成自检,共有 {cw.counter} 个警告。[/yellow]")
|
||||
|
||||
|
||||
app.add_typer(env_app, name="env", no_args_is_help=True, help="设置 NyaHome 应用的环境变量。")
|
||||
app.add_typer(aii_app, name="aii", no_args_is_help=True, help="添加、设置、修改 AI 提供商和模型。")
|
||||
app.add_typer(config_app, name="config", no_args_is_help=True, help="设置 NyaHome 的设置。(需要初始化)")
|
||||
app.add_typer(env_app, name="env", no_args_is_help=True, help="设置 NyaHome 应用的环境变量。(需要初始化)")
|
||||
app.add_typer(aii_app, name="aii", no_args_is_help=True, help="添加、设置、修改 AI 提供商和模型。(需要初始化)")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
|
||||
Reference in New Issue
Block a user