Skip to content

Commit

Permalink
Revert "Support passing custom filters with the same name as built-in…
Browse files Browse the repository at this point in the history
… flags"

Reverted the fix for 🎫`140` released in Mako 1.3.7 as it produced
regressions in existing user code.

This reverts commit f37777c.

Fixes: #415
Change-Id: I0fe9735828fd56bccae3d48bcc5a12b6de4aac40
  • Loading branch information
zzzeek committed Dec 7, 2024
1 parent fbfb812 commit 4e2de73
Show file tree
Hide file tree
Showing 9 changed files with 48 additions and 117 deletions.
2 changes: 1 addition & 1 deletion doc/build/changelog.rst
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ Changelog
:include_notes_from: unreleased

.. changelog::
:version: 1.3.7
:version: 1.3.7 (yanked)
:released: Tue Dec 3 2024

.. change::
Expand Down
7 changes: 7 additions & 0 deletions doc/build/unreleased/415.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
.. change::
:tags: bug, lexer
:tickets: 415, 140

Reverted the fix for :ticket:`140` released in Mako 1.3.7 as it produced
regressions in existing user code.

44 changes: 9 additions & 35 deletions mako/codegen.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@
from mako import filters
from mako import parsetree
from mako import util
from mako.filters import DEFAULT_ESCAPE_PREFIX
from mako.pygen import PythonPrinter


Expand All @@ -27,7 +26,6 @@
# context itself
TOPLEVEL_DECLARED = {"UNDEFINED", "STOP_RENDERING"}
RESERVED_NAMES = {"context", "loop"}.union(TOPLEVEL_DECLARED)
DEFAULT_ESCAPED_N = "%sn" % DEFAULT_ESCAPE_PREFIX


def compile( # noqa
Expand Down Expand Up @@ -524,7 +522,6 @@ def write_variable_declares(self, identifiers, toplevel=False, limit=None):
self.printer.writeline("loop = __M_loop = runtime.LoopStack()")

for ident in to_write:
ident = ident.replace(DEFAULT_ESCAPE_PREFIX, "")
if ident in comp_idents:
comp = comp_idents[ident]
if comp.is_block:
Expand Down Expand Up @@ -788,48 +785,25 @@ def locate_encode(name):
else:
return filters.DEFAULT_ESCAPES.get(name, name)

filter_args = set()
if DEFAULT_ESCAPED_N not in args:
if "n" not in args:
if is_expression:
if self.compiler.pagetag:
args = self.compiler.pagetag.filter_args.args + args
filter_args = set(self.compiler.pagetag.filter_args.args)
if (
self.compiler.default_filters
and DEFAULT_ESCAPED_N not in args
):
if self.compiler.default_filters and "n" not in args:
args = self.compiler.default_filters + args
for e in args:
if e == DEFAULT_ESCAPED_N:
continue

if e.startswith(DEFAULT_ESCAPE_PREFIX):
render_e = e.replace(DEFAULT_ESCAPE_PREFIX, "")
is_default_filter = True
else:
render_e = e
is_default_filter = False

# if filter given as a function, get just the identifier portion
if e == "n":
continue
m = re.match(r"(.+?)(\(.*\))", e)
if m:
if not is_default_filter:
ident, fargs = m.group(1, 2)
f = locate_encode(ident)
render_e = f + fargs
target = "%s(%s)" % (render_e, target)
elif is_default_filter and e not in filter_args:
target = "%s(%s) if %s is not UNDEFINED else %s(%s)" % (
render_e,
target,
render_e,
locate_encode(render_e),
target,
)
ident, fargs = m.group(1, 2)
f = locate_encode(ident)
e = f + fargs
else:
e = locate_encode(render_e)
e = locate_encode(e)
assert e is not None
target = "%s(%s)" % (e, target)
target = "%s(%s)" % (e, target)
return target

def visitExpression(self, node):
Expand Down
3 changes: 0 additions & 3 deletions mako/filters.py
Original file line number Diff line number Diff line change
Expand Up @@ -161,6 +161,3 @@ def htmlentityreplace_errors(ex):
"str": "str",
"n": "n",
}


DEFAULT_ESCAPE_PREFIX = "__DEFAULT_ESCAPE_"
21 changes: 2 additions & 19 deletions mako/pyparser.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,6 @@
from mako import compat
from mako import exceptions
from mako import util
from mako.filters import DEFAULT_ESCAPE_PREFIX
from mako.filters import DEFAULT_ESCAPES

