如何在 ruamel.yaml 中显式写入两个引用
how to explicitly write two references in ruamel.yaml
如果我有多个引用,当我使用 Python 中的 ruaml.yaml 将它们写入 YAML 文件时,我得到:
<<: [*name-name, *help-name]
但我更愿意
<<: *name-name
<<: *help-name
是否可以选择在写入文件时实现此目的?
更新
descriptions:
- &description-one-ref
description: >
helptexts:
- &help-one
help_text: |
questions:
- &question-one
title: "title test"
reference: "question-one-ref"
field: "ChoiceField"
choices:
- "Yes"
- "No"
required: true
<<: *description-one-ref
<<: *help-one
riskvalue_max: 10
calculations:
- conditions:
- comparator: "equal"
value: "Yes"
actions:
- riskvalue: 0
- conditions:
- comparator: "equal"
value: "No"
actions:
- riskvalue: 10
目前我正在读取这样的文件并修改 python 中的特定值,然后想将其写回。当我写作时,我发现参考文献是列表而不是概述的问题。
这意味着工作流程如下:我正在通过
阅读文档
yaml = ruamel.yaml.YAML()
with open('test.yaml') as f:
data = yaml.load(f)
for k in data.keys():
if k == 'questions':
q = data.get(k)
for i in range(0, len(q)):
q[i]['title'] = "my new title"
f.close()
g = open('new_file.yaml', 'w')
yaml(data)
g.close()
不,没有这样的选项,因为它会导致 YAML 文件无效。
<<
是一个映射键,其值被解释
特别假设解析器实现 独立的语言
合并密钥规范。并且映射键必须是唯一的
根据 YAML specification:
The content of a mapping node is an unordered set of key: value node
pairs, with the restriction that each of the keys is unique.
ruamel.yaml
(< 0.15.75) 不会在此类上引发错误
重复键是 bug。在重复的普通键上,ruamel.yaml
确实会引发错误。该错误继承自 PyYAML(不是
符合规范,即使在
复制普通键)。
然而,稍加预处理和 post- 处理你想做的事情就可以了
很容易实现。诀窍是在解析之前使 YAML 有效
通过使有问题的重复 <<
键唯一(但可识别)
然后,在将 YAML 写回文件时,用这些替换
唯一键再次 <<: *
。在下面第一次出现
<<: *
替换为 [<<, 0]:
,第二个替换为 [<<, 1]:
等
*
需要成为替换的一部分,因为其中没有锚点
这些别名的文档。
import sys
import subprocess
import ruamel.yaml
yaml = ruamel.yaml.YAML()
yaml.preserve_quotes = True
yaml.indent(sequence=4, offset=2)
class DoubleMergeKeyEnabler(object):
def __init__(self):
self.pat = '<<: ' # could be at the root level mapping, so no leading space
self.r_pat = '[<<, {}]: ' # probably not using sequences as keys
self.pat_nr = -1
def convert(self, doc):
while self.pat in doc:
self.pat_nr += 1
doc = doc.replace(self.pat, self.r_pat.format(self.pat_nr), 1)
return doc
def revert(self, doc):
while self.pat_nr >= 0:
doc = doc.replace(self.r_pat.format(self.pat_nr), self.pat, 1)
self.pat_nr -= 1
return doc
dmke = DoubleMergeKeyEnabler()
with open('test.yaml') as fp:
# we don't do this line by line, that would not work well on flow style mappings
orgdoc = fp.read()
doc = dmke.convert(orgdoc)
data = yaml.load(doc)
data['questions'][0].anchor.always_dump = True
#######################################
# >>>> do your thing on data here <<< #
#######################################
with open('output.yaml', 'w') as fp:
yaml.dump(data, fp, transform=dmke.revert)
res = subprocess.check_output(['diff', '-u', 'test.yaml', 'output.yaml']).decode('utf-8')
print('diff says:', res)
给出:
diff says:
这意味着文件在往返过程中是相同的(只要你不
在倾销之前改变任何东西)。
在 YAML
实例上设置 preserve_quotes
和调用 ident()
是必要的
保留你多余的引号,resp。保持缩进。
由于锚 question-one
没有别名,您需要显式启用转储
将该属性的 always_dump
设置为 True。如有必要,您可以递归
当 .anchor.value is not None
时,走过 data
并设置 anchor.always_dump = True
如果我有多个引用,当我使用 Python 中的 ruaml.yaml 将它们写入 YAML 文件时,我得到:
<<: [*name-name, *help-name]
但我更愿意
<<: *name-name
<<: *help-name
是否可以选择在写入文件时实现此目的?
更新
descriptions:
- &description-one-ref
description: >
helptexts:
- &help-one
help_text: |
questions:
- &question-one
title: "title test"
reference: "question-one-ref"
field: "ChoiceField"
choices:
- "Yes"
- "No"
required: true
<<: *description-one-ref
<<: *help-one
riskvalue_max: 10
calculations:
- conditions:
- comparator: "equal"
value: "Yes"
actions:
- riskvalue: 0
- conditions:
- comparator: "equal"
value: "No"
actions:
- riskvalue: 10
目前我正在读取这样的文件并修改 python 中的特定值,然后想将其写回。当我写作时,我发现参考文献是列表而不是概述的问题。
这意味着工作流程如下:我正在通过
阅读文档yaml = ruamel.yaml.YAML()
with open('test.yaml') as f:
data = yaml.load(f)
for k in data.keys():
if k == 'questions':
q = data.get(k)
for i in range(0, len(q)):
q[i]['title'] = "my new title"
f.close()
g = open('new_file.yaml', 'w')
yaml(data)
g.close()
不,没有这样的选项,因为它会导致 YAML 文件无效。
<<
是一个映射键,其值被解释
特别假设解析器实现 独立的语言
合并密钥规范。并且映射键必须是唯一的
根据 YAML specification:
The content of a mapping node is an unordered set of key: value node pairs, with the restriction that each of the keys is unique.
ruamel.yaml
(< 0.15.75) 不会在此类上引发错误
重复键是 bug。在重复的普通键上,ruamel.yaml
确实会引发错误。该错误继承自 PyYAML(不是
符合规范,即使在
复制普通键)。
然而,稍加预处理和 post- 处理你想做的事情就可以了
很容易实现。诀窍是在解析之前使 YAML 有效
通过使有问题的重复 <<
键唯一(但可识别)
然后,在将 YAML 写回文件时,用这些替换
唯一键再次 <<: *
。在下面第一次出现
<<: *
替换为 [<<, 0]:
,第二个替换为 [<<, 1]:
等
*
需要成为替换的一部分,因为其中没有锚点
这些别名的文档。
import sys
import subprocess
import ruamel.yaml
yaml = ruamel.yaml.YAML()
yaml.preserve_quotes = True
yaml.indent(sequence=4, offset=2)
class DoubleMergeKeyEnabler(object):
def __init__(self):
self.pat = '<<: ' # could be at the root level mapping, so no leading space
self.r_pat = '[<<, {}]: ' # probably not using sequences as keys
self.pat_nr = -1
def convert(self, doc):
while self.pat in doc:
self.pat_nr += 1
doc = doc.replace(self.pat, self.r_pat.format(self.pat_nr), 1)
return doc
def revert(self, doc):
while self.pat_nr >= 0:
doc = doc.replace(self.r_pat.format(self.pat_nr), self.pat, 1)
self.pat_nr -= 1
return doc
dmke = DoubleMergeKeyEnabler()
with open('test.yaml') as fp:
# we don't do this line by line, that would not work well on flow style mappings
orgdoc = fp.read()
doc = dmke.convert(orgdoc)
data = yaml.load(doc)
data['questions'][0].anchor.always_dump = True
#######################################
# >>>> do your thing on data here <<< #
#######################################
with open('output.yaml', 'w') as fp:
yaml.dump(data, fp, transform=dmke.revert)
res = subprocess.check_output(['diff', '-u', 'test.yaml', 'output.yaml']).decode('utf-8')
print('diff says:', res)
给出:
diff says:
这意味着文件在往返过程中是相同的(只要你不 在倾销之前改变任何东西)。
在 YAML
实例上设置 preserve_quotes
和调用 ident()
是必要的
保留你多余的引号,resp。保持缩进。
由于锚 question-one
没有别名,您需要显式启用转储
将该属性的 always_dump
设置为 True。如有必要,您可以递归
当 .anchor.value is not None
data
并设置 anchor.always_dump = True