使用 ruamel.yaml 加载和转储时,如何使用 yamllint 强制注释位置有效?
How to force the comment position to be valid with yamllint when load and dump with ruamel.yaml?
我希望能够 "reposition" yaml 文档中的现有注释,以便它们在生成的输出 运行 yamllint
时有效,默认配置为 min-spaces-from-content=2
(参考:https://yamllint.readthedocs.io/en/stable/rules.html#module-yamllint.rules.comments)。
根据 ,使用类似 yaml_add_eol_comment('the comment', 'the key', column=None)
的方法应该可以解决问题,但这不是我目前得到的结果。
这是我写的一段代码(在版本 0.16.7
中使用 ruamel.yaml
)来演示我当前的行为:
"""Play with comments."""
from __future__ import print_function
import sys
import ruamel.yaml
yaml = ruamel.yaml.YAML()
yaml.indent(mapping=2, sequence=4, offset=2)
inp = """\
---
list-of-maps:
- part_no: A4786 # comment 1
part_henon: mouhaha # you're not funny
- part_yes: A21 # also a comment here
part_iculier: partenaire # I don't always understand how it works
part_third: key # komment
list-only:
- first # comment 2
- third # I have a comment too
- second # what?
simple-map:
what-are-you-waiting-for: christmas? # duke nukem rulez
jingle: bels # not christmas yet
map-of-maps:
key:
another-sub-key: w00t # casimir
sub-key: sub-value # comment 3
my-sub-key-name-is-longuer-than-yours: 1 # sentinel vs superman
"""
data = yaml.load(inp)
def process_comments(data, column=None):
if isinstance(data, dict):
if data.ca:
if data.ca.items:
for key in data.ca.items.keys():
if data.ca.items[key][2]:
comment = data.ca.items[key][2].value.replace("\n", "")
data.yaml_add_eol_comment(comment, key, column=column)
for k, v in data.items():
process_comments(k, column=column)
process_comments(v, column=column)
elif isinstance(data, list):
if data.ca:
if data.ca.items:
for key in data.ca.items.keys():
if data.ca.items[key][0]:
comment = data.ca.items[key][0].value.replace("\n", "")
data.yaml_add_eol_comment(comment, key, column=column)
for elem in data:
process_comments(elem, column=column)
process_comments(data, column=None)
yaml.dump(data, sys.stdout)
预期输出为:
list-of-maps:
- part_no: A4786 # comment 1
part_henon: mouhaha # you're not funny
- part_yes: A21 # also a comment here
part_iculier: partenaire # I don't always understand how it works
part_third: key # komment
list-only:
- first # comment 2
- third # I have a comment too
- second # what?
simple-map:
what-are-you-waiting-for: christmas? # duke nukem rulez
jingle: bels # not christmas yet
map-of-maps:
key:
another-sub-key: w00t # casimir
sub-key: sub-value # comment 3
my-sub-key-name-is-longuer-than-yours: 1 # sentinel vs superman
实际输出为:
list-of-maps:
- part_no: A4786 # comment 1
part_henon: mouhaha # you're not funny
- part_yes: A21 # also a comment here
part_iculier: partenaire # I don't always understand how it works
part_third: key # komment
list-only:
- first # comment 2
- third # I have a comment too
- second # what?
simple-map:
what-are-you-waiting-for: christmas? # duke nukem rulez
jingle: bels # not christmas yet
map-of-maps:
key:
another-sub-key: w00t # casimir
sub-key: sub-value # comment 3
my-sub-key-name-is-longuer-than-yours: 1 # sentinel vs superman
看来是:
- 对于 CommentedMaps,第一个键的注释在 # 之前有两个 space,但与 CommentedMap
的其他键关联的其他注释则没有
- 对于 CommentedSeqs,#
之前总是有一个 space
我是不是漏掉了什么?
补充信息:
顺便说一下,一个更简单的例子给出了相同的 output/behaviour :
"""Test comments on a very simple CommentedMap."""
import sys
import ruamel.yaml
comment_column = None
insert = ruamel.yaml.comments.CommentedMap()
insert["test"] = "asdf"
insert.yaml_add_eol_comment("Test Comment!", "test", column=comment_column)
insert["second-key"] = "yop"
insert.yaml_add_eol_comment("Another comment", "second-key", column=comment_column)
yaml = ruamel.yaml.YAML()
yaml.dump(insert, sys.stdout)
输出:
test: asdf # Test Comment!
second-key: yop # Another comment
免责声明:
- 非常感谢
ruamel.yaml
的作者,这是一个很棒的库 ... 感谢您观看有关库的问题
- 我根本不是在假装自己是一个优秀的python开发人员所以如果我的代码质量不佳请原谅我
您在映射的第一条评论上得到两个 space 是一个错误。如果你不
指定一个列,该列是根据前面的键猜测的。为了第一
映射中的键值对不可用,导致略有不同
代码路径。
修复该错误对您没有帮助,您必须提供自己的 yaml_add_eol_comment
总是添加额外的 space:
import sys
import ruamel.yaml
yaml = ruamel.yaml.YAML()
yaml.indent(mapping=2, sequence=4, offset=2)
inp = """
list-of-maps:
- part_no: A4786 # comment 1
part_henon: mouhaha # you're not funny
- part_yes: A21 # also a comment here
part_iculier: partenaire # I don't always understand how it works
part_third: key # komment
list-only:
- first # comment 2
- third # I have a comment too
- second # what?
simple-map:
what-are-you-waiting-for: christmas? # duke nukem rulez
jingle: bels # not christmas yet
map-of-maps:
key:
another-sub-key: w00t # casimir
sub-key: sub-value # comment 3
my-sub-key-name-is-longuer-than-yours: 1 # sentinel vs superman
"""
data = yaml.load(inp)
def my_add_eol_comment(self, comment, key=ruamel.yaml.comments.NoComment, column=None):
org_col = column
if column is None:
try:
column = self._yaml_get_column(key)
except AttributeError:
column = 0
if comment[0] != '#':
comment = '# ' + comment
if org_col != 0: # only do this if the specified colunn is not the beginning of the line
if comment[0] == '#':
comment = ' ' + comment
column = 0
start_mark = ruamel.yaml.error.CommentMark(column)
ct = [ruamel.yaml.tokens.CommentToken(comment, start_mark, None), None]
self._yaml_add_eol_comment(ct, key=key)
ruamel.yaml.comments.CommentedBase.yaml_add_eol_comment = my_add_eol_comment
def process_comments(data, column=None):
if isinstance(data, dict):
if data.ca:
if data.ca.items:
for key in data.ca.items.keys():
if data.ca.items[key][2]:
comment = data.ca.items[key][2].value.replace("\n", "")
data.yaml_add_eol_comment(comment, key, column=column)
for k, v in data.items():
process_comments(k, column=column)
process_comments(v, column=column)
elif isinstance(data, list):
if data.ca:
if data.ca.items:
for key in data.ca.items.keys():
if data.ca.items[key][0]:
comment = data.ca.items[key][0].value.replace("\n", "")
data.yaml_add_eol_comment(comment, key, column=column)
for elem in data:
process_comments(elem, column=column)
process_comments(data, column=None)
yaml.dump(data, sys.stdout)
给出:
list-of-maps:
- part_no: A4786 # comment 1
part_henon: mouhaha # you're not funny
- part_yes: A21 # also a comment here
part_iculier: partenaire # I don't always understand how it works
part_third: key # komment
list-only:
- first # comment 2
- third # I have a comment too
- second # what?
simple-map:
what-are-you-waiting-for: christmas? # duke nukem rulez
jingle: bels # not christmas yet
map-of-maps:
key:
another-sub-key: w00t # casimir
sub-key: sub-value # comment 3
my-sub-key-name-is-longuer-than-yours: 1 # sentinel vs superman
我希望能够 "reposition" yaml 文档中的现有注释,以便它们在生成的输出 运行 yamllint
时有效,默认配置为 min-spaces-from-content=2
(参考:https://yamllint.readthedocs.io/en/stable/rules.html#module-yamllint.rules.comments)。
根据 yaml_add_eol_comment('the comment', 'the key', column=None)
的方法应该可以解决问题,但这不是我目前得到的结果。
这是我写的一段代码(在版本 0.16.7
中使用 ruamel.yaml
)来演示我当前的行为:
"""Play with comments."""
from __future__ import print_function
import sys
import ruamel.yaml
yaml = ruamel.yaml.YAML()
yaml.indent(mapping=2, sequence=4, offset=2)
inp = """\
---
list-of-maps:
- part_no: A4786 # comment 1
part_henon: mouhaha # you're not funny
- part_yes: A21 # also a comment here
part_iculier: partenaire # I don't always understand how it works
part_third: key # komment
list-only:
- first # comment 2
- third # I have a comment too
- second # what?
simple-map:
what-are-you-waiting-for: christmas? # duke nukem rulez
jingle: bels # not christmas yet
map-of-maps:
key:
another-sub-key: w00t # casimir
sub-key: sub-value # comment 3
my-sub-key-name-is-longuer-than-yours: 1 # sentinel vs superman
"""
data = yaml.load(inp)
def process_comments(data, column=None):
if isinstance(data, dict):
if data.ca:
if data.ca.items:
for key in data.ca.items.keys():
if data.ca.items[key][2]:
comment = data.ca.items[key][2].value.replace("\n", "")
data.yaml_add_eol_comment(comment, key, column=column)
for k, v in data.items():
process_comments(k, column=column)
process_comments(v, column=column)
elif isinstance(data, list):
if data.ca:
if data.ca.items:
for key in data.ca.items.keys():
if data.ca.items[key][0]:
comment = data.ca.items[key][0].value.replace("\n", "")
data.yaml_add_eol_comment(comment, key, column=column)
for elem in data:
process_comments(elem, column=column)
process_comments(data, column=None)
yaml.dump(data, sys.stdout)
预期输出为:
list-of-maps:
- part_no: A4786 # comment 1
part_henon: mouhaha # you're not funny
- part_yes: A21 # also a comment here
part_iculier: partenaire # I don't always understand how it works
part_third: key # komment
list-only:
- first # comment 2
- third # I have a comment too
- second # what?
simple-map:
what-are-you-waiting-for: christmas? # duke nukem rulez
jingle: bels # not christmas yet
map-of-maps:
key:
another-sub-key: w00t # casimir
sub-key: sub-value # comment 3
my-sub-key-name-is-longuer-than-yours: 1 # sentinel vs superman
实际输出为:
list-of-maps:
- part_no: A4786 # comment 1
part_henon: mouhaha # you're not funny
- part_yes: A21 # also a comment here
part_iculier: partenaire # I don't always understand how it works
part_third: key # komment
list-only:
- first # comment 2
- third # I have a comment too
- second # what?
simple-map:
what-are-you-waiting-for: christmas? # duke nukem rulez
jingle: bels # not christmas yet
map-of-maps:
key:
another-sub-key: w00t # casimir
sub-key: sub-value # comment 3
my-sub-key-name-is-longuer-than-yours: 1 # sentinel vs superman
看来是:
- 对于 CommentedMaps,第一个键的注释在 # 之前有两个 space,但与 CommentedMap 的其他键关联的其他注释则没有
- 对于 CommentedSeqs,# 之前总是有一个 space
我是不是漏掉了什么?
补充信息:
顺便说一下,一个更简单的例子给出了相同的 output/behaviour :
"""Test comments on a very simple CommentedMap."""
import sys
import ruamel.yaml
comment_column = None
insert = ruamel.yaml.comments.CommentedMap()
insert["test"] = "asdf"
insert.yaml_add_eol_comment("Test Comment!", "test", column=comment_column)
insert["second-key"] = "yop"
insert.yaml_add_eol_comment("Another comment", "second-key", column=comment_column)
yaml = ruamel.yaml.YAML()
yaml.dump(insert, sys.stdout)
输出:
test: asdf # Test Comment!
second-key: yop # Another comment
免责声明:
- 非常感谢
ruamel.yaml
的作者,这是一个很棒的库 ... 感谢您观看有关库的问题 - 我根本不是在假装自己是一个优秀的python开发人员所以如果我的代码质量不佳请原谅我
您在映射的第一条评论上得到两个 space 是一个错误。如果你不 指定一个列,该列是根据前面的键猜测的。为了第一 映射中的键值对不可用,导致略有不同 代码路径。
修复该错误对您没有帮助,您必须提供自己的 yaml_add_eol_comment
总是添加额外的 space:
import sys
import ruamel.yaml
yaml = ruamel.yaml.YAML()
yaml.indent(mapping=2, sequence=4, offset=2)
inp = """
list-of-maps:
- part_no: A4786 # comment 1
part_henon: mouhaha # you're not funny
- part_yes: A21 # also a comment here
part_iculier: partenaire # I don't always understand how it works
part_third: key # komment
list-only:
- first # comment 2
- third # I have a comment too
- second # what?
simple-map:
what-are-you-waiting-for: christmas? # duke nukem rulez
jingle: bels # not christmas yet
map-of-maps:
key:
another-sub-key: w00t # casimir
sub-key: sub-value # comment 3
my-sub-key-name-is-longuer-than-yours: 1 # sentinel vs superman
"""
data = yaml.load(inp)
def my_add_eol_comment(self, comment, key=ruamel.yaml.comments.NoComment, column=None):
org_col = column
if column is None:
try:
column = self._yaml_get_column(key)
except AttributeError:
column = 0
if comment[0] != '#':
comment = '# ' + comment
if org_col != 0: # only do this if the specified colunn is not the beginning of the line
if comment[0] == '#':
comment = ' ' + comment
column = 0
start_mark = ruamel.yaml.error.CommentMark(column)
ct = [ruamel.yaml.tokens.CommentToken(comment, start_mark, None), None]
self._yaml_add_eol_comment(ct, key=key)
ruamel.yaml.comments.CommentedBase.yaml_add_eol_comment = my_add_eol_comment
def process_comments(data, column=None):
if isinstance(data, dict):
if data.ca:
if data.ca.items:
for key in data.ca.items.keys():
if data.ca.items[key][2]:
comment = data.ca.items[key][2].value.replace("\n", "")
data.yaml_add_eol_comment(comment, key, column=column)
for k, v in data.items():
process_comments(k, column=column)
process_comments(v, column=column)
elif isinstance(data, list):
if data.ca:
if data.ca.items:
for key in data.ca.items.keys():
if data.ca.items[key][0]:
comment = data.ca.items[key][0].value.replace("\n", "")
data.yaml_add_eol_comment(comment, key, column=column)
for elem in data:
process_comments(elem, column=column)
process_comments(data, column=None)
yaml.dump(data, sys.stdout)
给出:
list-of-maps:
- part_no: A4786 # comment 1
part_henon: mouhaha # you're not funny
- part_yes: A21 # also a comment here
part_iculier: partenaire # I don't always understand how it works
part_third: key # komment
list-only:
- first # comment 2
- third # I have a comment too
- second # what?
simple-map:
what-are-you-waiting-for: christmas? # duke nukem rulez
jingle: bels # not christmas yet
map-of-maps:
key:
another-sub-key: w00t # casimir
sub-key: sub-value # comment 3
my-sub-key-name-is-longuer-than-yours: 1 # sentinel vs superman