[Python] How to flatten a mapping constructed from a tagged scalar using ruamel.yaml

Discussão em 'Python' iniciado por Stack, Abril 3, 2025.

  1. Stack

    Stack Membro Participativo

    My aim is to create a YAML loader that can construct mappings from tagged scalars. Here is a stripped-down version of the loader which constructs an object containing names from a scalar tagged !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()


    The loader can successfully substitute objects for tagged scalars i.e.

    >>> 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'}
    ]


    However, the construction fails when I try to merge the constructed mapping into an enclosing object

    >>> 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


    My understanding is that the type of the node is still a ScalarNode, so the constructor is unable to process it even though it ultimately resolves to a mapping. How to modify my code, such that !fullname {scalar} can be merged into the object?

    Continue reading...

Compartilhe esta Página