I'm using ruamel.yaml
for modifying a YAML file. My requirement is to add a value for an existing key, preserving everything else including the order. I got it to work, but looks like quotation marks of other keys/values get modified too in the process.
For some cases, double quotes get converted to single quotes. E.g.
Before
node_js:
- "0.10"
After
node_js:
- '0.10'
In some other cases, quotes get dropped altogether. E.g.:
Before
before_script:
- "cp test/config-x.js src/config.js"
After
before_script:
- cp test/config-x.js src/config.js
Both of these cases appear in the same file. How can I stop this from happening and preserve the quotes as it is in the original?
I use load_yaml_guess_indent()
for loading and round_trip_dump()
for writing it back.
yaml.preserve_quotes = True
works in the current version of ruamel.yaml
.
By default ruamel.yaml "normalizes" things like indentation and removes any superfluous quotes. It also defaults to the single quotes on output, when those are necessary as those indicate simpler strings (i.e. only single quotes have special meaning and these are a better/simpler option to distinguish strings that could be interpreted as numbers than double quotes are).
What you probably missed is that you explicitly have to tell the round_trip_loader()
to preserve quotes, using the preserve_quotes=True
argument:
import sys
import ruamel.yaml
yaml_str_1 = """\
node_js:
- "0.10"
"""
yaml_str_2 = """\
before_script:
- "cp test/config-x.js src/config.js"
"""
yaml = ruamel.yaml.YAML()
yaml.preserve_quotes = Truej
data = ruamel.yaml.load(yaml_str_1)
ruamel.yaml.dump(data, sys.stdout)
print('=====')
data = ruamel.yaml.load(yaml_str_2)
ruamel.yaml.dump(data, sys.stdout)
gives:
node_js:
- "0.10"
=====
before_script:
- "cp test/config-x.js src/config.js"
With that option all strings are loaded in special subclasses of strings that are then output as they were loaded. These classes need to be used if you replace such a loaded value, as just assigning a new value will not preserve the type. Adding:
data['before_script'][0] = type(data['before_script'][0])('ln -s xxx /usr/local/bin')
ruamel.yaml.round_trip_dump(data, sys.stdout)
gives:
before_script:
- "ln -s xxx /usr/local/bin"
(that type happens to be ruamel.yaml.scalarstring.DoubleQuotedScalarString()
)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With