在ruamel.yaml往返解析中保留空消息 [英] Preserve empty message in ruamel.yaml roundtrip parsing

查看:251
本文介绍了在ruamel.yaml往返解析中保留空消息的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

使用ruamel.yaml,YAML往返解析的输出

Using ruamel.yaml, the output of roundtrip parsing of the YAML

a: {b: }

a: {b: !!null ''}

是否有任何方法可以保留空消息,或覆盖None表示符以输出上述空消息?

Is there any way to preserve the empty message, or overwrite the None representer to output an empty message as above?

推荐答案

这不是微不足道的,并且我不确定下面介绍的解决方案是否没有不利影响.

This is not trivial and I am not sure if the solution presented below doesn't have adverse side-effects.

不平凡的原因与多种因素有关:

The cause for the non-triviality has to do with multiple things:

  • 您正在使用可读性较低的流样式

  • You are using the less readable flow style

a: {b: } 

代替块样式:

a:
    b:

后面的往返没有改变

a: {b:} 

与您的完全不同

a: {b: } 

目前,发射器为了安全起见,将标签信息插入流中.

and currently the emitter goes for safe and inserts tag information into the stream.

有了这些背景信息,您就可以将None的表示形式强制为空字符串,并根据这种情况对发射器进行修改:

With that background information, you can force the style of the representation for None to the empty string and based on that hack the emitter:

import sys
import ruamel.yaml

yaml_str = """\
a: {b: }
"""

class MyEmitter(ruamel.yaml.emitter.Emitter):
    def choose_scalar_style(self):
        # override selection for 'null'
        if self.analysis is None:
            self.analysis = self.analyze_scalar(self.event.value)
        if self.event.style == '"' or self.canonical:
            return '"'
        if (not self.event.style or self.event.style == '?') and \
           (self.event.implicit[0] or not self.event.implicit[2]):
            if (not (self.simple_key_context and
                     (self.analysis.empty or self.analysis.multiline)) and
                (self.flow_level and self.analysis.allow_flow_plain or
                    (not self.flow_level and self.analysis.allow_block_plain))):
                return ''
        if (self.event.style == '') and self.event.tag == 'tag:yaml.org,2002:null' and \
           (self.event.implicit[0] or not self.event.implicit[2]):
            if self.flow_level and not self.analysis.allow_flow_plain:
                return ''
        self.analysis.allow_block = True
        if self.event.style and self.event.style in '|>':
            if (not self.flow_level and not self.simple_key_context and
                    self.analysis.allow_block):
                return self.event.style
        if not self.event.style and self.analysis.allow_double_quoted:
            if "'" in self.event.value or '\n' in self.event.value:
                return '"'
        if not self.event.style or self.event.style == '\'':
            if (self.analysis.allow_single_quoted and
                    not (self.simple_key_context and self.analysis.multiline)):
                return '\''
        return '"'

    def process_scalar(self):
        # if style '' and tag is 'null' insert empty space
        if self.analysis is None:
            self.analysis = self.analyze_scalar(self.event.value)
        if self.style is None:
            self.style = self.choose_scalar_style()
        split = (not self.simple_key_context)
        if self.sequence_context and not self.flow_level:
            self.write_indent()
        if self.style == '"':
            self.write_double_quoted(self.analysis.scalar, split)
        elif self.style == '\'':
            self.write_single_quoted(self.analysis.scalar, split)
        elif self.style == '>':
            self.write_folded(self.analysis.scalar)
        elif self.style == '|':
            self.write_literal(self.analysis.scalar)
        elif self.event.tag == 'tag:yaml.org,2002:null':
            self.stream.write(u' ')  # not sure if this doesn't break other things
        else:
            self.write_plain(self.analysis.scalar, split)
        self.analysis = None
        self.style = None
        if self.event.comment:
            self.write_post_comment(self.event)

class MyRepresenter(ruamel.yaml.representer.RoundTripRepresenter):
    def represent_none(self, data):
        if len(self.represented_objects) == 0 and not self.serializer.use_explicit_start:
            # this will be open ended (although it is not yet)
            return self.represent_scalar(u'tag:yaml.org,2002:null', u'null')
        return self.represent_scalar(u'tag:yaml.org,2002:null', u'', style='')

MyRepresenter.add_representer(type(None),
                                     MyRepresenter.represent_none)


yaml = ruamel.yaml.YAML()
yaml.Emitter = MyEmitter
yaml.Representer = MyRepresenter
data = yaml.load(yaml_str)
yaml.dump(data, sys.stdout)

给出:

a: {b: }

这篇关于在ruamel.yaml往返解析中保留空消息的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