Libelektra: YAJL: o plug-in não salva valor diretamente abaixo do ponto de montagem

Criado em 27 jul. 2018  ·  17Comentários  ·  Fonte: ElektraInitiative/libelektra

Etapas para reproduzir o problema

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 

resultado esperado

O último comando deve imprimir o texto This May Be the Year I Disappear .

Resultado atual

O último comando imprime uma linha vazia.

Informação do sistema

  • Versão Elektra: mestre
  • SO: macOS 10.13.6
bug good first issue usability

Todos 17 comentários

Obrigado por relatar o problema!

Como seria esse documento JSON? Também precisamos de documentação para a semântica especial de arquivos de configuração contendo apenas a chave pai.

Como seria esse documento JSON?

O documento conteria apenas uma string neste caso:

"This May Be the Year I Disappear"

. O plugin já lê o valor correto, se eu substituir o arquivo de configuração pelo conteúdo acima:

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

.

Portanto, apenas o conjunto precisa ser corrigido? Isso parece muito fácil!

Portanto, apenas o conjunto precisa ser corrigido?

Pelo que eu posso dizer, sim.

Acho que posso considerar isso como meu primeiro problema. Você pode me dar algumas dicas de onde devo começar a procurar @ markus2330? Obrigado.

A fonte está em src / plugins / yajl / yajl_gen.c e src / plugins / yajl / yajl_parse.c

Felizmente, @sanssecours escreveu um excelente tutorial que descreve como os plug-ins de armazenamento devem se comportar (consulte doc / tutorials / storage-plugins.md). Portanto, você poderia considerar a próxima edição # 2132 (# 2477 talvez seja o resultado disso) e outros problemas relacionados ao yajl. Seu trabalho principal pode ser a validação de arrays no plugin yajl ou - melhor ainda - como plugin externo (veja # 1862).

Se eu montar um documento json vazio (o que significa que contém apenas {} ), o seguinte acontece quando chamo kdb set system/lvas/cm/yajl "test" .
elektraYajlSet é chamado com um KeySet que tem apenas (system/lvas/cm/yajl,test) como valores.

Na chamada a elektraGenEmpty a segunda cláusula é executada, pois o tamanho do KeySets é 1.
O strcmp também é bem-sucedido porque parentKey tem o mesmo valor que a última chave do conjunto de chaves.

Um mapa vazio é gerado e elektraYajlSet termina. Portanto, a função recebe o valor, mas não faz nada com ele.

Então, naquele ponto onde o mapa vazio é gerado, eu poderia adicionar o código que produz o valor das chaves em um documento json, conforme descrito por @sanssecours aqui .
Isso funcionaria, uma vez que kdb get lê esse valor corretamente e uma chamada como kdb set system/lvas/cm/yajl/second "hi" produz um documento json como este {"__dirdata": "test", "second": "hi"} , que mapeia as chaves conforme o esperado.

Acho que essa solução funcionaria, mas seria mais limpa se pudesse definir o documento json diretamente para {"__dirdata": "test"} , o que seria o mesmo semanticamente.

Mas não tenho certeza de como faria isso. Eu suponho que a maneira correta seria que o plugin directoryvalue modificaria o Keyset que elektraYajlSet recebe. Ou acho que poderia modificar o KeySet sozinho em elektraYajlSet.

Você tem uma sugestão @ markus2330?

Sim, o valor do diretório modifica o KeySet que elektraYajlSet recebe. Isso não acontece, no entanto, se apenas a parentKey estiver presente (já que não é considerada um "diretório"). Portanto, se você definir apenas a chave pai, como já descobriu, elektraGenEmpty será executado e o strcmp tem sucesso.

Mas elektraGenEmpty tem algumas suposições que agora não são mais verdadeiras (ele foi escrito antes que o valor do diretório existisse). Outros bugs estão lá, por exemplo, # 2132

Acho que essa solução funcionaria, mas seria mais limpa se pudesse definir o documento json diretamente para {"__dirdata": "test"}, que seria o mesmo semanticamente.

{"": "test"} seria o documento mínimo que descreve um único valor? Este também parece ser o comportamento do plugin "camel".

@sanssecours Você pode estender o tutorial de armazenamento para também descrever parentKeys e "chaves vazias" (%) (ou pelo menos como TODO por agora)?

Você pode estender o tutorial de armazenamento para também descrever parentKeys ...

Acho que o tutorial do

  • o valor das chaves pai (caminho de arquivo), e
  • que as chaves pai são usadas para emitir informações de erro e aviso

