On Python 2.7, and on Python 3.X with at least ruamel.yaml 0.11.11, this works fine:
import ruamel.yaml
yaml_str = """\
first_name: Art
occupation: Architect # This is an occupation comment
about: Art Vandelay is a fictional character that George invents...
"""
data = ruamel.yaml.round_trip_load(yaml_str)
data.insert(1, 'last name', 'Vandelay')
print(ruamel.yaml.round_trip_dump(data))
gives:
first_name: Art
last name: Vandelay
occupation: Architect # This is an occupation comment
about: Art Vandelay is a fictional character that George invents...
as the end-of-line comments are associated with the key of the line in the CommentedMap
. (Python 2.7.11 on Linux Mint with ruamel.yaml 0.11.10.)
This will not work on older versions of ruamel.yaml with Python3 as the .insert()
you are using is a feature of the full-fledged ruamel.ordereddict
and the OrderedDict in the standard library doesn't have that method. Therefore you need to graft an .insert()
function onto the CommentedMap
:
import ruamel.yaml
from ruamel.yaml.comments import CommentedMap
from ruamel.yaml.compat import ordereddict
yaml_str = """\
first_name: Art
occupation: Architect # This is an occupation comment
about: Art Vandelay is a fictional character that George invents...
"""
def com_insert(self, pos, key, value, comment=None):
od = ordereddict()
od.update(self)
for k in od:
del self[k]
for index, old_key in enumerate(od):
if pos == index:
self[key] = value
self[old_key] = od[old_key]
if comment is not None:
self.yaml_add_eol_comment(comment, key=key)
CommentedMap.insert = com_insert
data = ruamel.yaml.round_trip_load(yaml_str)
data.insert(1, 'last name', 'Vandelay', comment="new key")
print(ruamel.yaml.round_trip_dump(data))
gives on Python3:
first_name: Art
last name: Vandelay # new key
occupation: Architect # This is an occupation comment
about: Art Vandelay is a fictional character that George invents...
Please note that there is an optional parameter for insert()
that allows you to specify a comment for the newly inserted key-value pair. The above works because deleting a key from a CommentedMap
doesn't remove the comment associated with the key. So I temporarily park the old key-value pairs in od
delete all key-values, and then copy them back inserting the new stuff at the right moment
The above insert
, with comment, has been added in ruamel.yaml 0.11.11 for
both Python 2 and 3
The .round_trip_load()
is equivalent to .load(...., Loader=ruamel.yaml.RoundTripLoader, ...)
and .round_trip_dump()
to `.dump(....., Dumper=ruamel.yaml.RoundTripDumper, allow_unicode=True, ...)
.insert()
:D – Scarf