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

Ruamel yaml #145

Open
wants to merge 4 commits into
base: main
Choose a base branch
from
Open

Ruamel yaml #145

wants to merge 4 commits into from

Conversation

A2va
Copy link

@A2va A2va commented Dec 15, 2021

Hello ! I replaced pyyaml by Ruamel. This is needed by beetbox/beets#4188
and fixes #52

I removed the hack to keep comments but is there another hack elsewhere ?

@sampsyo
Copy link
Member

sampsyo commented Dec 16, 2021

Awesome; thanks for getting this started!

One other thing that #52 mentions is the OrderedDict extension. You can see where we preserve dictionary order here:

def construct_mapping(self, node, deep=False):

It might be nice to check whether the new library correctly does the same thing in an out-of-the-box way.

Have you been able to test yet whether this switch is effective at preserving comments, even without our hack?

@A2va
Copy link
Author

A2va commented Dec 20, 2021

It might be nice to check whether the new library correctly does the same thing in an out-of-the-box way.

I checked and ruamel uses OrderedDict .

Have you been able to test yet whether this switch is effective at preserving comments, even without our hack?
I tested it and for now it doesn't work,

It seems that more work is needed. But I have read the documentation and managed to get a working example.

from ruamel.yaml import YAML
from pathlib import Path

input = Path('./input.yaml')
output = Path('./output.yaml')
yml = YAML()
data = yml.load(input)
data["import"]["write"] = False
yml.dump(data, output)

To handle round tripping ruamel has special Dumper and Loader. With an empty type in YAML constructor, ruamel take automatically the round tripping classes. I tried to inherit RoundTripDumper to confuse Dumper and same for Loader but I couldn't get it to work

@A2va
Copy link
Author

A2va commented Dec 22, 2021

I found the problem when the yaml file loaded with yaml_util.load_yaml function. ruamel create special entry in class for handling comment but with update function, this information is lost.

"""Load YAML data from the source's filename.
"""
if self.optional and not os.path.isfile(self.filename):
value = {}
else:
value = yaml_util.load_yaml(self.filename,
loader=self.loader) or {}
self.update(value)

I also found an example closer to pyyaml api and this the old API of ruamel.

input = Path('./input.yaml')
with input.open() as ifile:
    doc = yaml.load(ifile, Loader=yaml.RoundTripLoader)
    print(yaml.dump(doc, Dumper=yaml.RoundTripDumper))

@A2va
Copy link
Author

A2va commented Dec 23, 2021

I also notice that round tripping doest't keep all comments but it appear only with old API of ruamel (example code from my previous message).

The first and second comment are dumped correctly but not the third one. Used the new API solves this but I don't see anything to custom the Dumper with the new API. The new API is like the first example I send,

#First comment
firstkey:
  # Second comment
    test:
      name: test
      # Third comment
      arrive: yes

ruamel.yaml is a YAML parser/emitter that supports roundtrip preservation of comments, seq/map flow style, and map key order

According to the description on pypi, it confirm that ruamel keeps key order.

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

Successfully merging this pull request may close these issues.

Switch to ruamel.yaml
2 participants