Default constructor parameters in pyyaml
I encountered the same problem: yaml_tag
doesn't work for some reason. So I used alternative approach:
import yaml
def constructor(loader, node) :
fields = loader.construct_mapping(node)
return Test(**fields)
yaml.add_constructor('!Test', constructor)
class Test(object) :
def __init__(self, foo, bar=3) :
self.foo = foo
self.bar = bar
def __repr__(self):
return "%s(foo=%r, bar=%r)" % (self.__class__.__name__, self.foo, self.bar)
print yaml.load("""
- !Test { foo: 1 }
- !Test { foo: 10, bar: 20 }""")
Output:
[Test(foo=1, bar=3), Test(foo=10, bar=20)]
Based on alexanderlukanin13's answer. Here's my cut.
import yaml
YAMLObjectTypeRegistry = {}
def register_type(target):
if target.__name__ in YAMLObjectTypeRegistry:
print "{0} already in registry.".format(target.__name__)
elif 'yaml_tag' not in target.__dict__.keys():
print target.__dict__
raise TypeError("{0} must have yaml_tag attribute".format(
target.__name__))
elif target.__dict__['yaml_tag'] is None:
pass
else:
YAMLObjectTypeRegistry[target.__name__] = target
yaml.add_constructor(
target.__dict__['yaml_tag'],
lambda loader, node: target(**loader.construct_mapping(node)))
print "{0} added to registry.".format(target.__name__)
class RegisteredYAMLObjectType(type):
def __new__(meta, name, bases, class_dict):
cls = type.__new__(meta, name, bases, class_dict)
register_type(cls)
return cls
class RegisteredYAMLObject(object):
__metaclass__=RegisteredYAMLObjectType
yaml_tag = None
You can then use it like this:
class MyType(registry.RegisteredYAMLObject):
yaml_tag = u'!mytype'
def __init__(self, name, attr1='default1', attr2='default2'):
super(MyType, self).__init__()
self.name = name
self.attr1 = attr1
self.attr2 = attr2