使用 ruamel.yaml 和 preserve_quotes=True 时,有没有办法强制往返 yaml 使用单引号?

When using ruamel.yaml and preserve_quotes=True is there a way to force roundtriped yaml to use single quotes?

[已更新问题,preserve_quotes 按预期工作]

无论输入中使用何种类型的引号,我如何强制输出使用单引号,但前提是使用了引号?

注意:我的项目的(简陋)源代码使用 ruamel.yaml =>

您的示例输出更改了单引号,即未保留 一个最小的例子表明事情不是这样运作的。

import sys
import ruamel.yaml

yaml_str = """---
metadata:
  annotations:
    first: '1'
    second: any string
"""

yaml = ruamel.yaml.YAML(typ='rt')
data = list(yaml.load_all(yaml_str))
yaml.preserve_quotes = True
yaml.explicit_start = True
yaml.dump_all(data, sys.stdout)

给出:

---
metadata:
  annotations:
    first: '1'
    second: any string

使用您的 format_yaml 例程:

import sys
import pathlib
import ruamel.yaml
YAML = ruamel.yaml.YAML

yaml_file = pathlib.Path("temp.yaml")
yaml_file.write_text("""---
metadata:
  annotations:
    first: '1'
    second: any string
""")


def format_yaml(input_file,
                output_file,
                explicit_start=True,
                explicit_end=False,
                default_flow_style=False,
                dash_inwards=True,
                quotes_preserved=True,
                parsing_mode='rt'):
    """
    Load a file and save it formated :
    :param input_file: the input file
    :param output_file: the output file
    :param explicit_start: write the start of the yaml doc even when there is \
                            only one done in the file
    :param default_flow_style: if False, block style will be used for nested \
                              arrays/maps
    :param dash_inwards: push dash inwards if True
    :param quotes_preserved: preserve quotes if True
    :param parsing_typ: safe or roundtrip (rt) more
    """
    yaml = YAML(typ=parsing_mode)
    yaml.explicit_start = explicit_start
    yaml.explicit_end = explicit_end
    yaml.default_flow_style = default_flow_style
    yaml.preserve_quotes = quotes_preserved
    if dash_inwards:
        yaml.indent(mapping=2, sequence=4, offset=2)

    if input_file is not None:
        with open(input_file, 'rt') as f_input:
            parsed = yaml.load_all(f_input.read())
    else:
        parsed = yaml.load_all(sys.stdin.read())
    ready_for_dump = []
    try:
        # Read the parsed content to force the scanner to issue errors if any
        for data in parsed:
            ready_for_dump.append(data)
    except ScannerError as e:
        print("Something is wrong in the input file, got error from Scanner")
        print(e)
        return
    if output_file is not None:
        with open(output_file, 'wt') as out:
            yaml.dump_all(ready_for_dump, out)
    else:
        yaml.dump_all(ready_for_dump, sys.stdout)

format_yaml(yaml_file, None)

这也给出了:

---
metadata:
  annotations:
    first: '1'
    second: any string

如果您在输入中使用双引号,您将在输出中得到双引号。 所以请提供一个 minimal 完整的示例程序来展示行为 你得到的,加上 ruamel.yaml 和 python 版本以及你测试过的平台(上面是在 Python 3.7.3 和 Python 上用 0.15.97 测试的Linux 上的 2.7.15(安装了 pathlib2)。


顺便说一句,将所有单引号字符串转储为双引号字符串的最简单方法 round-trip 模式是重写 represent_single_quoted_scalarstring 方法 在 yaml.representer 上(例如,通过将 represent_double_quoted_scalarstring 方法分配给它)。