在ruamel.yaml中保持评论

发布于 2025-02-10 08:17:36 字数 778 浏览 3 评论 0原文

我正在尝试使用ruamel.yaml来操纵一些YAML文件,特别是删除特定的密钥。这似乎有效,但是在此过程中,所有遵循键的评论行和空线(直到下一个键)也将被删除。最小示例:

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)

哪个给出:

# Our app configuration

# foo is our main variable
foo: bar

# foz is also important
opt1: foqz

是否有一种避免这种情况并仅删除密钥本身以及任何内联评论的方法?

I'm trying to manipulate some YAML files using ruamel.yaml, notably removing specific keys. 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?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

守不住的情 2025-02-17 08:17:36

ruamel.yaml 文档状态

除非您严重改变,否则这种保存通常不会破裂
组件的结构(删除键中的键,删除列表条目)。

因此,这种行为不应该令人惊讶。

你能做的是
在您删除密钥之前的关键上,将评论扩展到密钥上的评论
您将删除(实际上可以这样做,因为评论是
仍然在那里,在倾倒将其关联时不再有钥匙)。

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)

这给出了:

# 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

如果您需要能够在评论的地图中弹出第一个键,则需要检查self.ca
并处理其注释属性,这更复杂。

与往常一样,当使用此类内部设备时,您应该固定正在使用的Ruamel.yaml版本。
这些内部将会改变。

The ruamel.yaml documentation states

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.

As always when using these kind of internals, you should pin the version of ruamel.yaml that you are using.
This internals will change.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文