diff --git a/CHANGES.rst b/CHANGES.rst index bf491b28..534c3722 100644 --- a/CHANGES.rst +++ b/CHANGES.rst @@ -1,6 +1,18 @@ Changes ======= +In next release... + +Features: + +- Expression interpolation (using the ``${...}`` operator and + previously also ``$identifier``) now requires braces everywhere + except inside the ``string:`` expression type. + + This change is motivated by a number of legacy templates in which + the interpolation format without braces ``$identifier`` appears as + text. + 2.0.2 (2011-07-25) ------------------ diff --git a/docs/reference.rst b/docs/reference.rst index c94ade86..5048b32c 100644 --- a/docs/reference.rst +++ b/docs/reference.rst @@ -1406,9 +1406,6 @@ included in the output (all inserted text is escaped by default): ${content} -Note that to insert the value of a symbol, the curly braces can be -omitted entirely: ``Hello, $name!``. - To escape this behavior, prefix the notation with a backslash character: ``\${...}``. diff --git a/src/chameleon/compiler.py b/src/chameleon/compiler.py index 1d376ce8..9526d549 100644 --- a/src/chameleon/compiler.py +++ b/src/chameleon/compiler.py @@ -337,7 +337,7 @@ def engine(expression, target): node = Expression(expression) return self.translate(node, target) - expression = StringExpr(node.value) + expression = StringExpr(node.value, node.braces_required) return expression(target, engine) def visit_Translate(self, node, target): @@ -583,7 +583,7 @@ def engine(expression, target): return self._engine(node, target) + \ convert(target) - expression = StringExpr(node.value) + expression = StringExpr(node.value, node.braces_required) name = identifier("content") diff --git a/src/chameleon/nodes.py b/src/chameleon/nodes.py index 4ccd9ff0..e08355c0 100644 --- a/src/chameleon/nodes.py +++ b/src/chameleon/nodes.py @@ -139,7 +139,7 @@ class Text(Node): class Interpolation(Text): """String interpolation output.""" - _fields = "value", "escape" + _fields = "value", "escape", "braces_required" class Translate(Node): diff --git a/src/chameleon/tales.py b/src/chameleon/tales.py index cd9b830f..49eea732 100644 --- a/src/chameleon/tales.py +++ b/src/chameleon/tales.py @@ -337,6 +337,17 @@ class StringExpr(object): >>> test(StringExpr('Hello ${world}!')) 'Hello world!' + In the default configuration, braces may be omitted if the + expression is an identifier. + + >>> test(StringExpr('Hello $world!')) + 'Hello world!' + + The ``braces_required`` flag changes this setting: + + >>> test(StringExpr('Hello $world!', True)) + 'Hello $world!' + We can escape interpolation using the standard escaping syntax: @@ -382,15 +393,20 @@ class StringExpr(object): 'There are 11 characters in \"hello world\"' """ - regex = re.compile( + braces_required_regex = re.compile( + r'(?.*)})') + + braces_optional_regex = re.compile( r'(?.*)}|(?P[A-Za-z][A-Za-z0-9_]*))') - def __init__(self, expression): + def __init__(self, expression, braces_required=False): # The code relies on the expression being a token string if not isinstance(expression, Token): expression = Token(expression, 0) self.expression = expression + self.regex = self.braces_required_regex if braces_required else \ + self.braces_optional_regex def __call__(self, name, engine): """The strategy is to find possible expression strings and diff --git a/src/chameleon/tests/inputs/001-variable-scope.pt b/src/chameleon/tests/inputs/001-variable-scope.pt index d6f497ac..e46ee35a 100644 --- a/src/chameleon/tests/inputs/001-variable-scope.pt +++ b/src/chameleon/tests/inputs/001-variable-scope.pt @@ -1,7 +1,6 @@ ${text} - $text bad diff --git a/src/chameleon/tests/inputs/006-attribute-interpolation.pt b/src/chameleon/tests/inputs/006-attribute-interpolation.pt index 6ace653e..adea1a14 100644 --- a/src/chameleon/tests/inputs/006-attribute-interpolation.pt +++ b/src/chameleon/tests/inputs/006-attribute-interpolation.pt @@ -1,6 +1,8 @@ - + copyright (c) ${2010} - + copyright (c) ${2010} + copyright (c) ${2010} + $ignored diff --git a/src/chameleon/tests/inputs/007-content-interpolation.pt b/src/chameleon/tests/inputs/007-content-interpolation.pt index 903f0856..2f9b8fa2 100644 --- a/src/chameleon/tests/inputs/007-content-interpolation.pt +++ b/src/chameleon/tests/inputs/007-content-interpolation.pt @@ -3,6 +3,7 @@ ${'Hello world!'} ${literal} ${None} + $leftalone
${None}
diff --git a/src/chameleon/tests/inputs/063-continuation.pt b/src/chameleon/tests/inputs/063-continuation.pt index f7726df0..02e93034 100644 --- a/src/chameleon/tests/inputs/063-continuation.pt +++ b/src/chameleon/tests/inputs/063-continuation.pt @@ -1,4 +1,4 @@
- $foo + ${foo}
\ No newline at end of file diff --git a/src/chameleon/tests/outputs/001.pt b/src/chameleon/tests/outputs/001.pt index 4e6e7652..fff27d16 100644 --- a/src/chameleon/tests/outputs/001.pt +++ b/src/chameleon/tests/outputs/001.pt @@ -1,7 +1,6 @@ Hello world! - Hello world! diff --git a/src/chameleon/tests/outputs/006.pt b/src/chameleon/tests/outputs/006.pt index 13b506b5..d5b625b8 100644 --- a/src/chameleon/tests/outputs/006.pt +++ b/src/chameleon/tests/outputs/006.pt @@ -1,6 +1,8 @@ copyright (c) 2010 - + copyright (c) 2010 + copyright (c) 2010 + $ignored diff --git a/src/chameleon/tests/outputs/007.pt b/src/chameleon/tests/outputs/007.pt index 42e62630..9c1356e0 100644 --- a/src/chameleon/tests/outputs/007.pt +++ b/src/chameleon/tests/outputs/007.pt @@ -3,6 +3,7 @@ Hello world!
Hello world!
+ $leftalone
diff --git a/src/chameleon/zpt/program.py b/src/chameleon/zpt/program.py index 52da1a73..9c53e12a 100644 --- a/src/chameleon/zpt/program.py +++ b/src/chameleon/zpt/program.py @@ -476,7 +476,7 @@ def visit_comment(self, node): if self._interpolation[-1]: return nodes.Sequence( [nodes.Text(node[:4]), - nodes.Interpolation(node[4:-3], self._escape), + nodes.Interpolation(node[4:-3], self._escape, True), nodes.Text(node[-3:]) ]) @@ -486,7 +486,7 @@ def visit_text(self, node): self._last = node if self._interpolation_enabled: - return nodes.Interpolation(node, self._escape) + return nodes.Interpolation(node, self._escape, True) return nodes.Text(node) @@ -543,7 +543,7 @@ def _create_attributes_nodes(self, prepared, I18N_ATTRIBUTES): # more interpolation expressions, make the attribute # dynamic if expr is None and text is not None and '${' in text: - value = nodes.Interpolation(text, True) + value = nodes.Interpolation(text, True, True) # If this expression is non-trivial, the attribute is # dynamic (computed)