Preserve quotes and also add data with quotes in Ruamel
<p>I am using Ruamel to preserve quote styles in human-edited YAML files.</p>

<p>I have example input data as:</p>

<pre><code>---
a: '1'
b: "2"
c: 3
</code></pre>

<p>I read in data using:</p>

<pre><code>def read_file(f):
    with open(f, 'r') as _f:
        return ruamel.yaml.round_trip_load(_f.read(), preserve_quotes=True)
</code></pre>

<p>I then edit that data:</p>

<pre><code>data = read_file('in.yaml')
data['foo'] = 'bar'
</code></pre>

<p>I write back to disk using:</p>

<pre><code>def write_file(f, data):
    with open(f, 'w') as _f:
        _f.write(ruamel.yaml.dump(data, Dumper=ruamel.yaml.RoundTripDumper, width=1024))

write_file('out.yaml', data)
</code></pre>

<p>And the output file is:</p>

<pre><code>a: '1'
b: "2"
c: 3
foo: bar
</code></pre>

<p>Is there a way I can enforce hard quoting of the string 'bar' without also enforcing that quoting style throughout the rest of the file?</p>

<p>(Also, can I stop it from deleting the three dashes <code>---</code> ?)</p>

<p>In order to preserve quotes (and literal block style) for string scalars, ruamel.yamlÂ¹&mdash;in round-trip-mode&mdash;represents these scalars as  <code>SingleQuotedScalarString</code>, <code>DoubleQuotedScalarString</code> and <code>PreservedScalarString</code>. The class definitions for these very thin wrappers can be found in <code>scalarstring.py</code>. 
When serializing such instances are written "as they were read", although sometimes the representer falls back to double quotes when things get difficult, as that can represent any string. </p>

<p>To get this behaviour when adding new key-value pairs (or when updating an existing pair), you just have to create these instances yourself:</p>

<pre><code>import sys
import ruamel.yaml
from ruamel.yaml.scalarstring import SingleQuotedScalarString, DoubleQuotedScalarString

yaml_str = """\
---
a: '1'
b: "2"
c: 3
"""

data = ruamel.yaml.round_trip_load(yaml_str, preserve_quotes=True)
data['foo'] = SingleQuotedScalarString('bar')
data.yaml_add_eol_comment('# &lt;- single quotes added', 'foo', column=20)
ruamel.yaml.round_trip_dump(data, sys.stdout, explicit_start=True)
</code></pre>

<p>gives:</p>

<pre><code>---
a: '1'
b: "2"
c: 3
foo: 'bar'          # &lt;- single quotes added
</code></pre>

<p>the <code>explicit_start=True</code> recreates the (superfluous) document start marker. Whether such a marker was in the original file or not is not "known" by the top-level dictionary object, so you have to re-add it by hand.</p>

<p>Please note that without <code>preserve_quotes</code>, there would be (single) quotes around the values <code>1</code> and <code>2</code> anyway to make sure they are seen as string scalars and not as integers.</p>

<hr>

<p>Â¹ <sub>Of which I am the author.</sub></p>

python ruamel.yaml