Hi Massimo,
Thank you for py4web — I've been using it for a teaching project that helps developers transition from ASP Classic to Python web development. The framework's simplicity and "batteries included" approach have been a great fit for this audience.
I wanted to bring to your attention a bug in the Renoir templating engine (v1.9.0, bundled with py4web) that affects py4web users in a particularly painful way.
The Problem
When a single [[ ]] block contains a nested if statement, the template fails with:
TemplateError: missing "pass" in view
Example that triggers the bug:
[[
x = 1
if x:
y = 2
if y:
pass
]]
<p>Hello</p>
Single-level if inside [[ ]] works fine. Cross-block [[if:]]...[[pass]] also works fine. It's only nested if inside a single [[ ]] block that breaks.
Why This Hits py4web Users Hard
There are two compounding issues:
1. The error message is almost useless for debugging
reindent() raises TemplateError('missing "pass" in view', self.name, 1) — the 1 is a hardcoded line number, not the actual location of the problem. When this error hits in py4web, all the user sees is a ticket page with no useful information about which template, which line, or what went wrong.
For developers learning py4web (especially those coming from ASP Classic, where <% %> blocks with nested logic are normal), this error is extremely confusing. The template looks syntactically correct, the error message points to the wrong line, and there's no indication that the issue is with block nesting.
2. The recommended cross-block style is a non-obvious paradigm shift
In ASP Classic, developers routinely write:
<%
If x Then
If y Then
' do something
End If
End If
%>
The natural translation to py4web would be a single [[ ]] block with nested if, which silently fails. The "correct" cross-block style ([[if x:]]...[[if y:]]...[[pass]][[pass]]) is a fundamental paradigm difference that isn't obvious from the error message.
What I've Done
I've traced the root cause to TemplateParser.reindent() in Renoir's renoir/parsing/parsers.py. The method uses a simple counter to track indentation levels (: → +1, pass → -1), but it has no awareness of [[ ]] block boundaries. When a block ends with an unclosed if, the ]] delimiter acts as an implicit pass that the counter can't see.
I've filed an issue on the Renoir repository with a full root cause analysis and fix suggestions:
emmett-framework/renoir#10
Suggestion for py4web
Even if the upstream fix takes time, there are two things that could significantly improve the experience for py4web users:
-
Better error messages: Even a simple change like including the reindented code in the error output, or reporting the actual line where the indent counter went out of sync, would save users hours of debugging.
-
Documentation note: A brief mention in the py4web templating docs that nested if inside a single [[ ]] block is not supported (and will produce a confusing error) would help newcomers avoid this trap entirely.
Thank you for your time, and for building such an approachable framework. I'm happy to help with testing or documentation if needed.
Best regards,
Jeffrey
Hi Massimo,
Thank you for py4web — I've been using it for a teaching project that helps developers transition from ASP Classic to Python web development. The framework's simplicity and "batteries included" approach have been a great fit for this audience.
I wanted to bring to your attention a bug in the Renoir templating engine (v1.9.0, bundled with py4web) that affects py4web users in a particularly painful way.
The Problem
When a single
[[ ]]block contains a nestedifstatement, the template fails with:Example that triggers the bug:
[[ x = 1 if x: y = 2 if y: pass ]] <p>Hello</p>Single-level
ifinside[[ ]]works fine. Cross-block[[if:]]...[[pass]]also works fine. It's only nestedifinside a single[[ ]]block that breaks.Why This Hits py4web Users Hard
There are two compounding issues:
1. The error message is almost useless for debugging
reindent()raisesTemplateError('missing "pass" in view', self.name, 1)— the1is a hardcoded line number, not the actual location of the problem. When this error hits in py4web, all the user sees is a ticket page with no useful information about which template, which line, or what went wrong.For developers learning py4web (especially those coming from ASP Classic, where
<% %>blocks with nested logic are normal), this error is extremely confusing. The template looks syntactically correct, the error message points to the wrong line, and there's no indication that the issue is with block nesting.2. The recommended cross-block style is a non-obvious paradigm shift
In ASP Classic, developers routinely write:
The natural translation to py4web would be a single
[[ ]]block with nestedif, which silently fails. The "correct" cross-block style ([[if x:]]...[[if y:]]...[[pass]][[pass]]) is a fundamental paradigm difference that isn't obvious from the error message.What I've Done
I've traced the root cause to
TemplateParser.reindent()in Renoir'srenoir/parsing/parsers.py. The method uses a simple counter to track indentation levels (:→ +1,pass→ -1), but it has no awareness of[[ ]]block boundaries. When a block ends with an unclosedif, the]]delimiter acts as an implicitpassthat the counter can't see.I've filed an issue on the Renoir repository with a full root cause analysis and fix suggestions:
emmett-framework/renoir#10
Suggestion for py4web
Even if the upstream fix takes time, there are two things that could significantly improve the experience for py4web users:
Better error messages: Even a simple change like including the reindented code in the error output, or reporting the actual line where the indent counter went out of sync, would save users hours of debugging.
Documentation note: A brief mention in the py4web templating docs that nested
ifinside a single[[ ]]block is not supported (and will produce a confusing error) would help newcomers avoid this trap entirely.Thank you for your time, and for building such an approachable framework. I'm happy to help with testing or documentation if needed.
Best regards,
Jeffrey