spaceman_spiff
spaceman_spiff

Reputation: 105

How can I add a comment with ruamel.yaml

I'm trying to create a data structure with ruamel.yaml and want to add comments before dumping and/or loading it again. Unfortunately all examples load some string with the round trip dumper first or use no longer existing APIs.

This is what I am trying to dump:

test: asdf # Test Comment!

I tried the following:

insert = ruamel.yaml.comments.CommentedMap()
start_mark = ruamel.yaml.error.CommentMark(0)
insert['test'] = 'asdf'
insert.ca.items['test'] = [ None,
    [ruamel.yaml.CommentToken(value='# Test Comment!', start_mark=start_mark, end_mark=None)],
    None,
    None
]
ruamel.yaml.round_trip_dump(insert, sys.stdout)

which prints.

# Test Comment!test: asdf

Somehow the comment is in front instead of behind the values. What am I doing wrong?

Upvotes: 4

Views: 5853

Answers (2)

Brock
Brock

Reputation: 31

In reference to the latest documents, https://yaml.readthedocs.io/en/latest/example.html

The CommentedMap, which is the dict like construct one gets when round-trip loading, supports insertion of a key into a particular position, while optionally adding a comment:

import sys
from ruamel.yaml import YAML

yaml_str = """\
key: value # first line and comment!
"""

yaml = YAML()
data = yaml.load(yaml_str)
data.insert(1, 'test', 'asdf', comment="Test Comment!")
yaml.dump(data, sys.stdout)

Output:

key: value # first line and comment!
test: asdf # Test Comment!

Upvotes: 1

Anthon
Anthon

Reputation: 76599

You can try to do this by adding the CommentTokens, but the start_mark type would have to be comming from ruamel.yaml.error.

It is much more easy to make insert a CommentedMap (which is what the mapping would get loaded as, when doing a normal, round-trip, load), and then use its yaml_add_eol_comment method:

import sys
import ruamel.yaml


insert = ruamel.yaml.comments.CommentedMap()
insert['test'] = 'asdf'
insert.yaml_add_eol_comment('Test Comment!', 'test', column=0)

yaml = ruamel.yaml.YAML()
# yaml.indent(mapping=4, sequence=4, offset=2)
yaml.dump(insert, sys.stdout)

which gives:

test: asdf # Test Comment!

The column=0 is optional. If you don't specify the start column, you'll get two spaces before the #, 0 tries to push it all the way to the front, but of course the key-value pair is in the way.

You can specify the # in the EOL comment you specify to the yaml_add_eol_comment method, but if it is not there, it will be prepended.

If you have multiple comments after multiple keys on consecurive lines, and want your comments to align, you only have to specify the column of the first one added.

Upvotes: 5

Related Questions