In Pyyaml, how to represent empty strings and list

2019-07-12 13:06发布

I have added representers for folded strings, literal strings as mentioned in Any yaml libraries in Python that support dumping of long strings as block literals or folded blocks?. I have also added representer to print a list in block style in the dumped yaml content.

But the issue is that when the string is empty, i.e., "" or the list is empty, they appear in non-block style in the dumped YAML content.

How do force the pyyaml dumper to output "" empty strings with ">" or "|" style and empty list with flow_style=False in a block style in the generated YAML content?

1条回答
别忘想泡老子
2楼-- · 2019-07-12 13:40

After a bit of research, I am able to dump empty strings as block literals (style in '|>') in a YAML file using Pyyaml. My work is partially based on Any yaml libraries in Python that support dumping of long strings as block literals or folded blocks?.

import yaml
from yaml.emitter import Emitter, ScalarAnalysis

class MyEmitter(Emitter):  
    def analyze_scalar(self, scalar):   
        # Empty scalar is a special case.
        # By default, pyyaml sets allow_block=False
        # I override this to set allow_block=True
        if not scalar:         
            return ScalarAnalysis(scalar=scalar, empty=True, multiline=False,
                allow_flow_plain=False, allow_block_plain=True,
                allow_single_quoted=True, allow_double_quoted=True,
                allow_block=True)   
        return super(MyEmitter, self).analyze_scalar(scalar)

# And I subclass MyDumper from MyEmitter and yaml.Dumper        
class MyDumper(yaml.Dumper, MyEmitter):
    pass
class folded_unicode(unicode): pass
class literal_unicode(unicode): pass

def folded_unicode_representer(dumper, data):
    return dumper.represent_scalar(u'tag:yaml.org,2002:str', data, style='>')
def literal_unicode_representer(dumper, data):
    return dumper.represent_scalar(u'tag:yaml.org,2002:str', data, style='|')

yaml.add_representer(folded_unicode, folded_unicode_representer)
yaml.add_representer(literal_unicode, literal_unicode_representer)

# I test it now
d = {'foo': {'folded': folded_unicode(''), 'literal': literal_unicode('')}}
print yaml.dump(d, Dumper=MyDumper)

Output:

foo:
  folded: >
  literal: |

However, I am not able to find a way to dump an empty list in block style. For this, I tried to mess with yaml/emitter.py and realized that I needed a non-empty list to dump it in block style.

Anyways, this effort did not go in vain, rather it was quite exciting :) I hope that some one may find this useful or may have something to share.

查看更多
登录 后发表回答