How to reset YAML with explicit links?

Recursive links work fine in ruamel.yamlor pyyaml:

$ ruamel.yaml.dump(ruamel.yaml.load('&A [ *A ]'))
'&id001
- *id001'

However, it (obviously) does not work with normal links:

$ ruamel.yaml.dump(ruamel.yaml.load("foo: &foo { a: 42 }\nbar: { <<: *foo }"))
bar: {a: 42}
foo: {a: 42}

I would like to explicitly create a link:

data = {}
data['foo'] = {'foo': {'a': 42}}
data['bar'] = { '<<': data['foo'], 'b': 43 }

$ ruamel.yaml.dump(data, magic=True)
foo: &foo
    a: 42
bar: 
    <<: *foo
    b: 43

This will be very useful for creating YAML output for large data structures that have many common keys.

How can one exit without a controversial re.replace?

The actual result ruamel.yaml.dump(data)is

bar:
  '<<': &id001
    foo:
      a: 42
  b: 43
foo: *id001

So I need to replace '<<'with <<and possibly replace id001with foo.

+4
source share
1 answer

- , , ruamel.yaml ¹, "-", . :

import ruamel.yaml

yaml_str = """\
foo: &xyz
  a: 42
bar:
  <<: *xyz
"""

data = ruamel.yaml.round_trip_load(yaml_str)
assert ruamel.yaml.round_trip_dump(data) == yaml_str

, data , . , , " " . data['foo']['bar']['a'] , data['foo'] 'bar', " ".

( ), , data ruamel.yaml.comments.CommentedMap(), , merge_attrib ( _yaml_merge) , add_yaml_merge(). (int, CommentedMap()) .

baz = ruamel.yaml.comments.CommentedMap()
baz['b'] = 196
baz.yaml_set_anchor('klm')
data.insert(1, 'baz', baz)

'baz' 'bar' , . data['bar']:

data['bar'].add_yaml_merge([(0, baz)])
ruamel.yaml.round_trip_dump(data, sys.stdout)

:

foo: &xyz
  a: 42
baz: &klm
  b: 196
bar:
  <<: [*xyz, *klm]

( , add_yaml_merge

print(getattr(data['bar'], ruamel.yaml.comments.merge_attrib))

)

, :

data = ruamel.yaml.comments.CommentedMap([
    ('foo', ruamel.yaml.comments.CommentedMap([('a', 42)])),
    ])
data['foo'].yaml_set_anchor('xyz')
data['bar'] = bar = ruamel.yaml.comments.CommentedMap()
bar.add_yaml_merge([(0, data['foo'])])

data = ruamel.yaml.round_trip_load(yaml_str).


¹ : .

+3

Source: https://habr.com/ru/post/1654819/


All Articles