pyyaml
pyyaml copied to clipboard
Deep construction doesn't take into account merged or referenced anchors
For a YAML file like so:
test:
&anchor
foo: 2
bar:
- a
- b
- c
merge_test:
- !merge_test
<<: *anchor
If I try to construct a merge_test
object using deep mapping:
import yaml
def merge_test_constructor(loader, node):
m = loader.construct_mapping(node, deep=True)
print "Merge test constructor gets map %s." % m
yaml.add_constructor(u'!merge_test', merge_test_constructor)
The bar
sequence doesn't seem to get populated:
> yaml.load(open('merge_test.yml'))
Merge test constructor gets map {'foo': 2, 'bar': []}.
This appears to be because the test
object is already constructed (without deep construction), and thus construct_object()
in constructor.py
simply returns its cached copy:
def construct_object(self, node, deep=False):
if node in self.constructed_objects:
return self.constructed_objects[node]
I was able to work around this by making a custom loader that always does deep construction by default:
class MyLoader(yaml.SafeLoader):
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
# Do deep construction by default so that anchors are expanded
# before custom constructors are called
self.deep_construct = True
d = yaml.load(f, Loader=MyLoader)