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

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

- 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? Спецификация (1.1, 1.2) говорит, что в узле сопоставления существует "ограничение, что каждый из ключей уникален", однако это неясно должен ли сам ключ слияния подвергаться ограничению уникальности, или только ключи сопоставления после разрешенного слияния должны быть уникальными.

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

Действителен ли этот ввод в формате YAML и как его правильно проанализировать в Python?


person wim    schedule 13.02.2020    source источник
comment
PyYAML анализирует это и объединяет ключи, но комментарии теряются, так что это действительно? Я не уверен, что вы пытаетесь сделать, но я не уверен, что вопрос инкапсулирует это   -  person roganjosh    schedule 13.02.2020
comment
В идеале я хочу сохранить комментарии и не испортить слияния (я не контролирую ввод). Но это не то, о чем этот вопрос, этот вопрос намного меньше по объему: действительно ли разрешены дублирующиеся ключи слияния в спецификации YAML.   -  person wim    schedule 13.02.2020
comment
Отвечает ли это на ваш вопрос? Настройка ruamel.yaml для разрешения дублирования ключей   -  person sanyassh    schedule 14.02.2020
comment
Ответ в предложенном дубликате правильно выполняет слияние и сохраняет комментарии.   -  person sanyassh    schedule 14.02.2020
comment
Также проверено с помощью yamllint.com, yaml-online-parser.appspot.com и некоторые другие, все говорят, что это действительный yaml.   -  person sanyassh    schedule 14.02.2020
comment
@sanyash Эти сайты также утверждают, что YAML с некоторыми другими повторяющимися ключами сопоставления действителен, что неверно. Сайт неправильный. Предлагаемый дубликат вообще не касается вопроса.   -  person wim    schedule 14.02.2020
comment
Хорошо, вы можете быть правы в том, что сайты неверны, но уверены ли вы, что предлагаемый дубликат не решает вашу проблему? Ты через тело просматривал, не только заголовок? In this case the duplicate key happens to be a merge key <<:. очень похоже на ваш случай.   -  person sanyassh    schedule 14.02.2020
comment
Я уверен. Этот вопрос касается того, разрешает ли спецификация YAML дублировать ключи слияния. Ответ на этот вопрос не касается этого (и на самом деле они являются авторами ruamel, поэтому в любом случае это будет конфликт интересов). Но пост все равно интересный, так что спасибо за ссылку.   -  person wim    schedule 14.02.2020


Ответы (1)


Ключи слияния аналогичны любым другим ключам, только они интерпретируются особым образом, когда синтаксический анализатор 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 этого не позволяет.

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

      <<: [*splat0, *splat1]
person Anthon    schedule 13.02.2020
comment
Привет, Антон, альтернативный пример мне не интересен, потому что после разрешения слияний ключ VAR2 не уникален. Таким образом, он не должен успешно анализироваться, несмотря ни на что. Мы согласны с тем, что PyYAML здесь глючит, и у них всегда есть открытый вопрос по этому поводу... - person wim; 14.02.2020
comment
Что заставляет вас думать, что VAR2 должен быть уникальным. В спецификации слияния явно упоминается Keys in mapping nodes earlier in the sequence override keys specified in later mapping nodes. (что IIRC PyYAML делает неправильно и для действительного случая [*splat0, *splat1]). - person Anthon; 14.02.2020
comment
Потому что более разумно разрешить сопоставление ключей перед проверкой дубликатов, иначе вы не сможете обнаружить конфликты на одинаковых ключах, таких как 0xf и 15. - person wim; 14.02.2020
comment
Похоже, что PyYAML правильно объединяет [ *BIG, *LEFT, *SMALL ] для примера, т. е. окончательная карта закончилась 'r': 10. У вас есть какой-то другой режим отказа? - person wim; 14.02.2020
comment
Может быть, я не правильно вспомнил, или это было исправлено. В любом случае, у которого есть неуникальный ключ r, был ли ваш первый комментарий, указывающий, что если ключи двойного слияния будут разрешены, то все ключи всех сопоставлений (псевдонимов) должны быть уникальными? Это было бы расширением семантики ключа слияния. - person Anthon; 14.02.2020
comment
Я не знаю, но если вы спрашиваете мое мнение, я думаю, что YAML уже слишком сложен, и мне совсем не нравится синтаксис слияния. Кстати, это также похоже на ошибку ruamel.yaml, обнаруживающую дублирующиеся ключи, например. последний пример здесь: dpaste.com/1MGYMFJ - person wim; 14.02.2020