0

I'm editing YAML file but it isn't giving the exact output as I want. There is a difference between indentation and square brackets.

import yaml

add_info = {'network':
        {'version': 2,
         'renderer': 'networkd',
         'ethernets':
             {'enx1':
                {
                    'addresses': ['193.254.1.8/24'],
                    'nameservers': {'addresses':
                                    ['193.254.1.5, 8.8.8.8']},
                    'routes': [{
                        'to': '193.254.1.0/24',
                        'via': '193.254.1.5'
                    }]
                }
            }
        }
    }

with open('/etc/netplan/01-network-manager-test.yaml', 'w') as f:
    data1 = yaml.dump(add_info, f, sort_keys=False)
    print(data1)

Current Output I'm getting from above code.

network:
  version: 2
  renderer: networkd
  ethernets:
    enx1:
      addresses:
      - 193.254.1.8/24
      nameservers:
        addresses:
        - 193.254.1.5, 8.8.8.8
      routes:
      - to: 193.254.1.0/24
        via: 193.254.1.5

This is the exact Output I want:

network:
  version: 2
  renderer: networkd
  ethernets:
    enx1:
      addresses:
      - 193.254.1.6/24
      nameservers:
          addresses: [193.254.1.5, 8.8.8.8]
      routes:
          - to: 193.254.1.0/24
            via: 193.254.1.5

12
  • 1
    i dont think that's possible since the indentation style is not consistent in your expected output (see the lists under your addresses: and routes:). Commented Jun 20, 2022 at 8:19
  • 1
    and the two addresses: lists are using different notation (- style vs. [ ... ] style). Commented Jun 20, 2022 at 8:21
  • Why is this tagged bash? There is no bash involved in the question. Also, why do you say in the title that you want to edit a file, but everything you do is to create a file? Commented Jun 20, 2022 at 9:53
  • @user1934428 all I've to do is to edit a config file which is already available in the directory, currently I'm doing it for testing purpose Commented Jun 20, 2022 at 9:57
  • @pynexj that is what I want my 2nd addresses field, I want them in a list ([...])instead of "-". Commented Jun 20, 2022 at 10:02

1 Answer 1

1

You should not be using PyYAML. It only supports a subset of YAML 1.1 (which was superseded in 2009) and doesn't give you much fine control.

Start with what you want to get and see how well that round-trips in ruamel.yaml:

import sys
import ruamel.yaml

yaml_str = """\
network:
  version: 2
  renderer: networkd
  ethernets:
    enx1:
      addresses:
      - 193.254.1.6/24
      nameservers:
          addresses: [193.254.1.5, 8.8.8.8]
      routes:
          - to: 193.254.1.0/24
            via: 193.254.1.5
"""
    
yaml = ruamel.yaml.YAML()
# yaml.indent(mapping=4, sequence=4, offset=2)
yaml.preserve_quotes = True
data = yaml.load(yaml_str)
# print(data)
yaml.dump(data, sys.stdout)

which gives:

network:
  version: 2
  renderer: networkd
  ethernets:
    enx1:
      addresses:
      - 193.254.1.6/24
      nameservers:
        addresses: [193.254.1.5, 8.8.8.8]
      routes:
      - to: 193.254.1.0/24
        via: 193.254.1.5

You do have control seperately over indentation of mappings and sequences, but your sequences are not indented consistently: the sequence that is the value for addresses has an indent of 2 with an offset for the sequence indicator (-) within that of 0, and for the sequence that is the value of routes is indented 6 with an offset of 4; your mappings are not indented consistently either (using 2 and 4 positions). ruamel.yaml doesn't give you that fine control.

If you want to start with your datastructure you need to provide the valued for addresses not as list of a single string with embedded comma, but as the subclass of a list that ruamel.yaml uses (you could find which by inspecting data after loading) and mark it to be represented as flow style:

import sys
import ruamel.yaml

def FS(*args):
    seq = ruamel.yaml.CommentedSeq(args)
    seq.fa.set_flow_style()
    return seq

add_info = {'network':
        {'version': 2,
         'renderer': 'networkd',
         'ethernets':
             {'enx1':
                {
                    'addresses': ['193.254.1.8/24'],
                    'nameservers': {'addresses':
                                    FS('193.254.1.5', '8.8.8.8')},  # <- changed
                    'routes': [{
                        'to': '193.254.1.0/24',
                        'via': '193.254.1.5'
                    }]
                }
            }
        }
    }

yaml = ruamel.yaml.YAML()
yaml.dump(add_info, sys.stdout)

which also gives:

network:
  version: 2
  renderer: networkd
  ethernets:
    enx1:
      addresses:
      - 193.254.1.8/24
      nameservers:
        addresses: [193.254.1.5, 8.8.8.8]
      routes:
      - to: 193.254.1.0/24
        via: 193.254.1.5
Sign up to request clarification or add additional context in comments.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.