Search code examples
pythonconstructoryamlaws-cloudformationpyyaml

How to Parse YAML Using PyYAML if there are '!' within the YAML


I have a YAML file that I'd like to parse the description variable only; however, I know that the exclamation points in my CloudFormation template (YAML file) are giving PyYAML trouble.

I am receiving the following error:

yaml.constructor.ConstructorError: could not determine a constructor for the tag '!Equals'

The file has many !Ref and !Equals. How can I ignore these constructors and get a specific variable I'm looking for -- in this case, the description variable.


Solution

  • You can define a custom constructors using a custom yaml.SafeLoader

    import yaml
    
    doc = '''
    Conditions: 
      CreateNewSecurityGroup: !Equals [!Ref ExistingSecurityGroup, NONE]
    '''
    
    class Equals(object):
        def __init__(self, data):
            self.data = data
        def __repr__(self):
            return "Equals(%s)" % self.data
    
    class Ref(object):
        def __init__(self, data):
            self.data = data
        def __repr__(self):
            return "Ref(%s)" % self.data
    
    def create_equals(loader,node):
        value = loader.construct_sequence(node)
        return Equals(value)
    
    def create_ref(loader,node):
        value = loader.construct_scalar(node)
        return Ref(value)
    
    class Loader(yaml.SafeLoader):
        pass
    
    yaml.add_constructor(u'!Equals', create_equals, Loader)
    yaml.add_constructor(u'!Ref', create_ref, Loader)
    a = yaml.load(doc, Loader)
    print(a)
    

    Outputs:

    {'Conditions': {'CreateNewSecurityGroup': Equals([Ref(ExistingSecurityGroup), 'NONE'])}}