How to add a new element to a sequence with a EOL comment

121 views Asked by At

I have a YAML file as

# This is the group manages the permissions
group:
  - state: present
    group:
    name: "Developers"
    description: "The development team"
    userNames:
      - userl1  # <user1Name> - <User1email>
      - userd2  # <user2Name> - <User2email>
      - userr1  # <user3Name> - <User3email>
  - state: present
    group:
    name: "Admins"
    description: "The Admin team"
    userNames:
      - userl1  # <user1Name> - <User1email>
      - userd2  # <user2Name> - <User2email>

I want to add a new user to developer whose id is usermd with comment in line # <UserName> - <Useremail> similarly to the admin group too.

expected output as:

# This is the group manages the permissions
group:
  - state: present
    group:
    name: "Developers"
    description: "The development team"
    userNames:
      - userl1  # <user1Name> - <User1email>
      - userd2  # <user2Name> - <User2email>
      - userr1  # <user3Name> - <User3email>
      - usermd  # <usermdName, Surname> - <Usermdemail>
  - state: present
    group:
    name: "Admins"
    description: "The Admin team"
    userNames:
      - userl1  # <user1Name> - <User1email>
      - userd2  # <user2Name> - <User2email>

The code I have used is

import sys
import ruamel.yaml

with open('Access.yaml', 'r') as f:
    # Load the YAML data
    yaml = ruamel.yaml.YAML(typ='rt')
    data = yaml.load(f)

for x in data['jfrog']['groups']:
    if not x["group"]["name"].endswith('Developers'):
        continue
    usr = x['group']['userNames']
    usr.append('usermd')

yaml.dump(data, sys.stdout)

I am using a jfrog yaml so the jfrog is parent key for the repositories I haven't found a way to wrap the comment to the new user. but when I use this the output I got as

    group:
      name: Developers
      description: The development group
      autoJoin: false
      userNames:
      - userl1      # <user1Name> - <User1email>
      - userd2      # <user2Name> - <User2email>
      - userr1      # <user3Name> - <User3email>
      - usermd
  - state: present
      # This is the Admins group need to be added
    group:
      name: Admins
      description: The admin group
      autoJoin: false
      userNames:
      - userl1      # <user1Name> - <User1email>
      - userd2      # <user2Name> - <User2email>```
1

There are 1 answers

3
Anthon On

The sequence and its elements are loaded in a CommentedSeq which behaves like a Python list, but also contains the comments. You can inspect its .ca attribute to see what the comments on the existing lines look like and create an extra comment item for the added entry:

import sys
from pathlib import Path
import ruamel.yaml

path = Path('Access.yaml')

yaml = ruamel.yaml.YAML()
yaml.indent(mapping=4, sequence=4, offset=2)
yaml.preserve_quotes = True
data = yaml.load(path)

for x in data['group']:
    if not x["name"].endswith('Developers'):
        continue
    users = x['userNames']
    # print(users.ca)  # to check how the other comments are set
    key = len(users)  # index of the next item
    users.append('usermd') # add the item
    # create and set the comment
    mark = ruamel.yaml.error.CommentMark(16)
    comment = ruamel.yaml.tokens.CommentToken('# <usermdName, Surname> - <Usermdemail>', mark, None)
    users.ca.items[key] = [comment, None, None, None]

yaml.dump(data, sys.stdout)

which gives:

# This is the group manages the permissions
group:
  - state: present
    group:
    name: "Developers"
    description: "The development team"
    userNames:
      - userl1  # <user1Name> - <User1email>
      - userd2  # <user2Name> - <User2email>
      - userr1  # <user3Name> - <User3email>
      - usermd  # <usermdName, Surname> - <Usermdemail>
  - state: present
    group:
    name: "Admins"
    description: "The Admin team"
    userNames:
      - userl1  # <user1Name> - <User1email>
      - userd2  # <user2Name> - <User2email>