PHPFixing
  • Privacy Policy
  • TOS
  • Ask Question
  • Contact Us
  • Home
  • PHP
  • Programming
  • SQL Injection
  • Web3.0

Wednesday, June 29, 2022

[FIXED] how to add surrounding comments to an element in a list

 June 29, 2022     comments, python, ruamel.yaml, yaml     No comments   

Issue

fruits = CommentedSeq()
fruits.append('banana')
fruits.yaml_set_comment_before_after_key(0, 'comments above', after='comments below')
yaml.dump({'fruits': fruits}, sys.stdout)

I'd like the output to be the following:

fruits:
  # comments above
  - banana
  # comments below

But from my test, comments below is discarded.


Solution

The (undocumented) method you use is called yaml_set_comment_before_or_after_key. That last part key refers to the key of key-value pair in a mapping. You are using a sequence and although there is some similarity of handling both on round-trip, they are not handled in the same way.

First thing to do in this case is see if your desired results round-trips at all:

import sys
import ruamel.yaml

yaml_str = """\
fruits:
  # comments above
  - banana
  # comments below
"""

yaml = ruamel.yaml.YAML()
yaml.indent(sequence=4, offset=2)
data = yaml.load(yaml_str)
yaml.dump(data, sys.stdout)

This gives:

fruits:
  # comments above
  - banana
  # comments below

so it does round-trip.

Then compare the comments attached to the loaded data with your constructed data:

from ruamel.yaml.comments import CommentedSeq

fruits = CommentedSeq()
fruits.append('banana')
fruits.yaml_set_comment_before_after_key(0, 'comments above', after='comments below')

print('loaded:   ', data['fruits'].ca)
print('generated:', fruits.ca)

that is not the same:

loaded:    Comment(comment=[None, [CommentToken('# comments above\n', line: 1, col: 2)]],
  items={0: [CommentToken('\n  # comments below\n', line: 3, col: 2), None, None, None]})
generated: Comment(comment=None,
  items={0: [None, [CommentToken('# comments above\n', col: 0)], None, [CommentToken('# comments below\n', col: 2)]]})

The loaded data doesn't have comments above associated with sequence element 0. It is a comment that exists before the sequence start. You can still get what you want:

from ruamel.yaml.tokens import CommentToken
from ruamel.yaml.error import CommentMark

indent = 2
fruits.ca.comment = [None, [CommentToken('# comments above\n', CommentMark(indent))]]
fruits.ca.items[0] = [CommentToken(f'\n{" "*indent}# comments below\n', CommentMark(0)), None, None, None]
yaml.dump({'fruits': fruits}, sys.stdout)

which gives:

fruits:
  # comments above
  - banana
  # comments below

Make sure you pin the ruamel.yaml version for your application, when you are using these kind of internals that will change.



Answered By - Anthon
Answer Checked By - Marie Seifert (PHPFixing Admin)
  • Share This:  
  •  Facebook
  •  Twitter
  •  Stumble
  •  Digg
Newer Post Older Post Home

0 Comments:

Post a Comment

Note: Only a member of this blog may post a comment.

Total Pageviews

Featured Post

Why Learn PHP Programming

Why Learn PHP Programming A widely-used open source scripting language PHP is one of the most popular programming languages in the world. It...

Subscribe To

Posts
Atom
Posts
Comments
Atom
Comments

Copyright © PHPFixing