如何使用 ruamel.yaml 的往返正确设置 YAML 流式转储?

How to properly set up YAML flow style dumping using round-trip with ruamel.yaml?

我正在使用 ruamel.yaml 包,但我似乎无法以格式良好的流样式输出它。我想将元素保持在同一级别,并用尾随逗号和换行符分隔。我也想保留每条评论,似乎有些在转换为流式后消失了。这是一个例子:

原创

background_opacity: 0.9 # comment
cursor: {style: Beam}

# comment
font:
    normal: {family: Fira Code, style: Retina} # comment
    size: 12.0 # comment

有意

{
    background_opacity: 0.9, # comment
    cursor: {style: Beam},
    
    # comment
    font: {
        normal: {family: Fira Code, style: Retina}, # comment
        size: 12.0 # comment
    }
}

实际

{background_opacity: 0.9 # comment
, cursor: {style: Beam}, font: {normal: {family: Fira Code, style: Retina} # comment
, size: 12.0   # comment
}}

我的代码附在下面。我对 YAML 和 ruamel.yaml 还很陌生,所以对于任何简单的错误我深表歉意。

from ruamel.yaml import YAML

def round_trip(sout, sin, idt):
    yaml = YAML()
    assert idt >= 2
    yaml.indent(mapping=idt, sequence=idt, offset=idt-2)
    yaml.preserve_quotes = True

    data = yaml.load(sin)
    if data is not None:
        data.fa.set_flow_style() # needs fixing: commas are not trailing
        yaml.dump(data, sout)
    else:
        print("the file is empty") # needs fixing: should dump original file

您似乎没有做错任何事,但ruamel.yaml不支持进行那种输出。它只是试图在一行中填充尽可能多的流式,而你得到换行符是因为输出注释(与它们之前的映射键相关联,强制这样的换行符。

如果您的输入没有任何注释,那么根据您设置的输出宽度,您最终会得到一两行。

如果您在加载时向每一行附加一个虚拟注释,并在转储后删除它,您可能会得到更好的结果,但这仍然不会让您在自己的行上打开大括号。

目前您只设置了根级样式属性,该属性“有效”是因为您没有嵌套的块样式集合。您应该使用类似以下内容递归地执行此操作:

def set_style(d, flow):
    if isinstance(d, dict):
        if flow:
            d.fa.set_flow_style()
        else:
            d.fa.set_block_style()
        for k in d:
            set_style(d[k], flow)
    elif isinstance(d, list):
        if flow:
            d.fa.set_flow_style()
        else:
            d.fa.set_block_style()
        for item in d:
             set_style(item, flow)


data = yaml.load(sin)
set_style(data, flow=True)