certflow.config.config_center_backend 源代码

"""配置中心后端(T10):统一「基础层 + 覆盖层」读写。

见 docs/discussions/resource-paths-audit.md §11.3。供配置中心 UI(T13)与
``settings_ui.yaml`` spec 驱动。基础实现复用现有 ``paths_override``(``paths.local.yaml``
覆盖层)+ ``settings.merge_user_config``(userconfig 增量写),不重建配置模型。

分层落盘规则:
  - layer=override / base -> 写 ``paths.local.yaml``(gitignored,不污染仓库/状态文件)
  - layer=userconfig      -> 写 ``userconfig.yaml``(按顶层键归属自动分流到桶2/桶3)
"""

from __future__ import annotations

from typing import Any

from certflow.config.paths_override import (
    _get_nested,
    list_path_overrides,
    load_paths_local,
    set_path_override,
)
from certflow.config.settings import _cfg, _get_user_config, merge_user_config


def _build_nested(key: str, value: Any) -> dict:
    """把点路径键 + 值展开为嵌套字典(用于 userconfig 增量写)。

    例:``_build_nested("preferences.auto_save", True)`` -> ``{"preferences": {"auto_save": True}}``
    """
    parts = key.split(".")
    d: dict = {}
    cur = d
    for p in parts[:-1]:
        cur[p] = {}
        cur = cur[p]
    cur[parts[-1]] = value
    return d


[文档] class ConfigCenterBackend: """配置中心读写后端。""" LAYER_OVERRIDE = "override" LAYER_USERCONFIG = "userconfig" LAYER_BASE = "base"
[文档] def read(self, key: str) -> dict[str, Any]: """读取某键的三层视图。 Returns: ``{base, override, user, effective}`` - base: 基础层(``config.yaml`` 经 loader,忽略所有覆盖) - override: ``paths.local.yaml`` 覆盖层原始值,未覆盖为 ``None`` - user: ``userconfig`` 合并值(桶2 偏好/覆盖 + 桶3 易变状态),未配置为 ``None`` - effective: 实际生效值 = ``user`` > ``override`` > ``base`` 关键点(修复 T10 缺陷):偏好类键(``preferences.*`` / ``print_layout.*`` / ``printer_offsets.*``)的生效值来自 ``userconfig``,而非基础层;原实现只查 ``paths.local.yaml`` + 基础层,导致这类键始终读到 ``None``,配置中心「可编辑」tab 全部显示空白/0。此处补齐 userconfig 来源。 """ parts = key.split(".") base = _cfg(key) ov = load_paths_local() ok, override = _get_nested(ov, parts) if ov else (False, None) override = override if (ok and override is not None) else None uc = _get_user_config() ok_u, user = _get_nested(uc, parts) user = user if (ok_u and user is not None) else None if user is not None: effective = user elif override is not None: effective = override else: effective = base return { "base": base, "override": override, "user": user, "effective": effective, }
[文档] def write(self, key: str, value: Any, layer: str) -> None: """按 ``layer`` 落盘写入。 Args: key: 点路径键,如 ``paths.output.scans`` / ``preferences.auto_save``。 value: 待写入值。 layer: ``override`` / ``base``(写 paths.local.yaml)或 ``userconfig``(写 userconfig.yaml)。 """ if layer in (self.LAYER_OVERRIDE, self.LAYER_BASE): set_path_override(key, value) elif layer == self.LAYER_USERCONFIG: merge_user_config(_build_nested(key, value)) else: raise ValueError(f"未知 layer: {layer!r}(应为 override/userconfig/base)")
[文档] def list_overrides(self) -> list[str]: """返回覆盖层所有生效键(配置中心「我的覆盖」tab 数据源)。""" return list_path_overrides()