0

Trying to use pyyaml to parse mkdocs.yml file. It contains a snippet like this:

foo:
    emoji_index: !!python/name:materialx.emoji.twemoji

When I run:

with open("test.yml", 'r') as stream:
    try:
        print(yaml.safe_load(stream))
    except yaml.YAMLError as exc:
        print(exc)

This throws the following error:

could not determine a constructor for the tag 'tag:yaml.org,2002:python/name:materialx.emoji.twemoji'
  in "test.yml", line 2, column 18
AS_Butler
  • 281
  • 2
  • 12

1 Answers1

1

safe_load restricts the loader to load only types it knows. This is because loading arbitrary types can lead to arbitrary code execution, which is a security risk.

To properly load the file, you have the following options:

  • Use load instead of safe_load and import the library that contains materialx.emoji.twemoji (I am unsure where this is defined, I didn't find a definite answer online)
  • Instead of loading the YAML file to native types, load it into a node graph using yaml.compose. This will return the root node of the YAML document. This will not put the nodes directly into dicts, lists etc.
  • Register an own constructor:
def my_constructor(loader, node):
  # since the content of the node is empty, you should return a value that
  # can be used to identify the node, e.g.
  return "materialx.emoji.twemoji"

yaml.add_constructor('tag:yaml.org,2002:python/name:materialx.emoji.twemoji',
    my_constructor, yaml.SafeLoader)

Which approach is the best depends on what you want to do with the data.

flyx
  • 35,506
  • 7
  • 89
  • 126