How to load a YAML 1.1 file without the YAML directive?

Viewed 281

Using ruamel.yaml v0.17.20, I'm trying to load files produced with PyYAML (or written by authors for software that only uses PyYAML). These files do not have a YAML directive, but PyYAML only supports YAML 1.1, so I need to somehow inform ruamel.yaml that it should load the file with 1.1, even though there isn't a directive.

from pathlib import Path
from ruamel.yaml import YAML

yaml = YAML()
yaml.version = (1, 1)
yaml.load(Path("some/path/to/file.yml"))  # file.yml exists and does not have a YAML directive

print(yaml.version)  # prints None
assert yaml.version == (1, 1)  # this fails!

When I try to load a file without a YAML directive, the Parser overwrites my explicitly set yaml.version with None in Parser.process_directives():

    def process_directives(self):
        # ...
        yaml_version = None
        # code that loads directives (but there aren't any in my case)

        if self.loader is not None and hasattr(self.loader, 'tags'):
            self.loader.version = yaml_version
            # ...

https://sourceforge.net/p/ruamel-yaml/code/ci/default/tree/parser.py#l316

The load version matters for things like parsing octals and booleans.

How can I tell ruamel.yaml to use 1.1 when parsing a stream that is missing a YAML directive?

1 Answers

Your code doesn't indicate what happens when you load a YAML document without %YAML directive, but you should check that:

import sys
import ruamel.yaml

yaml_str = "- 042 # octal or not depending on YAML version"


print('# load as 1.1')
yaml = ruamel.yaml.YAML()
yaml.version = (1, 1)
data = yaml.load(yaml_str)
print(data[0])

print('# load as 1.2')  # the default no need to set the version
yaml = ruamel.yaml.YAML()
data = yaml.load(yaml_str)
print(data[0])

which gives:

# load as 1.1
34
# load as 1.2
42

You should be able to use ruamel.yaml (in round-trip) to load YAML 1.1 and dump as YAML 1.2. You cannot use ruamel.yaml as a 1.2 to 1.1 convertor, nor is roundtripping 1.1 to 1.1 guaranteed to work for all files. Those are not the intended use of ruamel.yaml

In 0.17 the version information is not attached to the data loaded, but to the YAML() instance that will change.

Alternatively to setting the version you can add an appropriate header to bytes/str before handing it to .load()

FYI: The YAML 1.1 spec has been superseded 12 years ago and a PR for YAML 1.2 support in PyYAML was made available in 2014. The recommended extension for files containing YAML documents has been .yaml since 2006.

Related