Сохраняйте кавычки, а также добавляйте данные с кавычками в Ruamel

Я использую Ruamel для сохранения стилей кавычек в файлах YAML, отредактированных человеком.

У меня есть пример входных данных:

---
a: '1'
b: "2"
c: 3

Я читаю данные, используя:

def read_file(f):
    with open(f, 'r') as _f:
        return ruamel.yaml.round_trip_load(_f.read(), preserve_quotes=True)

Затем я редактирую эти данные:

data = read_file('in.yaml')
data['foo'] = 'bar'

Я записываю обратно на диск, используя:

def write_file(f, data):
    with open(f, 'w') as _f:
        _f.write(ruamel.yaml.dump(data, Dumper=ruamel.yaml.RoundTripDumper, width=1024))

write_file('out.yaml', data)

И выходной файл:

a: '1'
b: "2"
c: 3
foo: bar

Есть ли способ, которым я могу принудительно заключить в кавычки строку «bar», не применяя этот стиль цитирования во всей остальной части файла?

(Кроме того, могу ли я остановить удаление трех дефисов --- ?)


person Alex Harvey    schedule 01.09.2016    source источник


Ответы (2)


Чтобы сохранить кавычки (и стиль литерального блока) для строковых скаляров, ruamel.yaml¹ в режиме туда и обратно представляет эти скаляры как SingleQuotedScalarString, DoubleQuotedScalarString и PreservedScalarString. Определения классов для этих очень тонких оболочек можно найти в scalarstring.py. При сериализации такие экземпляры записываются «как они были прочитаны», хотя иногда представитель возвращается к двойным кавычкам, когда возникают трудности, поскольку они могут представлять любую строку.

Чтобы получить такое поведение при добавлении новых пар ключ-значение (или при обновлении существующей пары), вам просто нужно создать эти экземпляры самостоятельно:

import sys
from ruamel.yaml import YAML
from ruamel.yaml.scalarstring import SingleQuotedScalarString, DoubleQuotedScalarString

yaml_str = """\
---
a: '1'
b: "2"
c: 3
"""

yaml = YAML()
yaml.preserve_quotes = True
yaml.explicit_start = True
data = yaml.load(yaml_str)
data['foo'] = SingleQuotedScalarString('bar')
data.yaml_add_eol_comment('# <- single quotes added', 'foo', column=20)
yaml.dump(data, sys.stdout)

дает:

---
a: '1'
b: "2"
c: 3
foo: 'bar'          # <- single quotes added

yaml.explicit_start = True воссоздает (лишний) маркер начала документа. Был ли такой маркер в исходном файле или нет, не «известно» объекту словаря верхнего уровня, поэтому вам нужно повторно добавить его вручную.

Обратите внимание, что без preserve_quotes вокруг значений 1 и 2 в любом случае были бы (одинарные) кавычки, чтобы убедиться, что они рассматриваются как строковые скаляры, а не как целые числа.


¹ Я являюсь автором.

person Anthon    schedule 01.09.2016
comment
Большое спасибо, это потрясающе. - person Alex Harvey; 01.09.2016

Начиная с Ruamel 0.15, установите флаг save_quotes следующим образом:

from ruamel.yaml import YAML
from pathlib import Path

yaml = YAML(typ='rt') # Round trip loading and dumping
yaml.preserve_quotes = True
data = yaml.load(Path("in.yaml"))
yaml.dump(data, Path("out.yaml"))
person Alex Spurling    schedule 13.10.2017