简体   繁体   English

如何生成包含带有 ruamel.yaml 的本地标签的 YAML?

[英]How do I generate YAML containing local tags with ruamel.yaml?

I'm using ruamel.yaml to generate a YAML file that will be read by Tavern , which requires the file to contain a list like this:我正在使用 ruamel.yaml 生成将由Tavern读取的 YAML 文件,该文件要求该文件包含如下列表:

includes:
- !include vars.yaml

Attempting to use any of the usual approaches to dump the data as strings results in single quotes being added around the tags , which doesn't work when the YAML is ingested by the next tool.尝试使用任何常用方法将数据转储为字符串会导致在tags 周围添加单引号,当下一个工具摄取 YAML 时,这将不起作用。

How do I generate a YAML file that contains unquoted local tags , starting with data that is defined in a dictionary?如何生成包含未引用本地标签的 YAML 文件,从字典中定义的数据开始?

I was able to create a YAML file with the required format using the following approach, based on prior examples .基于先前的示例,我能够使用以下方法创建具有所需格式的 YAML 文件。 My approach is more flexible because it allows the tag handle to be an instance property rather than a class property, so you don't need to define a different class for every tag handle.我的方法更灵活,因为它允许标签句柄成为实例属性而不是 class 属性,因此您不需要为每个标签句柄定义不同的 class。

import sys
from ruamel.yaml import YAML

yaml = YAML(typ='rt')

class TaggedString:    
    def __init__(self, handle, value):
        self.handle = handle
        self.value = value

    @classmethod
    def to_yaml(cls, representer, node):
        # I don't understand the arguments to the following function!
        return representer.represent_scalar(u'{.handle}'.format(node),
            u'{.value}'.format(node))

yaml.register_class(TaggedString)

data = {
    'includes': [
        TaggedString('!include', 'vars.yaml'),
        TaggedString('!exclude', 'dummy.yaml')
    ]
}

yaml.dump(data, sys.stdout)

Output: Output:

includes:
- !include vars.yaml
- !exclude dummy.yaml

I am not sure if this is the best approach.我不确定这是否是最好的方法。 I might be missing a simpler way to achieve the same result.我可能错过了一种更简单的方法来实现相同的结果。 Note that my goal is not to dump a Python class;请注意,我的目标不是转储 Python class; I'm just doing that as a way to get the tag to be written correctly.我这样做只是为了让标签正确写入。

I am not sure if this is a better approach, but if you had tried to round-trip your required output, you would have seen that ruamel.yaml actually can preserve your tagged strings, without you having to do anything.我不确定这是否是一种更好的方法,但是如果您尝试往返所需的 output,您会看到 ruamel.yaml 实际上可以保留您的标记字符串,而无需您做任何事情。 Inspecting the Python datastructure, you'll notice that ruamel.yaml does this by creating a TaggedScalar (as you cannnot attach attributes to the built-in string type).检查 Python 数据结构,您会注意到ruamel.yaml通过创建TaggedScalar来执行此操作(因为您无法将属性附加到内置字符串类型)。

import sys
import ruamel.yaml

yaml_str = """\
includes:
- !include vars.yaml
- !exclude dummy.yaml
"""

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

incl = data['includes'][0]
print(type(incl))

which gives:这使:

includes:
- !include vars.yaml
- !exclude dummy.yaml
<class 'ruamel.yaml.comments.TaggedScalar'>

After inspecting comments.py (and possible constructor.py ), you should be able to make ruamel.yaml 's internal data structure on the fly:在检查完comments.py (和可能的constructor.py )之后,您应该能够即时制作ruamel.yaml的内部数据结构:

import sys
import ruamel.yaml
from ruamel.yaml.comments import TaggedScalar

def tagged_string(tag, val):
    # starting with ruamel.yaml>0.16.5 you can replace the following lines with:
    # return TaggedScalar(value=val, tag=tag)
    ret_val = TaggedScalar()
    ret_val.value = val
    ret_val.yaml_set_tag(tag)
    return ret_val

yaml = ruamel.yaml.YAML()
data = dict(includes=[tagged_string('!include', 'vars.yaml'), 
                      tagged_string('!include', 'vars.yaml'),
                     ])
yaml.dump(data, sys.stdout)

which also gives:这也给出了:

includes:
- !include vars.yaml
- !include vars.yaml

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM