I want to interpret following YAML string with PyYaml:
- !Table
header:
- !Column
- !Paragraph
text: 'header1'
- !Column
- !Paragraph
text: 'header2'
I have Table and Paragraph classes that are inherited from yaml.YAMLObject class. But I don't know what to do about !Column tag? This tag should be treated only as a named array tag.
When I want to build objects from yaml.load() function, I got following error:
yaml.constructor.ConstructorError: could not determine a constructor
for the tag '!Column'
in "<unicode string>", line 19, column 17:
- !Column
^
There are two problems with using yaml.YAMLObject:
yaml.Loader forcing you to use the unsafe yaml.load() which you should not do unless you have full control over the input, now and in the future.Your !Table and !Paragraph are mapping nodes. But your !Column is a sequence, and you explicitly need to make a constructor for that:
import sys
from ruamel import yaml
yaml_str = """\
- !Table
header:
- !Column
- !Paragraph
text: 'header1'
- !Column
- !Paragraph
text: 'header2'
"""
class Table(yaml.YAMLObject):
yaml_tag = u'!Table'
pass
class Paragraph(yaml.YAMLObject):
yaml_tag = u'!Paragraph'
pass
def column_constructor(loader, node):
return loader.construct_sequence(node)
yaml.add_constructor('!Column', column_constructor)
data = yaml.load(yaml_str)
yaml.dump(data, sys.stdout, default_flow_style=False)
this prints:
- !Table
header:
- - !Paragraph
text: header1
- - !Paragraph
text: header2
and (because I use ruamel.yaml, also an UnsafeLoaderWarning).
If you want the output to include !Column then you should make a python class Column(list) and have column_constructor give back that type, and additionally write a representer for Column and add that to the loader.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With