Meu objetivo é criar um carregador YAML que possa construir mapeamentos de escalares marcados. Aqui está uma versão simplificada do carregador que constrói um objeto contendo nomes de um escalar marcado !fullname
.
import ruamel.yaml
class MyLoader(ruamel.yaml.YAML):
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.constructor.add_constructor("!fullname", self._fullname_constructor)
@staticmethod
def _fullname_constructor(constructor, node):
value = constructor.construct_scalar(node)
first, *middle, last = value.split()
return {
"first_name": first,
"middle_names": middle,
"last_name": last
}
myyaml = MyLoader()
O carregador pode substituir com sucesso objetos por escalares marcados, ou seja
>>> myyaml.load("""
- !fullname Albus Percival Wulfric Brian Dumbledore
- !fullname Severus Snape""")
[
{'first_name': 'Albus', 'middle_names': ['Percival', 'Wulfric', 'Brian'], 'last_name': 'Dumbledore'},
{'first_name': 'Severus', 'middle_names': [], 'last_name': 'Snape'}
]
No entanto, a construção falha quando tento mesclar o mapeamento construído em um objeto envolvente
>>> yaml.load("""
id: 0
<<: !fullname Albus Percival Wulfric Brian Dumbledore""")
ruamel.yaml.constructor.ConstructorError: while constructing a mapping (...)
expected a mapping or list of mappings for merging, but found scalar
Meu entendimento é que o tipo do nó ainda é um ScalarNode
, então o construtor não consegue processá-lo, mesmo que ele acabe resolvendo para um mapeamento. Como modificar meu código, de modo que ele !fullname {scalar}
possa ser mesclado ao objeto?