Search code examples
pythonyamlconfiguration-files

Load YAML preserving order


I have a Python library that defines a list like the next one:

config = [
    'task_a',
    ('task_b', {'task_b_opt_1': ' '}),
    ('task_a', {'task_a_opt_1': 42}),
    ('task_c', {'task_c_opt_1': 'foo', 'task_c_opt_2': 'bar'}),
    'task_b'
]

Basically this list defines 5 tasks that have to be applied in that specific order and using the parameters defined (if any). Also, the same task can define parameters or not (use default values).

Now I want to extend the library to support config files. To make them easier for the final user I was thinking in using YAML files. So the code above would become something like:

task_a:
task_b:
  task_b_opt_1: ' '
task_a:
  task_a_opt_1: 42
task_c:
  task_c_opt_1': 'foo'
  task_c_opt_2': 'bar'
task_b:

This is not even a valid YAML file as some keys have no value. So I have two questions:

  1. How can I define empty tasks?
  2. How can I preserve the order when loading the file in Python?

If none of those is possible, is there any other solution for this?


Solution

  • In YAML, a mapping is defined to not be ordered. The typical solution is to make it a list of mappings. However, the values (or even keys) can be missing, in which case they are implicitly null (the equivalent of None in Python)

    - task_a:
    - task_b:
        task_b_opt_1: ' '
    - task_a:
        task_a_opt_1: 42
    - task_c:
        task_c_opt_1: 'foo'
        task_c_opt_2: 'bar'
    - task_b:
    

    Another option is to not make the tasks without options into mappings, and instead use strings, by just removing the : from those lines:

    - task_a
    - task_b:
        task_b_opt_1: ' '
    - task_a:
        task_a_opt_1: 42
    - task_c:
        task_c_opt_1: 'foo'
        task_c_opt_2: 'bar'
    - task_b