ruamel.yaml<=0.12.18
キーの前の行にコメントを挿入する関数は実際にはありませんが、構造体の先頭にコメントを設定する関数があります: .yaml_set_start_comment
. これで、追加したい 3 つのコメントのうち 2 つをすでに設定できます。
import sys
import ruamel.yaml
yaml_str = """\
xyz:
a: 1 # comment 1
b: 2
test1:
test2:
test3: 3
"""
data = ruamel.yaml.round_trip_load(yaml_str)
data['test1'].yaml_set_start_comment('before test2', indent=2)
data['test1']['test2'].yaml_set_start_comment('after test2', indent=4)
ruamel.yaml.round_trip_dump(data, sys.stdout)
与えます:
xyz:
a: 1 # comment 1
b: 2
test1:
# before test2
test2:
# after test2
test3: 3
実際には、xyz
との値の間に空の行を構成する「コメント」がありtest1
ますが、その構造にコメントを追加してから新しいキーを挿入すると、test1
希望どおりに表示されません。したがって、行うべきことは、 key の前に明示的にコメントを挿入することですtest1
。期待される出力を往復ロードして、内部Comment
がどのように見えるかを確認できます。
yaml_str_out = """\
xyz:
a: 1 # comment 1
b: 2
# before test1 (top level)
test1:
# before test2
test2:
# before test3
test3: 3
"""
test = ruamel.yaml.round_trip_load(yaml_str_out)
print(test.ca)
与えます(見やすくするためにこれをラップします):
Comment(comment=None,
items={'test1': [None,
[CommentToken(value='# before test1 (top level)\n')],
None,
[CommentToken(value='# before test2\n')]]})
ご覧のとおり# before test2
、キーの後のコメントと見なされます。そして、test['test1'].yaml_set_start_comment('xxxxx', indent=2)
それに関連付けられたコメントが無視され、ダンプに表示されないため、実行しても何の効果もtest1
ありませ# xxxxx
ん。
その情報といくつかの背景知識を使用yaml_set_start_comment()
して、(元のインポートと を想定してyaml_str
)からのコードの一部を適応させました。
def yscbak(self, key, before=None, indent=0, after=None, after_indent=None):
"""
expects comment (before/after) to be without `#` and possible have multiple lines
"""
from ruamel.yaml.error import Mark
from ruamel.yaml.tokens import CommentToken
def comment_token(s, mark):
# handle empty lines as having no comment
return CommentToken(('# ' if s else '') + s + '\n', mark, None)
if after_indent is None:
after_indent = indent + 2
if before and before[-1] == '\n':
before = before[:-1] # strip final newline if there
if after and after[-1] == '\n':
after = after[:-1] # strip final newline if there
start_mark = Mark(None, None, None, indent, None, None)
c = self.ca.items.setdefault(key, [None, [], None, None])
if before:
for com in before.split('\n'):
c[1].append(comment_token(com, start_mark))
if after:
start_mark = Mark(None, None, None, after_indent, None, None)
if c[3] is None:
c[3] = []
for com in after.split('\n'):
c[3].append(comment_token(com, start_mark))
if not hasattr(ruamel.yaml.comments.CommentedMap,
'yaml_set_comment_before_after_key'):
ruamel.yaml.comments.CommentedMap.yaml_set_comment_before_after_key = yscbak
data = ruamel.yaml.round_trip_load(yaml_str)
data.yaml_set_comment_before_after_key('test1', 'before test1 (top level)',
after='before test2', after_indent=2)
data['test1']['test2'].yaml_set_start_comment('after test2', indent=4)
ruamel.yaml.round_trip_dump(data, sys.stdout)
そして得る:
xyz:
a: 1 # comment 1
b: 2
# before test1 (top level)
test1:
# before test2
test2:
# after test2
test3: 3
でのテストhasattr
は、そのような関数が追加されたときに上書きしないことを確認することですruamel.yaml
ところで: すべてのコメントは YAML の行末コメントです。これらのコメントの前に有効な YAML があるだけかもしれません。