Skip to content

Setting default multiconstructor results in an TypeError #317

@Losik

Description

@Losik

The issue is about the following lines in construct_object method of BaseConstructor class

for tag_prefix in self.yaml_multi_constructors:
if node.tag.startswith(tag_prefix):
tag_suffix = node.tag[len(tag_prefix):]
constructor = self.yaml_multi_constructors[tag_prefix]
break
else:
if None in self.yaml_multi_constructors:
tag_suffix = node.tag
constructor = self.yaml_multi_constructors[None]

I wanted to set up a multiconstructor for unknows tags. It seems like these lines are responsible for picking a default multiconstructor and therefore to define one I had to add a multiconstructor for None value as a tag_prefix

if None in self.yaml_multi_constructors:
tag_suffix = node.tag
constructor = self.yaml_multi_constructors[None]

At the very least the lines hint that None is considered a valid key for self.yaml_multi_constructors. But the only way the execution can reach these lines is by traversing all the keys in self.yaml_multi_constructors first.

Now, if None is one of the keys, we get an exception TypeError: startswith first arg must be str, unicode, or tuple, not NoneType on line 77 making lines 83-84 effectively unreachable

if node.tag.startswith(tag_prefix):

Minimal non-working example:

import yaml

class MyLoader(yaml.loader.Loader):
    pass

def default_multi_constructor(loader, tag_suffix, node):
    return node.tag

MyLoader.add_multi_constructor(None, default_multi_constructor)

if __name__ == '__main__':
    print yaml.load('''!som:multitag {}''', MyLoader)

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions