数组后保留注释

时间:2019-12-09 12:34:18

标签: python ruamel.yaml

这是我的YAML外观:

yaml_str = """\
steps:
  - init
  - run
  - cleanup

# This is a comment which needs to be preserved
"""

我想做的是从steps中删除第一个和最后一个项目,同时保留cleanup之后的注释。即输出需要是这样的:

yaml_str = """\
steps:
  - run

# This is a comment which needs to be preserved
"""

使用ruamel.yaml怎么可能?

P.S。据我了解,就API而言,情况并不完全相同: https://stackoverflow.com/a/57585928/896276,如果我错了,请纠正我。

2 个答案:

答案 0 :(得分:2)

好的,看来我需要使用此构造:

  

parsed ['steps']。ca.items [1] =解析的['steps']。ca.items.pop(2)

答案 1 :(得分:0)

从YAML文件加载数据时,ruamel.yaml通常会附加 根据密钥(在 映射)或索引(序列)。

因此,在您的情况下,注释(以及空行尾和空行 之前)附加到序列(而不是根级别) 映射)。

注释当前存储在属性ca中( c 注释 a 属性)。 因此,对于您的示例,您可以执行以下操作:

import sys
import ruamel.yaml

yaml_str = """\
steps:
  - init
  - run
  - cleanup

# This is a comment which needs to be preserved
"""

yaml = ruamel.yaml.YAML()
yaml.indent(sequence=4, offset=2)
yaml.preserve_quotes = True
data = yaml.load(yaml_str)
steps = data['steps']
del steps[0]
steps.pop(-1)

yaml.dump(data, sys.stdout)

给出:

steps:
  - run

# This is a comment which needs to be preserved

如果您从序列中删除单个项目,则字典类对象 (CommentedSeq)很聪明,可以“移动”评论。 (您可以 在删除之前和之间插入print(data['steps'].ca)以查看此内容 发生了。)

这并不总是有效,特别是当您的第二个元素 序列是一个集合。在这种情况下,您需要自己将评论移到最后 该集合的元素。如果该项目是序列/列表,则只需移动注释即可 但是,如果是映射/字典,则需要重新安排内容以免 注释出现在键和值之间:

import sys
import ruamel.yaml

yaml_str = """\
steps:
  - init
  - a: 42
    b: 39
  -   - 196
      - 3.0
  - cleanup

# This is a comment which needs to be preserved
"""

yaml = ruamel.yaml.YAML()
yaml.indent(sequence=4, offset=2)
yaml.preserve_quotes = True
data = yaml.load(yaml_str)
steps = data['steps']

print(steps.ca)

del steps[2]  # you can comment this out to get the comment attached to 3.0

if isinstance(steps, list):
    if len(steps)-1 in steps.ca.items and len(steps) > 1 and isinstance(steps[-2], (list, dict)):
        # move the comment in advance
        tmp = steps[-2]
        ct = steps.ca.items.pop(len(steps)-1)
        if isinstance(tmp, list):
            key_tmp = len(tmp)-1
        else:
            key_tmp = list(tmp.keys())[-1]  # the final mapping key
            ct[0], ct[2] = None, ct[0]
        tmp.ca.items[key_tmp] = ct


del steps[0]
steps.pop(-1)

yaml.dump(data, sys.stdout)

给出:

Comment(comment=None,
  items={3: [CommentToken('\n\n# This is a comment which needs to be preserved\n', line: 8, col: 0), None, None, None]})
steps:
  - a: 42
    b: 39

# This is a comment which needs to be preserved

请把您的代码固定在您测试过的ruamel.yaml版本上。这些内部因素可以而且会 有所改变(希望他们这样做时使用适当的API)。