PyYaml "include file" and yaml aliases (anchors/references)

Viewed 8185

I had a large YAML file with a massive use of YAML anchors and references, for example:

warehouse:
  obj1: &obj1
    key1: 1
    key2: 2
specific:
  spec1: 
    <<: *obj1
  spec2:
    <<: *obj1
    key1: 10

The file got too large, so I looked for a solution that will allow me split to 2 files: warehouse.yaml and specific.yaml, and to include the warehouse.yaml inside the specific.yaml. I read this simple article, which describes how I can use PyYAML to achieve that, but it also says that the merge key(<<) is not supported.

I really got an error:

yaml.composer.ComposerError: found undefined alias 'obj1

when I tried to go like that.

So, I started looking for alternative way and I got confused because I don't really know much about PyYAML.

Can I get the desired merge key support? Any other solutions for my problem?

2 Answers

It seems that someone has now solved this problem as an extension of ruamel.yaml.

pip install ruamel.yaml.include (source on GitHub)

To get the desired output above:

warehouse.yml

obj1: &obj1
  key1: 1
  key2: 2

specific.yml

specific:
  spec1: 
    <<: *obj1
  spec2:
    <<: *obj1
    key1: 10

Your code would be:

from ccorp.ruamel.yaml.include import YAML

yaml = YAML(typ='safe', pure=True)
yaml.allow_duplicate_keys = True

with open('specific.yml', 'r') as ymlfile:
    return yaml.load(ymlfile)

It also includes a handy !exclude function if you wanted to not have the warehouse key in your output. If you only wanted the specific key, your specific.yml could begin with:

!exclude includes:
- !include warehouse.yml

In that case, your warehouse.yml could also include the top-level warehouse: key.

Related