简体   繁体   English

在 ruamel.yaml 中保留评论

[英]Keeping comments in ruamel.yaml

I'm trying to manipulate some YAML files using ruamel.yaml , notably removing specific keys.我正在尝试使用ruamel.yaml操作一些 YAML 文件,特别是删除特定的键。 This seems to work, but in the process all comment lines and empty lines that follow the key, up to the next key, are also removed.这似乎可行,但在此过程中,键之后的所有注释行和空行,直到下一个键,也被删除。 Minimal example:最小的例子:

from ruamel.yaml import YAML
import sys


yaml_str = """\
# Our app configuration

# foo is our main variable
foo: bar

# foz is also important
foz: quz

# And finally we have our optional configs.
# These are not really mandatory, they can be
# considere as "would be nice".
opt1: foqz
"""


yaml = YAML(typ='rt')
data = yaml.load(yaml_str)

data.pop('foz', None)

yaml.dump(data, sys.stdout)

which gives:这使:

# Our app configuration

# foo is our main variable
foo: bar

# foz is also important
opt1: foqz

Is there maybe a way to avoid this and only remove the key itself, and any inline comment?有没有办法避免这种情况,只删除密钥本身和任何内联注释?

The ruamel.yaml documentation states ruamel.yaml文档状态

This preservation is normally not broken unless you severely alter the structure of a component (delete a key in a dict, remove list entries).除非您严重更改组件的结构(删除字典中的键,删除列表条目),否则这种保存通常不会被破坏。

so this behavior should not have come as a surprise.所以这种行为应该不足为奇。

What you can do is extend the comment on the key before the one you delete with the comment on the key you are going to delete (you can actually do it afterwards, as the comment is still there, there is just no longer a key while dumping to associate it with).您可以做的是在您要删除的键上添加对您要删除的键的评论之前对键的评论(实际上您可以在之后进行,因为评论仍然存在,只是不再有一个键,而倾销以将其与之关联)。

import sys
import ruamel.yaml

yaml_str = """\
# Our app configuration

# foo is our main variable
foo: bar

# foz is also important
foz: quz

# And finally we have our optional configs.
# These are not really mandatory, they can be
# considere as "would be nice".
opt1: foqz
"""

undefined = object()

def my_pop(self, key, default=undefined):
    if key not in self:
        if default is undefined:
            raise KeyError(key)
        return default
    keys = list(self.keys())
    idx = keys.index(key)
    if key in self.ca.items:
        if idx == 0:
            raise NotImplementedError('cannot handle moving comment when popping the first key', key)
        prev = keys[idx-1]
        # print('prev', prev, self.ca)
        comment = self.ca.items.pop(key)[2]
        if prev in self.ca.items:
            self.ca.items[prev][2].value += comment.value
        else:
            self.ca.items[prev] = self.ca.items.pop(key)
    res = self.__getitem__(key)
    self.__delitem__(key)
    return res

ruamel.yaml.comments.CommentedMap.pop = my_pop
    
yaml = ruamel.yaml.YAML()
data = yaml.load(yaml_str)

data.pop('foz', None)

yaml.dump(data, sys.stdout)

which gives:这使:

# Our app configuration

# foo is our main variable
foo: bar

# foz is also important


# And finally we have our optional configs.
# These are not really mandatory, they can be
# considere as "would be nice".
opt1: foqz

If you need to be able to pop the first key in a commented map, then you need to inspect self.ca and handle its comment attribute, which is somewhat more complicated.如果您需要能够弹出注释映射中的第一个键,则需要检查self.ca并处理其comment属性,这有点复杂。

As always when using these kind of internals, you should pin the version of ruamel.yaml that you are using.与往常一样,在使用这些内部组件时,您应该固定您正在使用的 ruamel.yaml 版本。 This internals will change.这种内部结构会改变。

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

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