admin 管理员组文章数量: 1086019
I have a config file that (purposely) contains some undefined aliases:
base:
foo: *args_foo
bar: *args_bar
fuz: fuz_val
buz: buz_val
Meanwhile I have a cli that takes --foo and --bar as arguments, where --foo can be specified multiple times. I wind up with a dict looking like:
args = {}
args["foo"] = ["foo_val_1", "foo_val_2", "foo_val_3"]
args["bar"] = "bar_val"
I'd like to dump the args to yaml, but with custom anchors for each key in arg. Something like this:
args:
foo: &args_foo
- foo_val_1
- foo_val_2
- foo_val_3
bar: &args_bar "bar_val"
I could write my own code to generate the doc, but I'd prefer somehow tell ruamel.yaml to handle adding the anchors before serializing. The question is, is that possible, and if so, how?
The intention is to then concatenate the two files like this:
args:
foo: &args_foo
- foo_val_1
- foo_val_2
- foo_val_3
bar: &args_bar "bar_val"
base:
foo: *args_foo
bar: *args_bar
fuz: fuz_val
buz: buz_val
and extract "base" as the final config after loading the concatenated doc.
I have a config file that (purposely) contains some undefined aliases:
base:
foo: *args_foo
bar: *args_bar
fuz: fuz_val
buz: buz_val
Meanwhile I have a cli that takes --foo and --bar as arguments, where --foo can be specified multiple times. I wind up with a dict looking like:
args = {}
args["foo"] = ["foo_val_1", "foo_val_2", "foo_val_3"]
args["bar"] = "bar_val"
I'd like to dump the args to yaml, but with custom anchors for each key in arg. Something like this:
args:
foo: &args_foo
- foo_val_1
- foo_val_2
- foo_val_3
bar: &args_bar "bar_val"
I could write my own code to generate the doc, but I'd prefer somehow tell ruamel.yaml to handle adding the anchors before serializing. The question is, is that possible, and if so, how?
The intention is to then concatenate the two files like this:
args:
foo: &args_foo
- foo_val_1
- foo_val_2
- foo_val_3
bar: &args_bar "bar_val"
base:
foo: *args_foo
bar: *args_bar
fuz: fuz_val
buz: buz_val
and extract "base" as the final config after loading the concatenated doc.
Share Improve this question edited Mar 30 at 9:31 Marc Swingler asked Mar 30 at 9:23 Marc SwinglerMarc Swingler 3331 silver badge11 bronze badges1 Answer
Reset to default 1Since you cannnot load your config file (as it is invalid YAML), the easiest IMO is to generate a a YAML file with the anchor definitions and append the config file to it.
I recommend to first round-trip the expected output:
import sys
import ruamel.yaml
yaml_str = """\
args:
foo: &args_foo
- foo_val_1
- foo_val_2
- foo_val_3
bar: &args_bar "bar_val"
base:
foo: *args_foo
bar: *args_bar
fuz: fuz_val
buz: buz_val
"""
yaml = ruamel.yaml.YAML()
data = yaml.load(yaml_str)
yaml.dump(data, sys.stdout)
which gives:
args:
foo: &args_foo
- foo_val_1
- foo_val_2
- foo_val_3
bar: &args_bar bar_val
base:
foo: *args_foo
bar: *args_bar
fuz: fuz_val
buz: buz_val
And then analysing data
, especially for the special types that need to
be created (see also this answer):
print('type', type(data['args']['foo']))
print('anchor', data['args']['foo'].anchor)
print('type', type(data['args']['bar']))
print('anchor', data['args']['foo'].anchor)
which gives:
type <class 'ruamel.yamlments.CommentedSeq'>
anchor Anchor('args_foo')
type <class 'ruamel.yaml.scalarstring.PlainScalarString'>
anchor Anchor('args_foo')
Your args
data structure needs some elaboration:
args = {}
args["foo"] = map = ruamel.yamlments.CommentedSeq(["foo_val_1", "foo_val_2", "foo_val_3"])
map.yaml_set_anchor('args_foo', always_dump=True)
args["bar"] = scalar = ruamel.yaml.scalarstring.DoubleQuotedScalarString("bar_val")
scalar.yaml_set_anchor('args_bar', always_dump=True)
yaml.dump(args, sys.stdout)
which gives:
foo: &args_foo
- foo_val_1
- foo_val_2
- foo_val_3
bar: &args_bar "bar_val"
The always_dump
is necessary, as spurious anchors are normally not dumped.
Now you can combine the above:
import sys
import io
import ruamel.yaml
from pathlib import Path
config = Path('config.nonyaml')
config.write_text("""\
base:
foo: *args_foo
bar: *args_bar
fuz: fuz_val
buz: buz_val
""")
yaml = ruamel.yaml.YAML()
args = {}
args["foo"] = map = ruamel.yamlments.CommentedSeq(["foo_val_1", "foo_val_2", "foo_val_3"])
map.yaml_set_anchor('args_foo', always_dump=True)
args["bar"] = scalar = ruamel.yaml.scalarstring.DoubleQuotedScalarString("bar_val")
scalar.yaml_set_anchor('args_bar', always_dump=True)
buf = io.BytesIO()
yaml.dump(dict(args=args), buf)
buf.write(config.read_bytes())
print(buf.getvalue().decode('utf-8'))
# check if buf contains loadable YAML
data = yaml.load(buf.getvalue())
print('data:', data)
which gives:
args:
foo: &args_foo
- foo_val_1
- foo_val_2
- foo_val_3
bar: &args_bar "bar_val"
base:
foo: *args_foo
bar: *args_bar
fuz: fuz_val
buz: buz_val
data: {'args': {'foo': ['foo_val_1', 'foo_val_2', 'foo_val_3'], 'bar': 'bar_val'}, 'base': {'foo': ['foo_val_1', 'foo_val_2', 'foo_val_3'], 'bar': 'bar_val', 'fuz': 'fuz_val', 'buz': 'buz_val'}}
本文标签: Add anchors to keys in dictionary before dumping wih ruamelyamlStack Overflow
版权声明:本文标题:Add anchors to keys in dictionary before dumping wih ruamel.yaml? - Stack Overflow 内容由网友自发贡献,该文观点仅代表作者本人, 转载请联系作者并注明出处:http://roclinux.cn/p/1743992674a2515021.html, 本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。
发表评论