admin管理员组文章数量:1355731
I want to create data in python and write it to a file as a yaml-document using anchors and merges in the output.
I think this could be possible with ruamel YAML, because, as described in ruamels official examples:
- it can load yaml-documents with anchors and merges transparently (transparent in the sense that access to the data is the same whether it is defined through anchors or not)
- it can round-trip yaml-files while preserving anchors (so loading a yaml-file which includes anchors can be read and rewritten to disk and still have anchors)
This means ruamel.yaml must have an internal representation of the yaml-data that includes and understands anchors (unlike PyYAML, which only reads anchors but does not preserve them). There does not seem to be a documented way to create such anchors from python code.
The most minimal file I want to be able to create would look like this:
base: &ANCHOR
x: 1
object:
<<: *ANCHOR
y: 2
I want to create data in python and write it to a file as a yaml-document using anchors and merges in the output.
I think this could be possible with ruamel YAML, because, as described in ruamels official examples:
- it can load yaml-documents with anchors and merges transparently (transparent in the sense that access to the data is the same whether it is defined through anchors or not)
- it can round-trip yaml-files while preserving anchors (so loading a yaml-file which includes anchors can be read and rewritten to disk and still have anchors)
This means ruamel.yaml must have an internal representation of the yaml-data that includes and understands anchors (unlike PyYAML, which only reads anchors but does not preserve them). There does not seem to be a documented way to create such anchors from python code.
The most minimal file I want to be able to create would look like this:
base: &ANCHOR
x: 1
object:
<<: *ANCHOR
y: 2
Share
Improve this question
edited Mar 28 at 22:51
julaine
asked Mar 28 at 8:41
julainejulaine
1,7561 gold badge14 silver badges31 bronze badges
3
- 1 You should include a minimal example YAML document of the output that you want to create. Additionally you should make sure this round-trips without changes (if ruamel.yaml cannot round-trip it, it is far less likely you can generate it from scratch). – Anthon Commented Mar 28 at 8:59
- @Anthon Good tip to say I can probably only create things I can roundtrip. – julaine Commented Mar 28 at 22:29
- @Anthon After further consideration, I have added an example to the question (and deleted my comment arguing against the need for an example). Turns out the yaml-spec is much bigger than I thought and my question was therefore not as clear as I thought. – julaine Commented Mar 28 at 22:54
1 Answer
Reset to default 1When you round-trip your data using the following program:
import sys
import ruamel.yaml
yaml_str = """\
base: &ANCHOR
x: 1
object:
<<: \*ANCHOR
y: 2
"""
yaml = ruamel.yaml.YAML()
data = yaml.load(yaml_str)
yaml.dump(data, sys.stdout)
you see that the output matches the input:
base: &ANCHOR
x: 1
object:
<<: *ANCHOR
y: 2
You could actually create a new YAML
instance for dumping and still get the same output.
This means that the information about anchors and merging is somewhere in the data structure
under data
. So you should inspect various items.
print('anchor', data['base'].anchor)
print('type', type(data['base'].anchor))
print('keys', list(data['object'].keys()))
print('merge', data['object'].merge)
print('merge type', type(data['object'].merge))
print('ids', id(data['object'].merge[0][1]), id(data['base']))
which gives:
anchor Anchor('ANCHOR')
type <class 'ruamel.yaml.anchor.Anchor'>
keys ['y', 'x']
merge [(0, {'x': 1})]
merge type <class 'list'>
ids 4304434048 4304434048
The above is normally an incremental process (even for me, having some knowledge about the internals). And it helps to look at the source, especially construct_mapping
in constructor.py
and CommentedMap
in comments. py
With the above information, lets first tackle the anchor ( you can have merges without anchor/alias, but they don't make much sense).
import sys
import ruamel.yaml
def CM(**kw):
return ruamel.yamlments.CommentedMap(**kw)
common = CM(x=1)
common.yaml_set_anchor('ANCHOR')
data = CM(base=common, object=CM(tmp=common, y=2))
yaml = ruamel.yaml.YAML()
yaml.dump(data, sys.stdout)
which gives:
base: &ANCHOR
x: 1
object:
tmp: *ANCHOR
y: 2
Creating the merge key, can be done by defining the CommentedMap
with only the y
key
and adding the merge
attribute:
import sys
import ruamel.yaml
def CM(**kw):
return ruamel.yamlments.CommentedMap(**kw)
common = CM(x=1)
common.yaml_set_anchor('ANCHOR')
data = CM(base=common, object=CM(y=2))
setattr(data['object'], ruamel.yamlments.merge_attrib, [(0, common)])
yaml = ruamel.yaml.YAML()
yaml.dump(data, sys.stdout)
which gives:
base: &ANCHOR
x: 1
object:
<<: *ANCHOR
y: 2
- There is no setter for the
.merge
attribute - that attribute is a list of because in YAML the merge key can have have either a mapping or a list of mappings as value. IIRC the integer
0
, determines the ordering.
Pin the version of ruamel.yaml
you are using. Internals like these will change without notice
本文标签: pythonHow do I write out an anchor using ruamelyamlStack Overflow
版权声明:本文标题:python - How do I write out an anchor using ruamel.yaml? - Stack Overflow 内容由网友自发贡献,该文观点仅代表作者本人, 转载请联系作者并注明出处:http://www.betaflare.com/web/1744047946a2581882.html, 本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。
发表评论