Libelektra: YAJL: плагин не сохраняет значение непосредственно под точкой подключения

Созданный на 27 июл. 2018  ·  17Комментарии  ·  Источник: ElektraInitiative/libelektra

Шаги по воспроизведению проблемы

kdb mount config.json user/tests/yajl yajl
kdb set user/tests/yajl 'This May Be the Year I Disappear'
kdb ls user/tests/yajl
#> user/tests/yajl
kdb get user/tests/yajl 

ожидаемый результат

Последняя команда должна вывести текст This May Be the Year I Disappear .

Фактический результат

Последняя команда выводит пустую строку.

Системная информация

  • Электра Версия: мастер
  • ОС: macOS 10.13.6
bug good first issue usability

Все 17 Комментарий

Спасибо, что сообщили о проблеме!

Как бы выглядел такой документ JSON? Нам также нужна документация по специальной семантике файлов конфигурации, содержащих только родительский ключ.

Как бы выглядел такой документ JSON?

В этом случае документ будет содержать только строку:

"This May Be the Year I Disappear"

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

printf '"This May Be the Year I Disappear"' > (kdb file user/tests/yajl/)
kdb get user/tests/yajl
#> This May Be the Year I Disappear

.

Значит, нужно исправить только набор? Звучит довольно просто!

Значит, нужно исправить только набор?

Насколько я могу судить, да.

Думаю, я могу рассмотреть это как свою первую проблему. Не могли бы вы дать мне несколько советов, с чего мне начать поиск @ markus2330? Благодарю.

Источник находится в src / plugins / yajl / yajl_gen.c и src / plugins / yajl / yajl_parse.c

К счастью, @sanssecours написал отличный учебник, описывающий, как должны себя вести плагины хранилища (см. Doc / tutorials / storage-plugins.md). Таким образом, вы можете принять следующий выпуск № 2132 (№ 2477 может быть результатом этого) и другие проблемы, связанные с yajl. Вашей основной работой может быть проверка массивов в плагине yajl или, что еще лучше, в качестве внешнего плагина (см. № 1862).

Если я монтирую пустой документ json (то есть он содержит только {} ), при вызове kdb set system/lvas/cm/yajl "test" .
elektraYajlSet вызывается с KeySet, который имеет jus (system/lvas/cm/yajl,test) качестве значений.

При вызове elektraGenEmpty выполняется второе предложение, поскольку их размер KeySets равен 1.
Strcmp также завершается успешно, потому что parentKey имеет то же значение, что и последний ключ в Keyset.

Создается пустая карта, и elektraYajlSet завершается. Таким образом, функция получает значение, но ничего с ним не делает.

Итак, в тот момент, когда создается пустая карта, я мог бы добавить код, который выводит значение ключей в json-документ, как описано здесь @sanssecours .
Это сработает, поскольку kdb get правильно считывает это значение, а вызов типа kdb set system/lvas/cm/yajl/second "hi" создает документ json, подобный этому {"__dirdata": "test", "second": "hi"} , который отображает ключи должным образом.

Я думаю, что это решение сработает, но я бы нашел его более чистым, если бы я мог установить json-документ напрямую на {"__dirdata": "test"} , что было бы семантически одинаково.

Но я не знаю, как бы я это сделал. Я предполагаю, что правильным способом будет то, что плагин directoryvalue изменит набор ключей, который получает elektraYajlSet. Или я мог бы сам изменить KeySet в elektraYajlSet.

У вас есть предложения @ markus2330?

Да, значение каталога изменяет KeySet, который получает elektraYajlSet. Однако этого не происходит, если присутствует только parentKey (поскольку тогда он не считается «каталогом»). Поэтому, если вы установите только родительский ключ, как вы уже выяснили, будет выполнен elektraGenEmpty и strcmp удается.

Но у elektraGenEmpty есть некоторые предположения, которые теперь больше не верны (они были написаны до того, как существовало значение каталога). Так что есть и другие ошибки, например # 2132

Я думаю, что это решение сработает, но я бы нашел его более чистым, если бы я мог установить json-документ непосредственно на {"__dirdata": "test"}, что было бы семантически таким же.

Разве {"": "test"} бы минимальным документом, описывающим одно значение? Похоже, это тоже поведение плагина "camel".

@sanssecours Можете ли вы расширить руководство по хранению, чтобы также описать parentKeys и «пустые ключи» (%) (или, по крайней мере, пока что как TODO)?

Не могли бы вы расширить руководство по хранению, чтобы также описать parentKeys…

Я думаю, что руководство по

  • значение родительских ключей (путь к файлу) и
  • что родительские ключи используются для выдачи информации об ошибках и предупреждениях

