输入合并与覆盖¶
DevConfig-Gen 支持从多个来源组装同一条请求上下文:内存上下文、多个输入 文件,以及最后的点路径覆盖。CLI 与 Python API 使用同一套规则,因此两条路径 产生的产物逐字节一致。
数据来源与优先级¶
上下文按以下顺序组装,后者覆盖前者:
- 内存中的
context(Python API;CLI 从第一个--input开始); - 每个输入文件,按出现顺序从左到右依次合并;
overrides(CLI--set KEY=VALUE,Python APIoverrides=),最后应用。
对应实现:engine.build_request → formats.deep_merge →
engine._set_nested。相关 CLI 细节见 CLI 命令参考。
深度合并规则(deep_merge)¶
formats.deep_merge(base, overlay) 的语义:
- 当基底和覆盖层都是映射时:递归合并,嵌套键取并集;
- 其他情况:覆盖层的值整体替换基底(标量、列表,以及用标量替换映射等);
- 不修改任何入参对象(返回新字典)。
from devconfig_gen import deep_merge
deep_merge(
{"app": {"name": "a", "port": 80, "labels": {"team": "core", "tier": "api"}}},
{"app": {"port": 8080, "labels": {"tier": "edge"}}},
)
# {"app": {"name": "a", "port": 8080, "labels": {"team": "core", "tier": "edge"}}}
deep_merge({"a": {"b": 1}}, {"a": 2}) # {"a": 2}
deep_merge({"a": [1]}, {"a": [2, 3]}) # {"a": [2, 3]}
输入文件的格式各自独立检测:同一个命令里可以混用 .yaml、.yml 和
.json(检测规则见格式支持与产物)。
覆盖(overrides)¶
点路径覆盖在合并之后应用,用来做命令行级别的最终定值:
devconfig-gen generate --provider custom \
--input configs/base.yaml \
--input configs/prod.json \
--set app.port=9090 \
--set app.environment=production \
--output-dir dist --format yaml
规则:
- 键使用
.分隔的路径(如app.port),中间层级不存在时自动创建字典; - 如果中间层级已存在但不是字典,会被替换为字典
(
{"app": 5}+app.port=1→{"app": {"port": 1}}); - CLI 的值经
formats.coerce_scalar推断 JSON 类型:true/false→ 布尔,42→ 整数,1.5→ 浮点,null→ 空,"text"→ 字符串,其余保持文本; - Python API 的
overrides不做类型推断,按传入的 Python 值原样设置; - CLI 中
--set缺少=或键为空会报错并返回退出码2。
from devconfig_gen import build_request
request = build_request(
context={"app": {"name": "web", "port": 80}},
overrides={"app.port": 8080, "app.environment": "production"},
)
request.context
# {"app": {"name": "web", "port": 8080, "environment": "production"}}
非映射文档的处理¶
build_request 逐文件合并时,如果某个文件加载结果不是映射,它会整体替换
当前上下文,而不是合并:
build_request(input_path=["base.yaml", "list.json"])
# list.json 为 [1, 2, 3] 时,最终 context == [1, 2, 3]
随后如果有 overrides,且当前上下文不是 dict,上下文会被重置为 {}
再写入覆盖值。custom Provider 接受列表或标量根;json 与 env 要求根为
映射(见 Provider 参考与开发)。
CLI 与 Python API 等价性¶
CLI 的 generate 调用 engine.generate_pipeline,其行为等价于:
from devconfig_gen import generate_pipeline
result = generate_pipeline(
"custom",
input_path=["configs/base.yaml", "configs/prod.json"],
overrides={"app.port": 9090, "app.environment": "production"},
output_format="yaml",
output_dir="dist",
)
测试 tests/test_api_parity.py 断言 CLI 与 Python API 生成的 JSON/YAML 产物
逐字节一致;该断言是 143 个用例测试套件的一部分。