Jinja: لا تحتفظ lstrip_blocks بمساحة قبل نهاية الكتلة على نفس السطر

تم إنشاؤها على ٢٩ يناير ٢٠٢٠  ·  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 (بواسطة @ petee-d في https://github.com/pallets/jinja/issues/857)

حسب الوثائق

lstrip_blocks
إذا تم تعيين هذا على True المسافات البادئة وعلامات التبويب يتم تجريدها من بداية سطر إلى كتلة. افتراضات على False.

لا أعتقد أنه يجب إزالة المسافة البيضاء قبل endfor ، حيث إنها ليست مسافة بيضاء "من بداية السطر". هل أنا أسيء فهم ذلك ، أم أن الإصدار الجديد يقدم تغييرًا غير متوقع في السلوك؟

Python 3.7.3 (ولكن يحدث أيضًا على 3.5 في CI)

bug

التعليق الأكثر فائدة

صدر للتو 2.11.2 مع هذا.

ال 13 كومينتر

سأبحث في الأمر ، آسف للتسبب في جلسة التصحيح المربكة التي ربطتها! للوهلة الأولى ، يبدو أن السلوك أكثر اتساقًا الآن ، ولم يكن لدينا اختبار للسلوك السابق ، لكن علي التحقق. هل من الممكن أن تستخدم {%+ endfor -%} للإعلان صراحة عن الاحتفاظ بالمسافة البيضاء؟

davidism شكرا لإلقاء نظرة.

نعم ، يمكننا إجراء تغييرات على Edalize (المكتبة التي تستخدم فيها Jinja) بعدة طرق (أضف + ، قم بالتبديل إلى lstrip_blocks = False ، وما إلى ذلك) ، لكن أود التأكد أولاً أن لدينا فهم مشترك للسلوك المتوقع.

هذا يؤثر علي أيضًا بنفس طريقة الملصق الأصلي. يبدو أن التوثيق واضح جدًا بالنسبة لي أن السلوك 2.11 خطأ. من https://github.com/pallets/jinja/blob/2.11.x/docs/templates.rst#whitespace -control:

(لن يتم تجريد أي شيء إذا كانت هناك أحرف أخرى قبل بدء الكتلة.)

هذا بسبب # 858 ، الذي أصلح مشكلة سرعة كبيرة جدًا تتعلق بتحليل المساحة. أنا بخير لإصلاح هذه المشكلة التي تسببت فيها ، لكنني لا أريد التراجع عن هذا التغيير فقط. إذا أراد أي شخص اللعب مع regex في lexer وإصلاح هذا ، فأنا سعيد بمراجعته.

آسف بشأن الإصلاح الذي كسر السلوك المقصود لـ lstrip_blocks ، أتذكر أنني كنت مرتبكًا بعض الشيء بشأن ما يفترض القيام به بالضبط وعدم تمكني من العثور على الوثائق المناسبة لذلك. لست متأكدًا من سبب عدم اصطحابي لـ Google إلى جزء المستندات

كما قال 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 text إلى elif إلى فشل مجموعة من الاختبارات لأن السطر الأول من القالب لا يحتوي على سطر جديد ولكن يجب تجريده إذا كان به مساحة فقط. إذا أصبحنا أكثر ذكاءً قليلاً وتتبعنا ما إذا كنا في السطر الأول ، فسيظل فشلًا إذا تم أيضًا تمكين trim_blocks لأن هذا يقطع السطر الجديد كجزء من regex.

يبدو أيضًا أن سلوك {%- 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 وإلا.

أوه ، نسيت ذلك تمامًا. سنحاول تحديد الوقت بالفعل هذا الأسبوع ، وإلا يمكنك الرجوع إليه إذا كانت الآثار الجانبية سيئة كما تبدو.

خطتي المبدئية هي إطلاق سراح يوم السبت. اسمحوا لي أن أعرف إذا كنت تعمل على ذلك ، يمكنني دفع ذلك للوراء إذا كان الأمر كذلك.

أعتقد أن لدي إصلاح. حاولت ألا أتأثر في إصلاحي بتعليقاتك السابقة

بادئ ذي بدء ، أعتقد أنني قصدت في الأصل أن يتصرف الإصلاح بشكل مختلف إذا لم يعثر l_pos = text.rfind("\n") + 1 على أي حرف جديد ثم نسيته. لذلك لم أعد أقوم بالتجريد إذا لم يكن هناك سطر جديد في text . ثم حاولت أيضًا حل المشكلة مع السطر الأول source الذي يحتاج إلى تجريده على أي حال ، ولكن بدلاً من استخدام or pos == 0 ، استخدمت علامة منطقية line_starting عند True. ثم قمت فقط بتعيين هذه العلامة بعد معالجة كل رمز مميز بناءً على ما إذا كانت السلسلة المطابقة تنتهي بسطر جديد كما أنها تحل مشكلة trim_blocks. انظر الإصلاح في # 1183.

تم اجتياز مجموعة الاختبار الحالية ، وسأضيف غدًا أيضًا اختبارات جديدة للحالات في هذه المشكلة وغيرها من الحالات التي يمكنني التفكير فيها. سأقوم أيضًا بتشغيل الإصدار الأصلي والإصلاح الأول والإصلاح الثاني حول مجموعة القوالب التي تم جمعها حديثًا والتي يبلغ حجمها 5 غيغابايت والتي قام المستخدم بجمعها من مشروعي ، ومقارنة أشجار التحليل والأداء.

تمت إضافة الاختبارات ، لم تظهر اختبارات الأداء أي تدهور ، لذلك تم إجراؤها من جانبي. :)

صدر للتو 2.11.2 مع هذا.

هل كانت هذه الصفحة مفيدة؟
0 / 5 - 0 التقييمات