Force string quoting, while saving flow style

Viewed 84

I have data, that looks somewhat like this

data = {"a": {"a": "0.1.2", "b": "0.2.3"}, "c": 3}

and I want it to create a YAML document, that should look like this

a: {a: "0.1.2", b: "0.2.3"}
c: 3

so, by default we will have

yaml = ruamel.yaml.YAML()
data = {"a": {"a": "0.1.2", "b": "0.2.3"}, "c": 3}
yaml.dump(data, sys.stdout)

which gives us this

a:
  a: 0.1.2
  b: 0.2.3
c: 3

but I need the dict to be inline and the strings to be quoted.
For inline dict I can use

yaml.default_flow_style = None

almost there

a: {a: 0.1.2, b: 0.2.3}
c: 3

and for strings

from ruamel.yaml.scalarstring import SingleQuotedScalarString as dq

(I could also use yaml.default_style = '"' but it also quotes the keys and doesn't help with the flow)

the thing is double quotes somehow break the flow:

yaml = ruamel.yaml.YAML()
yaml.default_flow_style = None
data = {"a": {"a": dq("0.1.2"), "b": dq("0.2.3")}, "c": 3}
yaml.dump(data, sys.stdout)

gives me this back

a:
  a: "0.1.2"
  b: "0.2.3"
c: 3

How can I get the desired output?

1 Answers

First thing to do in these kind of cases is see if ruamel.yaml can round-trip the required output:

import sys
import ruamel.yaml

yaml_str = """\
a: {a: "0.1.2", b: "0.2.3"}
c: 3
"""

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

which gives exactly your input:

a: {a: "0.1.2", b: "0.2.3"}
c: 3

If you do:

yaml.default_flow_style = None

essentially all sequences and mappings that only contain scalars (as elements resp. keys and values) are dumped in flow style. But since you wrap the strings that you want quoted in your output, the dump process no longer sees those as scalars and that causes the block-style to reappear.

If you insert print(type(data['a'])) in the program above, you'll see that the mapping is loaded in a CommentedMap and that can be coerced to be output as flow style:

DQ = ruamel.yaml.scalarstring.DoubleQuotedScalarString
CM = ruamel.yaml.comments.CommentedMap 

cm = CM({"a": DQ("0.1.2"), "b": DQ("0.2.3")})
cm.fa.set_flow_style()
data = {"a": cm , "c": 3}
yaml.dump(data, sys.stdout)

which gives:

a: {a: "0.1.2", b: "0.2.3"}
c: 3
  • I am not entirely sure how you could get double quotes using:

    from ruamel.yaml.scalarstring import SingleQuotedScalarString as dq
    

    so that is why I used DoubleQuotedScalarString.

  • there is no need to set yaml.default_flow_style = None

Related