23andMe / Yamale

A schema and validator for YAML.
MIT License
680 stars 88 forks source link

Validate Yaml file that includes custom tag such as '!include' #145

Closed apolline-fk closed 3 years ago

apolline-fk commented 3 years ago

I have a yaml file that for one of the fields, the value is '!include another_file.yaml'. File

entity:
  parent:
  attributes:
    - account_id
  attribute_sources: !include account_file.yaml

Schema

entity:
  parent: str(required=False)
  attributes: list()
  attribute_sources: ???

I have created a constructor that fills in the value with the yaml of the specified file and yaml.add_constructor('!include', construct_include, Loader), where construct_include is my custom constructor. However, when I call data = yamale.make_data('./yaml_file_im_validating') for later validation, it complains that a constructor could not be determined for my tag !include. yaml.constructor.ConstructorError: could not determine a constructor for the tag '!include'

Any help on validating files with tags would be greatly appreciated.

mildebrandt commented 3 years ago

Thanks for using Yamale!

You may be using the wrong loader. Try this: yaml.SafeLoader.add_constructor('!include', construct_include)

Here's an example:

import os
import yaml
import yamale

class EnvTag(yaml.YAMLObject):
    yaml_tag = u'!env'

    def __init__(self, env_var):
        self.env_var = env_var

    def __repr__(self):
        return os.environ.get(self.env_var)

    @classmethod
    def from_yaml(cls, loader, node):
        return str(cls(node.value))

try:
    Loader = yaml.CSafeLoader
except AttributeError:  # System does not have libyaml
    Loader = yaml.SafeLoader

Loader.add_constructor('!env', EnvTag.from_yaml)

schema = yamale.make_schema('./schema.yaml')
data = yamale.make_data('./data.yaml')
yamale.validate(schema, data)

schema.yaml:

example: str()

data.yaml:

example: !env foo

Call it as follows:

foo=bar python test.py
apolline-fk commented 3 years ago

Hi @mildebrandt, thanks for getting back to me! I'm still getting the same error even with just running your example - is there something I could be missing?

mildebrandt commented 3 years ago

Are you using ruamel or PyYAML? Also, can you share your code?

mildebrandt commented 3 years ago

Closing due to lack of activity.