Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to use ruamel.yaml to dump literal scalars

I've searched and found "similar" posts, but nothing that answers my question directly. I also found a stackoverflow post here, but no answers.

I need to write to a yaml file using the following format:

any_value: 123.4
data_points: |-
  0.0, 1.0
  0.1, 1.5
  0.2, 1.7

If I use a long string containing \n in it, it will just print it as-is:

any_value: 123.4
data_points: "0.0, 1.0\n0.1, 1.5\n0.2, 1.7"

Which is not what I want. I can also pass it as a list where each item looks like this

['0.0, 1.0', '0.1, 1.5', '0.2, 1.7']

But that only results in

any_value: 123.4
data_points:
- 0.0, 1.0
- 0.1, 1.5
- 0.2, 1.7

It kinda looks like the first one, but it isn't. How do I get ruamel.yaml to dump it the way I want?

like image 349
Ivar Stange Avatar asked Jun 14 '18 08:06

Ivar Stange


1 Answers

What you want are not folded scalars (which would have > instead of |) but block style literal scalars.

The general way to solve this is to look at whether ruamel.yaml can round-trip what you want:

import sys
import ruamel.yaml

yaml_str = """\
any_value: 123.4
data_points: |-
  a
  b
"""

yaml = ruamel.yaml.YAML()
data = yaml.load(yaml_str)
yaml.dump(data, sys.stdout)

this gives:

any_value: 123.4
data_points: |-
  a
  b

As the output looks like the input, examine the type that ruamel.yaml uses to preserve the literal style information:

print(type(data['data_points']))

which shows what ruamel.yaml uses interally:

<class 'ruamel.yaml.scalarstring.LiteralScalarString'>

With that knowledge you can do:

from ruamel.yaml.scalarstring import LiteralScalarString

data['data_points'] = literalScalarString("""\
0.0, 1.0
0.1, 1.5
0.2, 1.7""")

yaml.dump(data, sys.stdout)

resulting in:

any_value: 123.4
data_points: |-
  0.0, 1.0
  0.1, 1.5
  0.2, 1.7

Please note that the dash in |- indicates that your scalar doesn't have a final new-line. That is why your Python multi-line string should not have one either.

There is also a function walk_tree() in ruamel/yaml/scalarstring.py, which might be of help, it:

walks over a simple yaml tree (recursing in dict values and list items) and converts strings that have multiple lines to literal scalars

like image 127
Anthon Avatar answered Sep 28 '22 10:09

Anthon