在用ruamel转储类时保留锚名.并通过__getstate__和__setstate__进行过滤



我设置了使用ruamel加载/转储的类。yaml 0.17.21yaml_objectdecorator.

出于某种原因,我不希望类中的更改保存到yaml,除非用户特别要求。为了做到这一点,我使用__getstate____setstate__方法来缓存initial_state,并且如果用户想要永久更改,则指示用户修改该对象。

一切正常,除了在转储时丢失锚的名称。我无法准确地指出它是如何。当没有定义__{set|get}state__方法时,yaml通常保留这些方法。

这些易于阅读的锚名对我来说非常重要,因为它是一个用户友好的功能。

下面是一个例子:

import sys
from copy import deepcopy
from ruamel.yaml import YAML, yaml_object
yaml = YAML()
@yaml_object(yaml)
class ExampleClass():
def __init__(self):
self._permanent_state = {}
def __setstate__(self, state):
self.__dict__.update(deepcopy(state))
self._permanent_state = state
def __getstate__(self):
return self._permanent_state

source = """
simple: &simple !ExampleClass
potato: 10
turnip: 20
nested: !ExampleClass
sunflower: 30
others: *simple
"""
a = yaml.load(source)
a['simple'].potato = 10**6 # Should not be reflected in dump
a['nested']._permanent_state['sunflower'] = 100 # Should be reflected in dump
yaml.dump(a, sys.stdout)

输出simple锚重命名为id001:

simple: &id001 !ExampleClass
potato: 10
turnip: 20
nested: !ExampleClass
sunflower: 100
others: *id001

如果我删除__getstate____setstate__方法

import sys
from copy import deepcopy
from ruamel.yaml import YAML, yaml_object
yaml = YAML()
@yaml_object(yaml)
class ExampleClass():
pass
source = """
simple: &simple !ExampleClass
potato: 10
turnip: 20
nested: !ExampleClass
sunflower: 30
others: *simple
"""
a = yaml.load(source)
a['simple'].potato = 10**6   # Should not be reflected in dump
a['nested']._permanent_state = deepcopy(a['nested'].__dict__)
a['nested']._permanent_state['sunflower'] = 100  # Should not be reflected in dump
yaml.dump(a, sys.stdout)

输出现在保留simple锚(但期望的行为丢失):

simple: &simple !ExampleClass
potato: 1000000
turnip: 20
nested: !ExampleClass
sunflower: 30
others: *simple
_permanent_state:
sunflower: 100
others: !ExampleClass
potato: 1000000
turnip: 20

理想情况下,我希望保持第一个示例的行为,同时保留锚名称。

如果您没有提供反例,我就会猜测锚点不会保留在任何已注册类的实例上。

__setstate__的存在强制在构造函数中使用不同的执行路径,其中锚信息不会主动删除,但只是不使用。很可能子类化(并使用)RoundTripConstructorRoundTripRepresenter来存储/检索节点中可用的锚信息。同样地,你也会丢失那些"属于"的注释。你的标记映射。

加载YAML文档可能最简单的方法是不注册ExampleClass,然后递归地遍历加载的数据,寻找"dict"(子类)具有.tag属性(实际上是一个属性)设置为!ExcampleClass的实例,并将其替换为适当行为的实例(或可能添加您想要的特定行为,使用duck-typing)。

相关内容

  • 没有找到相关文章

最新更新