Jinja: lstrip_blocks ne conserve pas l'espace avant le bloc de fin sur la même ligne

Créé le 29 janv. 2020  ·  13Commentaires  ·  Source: pallets/jinja

Regardez le code de modèle suivant:

set_property verilog_define {
  {%- for k, v in vlogdefine.items() %}{{ k }}={{ v|param_value_str }} {% endfor -%}
  } [get_filesets sources_1]

https://github.com/olofk/edalize/blob/bdb6c9ccc666e9f60333279ad53ed09cda88b3dc/edalize/templates/vivado/vivado-project.tcl.j2#L27 -L29

Jusqu'à Jinja2 2.10.3 cela aboutirait à quelque chose comme

set_property verilog_define {vlogdefine_bool=1 vlogdefine_int=42 vlogdefine_str=hello } [get_filesets sources_1]

https://github.com/olofk/edalize/blob/bdb6c9ccc666e9f60333279ad53ed09cda88b3dc/tests/test_vivado/test_vivado_0.tcl#L10

Le code a lstrip_blocks = True .

Maintenant, avec la version 2.11.0, le code est rendu comme ceci:

set_property verilog_define {vlogdefine_bool=1vlogdefine_int=42vlogdefine_str=hello} [get_filesets sources_1]

@towoe a divisé en deux le changement de comportement jusqu'à https://github.com/pallets/jinja/commit/7d00a40465c89bee141ab5a3db545a20e7d30509 (par @ petee-d sur https://github.com/pallets/jinja/issues/857)

Selon la documentation

lstrip_blocks
Si ce paramètre est défini sur Vrai, les espaces de début et les tabulations sont supprimés du début d'une ligne vers un bloc. La valeur par défaut est False.

Je ne pense pas que l'espace blanc devrait être supprimé avant le endfor , car ce n'est pas un espace "depuis le début de la ligne". Suis-je mal compris ou la nouvelle version introduit-elle un changement de comportement inattendu?

Python 3.7.3 (mais se produit également sur 3.5 dans CI)

bug

Commentaire le plus utile

Je viens de publier 2.11.2 avec ça.

Tous les 13 commentaires

Je vais l'examiner, désolé pour la cause de cette session de débogage déroutante que vous avez liée! À première vue, il semble que le comportement est plus cohérent maintenant, et nous n'avons pas eu de test pour le comportement précédent, mais je vais devoir vérifier. Serait-il possible pour vous d'utiliser {%+ endfor -%} pour déclarer explicitement la préservation de l'espace blanc?

@davidism merci d'avoir jeté un coup d'œil.

Oui, nous pouvons apporter des modifications à edalize (la bibliothèque où Jinja est utilisé) de différentes manières (ajoutez le + , passez à lstrip_blocks = False , etc.), mais je voudrais d'abord m'assurer que nous avons une compréhension commune du comportement attendu.

Cela m'affecte également de la même manière que l'affiche originale. La documentation me semble assez claire que le comportement 2.11 est incorrect. Depuis https://github.com/pallets/jinja/blob/2.11.x/docs/templates.rst#whitespace -control:

(Rien ne sera supprimé s'il y a d'autres caractères avant le début du bloc.)

Cela est dû à # 858, qui a résolu un problème de vitesse assez important avec l'espace d'analyse. Je suis d'accord pour résoudre le problème qu'il a causé, mais je ne veux pas simplement annuler ce changement. Si quelqu'un veut jouer avec l'expression régulière dans le lexer et résoudre ce problème, je suis heureux de l'examiner.

Désolé pour le correctif cassant le comportement prévu de lstrip_blocks, je me souviens avoir été un peu confus sur ce qu'il est censé faire exactement et être incapable de trouver la documentation appropriée pour cela. Je ne sais pas pourquoi Google ne m'a pas amené à la partie de la @kenyon , très étrange. J'ai donc fini par comprendre le comportement prévu à partir des tests et de la mise en œuvre et j'ai apparemment manqué cela.

Comme @davidism l'a dit, l'

from jinja2 import Template

t = Template(
    "{% if x %}{{ x }} {% endif %}y",
    lstrip_blocks=True,
)
out = t.render(x="x")
assert out == "x y"

https://github.com/pallets/jinja/blob/547e6e39ec3994c9dd0c806ee7bb29353843060e/src/jinja2/lexer.py#L721 -L735

Voici le problème. Lorsque ce modèle est en cours de tokenisation, find("\n") reçoit un texte contenant uniquement l'espace entre {{ x }} et {% endif %} , ne voit pas de nouvelle ligne, puis supprime le début du texte.

Ajouter "\n" in text au elif fait échouer un tas de tests car la première ligne d'un modèle ne contient pas de nouvelle ligne mais devrait être supprimée si elle ne contient que de l'espace. Si nous devenons un peu plus intelligents et suivons si nous sommes sur la première ligne, cela échoue toujours si trim_blocks est également activé car cela supprime la nouvelle ligne dans le cadre de l'expression régulière.

Il semble également que le comportement de {%- raw %} {% endraw -%} soit affecté. Avant la version 2.11.0, cela forcera un espace à cet endroit. Maintenant, cet espace est supprimé.

from jinja2 import Template

t = Template(
    "{{x}}\n{%- raw %} {% endraw -%}\n{{ y }}",
    lstrip_blocks=True,
)
out = t.render(x="x", y="y")
assert out == "x y"

@ petee-d une chance que vous ayez le temps de revoir cela? Je vais le rétablir pour 2.11.2 sinon.

Aïe, j'ai totalement oublié ça. Je vais essayer de prendre le temps cette semaine, sinon le retourner si les effets secondaires sont aussi mauvais qu'il y paraît.

Mon plan provisoire est de sortir samedi. Faites-moi savoir si vous y travaillez, je peux repousser cela si oui.

Je pense que j'ai une solution. J'ai essayé de ne pas être influencé dans mon correctif par vos précédents commentaires @davidism et pourtant

Tout d'abord, je pense que j'avais initialement prévu que mon correctif se comporte différemment si l_pos = text.rfind("\n") + 1 ne trouve aucun caractère de nouvelle ligne mais l'oublie. Donc je ne fais plus le stripping s'il n'y a pas de nouvelle ligne dans text . Ensuite, j'ai également essayé de résoudre le problème avec la première ligne source devant être supprimée de toute façon, mais au lieu d'utiliser or pos == 0 , j'ai utilisé un drapeau booléen line_starting initialisé à True. Ensuite, je viens de définir cet indicateur après le traitement de chaque jeton en fonction du fait que la chaîne correspondante se termine par une nouvelle ligne et cela résout également le problème trim_blocks. Voir le correctif dans # 1183.

La suite de tests actuelle réussit, demain j'ajouterai également de nouveaux tests pour les cas de ce numéro et d'autres auxquels je peux penser. Je vais également exécuter la version originale, le premier correctif et le deuxième correctif concernant mon ensemble de 5 Go fraîchement collecté de modèles créés par l'utilisateur que j'ai collectés à partir de mon projet, comparer les arbres d'analyse et les performances.

Tests ajoutés, les tests de performance n'ont montré aucune dégradation, donc c'est fait de mon côté. :)

Je viens de publier 2.11.2 avec ça.

Cette page vous a été utile?
0 / 5 - 0 notes