Сохранить порядок файлов YAML с помощью ruamel - PullRequest
1 голос
/ 02 июля 2019

Я пытаюсь добавить новые элементы в файл YAML, но мне бы хотелось, чтобы новые элементы сохраняли визуальный порядок, чтобы было проще читать файл людям. Я пытался сохранить порядок с помощью orderdict, но с этим мы получаем директиву !! omap, «загрязняющую» файл YAML. Я хотел бы, чтобы новые элементы имели такой же порядок, как в примере ниже с кодом "yaml_doc".

Есть ли способ добавить новые элементы в YAML и сохранить порядок при выводе файла без указания директивы omap?

Ниже приведен код, который у меня есть, и вывод, который я получаю:

import sys
from ruamel.yaml import YAML
from ruamel.yaml.comments import CommentedSeq as cs
from ruamel.yaml.comments import TaggedScalar as ts
from ruamel.yaml.scalarstring import SingleQuotedScalarString as sq
from ruamel.ordereddict import ordereddict


yaml_doc = """\
version: 0
projects:
  - name: A1
    dir: B1
    aplan:
      when: ["X", "Y", "Z"]
    wflow: l
"""
yaml = YAML()
yaml.preserve_quotes = True
yaml.width = 4096
data = yaml.load(yaml_doc)

ref = data['projects']

record_to_add = dict(name='A2', dir='B2',
                     aplan=dict(when=["X", "Y", "Z"]), wflow='l')
ref.append(record_to_add)

record_to_add_2 = ordereddict([('name', 'A3'), ('dir', 'B3'), ('aplan', ordereddict(
    [('when', ['X', 'Y', 'Z'])])), ('wflow', 'l')])
ref.append(record_to_add_2)

yaml.dump(data, sys.stdout)

Вывод дампа

version: 0
projects:
- name: A1
  dir: B1
  aplan:
    when: ["X", "Y", "Z"]
  wflow: l
- aplan:
    when:
    - X
    - Y
    - Z
  wflow: l
  name: A2
  dir: B2
- !!omap
  - name: A3
  - dir: B3
  - aplan: !!omap
    - when:
      - X
      - Y
      - Z
  - wflow: l

1 Ответ

1 голос
/ 02 июля 2019

Чтобы сохранить порядок ключей, ruamel.yaml использует подкласс ordereddict, который можно проверить с помощью print(type(data)) сразу после загрузки.Это CommentedMap, и вы должны создать такие же, как вы сделали ordereddict:

import sys
from ruamel.yaml import YAML
from ruamel.yaml.comments import CommentedSeq as cs
from ruamel.yaml.comments import TaggedScalar as ts
from ruamel.yaml.scalarstring import SingleQuotedScalarString as sq
from ruamel.yaml.comments import CommentedMap as ordereddict


yaml_doc = """\
version: 0
projects:
  - name: A1
    dir: B1
    aplan:
      when: ["X", "Y", "Z"]
    wflow: l
"""
yaml = YAML()
yaml.preserve_quotes = True
yaml.width = 4096
data = yaml.load(yaml_doc)
# print(type(data['projects'][0])) # would give: <class 'ruamel.yaml.comments.CommentedMap'>

ref = data['projects']

record_to_add = dict(name='A2', dir='B2',
                     aplan=dict(when=["X", "Y", "Z"]), wflow='l')
ref.append(record_to_add)

record_to_add_2 = ordereddict([('name', 'A3'), ('dir', 'B3'), ('aplan', ordereddict(
    [('when', ['X', 'Y', 'Z'])])), ('wflow', 'l')])
ref.append(record_to_add_2)

yaml.dump(data, sys.stdout)

, что дает:

version: 0
projects:
- name: A1
  dir: B1
  aplan:
    when: ["X", "Y", "Z"]
  wflow: l
- name: A2
  dir: B2
  aplan:
    when:
    - X
    - Y
    - Z
  wflow: l
- name: A3
  dir: B3
  aplan:
    when:
    - X
    - Y
    - Z
  wflow: l

Упорядоченные отображения явно упоминаются в Спецификация YAML и это то, на что указывает упорядоченный приговор Python при выгрузке (и наоборот при загрузке).CommentedMap также может обрабатывать сохранение комментариев и атрибутов узла.

...