Дамп Python YAML с использованием стиля блока без кавычек - PullRequest
0 голосов
/ 25 мая 2018

Как загрузить и выгрузить YAML с помощью PyYAML, чтобы он как можно точнее использовал исходный стиль?

У меня есть Python для загрузки и выгрузки данных YAML, например:

import sys
import yaml

def _represent_dictorder(self, data):
    # Maintains ordering of specific dictionary keys in the YAML output.
    _data = []
    ordering = ['questions', 'tags', 'answers', 'weight', 'date', 'text']
    for key in ordering:
        if key in data:
            _data.append((str(key), data.pop(key)))
    if data:
        _data.extend(data.items())
    return self.represent_mapping(u'tag:yaml.org,2002:map', _data)

yaml.add_representer(dict, _represent_dictorder)

text="""-   questions:
    -   Lorem ipsum dolor sit amet, consectetur adipiscing elit.
    tags:
        context: curabitur
    answers:
    -   weight: 2
        date: 2014-1-19
        text: |-
            1. Mauris lorem magna, auctor et tristique id, fringilla ut metus.
            2. Donec pellentesque elit non felis feugiat, in gravida ex hendrerit.
            3. Mauris quis velit sapien. Nullam blandit, diam et pharetra maximus, mi erat scelerisque turpis, eu vestibulum dui ligula non lectus.
                a. Aenean consectetur eleifend accumsan.
            4. In erat lacus, egestas ut tincidunt ac, congue quis elit. Suspendisse semper purus ac turpis maximus dignissim.
                a. Proin nec neque convallis, placerat odio non, suscipit erat. Nulla nec mattis nibh, accumsan feugiat felis.
            5. Mauris lorem magna, auctor et tristique id, fringilla ut metus.
                a. Morbi non arcu odio. Maecenas faucibus urna et leo euismod placerat.
                b. Nulla facilisi. Pellentesque at pretium nunc.
                c. Ut ipsum nibh, suscipit a pretium eu, eleifend vitae purus.
"""
yaml.dump(yaml.load(text), stream=sys.stdout, default_flow_style=False, indent=4)

но это выводит YAML в другом стиле, например:

-   questions:
    - Lorem ipsum dolor sit amet, consectetur adipiscing elit.
    tags:
        context: curabitur
    answers:
    -   weight: 2
        date: 2014-1-19
        text: "1. Mauris lorem magna, auctor et tristique id, fringilla ut metus.\n\
            2. Donec pellentesque elit non felis feugiat, in gravida ex hendrerit.\n\
            3. Mauris quis velit sapien. Nullam blandit, diam et pharetra maximus,\
            \ mi erat scelerisque turpis, eu vestibulum dui ligula non lectus.\n \
            \   a. Aenean consectetur eleifend accumsan.\n4. In erat lacus, egestas\
            \ ut tincidunt ac, congue quis elit. Suspendisse semper purus ac turpis\
            \ maximus dignissim.\n    a. Proin nec neque convallis, placerat odio\
            \ non, suscipit erat. Nulla nec mattis nibh, accumsan feugiat felis.\n\
            5. Mauris lorem magna, auctor et tristique id, fringilla ut metus.\n \
            \   a. Morbi non arcu odio. Maecenas faucibus urna et leo euismod placerat.\n\
            \    b. Nulla facilisi. Pellentesque at pretium nunc.\n    c. Ut ipsum\
            \ nibh, suscipit a pretium eu, eleifend vitae purus."

Как вы можете видеть, он меняет стиль текстового блока, так что экранированные строки экранируются, что делает его намного труднее для чтения.

Поэтому я попытался указать атрибут default_style, например:

yaml.dump(yaml.load(text), stream=sys.stdout, default_flow_style=False, default_style='|', indent=4)

И это исправило стиль текстового блока, но затем он нарушил другие стили, поместив кавычки вокруг всех других строк,добавление новых строк к однострочным строкам и целых чисел, например:

-   "questions":
    - |-
        Lorem ipsum dolor sit amet, consectetur adipiscing elit.
    "tags":
        "context": |-
            curabitur
    "answers":
    -   "weight": !!int |-
            2
        "date": |-
            2014-1-19
        "text": |-
            1. Mauris lorem magna, auctor et tristique id, fringilla ut metus.
            2. Donec pellentesque elit non felis feugiat, in gravida ex hendrerit.
            3. Mauris quis velit sapien. Nullam blandit, diam et pharetra maximus, mi erat scelerisque turpis, eu vestibulum dui ligula non lectus.
                a. Aenean consectetur eleifend accumsan.
            4. In erat lacus, egestas ut tincidunt ac, congue quis elit. Suspendisse semper purus ac turpis maximus dignissim.
                a. Proin nec neque convallis, placerat odio non, suscipit erat. Nulla nec mattis nibh, accumsan feugiat felis.
            5. Mauris lorem magna, auctor et tristique id, fringilla ut metus.
                a. Morbi non arcu odio. Maecenas faucibus urna et leo euismod placerat.
                b. Nulla facilisi. Pellentesque at pretium nunc.
                c. Ut ipsum nibh, suscipit a pretium eu, eleifend vitae purus.

Как это исправить, чтобы выходные данные напоминали стиль моего исходного ввода?

1 Ответ

0 голосов
/ 25 мая 2018

Как бы вы определили, какую строку представлять в виде литерала блока (или сложенного блока в этом отношении) и что представлять в строке?

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

def selective_representer(dumper, data):
    return dumper.represent_scalar(u"tag:yaml.org,2002:str", data,
                                   style="|" if "\n" in data else None)

yaml.add_representer(str, selective_representer)

Теперь, если вы сбрасываете свои данные со стилем потока по умолчанию, установленным на False (для предотвращения dict / list inlining):

yaml.dump(yaml.load(text), stream=sys.stdout, default_flow_style=False, indent=4)

Ваши скаляры будут действовать так, как вы ожидаете.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...