Jason S
Jason S

Reputation: 189786

How do you add a type tag when using a PyYAML dumper?

I have a plain data structure that I need to dump into a YAML file and add a type tag at the beginning with a !v2 line.

How do I do that with the PyYAML library?

import yaml

class MyDumper(yaml.SafeDumper):
    # ???
    # somehow add a "!v2" type tag at the beginning

y = {'foo': 3, 'bar': 'haha', 'baz': [1,2,3]}

with open(myfile, 'w') as f:
   # a hack would be to write the "!v2" here,
   # outside the normal yaml.dump process, 
   # but I'd like to learn the right way
   yaml.dump(f, y, Dumper=MyDumper)

Upvotes: 1

Views: 757

Answers (1)

Anthon
Anthon

Reputation: 76682

If I read your !v2 addition correctly this is essentially a tag for the top-level dictionary (and thereby implicit for the whole file). In order to write that out with a tag correctly make that top-level dict into separate type (subclassed from dict) and create a type specific dumper:

import ruamel.yaml as yaml
from ruamel.yaml.representer import RoundTripRepresenter

class VersionedDict(dict):
    pass

y = VersionedDict(foo=3, bar='haha', baz=[1,2,3])

def vdict_representer(dumper, data):
    return dumper.represent_mapping('!v2', dict(data))

RoundTripRepresenter.add_representer(VersionedDict, vdict_representer)

print(yaml.round_trip_dump(y))

will give you:

!v2
bar: haha
foo: 3
baz:
- 1
- 2
- 3

roundtrip_dump is a safe_dump

Please note that when you load this using yaml.load() in some way, that your loader expects to find a constructor for the !v2 tag type, unless you read the first line outside of the actual loading routine.


The above was done with ruamel.yaml (of which I am the author) an enhanced version of PyYAML if you have to stick with PyYAML (e.g if you have to stick with YAML 1.1) then you should be able to make the necessary changes relatively easily. Just make sure you add the representer to the representer you are using to dump: SafeRepresenter when using safe_dump.

Upvotes: 1

Related Questions