如何区分行尾注释和 ruamel.yaml 中的整行注释?

How can I distinguish end of line comments from full line comments in ruamel.yaml?

为了使复杂的 Azure DevOps 管道自我记录,我试图自动从 YAML 文件中读取注释。我决定使用 ruamel.yaml python 库。

阅读评论效果很好,但我没有找到如何区分行尾评论和全行评论:

  - book # This is an end-of-the-line comment
    # This is a full line comment

有人知道我是怎么做到的吗?

代码示例,阅读所有stage的stage级注释,不带stage子实体的注释:

from ruamel.yaml import YAML
from ruamel.yaml.comments import CommentedMap, CommentedSeq

file_name = 'test.yaml'

yaml=YAML()
with open(file_name) as doc:
    data = yaml.load(doc)

i = 0
for item in data['stages']:
    i+=1
    print("*** stage", i, item['stage'])
    if isinstance(item, CommentedMap):
        comment_token = item.ca.items.get('stage')
        stage_help = {"stage_id": i}
        current_key = "Comment"
        if comment_token:
            for tab in comment_token:
                if tab:
                    vals = tab.value.split('\n')

                    for line in vals:
                        if line[1:1] == "#":
                            line = line[1:]
                        else:
                            line = line.strip()[1:].strip()
                        if len(line) == 0:
                            continue
                        if line[0:1] == "@":
                            current_key = line[1:line.index(':')]
                            content = line[line.index(':')+1:].strip()
                        else:
                            content = line
                        if current_key not in stage_help:
                            stage_help[current_key] = f"{content}"
                        else:
                            stage_help[current_key] = f"{stage_help[current_key]}\n{content}"

                    print(stage_help)

YAML:

stages:
  - stage: TestA
    # @Comment: I write what it does
    # @Link: https://documentation
  - stage: TestB # My favorite stage!
    # @Comment: We can also write
    # Multiline docs
    # @Link: https://doc2
    displayName: Test B # The displayName is shown in the pipeline's GUI

运行 这给了我:

*** stage 1 TestA
{'stage_id': 1, 'Comment': 'I write what it does', 'Link': 'https://documentation'}
*** stage 2 TestB
{'stage_id': 2, 'Comment': 'My favorite stage!\nWe can also write\nMultiline docs', 'Link': 'https://doc2'}

首先,ruamel.yaml 包 indicates 是:

The 0.17 series will also see changes in how comments are attached during roundtrip. This will result in backwards incompatibilities on the .ca data and it might even be necessary for documented methods that handle comments.

所以你当然应该在你的代码中测试安装的版本 ruamel.yaml。

在ruamel.yaml<0.17。任何仅注释行(和空行)都附加到前面的 与小睡键(或序列元素)关联的行尾注释 指数)。如果不存在这样的行尾注释,则将其构造为换行符。那 是你应该检查的

import sys
import ruamel.yaml

assert ruamel.yaml.version_info < (0, 17)

yaml_str = """\
stages:
  - stage: TestA
    # @Comment: I write what it does
    # @Link: https://documentation
  - stage: TestB # My favorite stage!
    # @Comment: We can also write
    # Multiline docs
    # @Link: https://doc2
    displayName: Test B # The displayName is shown in the pipeline's GUI
"""

def comment_splitter(comment_list):
     """ expects the list that is a comment attached to key/index as argument
     returns a tuple containing;
     - the eol comment for the key/index (empty string if not available)
     - a list of, non-empty, full comments lines following the key/index
     """
     token = comment_list[2]
     # print(token)
     eol, rest = token.value.split('\n', 1)
     return eol.strip(), [y for y in [x.strip() for x in rest.split('\n')] if y]

yaml = ruamel.yaml.YAML()
data = yaml.load(yaml_str)
print(comment_splitter(data['stages'][0].ca.items.get('stage')))
print(comment_splitter(data['stages'][1].ca.items.get('stage')))

给出:

('', ['# @Comment: I write what it does', '# @Link: https://documentation'])
('# My favorite stage!', ['# @Comment: We can also write', '# Multiline docs', '# @Link: https://doc2'])

因为你在你的程序中立即拆分了 CommentToken 的值(如果可用)然后就跳过了 如果该行的长度为零,您可能错过了这一点。如果您取消注释 # print(token) 这应该会变得清楚。


我建议不要以这种方式滥用 YAML 注释,而是要求考虑生成 azure 管道的文件 期望通过 python 小程序从更完整的 YAML 文件中提取信息。我就是这样克服的 docker-compose.yaml 文件格式的不足。

您是签入生成的(更简单的)YAML,还是始终生成 它的运行取决于管道 cq 的功能。你如何调用它。

我可能会从以下内容开始,然后处理:

stages:
  - @Stage
    name: TestA
    comment: I write what it does
    link: https://documentation
  - @Stage
    name: TestB # My favorite stage!
    Comment: |
        We can also write
        Multiline docs
    link: https://doc2
    displayName: Test B # The displayName is shown in the pipeline's GUI

这样一来,在 ruamel.yaml.

的未来版本中,您不必处理评论附加方式的任何变化