# words that cannot be assigned to (notably
# smaller than the total keys in __builtins__)
Expand Down Expand Up @@ -198,24 +196,9 @@ def visit_Tuple(self, node):
p.declared_identifiers
)
lui = self.listener.undeclared_identifiers
undeclared_identifiers = lui.union(p.undeclared_identifiers)
conflict_identifiers = undeclared_identifiers.intersection(
DEFAULT_ESCAPES
self.listener.undeclared_identifiers = lui.union(
p.undeclared_identifiers
)
if conflict_identifiers:
_map = {
i: DEFAULT_ESCAPE_PREFIX + i for i in conflict_identifiers
}
for i, arg in enumerate(self.listener.args):
if arg in _map:
self.listener.args[i] = _map[arg]
self.listener.undeclared_identifiers = (
undeclared_identifiers.symmetric_difference(
conflict_identifiers
).union(_map.values())
)
else:
self.listener.undeclared_identifiers = undeclared_identifiers


class ParseFunc(_ast_util.NodeVisitor):
Expand Down
30 changes: 5 additions & 25 deletions test/test_ast.py
Original file line number Diff line number Diff line change
Expand Up @@ -285,36 +285,16 @@ def test_python_fragment(self):

def test_argument_list(self):
parsed = ast.ArgumentList(
"3, 5, 'hi', g+5, " "context.get('lala')", **exception_kwargs
"3, 5, 'hi', x+5, " "context.get('lala')", **exception_kwargs
)
eq_(parsed.undeclared_identifiers, {"g", "context"})
eq_(parsed.undeclared_identifiers, {"x", "context"})
eq_(
[x for x in parsed.args],
["3", "5", "'hi'", "(g + 5)", "context.get('lala')"],
["3", "5", "'hi'", "(x + 5)", "context.get('lala')"],
)

parsed = ast.ArgumentList("m", **exception_kwargs)
eq_(parsed.args, ["m"])

def test_conflict_argument_list(self):
parsed = ast.ArgumentList(
"x-2, h*2, '(u)', n+5, trim, entity, unicode, decode, str, other",
**exception_kwargs,
)
eq_(
parsed.undeclared_identifiers,
{
"__DEFAULT_ESCAPE_trim",
"__DEFAULT_ESCAPE_h",
"__DEFAULT_ESCAPE_decode",
"__DEFAULT_ESCAPE_unicode",
"__DEFAULT_ESCAPE_x",
"__DEFAULT_ESCAPE_str",
"__DEFAULT_ESCAPE_entity",
"__DEFAULT_ESCAPE_n",
"other",
},
)
parsed = ast.ArgumentList("h", **exception_kwargs)
eq_(parsed.args, ["h"])

def test_function_decl(self):
"""test getting the arguments from a function"""
Expand Down
33 changes: 0 additions & 33 deletions test/test_filters.py
Original file line number Diff line number Diff line change
Expand Up @@ -453,36 +453,3 @@ def test_capture_ccall(self):

# print t.render()
assert flatten_result(t.render()) == "this is foo. body: ccall body"

def test_conflict_filter_ident(self):
class h(object):
foo = str

t = Template(
"""
X:
${"asdf" | h.foo}
"""
)
assert flatten_result(t.render(h=h)) == "X: asdf"

def h(i):
return str(i) + "1"

t = Template(
"""
${123 | h}
"""
)
assert flatten_result(t.render()) == "123"
assert flatten_result(t.render(h=h)) == "1231"

t = Template(
"""
<%def name="foo()" filter="h">
this is foo</%def>
${foo()}
"""
)
assert flatten_result(t.render()) == "this is foo"
assert flatten_result(t.render(h=h)) == "this is foo1"
2 changes: 1 addition & 1 deletion test/test_lexer.py
Original file line number Diff line number Diff line change
Expand Up @@ -1543,7 +1543,7 @@ def test_integration(self):
Text(" <tr>\n", (14, 1)),
ControlLine("for", "for x in j:", False, (15, 1)),
Text(" <td>Hello ", (16, 1)),
Expression("x", ["__DEFAULT_ESCAPE_h"], (16, 23)),
Expression("x", ["h"], (16, 23)),
Text("</td>\n", (16, 30)),
ControlLine("for", "endfor", True, (17, 1)),
Text(" </tr>\n", (18, 1)),
Expand Down
23 changes: 23 additions & 0 deletions test/test_template.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
import os

import pytest

from mako import exceptions
from mako import runtime
from mako import util
Expand Down Expand Up @@ -722,6 +724,27 @@ def handle(context, error):


class UndefinedVarsTest(TemplateTest):
@pytest.mark.parametrize(
"filters",
[
["str", "n"],
["n"],
["str", "h"],
["h"],
[],
],
)
def test_140_regression(self, filters):
"""test #415, regression on #140"""

t1 = Template(
"hello world ${x}",
strict_undefined=True,
default_filters=filters,
)

t1.render_unicode(x="hi")

def test_undefined(self):
t = Template(
"""
Expand Down

0 comments on commit 4e2de73

Please sign in to comment.