Skip to content

Commit

Permalink
improve unsolicited translation avoidance (#879)
Browse files Browse the repository at this point in the history
* improve unsolicited translation avoidance

* keep `Token` in exceptions for better error reports

* handle PY2 as well (even though no problems have been observed yet)

* - fix lint issue by defining unicode

* explain why the `Token` casting is safe

Co-authored-by: Jens Vagelpohl <jens@netz.ooo>
  • Loading branch information
d-maurer and dataflake committed Jul 23, 2020
1 parent 0a4c07b commit a5cb4c7
Showing 1 changed file with 13 additions and 8 deletions.
21 changes: 13 additions & 8 deletions src/Products/PageTemplates/engine.py
Expand Up @@ -41,6 +41,10 @@
from .interfaces import IZopeAwareEngine


if six.PY3:
unicode = str


class _PseudoContext(object):
"""auxiliary context object.
Expand Down Expand Up @@ -136,13 +140,6 @@ def _compile_zt_expr(type, expression, engine=None, econtext=None):
"""
if engine is None:
engine = econtext["__zt_engine__"]
# *expression* is a ``chameleon.tokenize.Token`` when
# the template is compiled but "text" when the template code
# comes from the ``chameleon`` cache.
# Under PY3, ``chameleon`` wrongly translates ``Token``;
# convert to ``str`` to avoid this
if six.PY3:
expression = str(expression)
key = id(engine), type, expression
# cache lookup does not need to be protected by locking
# (but we could potentially prevent unnecessary computations)
Expand Down Expand Up @@ -253,11 +250,19 @@ class MappedExpr(object):
"""map expression: ``zope.tales`` --> ``chameleon.tales``."""
def __init__(self, type, expression, zt_engine):
self.type = type
# At this place, *expression* is a `chameleon.tokenize.Token`
# (a subtype of `str` for PY3 and of `unicode` for PY2).
# The ``_compile_zt_expr`` below causes this to be cached
# which can lead under Python 3 to unsolicited translations
# (details "https://github.com/zopefoundation/Zope/issues/876")
# To avoid this, call ``_compile_zt_expr`` with
# *expression* cast to the `Token` base type.
expr = unicode(expression)
self.expression = expression
# compile to be able to report errors
compiler_error = zt_engine.getCompilerError()
try:
zt_expr = _compile_zt_expr(type, expression, engine=zt_engine)
zt_expr = _compile_zt_expr(type, expr, engine=zt_engine)
except compiler_error as e:
raise ExpressionError(str(e), self.expression)
if (self.type == "path" and "$" in self.expression
Expand Down

0 comments on commit a5cb4c7

Please sign in to comment.