【问题标题】:How do I generate YAML containing local tags with ruamel.yaml?如何使用 ruamel.yaml 生成包含本地标签的 YAML?
【发布时间】:2019-11-05 03:07:58
【问题描述】:

我正在使用 ruamel.yaml 生成一个 YAML 文件,该文件将被 Tavern 读取,这要求该文件包含如下列表:

includes:
- !include vars.yaml

尝试使用任何常用方法将数据转储为字符串会导致 single quotes being added around the tags,当 YAML 被下一个工具提取时,这将不起作用。

如何生成包含未引用的local tags 的 YAML 文件,从字典中定义的数据开始?

【问题讨论】:

    标签: python yaml ruamel.yaml


    【解决方案1】:

    我能够使用基于prior examples 的以下方法创建具有所需格式的 YAML 文件。我的方法更灵活,因为它允许标签句柄成为实例属性而不是类属性,因此您不需要为每个标签句柄定义不同的类。

    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)
    

    输出:

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

    我不确定这是否是最好的方法。我可能错过了一种更简单的方法来实现相同的结果。请注意,我的目标不是转储 Python 类。我这样做只是为了让标签正确写入。

    【讨论】:

      【解决方案2】:

      我不确定这是否是更好的方法,但如果您尝试往返所需的输出,您 会看到 ruamel.yaml 实际上可以保留您标记的字符串,而无需您 做任何事情。检查 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))
      

      给出:

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

      检查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)
      

      这也给出了:

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

      【讨论】:

        猜你喜欢
        • 2018-11-27
        • 2021-08-30
        • 1970-01-01
        • 1970-01-01
        • 2023-03-25
        • 2021-12-24
        • 2020-04-25
        • 2016-09-14
        • 2021-08-03
        相关资源
        最近更新 更多