Это действительный файл YAML? - PullRequest
       51

Это действительный файл YAML?

0 голосов
/ 13 февраля 2020

Рассмотрим следующий файл:

- k0: v0
  vars: &splat0
    VAR0: potato  # vars from blob0

- k1: v1
  vars: &splat1
    VAR1: spud    # vars from blob1

- k: v
  extra:          # merged vars from blob0 + blob1
    <<: *splat0
    <<: *splat1

Использует ключ слияния функции YAML.

Это допустимый файл YAML? Spe c ( 1.1 , 1.2 ) говорит, что в узле отображения есть ограничение ", что каждый из ключей уникален ", однако Неясно, подчиняются ли сами ключи слияния ограничениям уникальности, или только ключи сопоставления после разрешенного слияния должны быть уникальными.

PyYAML анализирует это и объединяет ключи, но комментарии теряются. ruamel может сохранять комментарии, но вызывает DuplicateKeyError, и если вы явно разрешаете дубликаты ключей, то он анализирует, но объединение потеряно.

Является ли этот ввод допустимым YAML и как его правильно анализировать в Python?

1 Ответ

0 голосов
/ 14 февраля 2020

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

Но есть еще один аргумент против этого, даже если ключ слияния будет настолько особенным, что он не будет следовать нормальным ограничениям ключа. Давайте предположим, что ваш входной файл будет выглядеть так:

- k0: v0
  vars: &splat0
    VAR0: potato  # vars from blob0
    VAR2: tater

- k1: v1
  vars: &splat1
    VAR1: spud    # vars from blob1
    VAR2: tuber

- k: v
  extra:          # merged vars from blob0 + blob1
    <<: *splat0
    <<: *splat1

А также предположим, что вы можете загрузить этот неверный YAML в data. Каким будет значение data[2]['extra']['VAR2']?

Поскольку спецификация YAML явно указывает:

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

Поэтому, если вы не нарушите другое явное ограничение (порядок ключей), вы не сможете правильно проанализировать это (что и делает PyYAML. ИМХО ошибка).

Это означает, что когда вы правильно реализовать спецификацию YAML, вы не можете решить, будут ли значения data[2]['extra'] сначала обновляться с VAR2: tuber или с VAR2: tater. Вот почему ruamel.yaml не позволяет этого.

Конечно, в ключе слияния spe c четко определено, какое значение для ключа VAR2 вы получаете, когда делаете:

      <<: [*splat0, *splat1]
...