pyyaml
pyyaml copied to clipboard
Custom constructors with nested YAML
Hello,
I have the following yaml file:
A: &a
p1:
pp1: coucou
pp2: 3
p2: 0
B:
pb1:
<<: *a
p2: 1
Here is the python code I use to load this:
import yaml
from yaml import FullLoader
class A:
def __init__(self, p1_trans, p2):
self.p1_trans = p1_trans
self.p2 = p2
@classmethod
def from_yaml(cls, loader: FullLoader, node):
data = loader.construct_mapping(node, deep=True)
data['p1_trans'] = data['p1']['pp1'] + str(data['p1']['pp2'])
del data['p1']
return cls(**data)
yaml.add_constructor('!A', A.from_yaml)
yaml.add_path_resolver('!A', ['B', 'pb1'], dict)
with open('params.yaml') as f:
params = yaml.load(f.read(), Loader=FullLoader)
__import__('pprint').pprint(params)
This fails with the following output:
$ python testpyyaml.py
Traceback (most recent call last):
File "/srv/longdd/kchoi/isolating-gan/notebooks/testpyyaml.py", line 23, in <module>
params = yaml.load(f.read(), Loader=FullLoader)
File "/srv/longdd/kchoi/mambaforge/envs/isolating-gan/lib/python3.9/site-packages/yaml/__init__.py", line 114, in load
return loader.get_single_data()
File "/srv/longdd/kchoi/mambaforge/envs/isolating-gan/lib/python3.9/site-packages/yaml/constructor.py", line 51, in get_single_data
return self.construct_document(node)
File "/srv/longdd/kchoi/mambaforge/envs/isolating-gan/lib/python3.9/site-packages/yaml/constructor.py", line 60, in construct_document
for dummy in generator:
File "/srv/longdd/kchoi/mambaforge/envs/isolating-gan/lib/python3.9/site-packages/yaml/constructor.py", line 413, in construct_yaml_map
value = self.construct_mapping(node)
File "/srv/longdd/kchoi/mambaforge/envs/isolating-gan/lib/python3.9/site-packages/yaml/constructor.py", line 218, in construct_mapping
return super().construct_mapping(node, deep=deep)
File "/srv/longdd/kchoi/mambaforge/envs/isolating-gan/lib/python3.9/site-packages/yaml/constructor.py", line 143, in construct_mapping
value = self.construct_object(value_node, deep=deep)
File "/srv/longdd/kchoi/mambaforge/envs/isolating-gan/lib/python3.9/site-packages/yaml/constructor.py", line 100, in construct_object
data = constructor(self, node)
File "/srv/longdd/kchoi/isolating-gan/notebooks/testpyyaml.py", line 14, in from_yaml
data['p1_trans'] = data['p1']['pp1'] + str(data['p1']['pp2'])
KeyError: 'pp1'
From what I could gather, it seems that data = loader.construct_mapping(node, deep=True)
fails to construct the p1
key of pb1
.
This behavior seems to be a bug of pyyaml because if I do
yaml.add_constructor('!A', A.from_yaml)
yaml.add_path_resolver('!A', ['A'], dict)
yaml.add_path_resolver('!A', ['B', 'pb1'], dict)
The loading works as expected.