Jinja: lstrip_blocksは、同じ行の終了ブロックの前のスペースを保持しません

作成日 2020年01月29日  ·  13コメント  ·  ソース: pallets/jinja

次のテンプレートコードを見てください。

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

Jinja2 2.10.3までは、これは次のような結果になります。

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

コードにlstrip_blocks = Trueます。

2.11.0では、コードは次のようにレンダリングされます。

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

@towoeは、動作の変更をhttps://github.com/pallets/jinja/commit/7d00a40465c89bee141ab5a3db545a20e7d30509に二分しました(

ドキュメントによると

lstrip_blocks
これがTrueに設定されている場合、先頭のスペースとタブは行の先頭からブロックまで削除されます。 デフォルトはFalseです。

endfor前に空白を削除する必要はないと思います。これは、「行の先頭から」の空白ではないためです。 私はそれを誤解していますか、それとも新しいバージョンは予期しない動作の変化をもたらしますか?

Python 3.7.3(ただし、CIの3.5でも発生します)

bug

最も参考になるコメント

これで2.11.2をリリースしました。

全てのコメント13件

あなたがリンクしたその混乱したデバッグセッションを引き起こしてすみません、私はそれを調べます! 一見すると、動作はより一貫しているように見え、以前の動作のテストはありませんでしたが、確認する必要があります。 {%+ endfor -%}を使用して、空白の保持を明示的に宣言することは可能ですか?

@davidismご覧いただきありがとう

はい、私たちはさまざまな方法でedalizeへの変更(神社が使用されているライブラリー)(追加することができます+に、スイッチをlstrip_blocks = Falseなど)が、私は最初に好きなことを確認したいです期待される行動についての共通の理解があること。

これも元のポスターと同じように私に影響を与えます。 ドキュメントは、2.11の動作が間違っていることを私にはかなり明確に思われます。 https://github.com/pallets/jinja/blob/2.11.x/docs/templates.rst#whitespace -controlから:

(ブロックの開始前に他の文字がある場合、何も削除されません。)

これは、スペースの解析に関するかなり大きな速度の問題を修正した#858によ​​るものです。 私はそれが引き起こしたこの問題を修正することに問題はありませんが、私はその変更を単に元に戻したくありません。 レクサーの正規表現をいじって修正したい人がいたら、喜んでレビューします。

lstrip_blocksの意図された動作を壊す修正について申し訳ありませんが、正確に何をすべきかについて少し混乱し、適切なドキュメントを見つけることができなかったことを覚えています。 Googleが@kenyonにリンクされているドキュメントの部分に私を連れて行かなかった理由が

@davidismが言ったように、修正を元に戻すと他の問題が発生するため、新しい修正を考案する必要があります。 今週はその時間を作ってみます。

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

これが問題です。 このテンプレートがトークン化されると、 find("\n")は、 {{ x }}{% endif %}間のスペースのみを含むテキストを渡され、改行が表示されず、テキストの先頭から削除されます。

"\n" in textelif追加すると、テンプレートの最初の行に改行が含まれていないため、一連のテストが失敗しますが、スペースしかない場合は削除する必要があります。 少し賢くなり、最初の行にいるかどうかを追跡する場合、 trim_blocksも有効にすると、正規表現の一部として改行が削除されるため、失敗します。

また、 {%- raw %} {% endraw -%}も影響を受けているようです。 2.11.0より前では、これによりこの場所にスペースが強制されます。 これで、このスペースは削除されます。

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もう一度これを見る時間がありますか? それ以外の場合は、2.11.2に戻します。

痛い、これを完全に忘れてしまった。 今週は実際に時間を作ってみますが、副作用が思ったほどひどい場合は元に戻します。

私の暫定的な計画は土曜日にリリースすることです。 あなたがそれに取り組んでいるなら私に知らせてください、もしそうなら私はそれを押し戻すことができます。

修正があると思います。 私はあなたの以前のコメント@davidismによって私の修正に影響されないように努めましたが、それでもあなたが試したのと同じ解決策に

まず、 l_pos = text.rfind("\n") + 1改行文字が見つからなかったが、それを忘れた場合に、修正の動作が異なるように意図していたと思います。 したがって、 text改行がない場合は、ストリッピングを実行しなくなります。 次に、 source最初の行を削除する必要があるという問題も解決しようとしましたが、 or pos == 0を使用する代わりに、Trueで初期化されたline_startingブールフラグを使用しました。 次に、一致する文字列が改行で終わるかどうかに基づいて各トークンを処理した後、このフラグを設定します。これにより、trim_blocksの問題も解決されます。 #1183の修正を参照してください。

現在のテストスイートは合格です。明日は、この号やその他の考えられるケースの新しいテストも追加します。 また、元のバージョン、最初の修正、およびプロジェクトから収集した新しく収集した5 GBのユーザー作成テンプレートのセットに関する2番目の修正を実行し、解析ツリーとパフォーマンスを比較します。

テストが追加され、パフォーマンステストでは劣化が見られなかったので、私の側から行いました。 :)

これで2.11.2をリリースしました。

このページは役に立ちましたか?
0 / 5 - 0 評価