如何解决如何区分 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 举报,一经查实,本站将立刻删除。