Specifying Styles for Parts of a PyYAML (II) Dump: Sequences

This is the next question Specifying Styles for Parts of a PyYAML Dump :

Consider the following code encoding as manually formatted YAML input. I am modifying YAML data, but would like to keep edges in single lines in a written YAML file.

import yaml st2 = yaml.load(""" edges: - [1, 2] - [2, 1, [1,0]] """) print yaml.dump(st2) class blockseq( dict ): pass def blockseq_rep(dumper, data): return dumper.represent_mapping( u'tag:yaml.org,2002:seq', data, flow_style=False ) class flowmap( dict ): pass def flowmap_rep(dumper, data): return dumper.represent_mapping( u'tag:yaml.org,2002:map', data, flow_style=True ) class blockseqtrue( dict ): pass def blockseqtrue_rep(dumper, data): return dumper.represent_mapping( u'tag:yaml.org,2002:seq', data, flow_style=True ) yaml.add_representer(blockseq, blockseq_rep) yaml.add_representer(blockseqtrue, blockseqtrue_rep) yaml.add_representer(flowmap, flowmap_rep) st2['edges'] = [ blockseqtrue(x) for x in st2['edges'] ] print yaml.dump(st2) 

This script exits with the following output displaying an error message:

 edges: - [1, 2] - - 2 - 1 - [1, 0] Traceback (most recent call last): File "test-yaml-rep.py", line 42, in <module> st2['edges'] = [ blockseqtrue(x) for x in st2['edges'] ] TypeError: cannot convert dictionary update sequence element #0 to a sequence 
+3
source share
2 answers

Your problem is that the two classes that I had work on dicts, not lists. You want something that will work with lists:

 class blockseqtrue( list ): pass def blockseqtrue_rep(dumper, data): return dumper.represent_sequence( u'tag:yaml.org,2002:seq', data, flow_style=True ) 

Python lists are YAML / seqs sequences. Python dicts are YAML mappings / maps.

+2
source

If you do YAML round-trip in python, it is much easier to use ruamel.yaml (I am the author of this extended version of PyYAML). It saves sequence / lists of stream / block style, as well as mapppings / dicts (as well as comments):

 import ruamel.yaml st2 = ruamel.yaml.load(""" edges: - [1, 2] # <- change the second item - [2, 1, [1,0]] """, Loader=ruamel.yaml.RoundTripLoader) st2['edges'][0][1] = 42 print(ruamel.yaml.dump(st2, Dumper=ruamel.yaml.RoundTripDumper)) 

will provide you with:

 edges: - [1, 42] # <- change the second item - [2, 1, [1, 0]] 

As you can see, this preserves the block style in the topmost sequence ( edges value) and the stream style in other sequences.

+3
source

All Articles