. Não sei mais nada de especial sobre as chaves dos pais.

e "chaves vazias" (%) (ou pelo menos como TODO por agora)?

Como esta é a primeira vez que ouço falar de chaves vazias, não acho que seja a pessoa certa para fazer isso.

Eu poderia adicionar o código que gera o valor das chaves em um documento json, conforme descrito por @sanssecours aqui .

Não tenho mais certeza de que essa seja a maneira correta de YAJL lidar com o problema, já que um documento JSON válido parece sempre exigir uma matriz ou objeto no nível superior.

Não sei mais nada de especial sobre as chaves dos pais.

Também não há nada de especial nisso, exceto que alguns formatos de arquivo de configuração não têm uma maneira de simplesmente descrever um valor sem uma chave.

"chaves vazias" (%)

Teclas vazias permitem mapear documentos como {"root": {"": "something"}} . Como você mapeia isso atualmente para um KeySet?

Não tenho mais certeza de que essa seja a maneira correta de YAJL lidar com o problema, já que um documento JSON válido parece sempre exigir uma matriz ou objeto no nível superior.

Isso parece ter mudado: https://stackoverflow.com/questions/13318420/is-a-single-string-value-considered-valid-json

Em https://www.ietf.org/rfc/rfc7159.txt, existem até exemplos que mostram que "apenas valores" são permitidos. Mas parece que yajl não suporta isso ... (yajl 2.1.0-2 + ​​b3 retorna o erro Expected “{” but found “"” )

Com o recurso da RFC 7159, podemos mapear:

"some value" -> parent = "algum valor"
{"", "some value"} -> parent /% = "algum valor"

Mas precisaríamos contornar yajl então ... (o ChangeLog também não indica que esse recurso foi adicionado posteriormente).

As teclas vazias permitem mapear documentos como {"root": {"": "something"}}. Como você mapeia isso atualmente para um KeySet?

Parece que YAML CPP lida com esses dados corretamente:

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

. Eu não adaptei o plugin para chaves vazias. Apenas chamar setBaseName em um plugin de armazenamento, usando o valor de string correto ( "" ), deve ser o suficiente para oferecer suporte a esse recurso.

É bom ver que isso funciona fora da caixa, sem tratamento especial: +1:

@sanssecours Queremos agora oferecer suporte ao RFC 7159? O que seus plug-ins fazem se apenas parentKey estiver definido?

Queremos oferecer suporte ao RFC 7159?

Na minha opinião, o suporte a todos os tipos de dados no nível superior faz sentido.

O que seus plug-ins fazem se apenas parentKey estiver definido?

Eles apenas armazenam o texto (sem a chave):

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

.

Eu adicionei tratamento especial para o nível superior neste commit .
Isso interrompe um teste no módulo yajl, mas antes de passar algum tempo consertando o que eu queria verificar primeiro, seria uma solução aceitável @ markus2330?

Apenas para elaborar um pouco: se o tamanho do KeySet for 1, então posso ter certeza de que apenas a chave de nível superior está nele. Então eu gero o valor dessa chave. Mas, nesse caso, tenho que evitar que elektraGenOpenValue seja chamado, porque, de outra forma, geraria a chave como uma string.

Parece que YAML CPP lida com esses dados corretamente:
...

Este exemplo funciona para mim com yajl. Estou esquecendo de algo?

Isso quebra um teste no módulo yajl

Qual teste? (veja também abaixo)

Eu queria verificar primeiro, se isso seria uma solução aceitável

É mais fácil ver se algo é uma solução aceitável se:

  • você criou um PR (que executará todos os casos de teste)
  • descreva em um teste e com exemplos qual comportamento você deseja implementar agora

Este exemplo funciona para mim com yajl. Estou esquecendo de algo?

Não, este exemplo apenas demonstra que {"", "some value"} não é uma forma ideal de representar o valor de parentKey.

Queremos oferecer suporte ao RFC 7159?
Na minha opinião, o suporte a todos os tipos de dados no nível superior faz sentido.

Eu concordo plenamente.

Eles apenas armazenam o texto (sem a chave):

Então, vamos implementar o mesmo com yajl.

Funciona perfeitamente para mim agora!

Esta página foi útil?
0 / 5 - 0 avaliações

Questões relacionadas

e1528532 picture e1528532  ·  4Comentários

markus2330 picture markus2330  ·  4Comentários

dmoisej picture dmoisej  ·  3Comentários

sanssecours picture sanssecours  ·  4Comentários

mpranj picture mpranj  ·  4Comentários