Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Error when dealing with duplicate anchors #200

Open
ghost opened this issue Jun 29, 2022 · 1 comment
Open

Error when dealing with duplicate anchors #200

ghost opened this issue Jun 29, 2022 · 1 comment

Comments

@ghost
Copy link

ghost commented Jun 29, 2022

Hello and thank you for this tool.

Consider the following sample YAML file:

test:
  - name: &name foo
    properties:
      name: *name
  
  - name: &name bar
    properties:
      name: *name

Note the two anchors with the same name, which is fine according to the YAML specification. Here is a schema to validate this file:

test: list(include('value'))
value:
  name: str()
  properties:
    name: str()

Running Yamale with default options produces the following error:

yaml.composer.ComposerError: found duplicate anchor; first occurrence
  in "test.yaml", line 3, column 11
second occurrence
  in "test.yaml", line 7, column 11

Same behavior with --parser ruamel but the exception is ruamel.yaml.composer.ComposerError.

As described here, ruamel.yaml can parse this correctly, but pure=True must be specified when initializing it:

from ruamel.yaml import YAML
yaml = YAML(typ='safe', pure=True)

Can you please consider adding a flag to toggle the pure option in ruamel so Yamale doesn't error out in this scenario?

@mildebrandt
Copy link

Hi, thanks for your interest in Yamale.

I think I'd like to handle this by allowing users to pass in their own parser. Take a look at this file: https://github.com/23andMe/Yamale/blob/master/yamale/readers/yaml_reader.py

In your case, you'd create a file/module/package/whatever that has this function:

def ruamel_pure(f):
    from ruamel.yaml import YAML
    yaml = YAML(typ='safe', pure=True)
    return list(yaml.load_all(f))

Perhaps that's in a package called romain-depres.prasers. Then the command like would look like:

yamale -p romain-depres.prasers.ruamel_pure -s schema.yaml data.yaml

Then in here:

def parse_yaml(path=None, parser='pyyaml', content=None):
    try:
        parse = _parsers[parser.lower()]
    except KeyError:
        raise NameError('Parser "' + parser + '" is not supported\nAvailable parsers are listed below:\nPyYAML\nruamel')

Before raising the NameError, we can try to load the module/function that is passed into the parser argument by the -p option. If it exists, then use that as the parser.

I'm happy to review any pull request that will implement what I've mentioned above. Let me know if you have any questions.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant