ruamel yaml 为转储禁用别名

ruamel yaml disabling alias for dumping

过去两天我一直在翻阅文档,努力寻找有关如何处理 ignore_aliases() 调用的任何最新示例。

配置对象是一个 python 包含字典列表的字典。如果我禁用 ignore_aliases() 调用,则会生成下面的输出。

if __name__ == '__main__':
    team = TeamConfig("../TeamConfig.yml")
    config = team.generateSonarConfig()

    with open("../Test.yml", 'w') as f:
        yml = YAML()
        yml.indent(mapping=2, sequence=4, offset=2)
        yml.Representer.ignore_aliases(yml, config)
        yml.dump(config, f)

缩进很好,顺序也保留了,我只需要去掉锚点和别名:

templates:
  - name: freedom
    users:
      - &id001
        name: service-account2
        permissions:
          - browse
          - read
  - name: liberty
    users:
      - *id001
      - *id002
      - name: service-account3
        permissions:
          - browse
          - read
      - name: service-account4
        permissions:
          - browse
          - read

有什么想法吗?

首先,我不认为你提供的输出是完整的,因为它是无效的 YAML 和我当然希望 ruamel.yaml 没有生成如图所示(如果它 确实提交了包含完整源代码的错误报告)。


我不知道你从哪里得到这个例子,但是方法 ignore_aliases() 使用数据结构调用并且应该 return True 如果任何别名应该是 忽略。这不是你自称的东西。您可以将 Representer 或 RoundTripRepresenter 上的 monkey-patch 子类化。

representer.py 中的方法应采用数据参数并且始终 return False:

import sys
from pathlib import Path
import ruamel.yaml

# your output minus the `- *id002` alias that has no corresponding anchor
in_file = Path('Test.yaml')  

# monkey patch:
ruamel.yaml.representer.RoundTripRepresenter.ignore_aliases = lambda x, y: True

yaml = ruamel.yaml.YAML()
yaml.indent(mapping=2, sequence=4, offset=2)
data = yaml.load(in_file)

yaml.dump(data, sys.stdout)

给出:

templates:
  - name: freedom
    users:
      - name: service-account2
        permissions:
          - browse
          - read
  - name: liberty
    users:
      - name: service-account2
        permissions:
          - browse
          - read
      - name: service-account3
        permissions:
          - browse
          - read
      - name: service-account4
        permissions:
          - browse
          - read

或者你可以做更详细的:

import sys
from pathlib import Path
import ruamel.yaml

# your output minus the `- *id002` alias that has no corresponding anchor
in_file = Path('Test.yaml')  

class NonAliasingRTRepresenter(ruamel.yaml.representer.RoundTripRepresenter):
    def ignore_aliases(self, data):
        return True


yaml = ruamel.yaml.YAML()
yaml.Representer = NonAliasingRTRepresenter
yaml.indent(mapping=2, sequence=4, offset=2)
data = yaml.load(in_file)

yaml.dump(data, sys.stdout)

给出相同的输出。

这最终对我有用。

import sys
import ruamel.yaml

from configure.python.TeamConfig import TeamConfig

class NonAliasingRTRepresenter(ruamel.yaml.RoundTripRepresenter):
    def ignore_aliases(self, data):
        return True

if __name__ == '__main__':
    team = TeamConfig("../TeamConfig.yml")
    config = team.generateSonarConfig()

    with open("../Test.yml", 'w') as f:
        yml = ruamel.yaml.YAML()
        yml.indent(mapping=2, sequence=4, offset=2)
        yml.Representer = NonAliasingRTRepresenter
        yml.dump(config, f)