使用deepmerge-python模块和ruamel.yaml合并2个yaml时保留注释的问题



代码:

from deepmerge import always_merger
import ruamel.yaml
fileA = "source.yaml"
fileB = "dest.yaml"
yaml = ruamel.yaml.YAML()
with open(fileA,'r+') as f:
fileAdictionary= yaml.load(f)
with open(fileB,'r+') as f:
fileBdictionary = yaml.load(f)
result = always_merger.merge(fileAdictionary, fileBdictionary)
with open('output.yaml','w+') as f:
yaml.dump(result,f)

来源.yaml

element:
connection:
test: true

dest.yaml

element:
connection:
test: true
networkPolicy:
enabled: true
# network policy has been enabled
test_str_param: "abc"
# comment for string parameter
test_int_param: 10
# comment for the integer parameter
test_bool_param: true
# comment for the boolean parameter

实际输出

输出.yaml

element:
connection:
test: true
networkPolicy:
enabled: true
# network policy has been enabled
test_str_param: abc
test_int_param: 10
test_bool_param: true

问题描述

正如您在output.yaml中所看到的,元素test_str_paramtest_int_paramtest_bool_param的注释不会保留或从dest.yaml转发

预期

需要做些什么才能将与所有参数相关的所有注释保存在最终的output.yaml

预期输出

element:
connection:
test: true
networkPolicy:
enabled: true
# network policy has been enabled
test_str_param: "abc"
# comment for string parameter
test_int_param: 10
# comment for the integer parameter
test_bool_param: true
# comment for the boolean parameter

您从输入中加载的是CommentedMap实例,这些都是子类CCD_ 7。deepmerge将它们作为dict处理,但由于它没有做任何特殊的事情对于注释,如果键合并到已存在的CommentedMap(类似于fileAdictionary['element']),但在是CommentedMap并且还不存在于fileAdictionary中(即没有fileAdictionary['element']['networkPolicy'])

deepmerge允许您添加自己的策略,但我不确定是什么添加新类型的最佳/推荐程序:

import sys
from pathlib import Path
# from deepmerge import always_merger
import deepmerge
import ruamel.yaml
RYCM = ruamel.yaml.comments.CommentedMap
class CommentedMapStrategies(deepmerge.strategy.core.StrategyList):
NAME = 'CommentedMap'
@staticmethod
def strategy_merge(config, path, base, nxt):
for k, v in nxt.items():
if k not in base:
base[k] = v
else:
base[k] = config.value_strategy(path + [k], base[k], v)
try:
for k, v in nxt.ca.items.items():
base.ca.items[k] = v
except AttributeError:
pass

return base
@staticmethod
def strategy_override(config, path, base, nxt):
"""
move all keys in nxt into base, overriding
conflicts.
"""
return nxt
# insert as it needs to be before 'dict'
deepmerge.DEFAULT_TYPE_SPECIFIC_MERGE_STRATEGIES.insert(0, (RYCM, 'merge'))
Merger = deepmerge.merger.Merger
Merger.PROVIDED_TYPE_STRATEGIES[RYCM] = CommentedMapStrategies
always_merger = Merger(deepmerge.DEFAULT_TYPE_SPECIFIC_MERGE_STRATEGIES, ['override'], ['override'])
fileA = Path('source.yaml')
fileB = Path('dest.yaml')
yaml = ruamel.yaml.YAML()
yaml.indent(mapping=4)
result = always_merger.merge(yaml.load(fileA), yaml.load(fileB))
yaml.dump(result, sys.stdout)

它给出:

element:
connection:
test: true
networkPolicy:
enabled: true
# network policy has been enabled
test_str_param: abc
# comment for string parameter
test_int_param: 10
# comment for the integer parameter
test_bool_param: true
# comment for the boolean parameter

根据您在YAML文件中的意见,您可能需要修改/完成CCD_ 15中的注释复制。

请注意,以上依赖于可能发生变化的CCD_ 16内部,所以在升级之前先锁定ruamel.yaml版本并进行测试。

最新更新