crdoconnor / strictyaml

Type-safe YAML parser and validator.
https://hitchdev.com/strictyaml/
MIT License
1.46k stars 61 forks source link

How can I sort yaml keys and output it back to yaml? #83

Open Jackenmen opened 4 years ago

Jackenmen commented 4 years ago

Hi, I've been using this project for short time, and recently I figured that after loading the yaml with provided schema, I also want to sort keys in the data and output it back to file so that it always stays in same order. I thought it's gonna be easy at first, but unfortunately it only seemed that way. I tried to do this in 2 ways:

  1. Edit the YAML object which at first seemed like the way docs intended me to use:

    # schema made shorter just for easier repro
    SCHEMA = Map({"repo": Map({"install_msg": Str()})})
    yaml = load(yaml_input, SCHEMA)
    yaml["repo"] = OrderedDict(sorted(yaml["repo"].items(), key=lambda tup: tup[0]))

    The second line immediately failed because the keys and values in the dict are in fact YAML objects and doing this fails with serialization error.

  2. Get YAML.data, modify the returned dict and serialize it with as_document:

    
    # schema made shorter just for easier repro
    SCHEMA = Map({"repo": Map({"install_msg": Str()})})

yaml = load(yaml_input, SCHEMA) data = yaml.data data["repo"] = OrderedDict(sorted(yaml["repo"].items(), key=lambda tup: tup[0])) document = as_document(data, SCHEMA)

The last line fails because this time, it can't serialize `FoldedScalarString` which I got because this is how yaml file looks:

repo: install_msg: >- Thanks for using RepoName. If you have any issues, check for more information in my repo:



I don't know if either of these ways should actually work and is an actual issue, but I currently don't see a good way of non in-place editing dicts in YAML data and I feel like there should be one (with preserving comments and the scalars)

Edit: Having a way to sort in-place would be cool too by the way, I'm not expecting anything more than being able to use a variant of `OrderedDict.move_to_end()` that would allow me to do it on YAML object I get from parsing yaml file.
crdoconnor commented 4 years ago

Thanks for raising this. When I wrote this I was focused almost exclusively on deterministic roundtripping (i.e. the ordering out should match the ordering in), and believe it or not I've yet to try reordering keys.

I am somewhat concerned that it might not be possible to fix this without first doing #56 but I'll take a look.