如何在保留引号的同时将带有字符串的列表设置为 yaml 值?

How to set list with strings as a yaml value while preserving quotes?

我有这样的代码:

import ruamel.yaml
from ruamel.yaml.scalarstring import DoubleQuotedScalarString as dq    
yaml = ruamel.yaml.YAML()
yaml.indent(sequence=2)
yaml.preserve_quotes = True
yaml.default_flow_style=None

CF2_cloudbuild = {
            'steps':[
            {'name': dq("gcr.io/cloud-builders/gcloud"),
            'args': ["functions", "deploy", "publish_resized"],
            'timeout': dq("1600s")}
            ]
            }

with open("file.yaml", 'w') as fp:
    yaml.dump(CF2_cloudbuild, fp)

这是file.yaml的内容:

steps:
- name: "gcr.io/cloud-builders/gcloud"
  args: [functions, deploy, publish_resized]
  timeout: "1600s"

我需要:

steps:
- name: "gcr.io/cloud-builders/gcloud"
  args: ["functions", "deploy", "publish_resized"]
  timeout: "1600s"

为了使格式符合有关构建配置文件的 GCP 文档GCP Build configuration overview docs

如何获得?
当我尝试使用 [dq("functions"), dq("deploy"), dq("publish_resized")] 功能时,我得到:

steps:
- name: "gcr.io/cloud-builders/gcloud"
  args:
  - "functions"
  - "deploy"
  - "publish_resized"
  timeout: "1600s"

我认为这与 ["functions", "deploy", "publish_resized"] 不同。

正如@Stephen Rauch 所指出的,这两个输出是等价的,你 "need" 的一个具有流式序列,而另一个 你得到的是块样式的序列。任何 YAML 解析器都应该以相同的方式加载它。如果您没有明确添加双引号,ruamel.yaml 将在需要时添加它们(例如,防止字符串 true 作为布尔值加载)。

但是由于您设置了 .default_flow_style,您期望 YAML 输出中的叶节点是流式的是正确的,并且您可能遇到了 ruamel.yaml 回合中的错误-绊倒者。

当 ruamel.yaml 加载您预期的输出时,它会保留

import sys
import ruamel.yaml

yaml_str = """
steps:
- name: "gcr.io/cloud-builders/gcloud"
  args: ["functions", "deploy", "publish_resized"]
  timeout: "1600s"
"""

yaml = ruamel.yaml.YAML()
yaml.preserve_quotes = True

data = yaml.load(yaml_str)
yaml.dump(data, sys.stdout)

给出:

steps:
- name: "gcr.io/cloud-builders/gcloud"
  args: ["functions", "deploy", "publish_resized"]
  timeout: "1600s"

这是因为映射和序列节点未加载为 dict resp。 list,但是其子类,保留有关其原始信息的信息 flow/block风格。

您可以通过为您的列表构建该子类来模拟这一点:

from ruamel.yaml.scalarstring import DoubleQuotedScalarString as dq
from ruamel.yaml.comments import CommentedSeq

def cs(*elements):
     res = CommentedSeq(*elements)
     res.fa.set_flow_style()
     return res


CF2_cloudbuild = {
            'steps':[
            {'name': dq("gcr.io/cloud-builders/gcloud"),
            'args': cs(dq(l) for l in ["functions", "deploy", "publish_resized"]),
            'timeout': dq("1600s")}
            ]
            }

yaml.dump(CF2_cloudbuild, sys.stdout)

给出:

steps:
- name: "gcr.io/cloud-builders/gcloud"
  args: ["functions", "deploy", "publish_resized"]
  timeout: "1600s"

但是,同样,如果 cloudbuilder 软件使用的 YAML 解析器是一致的, 您的流程样式和任何双引号都不是必需的 例子。如果它们是,您可以依靠 ruamel.yaml 添加后者 必要的。