Python Ruamel YAML - 如何获取合并部分的评论

Python Ruamel YAML - how to get comments of merged portions

如果我加载此示例 YAML 文件:

aliases:
  - &a1
    b1: 5         # Comment for b1=5
    c1: 3         # Comment for c1=3

model:
  obj1:
    <<: *a1
    d1: 7         # Comment for d1=7
  obj2:
    *a1
  obj3:
    *a1

使用此代码:

import ruamel.yaml as yaml

with open("test.yaml") as fp:
    d = yaml.load(fp, yaml.RoundTripLoader)

def showcmts(d):
    for k,v in d.items():
        print("Key {} has {}".format(k, (d.ca.items[k][2] if k in d.ca.items and d.ca.items[k][2] is not None else "no comment")))

print("Model obj1 contents and comments are:")
showcmts(d["model"]["obj1"])
print("Model obj2 contents and comments are:")
showcmts(d["model"]["obj2"])
print("Model obj3 contents and comments are:")
showcmts(d["model"]["obj3"])

我得到这个输出:

Model obj1 contents and comments are:
Key d1 has CommentToken('# Comment for d1=7\n', line: 8, col: 18)
Key b1 has no comment
Key c1 has no comment
Model obj2 contents and comments are:
Key b1 has CommentToken('# Comment for b1=5\n', line: 2, col: 18)
Key c1 has CommentToken('# Comment for c1=3\n\n', line: 3, col: 18)
Model obj3 contents and comments are:
Key b1 has CommentToken('# Comment for b1=5\n', line: 2, col: 18)
Key c1 has CommentToken('# Comment for c1=3\n\n', line: 3, col: 18)

如何获取与 obj1/b1obj1/c1 关联的评论? obj2/b1 等的评论正在加载和正确阅读,但我需要它们也存在 obj1/b1

ruamel.yaml,使用往返 loader/dumper,并没有真正合并映射。它让他们 分开,因此它们可以作为单独的实体转储,但提供特殊版本的 key/value 访问从“合并映射”构造的对象,就好像这是一个字典。

所以你需要做两件事:

  • 区分真实密钥和合并密钥
  • 访问合并键的注释

请注意,为此您需要访问未记录的内部信息 可能会更改,恕不另行通知。将您的生产代码固定到特定的 YAML 版本 您正在开发的。

from pathlib import Path
import ruamel.yaml


def showcmts(d):
    def pkc(k, d):
        print("Key {} has {}".format(k, (d.ca.items[k][2] if k in d.ca.items and d.ca.items[k][2] is not None else "no comment")))

    for k in d:
        if k in d._ok:  # Own Keys i.e. not merged-in
            pkc(k, d)
            continue
        for pos, merge in d.merge:
            if k in merge._ok:
                pkc(k, merge)
                break
    
yaml = ruamel.yaml.YAML()
d = yaml.load(Path('test.yaml'))

print("Model obj1 contents and comments are:")
showcmts(d["model"]["obj1"])
print("Model obj2 contents and comments are:")
showcmts(d["model"]["obj2"])
print("Model obj3 contents and comments are:")
showcmts(d["model"]["obj3"])

给出:

Model obj1 contents and comments are:
Key d1 has CommentToken('# Comment for d1=7\n', line: 8, col: 18)
Key b1 has CommentToken('# Comment for b1=5\n', line: 2, col: 18)
Key c1 has CommentToken('# Comment for c1=3\n\n', line: 3, col: 18)
Model obj2 contents and comments are:
Key b1 has CommentToken('# Comment for b1=5\n', line: 2, col: 18)
Key c1 has CommentToken('# Comment for c1=3\n\n', line: 3, col: 18)
Model obj3 contents and comments are:
Key b1 has CommentToken('# Comment for b1=5\n', line: 2, col: 18)
Key c1 has CommentToken('# Comment for c1=3\n\n', line: 3, col: 18)