I\'m trying to make a custom YAML dumper/loader for some configuration objects. For simplicity, assuming we want to dump a object of class Hero
to a hero.
The defintion for the RoundTripConstructor.construct_mapping
is::
def construct_mapping(self, node, maptyp=None, deep=False)
and it needs to know what kind of mapping it is expected to
construct. There is some expectation in the RoundTripDumper on what
can be attached to such an object, so you best of emulating what the
routines in the RoundTripDumper pass: CommentedMap
(a normal
dict
is not going to work).
So you will need to do something like:
from ruamel.yaml import YAML
from ruamel.yaml.comments import CommentedMap
yaml = YAML()
class Hero:
yaml_tag = '!Hero'
def __init__(self, name, age):
self.name = name
self.age = age
@classmethod
def to_yaml(cls, representer, data):
return representer.represent_mapping(cls.yaml_tag,
{'name': data.name, 'age': data.age})
@classmethod
def from_yaml(cls, constructor, node):
data = CommentedMap()
constructor.construct_mapping(node, data, deep=True)
return cls(**data)
def __str__(self):
return "Hero(name -> {}, age -> {})".format(self.name, self.age)
yaml.register_class(Hero)
ante_hero = Hero('Saber', 15)
with open('config.yml', 'w') as fout:
yaml.dump(ante_hero, fout)
with open('config.yml') as fin:
post_hero = yaml.load(fin)
print(post_hero)
which gives:
Hero(name -> Saber, age -> 15)
The above works because your class is relatively simple, if it could have recursive parts, you would need to follow a two-step creation process, with initial yield of the object created, so that it can be used during the recursion.
That the maptyp
defaults to None
is historical, it must be
set. E.g. one of the first things that construct_mapping
does is
trying to attach comments (if any were available on the node).
I'll remove the default value in 0.15.55, which gives a more sensible
error if you leave it out, like you did.