I have code like this:
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)
and this is the content of file.yaml
:
steps:
- name: "gcr.io/cloud-builders/gcloud"
args: [functions, deploy, publish_resized]
timeout: "1600s"
and I need:
steps:
- name: "gcr.io/cloud-builders/gcloud"
args: ["functions", "deploy", "publish_resized"]
timeout: "1600s"
in order to get format compliant with the GCP documentation concerning build configuration files GCP Build configuration overview docs
How to obtain that?
When I try to use [dq("functions"), dq("deploy"), dq("publish_resized")]
functionality I get:
steps:
- name: "gcr.io/cloud-builders/gcloud"
args:
- "functions"
- "deploy"
- "publish_resized"
timeout: "1600s"
which I think is not the same as ["functions", "deploy", "publish_resized"]
.
As @Stephen Rauch indicates, the two outputs are equivalent, the one you "need" has a sequence in flow style and the one
you get is a sequence in block style. Any YAML parser should load that in the same way. And if you don't explicitly add the double quotes, ruamel.yaml
will add them if they are needed (e.g. to prevent the string true
from being loaded as a boolean).
But since you set .default_flow_style
you are right to expect a leaf node in the YAML output to be flow-style, and you might have hit on a bug in ruamel.yaml
's round-tripdumper.
When ruamel.yaml loads your expected output, then it preserves
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)
which gives:
steps:
- name: "gcr.io/cloud-builders/gcloud"
args: ["functions", "deploy", "publish_resized"]
timeout: "1600s"
This is because the mapping and sequence nodes are not loaded as dict
resp.
list
, butsubclasses thereof, that keep information about their original
flow/block style.
You can emulate this by constructing that subclass for your list:
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)
which gives:
steps:
- name: "gcr.io/cloud-builders/gcloud"
args: ["functions", "deploy", "publish_resized"]
timeout: "1600s"
But, again, if the YAML parser that cloudbuilder software uses is conformant, neither the flow style, nor any of the double quotes are necessary in your example. And you can rely on ruamel.yaml on adding the latter if they are necessary.