Add the ability to choose the sort order of dict elements

Issue #1 new
Former user created an issue


I apologize if I'm not submitting this the right way. I worked on a project that needed to control the order of a dict. I'm attaching a patch for inclusion upstream. This is my first time modifying this code. I hope I inserted this functionality in a way that you approve of.

With this patch you can pass a function that specifies how to re-order the items in a dict before they are output:


power: - connections: - {name: 0, to: A1/B} - {name: 1, to: A1/A} - {name: 2, to: A1/C} name: wallsocket


power: - name: wallsocket connections: - {name: 0, to: A1/B} - {name: 1, to: A1/A} - {name: 2, to: A1/C}

It may not be obvious from this example but the 2nd is much easier to read for humans.

I will attach to this bug my patch and some tests/examples.

Comments (3)

  1. TomRitchford

    Have you tried simply using an OrderedDict? It's built into Python 2.7/3.x, and you can download it for other versions of Python.

    Unlike the regular dictionary, OrderedDict iterates its values in the exact ordered you added them...

    So you'd create your dictionary as an OrderedDict in the order you want, and then pass it into the pyyaml. You should then get your output in the desired order!

  2. Tom Limoncelli

    Tom, Thank you for the suggestion. However, my patch is about presentation not storage.

    1. Using OrderedDict means rewriting the code datastructures to use OrderedDicts. For the simple case of just wanting to output an existing structure, this will mean implementing something like a version of copy.deepcopy() that converts dicts to OrderedDicts as it traverses the datastructure. That's a lot of work just to get pretty output.
    2. Using OrderedDict creates output that is, essentially, unreadable to humans. That's fine if you are using YAML as a encapsulation mechanism but terrible if you are just trying to produce human-editable files.

    Compare these two outputs:

    >>> oc = collections.OrderedDict(a=2, b=3)
    >>> print yaml.dump(oc, indent=2, canonical=False)
    - - [a, 2]
      - [b, 3]
    >>> d = {'a':2, 'b':3}
    >>> print yaml.dump(d, indent=2, canonical=False)
    {a: 2, b: 3}
  3. TomRitchford

    Sorry for the delay (and I'm just a passer-by anyway).

    You shouldn't be using yaml.dump or yaml.load anyway - it's unsafe.

    Now, if you used safe_dump, you shouldn't have this problem - except for bug 5, which causes a traceback when you do that.

    Luckily, I have a small tweak to pyyaml that fixes bug 5, and I tested your issue and it works! The change is here.

    print yaml.safe_dump(collections.OrderedDict(a=2, b=3), indent=2, canonical=False)
    {a: 2, b: 3}

    Let's hope we can get this into this main repository, it's a simple change...

  4. Log in to comment