Замена строк в YAML с использованием Python - PullRequest
0 голосов
/ 04 октября 2018

У меня есть следующий YAML:

instance:
  name: test
  flavor: x-large
  image: centos7

tasks:
  centos-7-prepare:
    priority: 1
    details::
      ha: 0
      args:
        template: &startup
          name: startup-centos-7
          version: 1.2
        timeout: 1800

  centos-7-crawl:
    priority: 5
    details::
      ha: 1
      args:
        template: *startup
        timeout: 0

Первая задача определяет имя шаблона и версию, которая затем используется другими задачами.Определение шаблона не должно меняться, однако другие, особенно имя задачи, будут.

Каков наилучший способ изменить имя и версию шаблона в Python?

У меня есть следующее регулярное выражение для сопоставления (используя re.DOTALL):

template:.*name: (.*?)version: (.*?)\s

Однако до сих пор не выяснил использование re.sub.Или есть более удобный способ сделать это?

Ответы [ 2 ]

0 голосов
/ 04 октября 2018

Для этого вида циклического отключения (load-modify-dump) YAML вы должны использовать ruamel.yaml (заявление об отказе: я являюсь автором этого пакета).

Если вы вводите в input.yaml, вы можете относительно легко найти name и version под ключом template и обновить их:

import sys
import ruamel.yaml

def find_template(d):
    if isinstance(d, list):
        for elem in d:
            x = find_template(elem)
            if x is not None:
                return x
    elif isinstance(d, dict):
        for k in d:
            v = d[k]
            if k == 'template':
                if 'name' in v and 'version' in v:
                    return v
            x = find_template(v)
            if x is not None:
                return x
    return None


yaml = ruamel.yaml.YAML()
# yaml.indent(mapping=4, sequence=4, offset=2)
yaml.preserve_quotes = True

with open('input.yaml') as ifp:
    data = yaml.load(ifp)
template = find_template(data)
template['name'] = 'startup-centos-8'
template['version'] = '1.3'

yaml.dump(data, sys.stdout)

, что дает:

instance:
  name: test
  flavor: x-large
  image: centos7

tasks:
  centos-7-prepare:
    priority: 1
    'details:':
      ha: 0
      args:
        template: &startup
          name: startup-centos-8
          version: '1.3'
        timeout: 1800

  centos-7-crawl:
    priority: 5
    'details:':
      ha: 1
      args:
        template: *startup
        timeout: 0

Обратите внимание, что(лишние) кавычки, которые я вставил во входные данные, а также комментарий и имя псевдонима сохраняются.

0 голосов
/ 04 октября 2018

Я бы проанализировал файл yaml в словаре, отредактировал поле и записал словарь обратно в yaml.

См. Этот вопрос для обсуждения разбора yaml в python Как я могу разобратьYAML-файл на Python , но я думаю, что вы получите что-то вроде этого.

from ruamel.yaml import YAML
from io import StringIO

yaml=YAML(typ='safe')
yaml.default_flow_style = False

#Parse from string
myConfig = yaml.load(doc)
#Example replacement code
for task in myConfig["tasks"]:
    if myConfig["tasks"][task]["details"]["args"]["template"]["name"] == "&startup":
        myConfig["tasks"][task]["details"]["args"]["template"]["name"] = "new value"
#Convert back to string
buf = StringIO()
yaml.dump(myConfig, buf)
updatedYml = buf.getvalue()
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...