如何往返 ruamel.yaml 字符串,如 "on"

How to round trip ruamel.yaml strings like "on"

当使用 ruamel.yaml 往返一些 YAML 时,我看到以下问题。鉴于此输入:

root:
  matchers:
    - select: "response.body#state"
      test: all
      expected: "on"

我看到这个输出:

root:
  matchers:
    - select: response.body#state
      test: all
      expected: on

请注意,在 YAML 中,on 解析为布尔值 true,而 off 解析为 false

以下代码用于read/write:

# Use the default (round-trip) settings.
yaml = YAML()

if args.source == '-':
    src = sys.stdin
else:
    src = open(args.source)

doc = yaml.load(src)
process(args.tag, set(args.keep.split(',')), doc)

if args.destination == '-':
    dest = sys.stdout
else:
    dest = open(args.destination, 'w')

yaml.dump(doc, dest)

process 函数未修改值。它只会在爬取结构后删除输入中带有特殊标签的东西。

如何使输出成为字符串而不是布尔值?

你这样写:

Note that in YAML, on parses as a boolean true value while off parses as false.

该说法不正确(或更好: 十年来都不是真的)。如果您的 on 中有一个不带引号的 on YAML,就像在您的输出中一样,使用 ruamel.yaml:

时显然不是这种情况
import sys
import ruamel.yaml

yaml_str = """\
root:
  matchers:
    - select: response.body#state
      test: all
      expected: on
"""

yaml = ruamel.yaml.YAML()
data = yaml.load(yaml_str)
expected = data['root']['matchers'][0]['expected']
print(type(expected), repr(expected))

给出:

<class 'str'> 'on'

这是因为在 YAML 1.2 规范中 on/off/yes/no 是没有的 不再提到与 true 具有相同的含义 分别false。 YAML 1.1 规范中提到了它们 ,但那是 于 2009 年被取代。不幸的是,YAML 库在 野生的,从那以后就没有更新了。

实际发生的是你的多余引号 输入被往返过程自动丢弃。你可以 还可以看到值 "response.body#state" 的情况。虽然 那里包含开始评论的字符(#),以 实际上开始评论字符必须由 white-space,因为它不是,所以不需要引号。

所以你的输出很好,但如果你不幸 您必须依赖于其他程序的情况 过时的 YAML 1.1,那么你可以,例如指定您要保留 你对往返的报价:

yaml_str = """\
root:
  matchers:
    - select: "response.body#state"
      test: all
      expected: "on"
"""

yaml = ruamel.yaml.YAML()
yaml.indent(sequence=4, offset=2)
yaml.preserve_quotes = True
data = yaml.load(yaml_str)
yaml.dump(data, sys.stdout)

因为这给出了您的准确输入:

root:
  matchers:
    - select: "response.body#state"
      test: all
      expected: "on"

然而,也许更好的选择是您实际指定您的 YAML 必须符合 YAML 1.1 规范 你的意图,以及输出文档,explicit:

yaml_str = """\
root:
  matchers:
    - select: response.body#state
      test: all
      expected: on
"""

yaml_in = ruamel.yaml.YAML()
yaml_out = ruamel.yaml.YAML()
yaml_out.indent(sequence=4, offset=2)
yaml_out.version = (1, 1)
data = yaml_in.load(yaml_str)
yaml_out.dump(data, sys.stdout)

请注意,"unquoted" YAML 1.2 输入在引用 on 的地方给出输出:

%YAML 1.1
---
root:
  matchers:
    - select: response.body#state
      test: all
      expected: 'on'