Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How get the sequences properly indented with ruamel.yaml?

With the following data

from ruamel import yaml
data = {1: {1:[{1:1,2:2},{1:1,2:2}], 2:2}, 2: 42}

I get an incorrect indentation for the sequence

>>> print yaml.round_trip_dump(data)
1:
  1:
  - 1: 1
    2: 2
  - 1: 1
    2: 2
  2: 2
2: 42

Which cannot be folded on Notepad++. However with the proper indent it works:

Bad:

Bad Indent

Good:

Good Indent

I have tried to use block_seq_indent=2:

>>> print yaml.round_trip_dump(data, block_seq_indent=2)
1:
  1:
    - 1: 1
    2: 2
    - 1: 1
    2: 2
  2: 2
2: 42

How can I solve this issue?

like image 476
nowox Avatar asked Jun 06 '17 11:06

nowox


1 Answers

The ruamel.yaml documentation, although generally lacking, says the following about offset of the dash within the indent:

If the offset equals sequence, there is not enough room for the dash and the space that has to follow it. In that case the element itself would normally be pushed to the next line (and older versions of ruamel.yaml did so). But this is prevented from happening. However the indent level is what is used for calculating the cumulative indent for deeper levels and specifying sequence=3 resp. offset=2, might give correct, but counter intuitive results.

It is best to always have sequence >= offset + 2 but this is not enforced. Depending on your structure, not following this advice might lead to invalid output.

By default indent (both for mappings and for sequences) equals 2, if you do:

import sys
from ruamel import yaml

data = {1: {1:[{1:1,2:2},{1:1,2:2}], 2:2}, 2: 42}

yml = yaml.YAML()
yml.indent(mapping=2, sequence=4, offset=2)
yml.dump(data, sys.stdout)

you get:

1:
  1:
    - 1: 1
      2: 2
    - 1: 1
      2: 2
  2: 2
2: 42

With the old API, that you use in your question, you cannot do the different indent for mappings and sequences in a trivial way (you need to subclass the Emitter, and on post __init__ of the base class, set the values). And with older versions of ruamel.yaml this was not possible at all.

This only works with the default (round-trip, i.e. typ='rt') dumper, but does work with both the normal Python dict resp. list (e.g. from YAML(typ='safe').load(....)) and the more convulated subclasses thereof used when doing YAML().load(....)

(the above requires ruamel.yaml>=0.15.30)

like image 159
Anthon Avatar answered Sep 18 '22 02:09

Anthon