Сохранение отступа смещения для файла YAML с использованием python ruamel-yaml - PullRequest
1 голос
/ 07 февраля 2020

Я пытаюсь использовать ruamel-yaml для достижения следующего. У меня есть YAML-файл с набором переменных вроде этого (обратите внимание на тот факт, что все ключи начинаются с отступа 6):

      app:
        version: 'latest'
        env: 'test'

      #auth
      auth_endpoint: 'http://localhost/login'
      auth_token: 23NSDQD94NFDFKF0SQS

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

app:
  version: 'latest'
  env: 'test'

      #auth
auth_endpoint: 'http://localhost/login'
auth_token: 23NSDQD94NFDFKF0SQS

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

def update_yaml(file):
  yaml = ruamel.yaml.YAML()
  yaml.indent(mapping=6)
  config_yaml = yaml.load(file)
  # value changing code ommited for readability
  with open(os.path.join(sys.path[0], "config.yml"), 'w') as file:
    yaml.dump(config_yml, file)

Я пробовал несколько вещей с методом отступа, но безрезультатно, есть идеи, как сохранить этот оригинальный отступ?

1 Ответ

1 голос
/ 09 февраля 2020

Прежде всего, неверно, что все ваши ключи имеют отступ 6, как ключи version и env, которые являются частью сопоставления, являющегося значением для ключа уровня root app, имеют только две позиции с отступом .

ruamel.yaml приведет к тому, что ваш вывод будет соответствовать отступам. Все сопоставления будут иметь одинаковый отступ, а также все последовательности (хотя сопоставления и последовательности могут отличаться). Поскольку требуемый вывод не является согласованным, вам необходимо выполнить некоторую постобработку:

import sys
import ruamel.yaml

yaml_str = """\
      app:
        version: 'latest'
        env: 'test'

      #auth
      auth_endpoint: 'http://localhost/login'
      auth_token: 23NSDQD94NFDFKF0SQS
"""

class PushRootLeft:
    def __init__(self, positions=42):
        self.positions = positions

    def __call__(self, s):
        result = []
        for line in s.splitlines(True):
            sline = line.strip()
            if not sline or sline[0] == '#':
                result.append(line)
            else:
                result.append(' ' * self.positions + line)
        return ''.join(result)

yaml = ruamel.yaml.YAML()
yaml.indent(mapping=2) # not necessary, this is the default
yaml.preserve_quotes = True

data = yaml.load(yaml_str)
print('123456780') # just to better see the alignment of the actual YAML output
yaml.dump(data, sys.stdout, transform=PushRootLeft(6))

, что даст:

123456780
      app:
        version: 'latest'
        env: 'test'

      #auth
      auth_endpoint: 'http://localhost/login'
      auth_token: 23NSDQD94NFDFKF0SQS

Вам следует установить .preserve_quotes как некоторое ( не разбирается) синтаксический анализатор не любит двоеточие в вашем URL без кавычек, интерпретировать его как индикатор значения, даже если за ним не стоит пробел.

То, что вы должны сделать что-то особенное для комментариев, это потому, что при -trip знает, в каком столбце он изначально появился, и попытается восстановить его (если только какое-то изменение значения не подтолкнет его правильно).

Рекомендуемое расширение для файлов YAML .yaml с сентября 2006 г.

...