Reputation: 2234
How to preserve indenting in key-value when dumping yaml ? I am using ruamel yaml
Code:
in_str='''Pets:
Cat:
Tom
Mouse:
Jerry
Dog:
Scooby
'''
import ruamel.yaml, sys
results = ruamel.yaml.load(in_str, ruamel.yaml.RoundTripLoader, preserve_quotes=True)
results['Pets']['Bird']='Tweety'
ruamel.yaml.dump(results, sys.stdout, ruamel.yaml.RoundTripDumper, default_flow_style=True,indent=2, block_seq_indent=2)
Output :
Pets:
Cat: Tom
Mouse: Jerry
Dog: Scooby
Bird: Tweety
Expected Output:
Pets:
Cat:
Tom
Mouse:
Jerry
Dog:
Scooby
Bird:
Tweety
Upvotes: 2
Views: 4057
Reputation: 76578
In order to achieve this you'll have to hook into the Emitter
and have it insert a newline and appropriate indentation when processing a mapping value. This can be done with the old style API that you use, but is better done with the new ruamel.yaml API, which gives you e.g. the possibility to indent sequences and mappings with different values:
import sys
import ruamel.yaml
from ruamel.yaml.emitter import Emitter
class MyEmitter(Emitter):
def expect_block_mapping_simple_value(self):
# type: () -> None
if getattr(self.event, 'style', None) != '?':
# prefix = u''
if self.indent == 0 and self.top_level_colon_align is not None:
# write non-prefixed colon
c = u' ' * (self.top_level_colon_align - self.column) + self.colon
else:
c = self.prefixed_colon
self.write_indicator(c, False)
# the next four lines force a line break and proper indent of the value
self.write_line_break()
self.indent += self.best_map_indent
self.write_indent()
self.indent -= self.best_map_indent
self.states.append(self.expect_block_mapping_key)
self.expect_node(mapping=True)
in_str='''\
Pets:
Cat:
Tom
Mouse:
- Jerry
- 'Mickey'
Dog:
Scooby
'''
yaml = ruamel.yaml.YAML()
yaml.Emitter = MyEmitter
yaml.indent(mapping=4, sequence=2, offset=0)
yaml.preserve_quotes = True
results = yaml.load(in_str)
results['Pets']['Bird']='Tweety'
yaml.dump(results, sys.stdout)
this gives:
Pets:
Cat:
Tom
Mouse:
- Jerry
- 'Mickey'
Dog:
Scooby
Bird:
Tweety
Things to note:
expect_block_mapping_simple_value
is copied from the source and a few lines added. There is currently no "hook" to do this without duplicating some code.sequence
and offset
values for yaml.indent()
if you have sequences and need different indentation for that.Upvotes: 2