9

I'd like to get the comment strings from a YAML file I loaded using ruamel.yaml. The project documentation lacks an API reference and I can't find a relevant example. What's the right way to access the comments?

import ruamel.yaml

yaml = """\
%YAML 1.2
---
# C1
a: # C2
  # C3
  # C4
  b: 1 # C5
  c: # A comment here will not be parsed properly by ruamel.yaml v0.11.14
  - abc # C6
  - xyz # C7
  # C8
# C9
"""

loaded = ruamel.yaml.round_trip_load(yaml)

# Now what?
M. Dudley
  • 26,519
  • 30
  • 137
  • 228
  • 1
    It is indeed still not possible to have comment on a line that only has a key and properly preserve that. That is one of the reasons there is no API, as for that `ruamel.yaml` should be more complete (including supporting these infrequent cases for which the underlying datastructure should change). The comment storage will also need meaningful attribute names instead of list indices (in some scrambled order). `ruamel.yaml` should get rid of more of PyYAMLs legacy and comment round-tripping should also work when using the C based parser stages. – Anthon Jul 07 '16 at 19:50
  • 1
    And then there is of course the problem of deciding if a comment on a line of its own belongs to the previous scalar, or to the next one etc. – Anthon Jul 07 '16 at 19:53

1 Answers1

7

The library author comments on this in an issue on BitBucket (May 9, 2016):

The comment preservation has not stabilized, e.g. I need to do something if the key and value of a mapping are not on the same line and the key (or both key and value) have a comment. And my initial target was preservation of existing comments, not so much manipulation.

Through some experimentation I determined the following works for the example code provided in the question above:

print('Comment 1: ' + loaded.ca.comment[1][0].value)
print('Comment 2: ' + loaded.ca.items['a'][2].value)
print('Comment 3: ' + loaded.ca.items['a'][3][0].value)
print('Comment 4: ' + loaded.ca.items['a'][3][1].value)
print('Comment 5: ' + loaded['a'].ca.items['b'][2].value)
print('Comment 6: ' + loaded['a']['c'].ca.items[0][0].value)
print('Comment 7: ' + loaded['a']['c'].ca.items[1][0].value)
print('Comment 8: ' + loaded['a']['c'].ca.end[0].value)
print('Comment 9: ' + loaded['a']['c'].ca.end[1].value)
M. Dudley
  • 26,519
  • 30
  • 137
  • 228
  • 2
    Yes, in general if you have a mapping/dict object you use `ca.items[key] to get the comments associated with the key, and similarly for sequences/list you use `ca.items[index]` for a particular element. The manipulation in `_test/test_comment_manipulation.py` could further give some clues as to how to set new comments. – Anthon Jul 07 '16 at 20:02