. Я не знаю ничего особенного о родительских ключах.

и "пустые ключи" (%) (или хотя бы как TODO пока)?

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

Я мог бы добавить код, который выводит значение ключей в документ json, как описано здесь @sanssecours .

Я не уверен, что это правильный способ решения проблемы YAJL, поскольку для действительного документа JSON, похоже, всегда требуется массив или объект на верхнем уровне.

Я не знаю ничего особенного о родительских ключах.

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

«пустые ключи» (%)

Пустые ключи позволяют отображать такие документы, как {"root": {"": "something"}} . Как вы сопоставите это в настоящее время с KeySet?

Я не уверен, что это правильный способ решения проблемы YAJL, поскольку для действительного документа JSON, похоже, всегда требуется массив или объект на верхнем уровне.

Кажется, это изменилось: https://stackoverflow.com/questions/13318420/is-a-single-string-value-considered-valid-json

В https://www.ietf.org/rfc/rfc7159.txt есть даже примеры, показывающие, что разрешены "только значения". Но похоже, что yajl не поддерживает это ... (yajl 2.1.0-2 + ​​b3 выдает ошибку Expected “{” but found “"” )

С помощью функции из RFC 7159 мы могли сопоставить:

"some value" -> parent = "какое-то значение"
{"", "some value"} -> parent /% = "какое-то значение"

Но тогда нам нужно обойти yajl ... (журнал изменений также не указывает, что эта функция была добавлена ​​позже).

Пустые ключи позволяют отображать такие документы, как {"root": {"": "something"}}. Как вы сопоставите это в настоящее время с KeySet?

Похоже, что YAML CPP правильно обрабатывает эти данные:

kdb mount config.yaml user/tests/yaml yamlcpp
printf '{"root": {"": "something"}}' > "$(kdb file user/tests/yaml)"
kdb ls user/tests/yaml
#> user/tests/yaml/root/%
kdb get user/tests/yaml/root/%
#> something

. Однако я не адаптировал плагин для пустых ключей. Простого вызова setBaseName в подключаемом модуле хранилища с использованием правильного строкового значения ( "" ) должно быть достаточно для поддержки этой функции.

Приятно видеть, что это работает из коробки без особой обработки: +1:

@sanssecours Хотим ли мы теперь поддерживать RFC 7159? Что делают ваши плагины, если установлен только parentKey?

Хотим ли мы теперь поддерживать RFC 7159?

На мой взгляд, поддержка каждого типа данных на верхнем уровне имеет смысл.

Что делают ваши плагины, если установлен только parentKey?

Они просто хранят текст (без ключа):

kdb mount config.yaml user/tests/yaml yamlcpp
kdb set user/tests/yaml value
kdb file user/tests/yaml | xargs cat
#> value

.

Я добавил в этот коммит специальную обработку для верхнего уровня.
Это нарушает тест в модуле yajl, но прежде чем я уйду и потрачу время на исправление, я хотел сначала проверить, будет ли это приемлемым решением @ markus2330?

Просто чтобы уточнить: если размер KeySet равен 1, то я могу быть уверен, что в нем находится только ключ верхнего уровня. Затем я генерирую значение этого ключа. Но в этом случае я должен предотвратить вызов elektraGenOpenValue , потому что в противном случае он сгенерирует ключ в виде строки.

Похоже, что YAML CPP правильно обрабатывает эти данные:
...

Этот пример у меня работает с yajl. Я что-то пропустил?

Это нарушает тест в модуле yajl

Какой тест? (см. также ниже)

Я хотел сначала проверить, будет ли это приемлемым решением

Легче увидеть, является ли что-то приемлемым решением, если:

  • вы создали PR (который затем запустит все тестовые примеры)
  • опишите в тесте и с примерами, какое поведение вы хотите реализовать

Этот пример у меня работает с yajl. Я что-то пропустил?

Нет, этот пример демонстрирует только то, что {"", "some value"} не является идеальным способом представления значения parentKey.

Хотим ли мы теперь поддерживать RFC 7159?
На мой взгляд, поддержка каждого типа данных на верхнем уровне имеет смысл.

Я полностью согласен.

Они просто хранят текст (без ключа):

Так что давайте реализуем то же самое с yajl.

Теперь у меня работает отлично!

Была ли эта страница полезной?
0 / 5 - 0 рейтинги

Смежные вопросы

markus2330 picture markus2330  ·  4Комментарии

markus2330 picture markus2330  ·  4Комментарии

e1528532 picture e1528532  ·  4Комментарии

mpranj picture mpranj  ·  3Комментарии

sanssecours picture sanssecours  ·  4Комментарии