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

如何解决如何区分 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

0.17 系列也将看到评论附加方式的变化 往返。这将导致 .ca 数据向后不兼容 甚至可能需要处理注释的文档化方法。

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

在 ruamel.yaml

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 pipelines 的文件 期望通过使用小型 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 的未来版本中处理注释附加方式的任何更改。

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其他元素将获得点击?
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。)
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbcDriver发生异常。为什么?
这是用Java进行XML解析的最佳库。
Java的PriorityQueue的内置迭代器不会以任何特定顺序遍历数据结构。为什么?
如何在Java中聆听按键时移动图像。
Java“Program to an interface”。这是什么意思?
Java在半透明框架/面板/组件上重新绘画。
Java“ Class.forName()”和“ Class.forName()。newInstance()”之间有什么区别?
在此环境中不提供编译器。也许是在JRE而不是JDK上运行?
Java用相同的方法在一个类中实现两个接口。哪种接口方法被覆盖?
Java 什么是Runtime.getRuntime()。totalMemory()和freeMemory()?
java.library.path中的java.lang.UnsatisfiedLinkError否*****。dll
JavaFX“位置是必需的。” 即使在同一包装中
Java 导入两个具有相同名称的类。怎么处理?
Java 是否应该在HttpServletResponse.getOutputStream()/。getWriter()上调用.close()?
Java RegEx元字符(。)和普通点?