You should load the result that you want in ruamel.yaml
. For good measure you can
then dump it back to see if the extra line is preserved. If it isn't you might not
be able to write out such a format in the first place. As you will see the extra line is
preserved, so you should be able to get it inothe output in some way if you
can reconstruct the loaded data from scratch.
ruamel.yaml
normally attaches comments to the node just parsed, so
you should investigate the sequence that is the value for the first key 'list':
import sys
import ruamel.yaml
yaml_str = """\
category:
- year: 2023
users:
- login: login1
fullName: First1 Last1
list:
- a
- login: login2
fullName: First2 Last2
list:
- b
"""
yaml = ruamel.yaml.YAML()
# yaml.indent(mapping=4, sequence=4, offset=2)
# yaml.preserve_quotes = True
data = yaml.load(yaml_str)
# yaml.dump(data, sys.stdout)
seq = data['category'][0]['users'][0]['list']
print('seq', type(seq), seq.ca)
which gives:
seq <class 'ruamel.yaml.comments.CommentedSeq'> Comment(comment=None,
items={0: [CommentToken('\n\n', line: 6, col: 12), None, None, None]})
In that seq.ca
is the comment attribute. Such an attribute cannot be
added to a normal list, so at least for that part of your data structure user
you need to create a CommentedSeq
instance. You can also see that the comment
token consists of two newlines (\n\n
). The first newline indicates that the end-of-line
comment following 'a' the first element (indicated by 0
) is empty, the second
newline is your actual empty line before the second "user".
However it is actually easier to insert the line before the second user. The CommentedSeq
instance has
a method that allows you to add a comment before a key (in this case the key is the element index):
import sys
import ruamel.yaml
CS = ruamel.yaml.comments.CommentedSeq
yaml = ruamel.yaml.YAML()
user = CS([{"login":"login1","fullName":"First1 Last1", "list":["a"]},{"login":"login2","fullName":"First2 Last2", "list":["b"]}])
user.yaml_set_comment_before_after_key(1, before='\n')
test = {"category":[{"year":2023,"users":user}]}
yaml.indent(mapping=4, sequence=4, offset=2)
yaml.width = 2048
documents = yaml.dump(test, sys.stdout)
which gives:
category:
- year: 2023
users:
- login: login1
fullName: First1 Last1
list:
- a
- login: login2
fullName: First2 Last2
list:
- b
Make sure you fix the version of ruamel.yaml you are using in your installation,
routines like yaml_set_comment_before_after_key
may still change.
During testing I usually write to stdout, easier to see if the output is correct.
If you write the YAML document to a file, you should consider using the extension
.yaml
, which has been the recommended extension for such files since at least 15 years.
ruamel.yaml
can roundtrip the YAML document preserving the empty line, there is no need for post-processing, you just have to find out where to attach the comment (an empty line is considered a comment that doesn't start with a#
) – Package