Разделение файла .yml - PullRequest
       9

Разделение файла .yml

0 голосов
/ 26 декабря 2018

Мне нужно разбить файлы .yml на 3 части: верхний колонтитул, рабочий (часть, которую мне нужно отредактировать) и нижний колонтитул.Заголовок - это все, что находится перед блоком «Resource:», а нижний колонтитул - это все, что находится после блока ресурсов.По сути, мне нужно создать код, который создает 3 списка, словари, строки, все, что работает, который содержит эти три раздела файла YAML, а затем позволяет мне выполнить больше кода для рабочего элемента, затем объединить их все вместе в конце исоздайте новый документ с такими же отступами.Не следует вносить изменения в заголовок или хвост.

Примечание. Я просмотрел все, что касается разбора yaml и прочего, но, похоже, не могу реализовать совет, который нашел эффективно.Было бы предпочтительнее решение, не включающее импорт yaml, но если вам необходимо, пожалуйста, объясните, что на самом деле происходит с кодом импорта yaml, чтобы я мог понять, что я испортил.

1 Ответ

0 голосов
/ 26 декабря 2018

Файлы, которые содержат один или несколько документов YAML (короче: файл YAML, который, начиная с сентября 2006 года, рекомендуется иметь расширение .yaml), являются текстовыми файлами и могут быть объединены из частей как таковые.Единственное требование состоит в том, чтобы в конце концов у вас был текстовый файл, который является действительным файлом YAML.

Самым простым является, конечно, иметь верхний и нижний колонтитулы в отдельных файлах для этого, но, как вы говорите о несколькихФайлы YAML это скоро становится громоздким.Однако всегда можно выполнить базовый анализ содержимого файла.

Поскольку ваша рабочая часть начинается с Resource:, и вы указываете 3 списка или словаря (у вас не может быть трех строк в корне YAMLдокумент).Структура данных корневого уровня вашего документа YAML должна быть либо mapping , а все остальное, кроме ключей для этого отображения, должно иметь отступ (теоретически, нужно только больше отступать, нона практике это почти всегда означает, что ключи не имеют отступов), например (m.yaml):

# header
a: 1
b:
  - 2
  - c: 3    # end of header
Resource:
# footer
c: 
d: "the end"   # really

или корневой уровень должен быть последовательностью (s.yaml):

# header
- a: 1
  b:
  - 2
  - c: 3
- 42         # end of header
- Resource:
# footer
- c: 
  d: "the end"  # really

оба могут быть легко разделены без загрузки YAML, вот пример кода для этого для файла с отображением корневого уровня:

from pathlib import Path
from ruamel.yaml import YAML

inf = Path('m.yaml')
header = []  # list of lines
resource = [] 
footer = []
for line in inf.open():
    if not resource:
        if line.startswith('Resource:'):  # check if we are at end of the header
            resource.append(line)
            continue
        header.append(line)
        continue
    elif not footer:
        if not line or line[0] == ' ':   # still in the resource part
            resource.append(line)
            continue
    footer.append(line)

# you now have lists of lines for the header and the footer
# define the new data structure for the resource this is going to be a single key/value dict
upd_resource = dict(Resource=['some text', 'for the resource spec', {'a': 1, 'b': 2}])

# write the header lines, dump the resource lines, write the footer lines

outf = Path('out.yaml')

with outf.open('w') as out:
    out.write(''.join(header))
    yaml = YAML()
    yaml.indent(mapping=2, sequence=2, offset=0)  # the default values
    yaml.dump(upd_resource, out)
    out.write(''.join(footer))

print(outf.read_text())

это дает:

# header
a: 1
b:
  - 2
  - c: 3    # end of header
Resource:
- some text
- for the resource spec
- a: 1
  b: 2
# footer
c: 
d: "the end"   # really

То же самое при разборе файла YAML не сложнее.Следующее автоматически обрабатывает оба случая (независимо от того, является ли корневой уровень отображением или последовательностью):

from pathlib import Path
from ruamel.yaml import YAML

inf = Path('s.yaml')
upd_resource_val = ['some text', 'for the resource spec', {'a': 1, 'b': 2}]
outf = Path('out.yaml')


yaml = ruamel.yaml.YAML()
yaml.indent(mapping=2, sequence=2, offset=0)
yaml.preserve_quotes = True
data = yaml.load(inf)
if isinstance(data, dict):
    data['Resource'] = upd_resource_val
else:  # assume a list, 
    for item in data:  # search for the item which has as value a dict with key Resource
        try:
            if 'Resource' in item:
                item['Resource'] = upd_resource_val
                break
        except TypeError:
            pass
yaml.dump(data, outf)

Это создает следующее out.yaml:

# header
- a: 1
  b:
  - 2
  - c: 3
- 42         # end of header
- Resource:
  - some text
  - for the resource spec
  - a: 1
    b: 2
# footer
- c:
  d: "the end"  # really

Если m.yamlфайл был входным, выходной был бы точно таким же, как и в текстовом примере кода «конкатенации».

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