Jason S
Jason S

Reputation: 189836

pyyaml safe_load: how to ignore local tags

I am using yaml.safe_load() but I need to ignore a tag !v2 -- is there a way to do this but still use safe_load() ?

Upvotes: 11

Views: 10257

Answers (3)

onlynone
onlynone

Reputation: 8339

The problem with this solution is that it only works for v2 tags, and only if the yaml object it's on is a mapping type object.

This solution will work for all tags, but the problem is that the data will be completely ignored. You'll just get a null for the data.

If you'd like to ignore any special processing for all tags, but still get the values parsed as if the tags just weren't there, the following should work:

def unknown(loader, suffix, node):
    if isinstance(node, yaml.ScalarNode):
        constructor = loader.__class__.construct_scalar
    elif isinstance(node, yaml.SequenceNode):
        constructor = loader.__class__.construct_sequence
    elif isinstance(node, yaml.MappingNode):
        constructor = loader.__class__.construct_mapping

    data = constructor(loader, node)

    return data

yaml.add_multi_constructor('!', unknown)
yaml.add_multi_constructor('tag:', unknown)

return yaml.load_all(infile, Loader=yaml.FullLoader)

Note that if you want to use a different loader, such as SafeLoader, you'll need to explicitly provide a Loader to add_multi_constructor() before including that Loader in your call to a load function:

yaml.add_multi_constructor('!', unknown, Loader=yaml.SafeLoader)

...

return yaml.load_all(infile, Loader=yaml.SafeLoader)

Upvotes: 0

Markus Cozowicz
Markus Cozowicz

Reputation: 315

Extending the existing answer to support ignoring all unknown tags.

import yaml

class SafeLoaderIgnoreUnknown(yaml.SafeLoader):
    def ignore_unknown(self, node):
        return None 

SafeLoaderIgnoreUnknown.add_constructor(None, SafeLoaderIgnoreUnknown.ignore_unknown)

root = yaml.load(content, Loader=SafeLoaderIgnoreUnknown)

Upvotes: 13

Jason S
Jason S

Reputation: 189836

I figured it out, it's related to How can I add a python tuple to a YAML file using pyYAML?

I just have to do this:

  • subclass yaml.SafeLoader
  • call add_constructor to assign !v2 to a custom construction method
  • in the custom construction method, do whatever is appropriate
  • use yaml.load(..., MyLoaderClass) instead of yaml.safe_load(...)

and it works.

class V2Loader(yaml.SafeLoader):
    def let_v2_through(self, node):
        return self.construct_mapping(node)
V2Loader.add_constructor(
    u'!v2',
    V2Loader.let_v2_through)

   ....

y = yaml.load(info, Loader=V2Loader)

Upvotes: 8

Related Questions