[Checkins] SVN: z3c.pt/trunk/z3c/pt/ Implemented support for path
expressions.
Malthe Borch
mborch at gmail.com
Sun Mar 16 14:44:49 EDT 2008
Log message for revision 84714:
Implemented support for path expressions.
Changed:
U z3c.pt/trunk/z3c/pt/expressions.py
U z3c.pt/trunk/z3c/pt/generation.py
U z3c.pt/trunk/z3c/pt/interfaces.py
U z3c.pt/trunk/z3c/pt/translation.txt
U z3c.pt/trunk/z3c/pt/utils.py
-=-
Modified: z3c.pt/trunk/z3c/pt/expressions.py
===================================================================
--- z3c.pt/trunk/z3c/pt/expressions.py 2008-03-16 18:43:59 UTC (rev 84713)
+++ z3c.pt/trunk/z3c/pt/expressions.py 2008-03-16 18:44:45 UTC (rev 84714)
@@ -1,5 +1,8 @@
import zope.interface
+import zope.traversing.adapters
+
import parser
+import re
from interfaces import IExpressionTranslation
@@ -213,36 +216,27 @@
return defs[0]
-class PythonTranslation(ExpressionTranslation):
def value(self, string):
"""
- Specification:
+ We need to implement a ``value``-method. Let's define that an
+ expression is valid if it contains an odd number of
+ characters.
+
+ >>> class MockExpressionTranslation(ExpressionTranslation):
+ ... def validate(self, string):
+ ... return True
+ ...
+ ... def translate(self, string):
+ ... return '<translated %s>' % string
+
+ >>> value = MockExpressionTranslation().value
- value :: = python_expression [ |* value ]
- python_expresion ::= a python expression string
+ >>> value('a')
+ ('<translated a>',)
- *) Using | as logical or is not supported.
-
- >>> value = PythonTranslation().value
-
- >>> value("4 + 5")
- ['4 + 5']
-
- Complex expressions:
-
- >>> value("a.non_defined_method() | 1")
- ['a.non_defined_method() ', '1']
-
- Expression with non-semantic horizontal bar.
-
- >>> value("'|'")
- ["'|'"]
-
- Expression with non-semantic horizontal bar and semantic bar.
-
- >>> value("a.non_defined_method() | '|'")
- ['a.non_defined_method() ', "'|'"]
-
+ >>> value('a|b')
+ ('<translated a>', '<translated b>')
+
"""
string = string.replace('\n', '').strip()
@@ -261,16 +255,64 @@
expr = string[i:j].lstrip()
try:
- # we use the ``parser`` module to determine if
- # an expression is a valid python expression
- parser.expr(expr.encode('utf-8'))
- except SyntaxError, e:
+ self.validate(expr)
+ except Exception, e:
if j < len(string):
continue
raise e
- expressions.append(expr)
+ expressions.append(self.translate(expr))
i = j + 1
- return expressions
+ return tuple(expressions)
+
+class PythonTranslation(ExpressionTranslation):
+ def validate(self, string):
+ """We use the ``parser`` module to determine if
+ an expression is a valid python expression."""
+
+ parser.expr(string.encode('utf-8'))
+
+ def translate(self, string):
+ return string
+
+class PathTranslation(ExpressionTranslation):
+ path_regex = re.compile(r'^([A-Za-z_]+)(/[A-Za-z_ at -]+)+$')
+
+ @classmethod
+ def traverse(cls, base, request, *path_items):
+ """See ``zope.app.pagetemplate.engine``."""
+
+ for i in range(len(path_items)):
+ name = path_items[i]
+
+ # special-case dicts for performance reasons
+ if getattr(base, '__class__', None) == dict:
+ base = base[name]
+ else:
+ base = zope.traversing.adapters.traversePathElement(
+ base, name, path_items[i+1:], request=request)
+
+ return base
+
+ def validate(self, string):
+ if not self.path_regex.match(string):
+ raise ValueError("Not a valid path-expression.")
+
+ def translate(self, string):
+ """
+ >>> translate = PathTranslation().translate
+ >>> translate("a/b")
+ "_path(a, request, 'b')"
+
+ >>> translate("context/@@view")
+ "_path(context, request, '@@view')"
+ """
+
+ parts = string.split('/')
+
+ base = parts[0]
+ components = [repr(part) for part in parts[1:]]
+
+ return '_path(%s, request, %s)' % (base, ', '.join(components))
Modified: z3c.pt/trunk/z3c/pt/generation.py
===================================================================
--- z3c.pt/trunk/z3c/pt/generation.py 2008-03-16 18:43:59 UTC (rev 84713)
+++ z3c.pt/trunk/z3c/pt/generation.py 2008-03-16 18:44:45 UTC (rev 84714)
@@ -9,6 +9,7 @@
\t(_attributes, repeat) = utils.initialize_tal()
\t(_domain, _translate) = utils.initialize_i18n()
\t(_escape, _marker) = utils.initialize_helpers()
+\t_path = utils.initialize_traversal()
\t_target_language = target_language
%s
Modified: z3c.pt/trunk/z3c/pt/interfaces.py
===================================================================
--- z3c.pt/trunk/z3c/pt/interfaces.py 2008-03-16 18:43:59 UTC (rev 84713)
+++ z3c.pt/trunk/z3c/pt/interfaces.py 2008-03-16 18:44:45 UTC (rev 84714)
@@ -8,7 +8,22 @@
usually be the identity function."""
def value(string):
- """Translate ``string`` to a Python value-expression."""
+ """Translate ``string`` to a value-expression tuple.
+
+ Specification:
+
+ value :: = expression [ |* value ]
+ expresion ::= an expression string
+
+ *) Using | as _logical or_ is not supported.
+
+ """
+
+ def validate(string):
+ """Raises exception if ``string`` is not a valid exception."""
+
+ def translate(string):
+ """Translates ``string``."""
def search(string):
"""Extracts the longest valid expression from the beginning of
Modified: z3c.pt/trunk/z3c/pt/translation.txt
===================================================================
--- z3c.pt/trunk/z3c/pt/translation.txt 2008-03-16 18:43:59 UTC (rev 84713)
+++ z3c.pt/trunk/z3c/pt/translation.txt 2008-03-16 18:44:45 UTC (rev 84714)
@@ -1,9 +1,9 @@
Translation
------------
+===========
This document contains functional template tests.
-We use a generic render-method for convenience.
+A generic render-method is used for convenience.
>>> def render(body, translator, **kwargs):
... source, _globals = translator(body)
@@ -11,12 +11,19 @@
... exec source in _globals, _locals
... return _locals['render'](**kwargs)
-We'll first register the Python expression translator.
+Expressions
+-----------
+
+First we'll register the expression translation utilities:
+ >>> from zope.component import provideUtility
+
>>> from z3c.pt.expressions import PythonTranslation
- >>> from zope.component import provideUtility
>>> provideUtility(PythonTranslation(), name="python")
+ >>> from z3c.pt.expressions import PathTranslation
+ >>> provideUtility(PathTranslation(), name="path")
+
TAL templates
-------------
@@ -28,7 +35,8 @@
>>> body = """\
... <div xmlns="http://www.w3.org/1999/xhtml"
- ... xmlns:tal="http://xml.zope.org/namespaces/tal">
+ ... xmlns:tal="http://xml.zope.org/namespaces/tal"
+ ... tal:default-expression="python">
... <span id="test"
... class="dummy"
... tal:define="a 'abc'"
@@ -65,7 +73,16 @@
... <img alt="La Peña, oh ${'La Peña'}" />
... ${unicode('La Pe\xc3\xb1a', 'utf-8')}
... <img alt="${unicode('La Pe\xc3\xb1a', 'utf-8')}" />
- ... <img alt="Hello ${unicode('La Pe\xc3\xb1a', 'utf-8').encode('utf-8')}!" />
+ ... <img alt="Hello ${unicode('La Pe\xc3\xb1a', 'utf-8').encode('utf-8')}!" />
+ ... <tal:path-expression-testing
+ ... define="request object();
+ ... mydict {'a': 1, 'c': {'a': 2}}">
+ ... <div tal:default-expression="path">
+ ... <span tal:replace="mydict/a" />
+ ... <span tal:replace="mydict/b|mydict/a" />
+ ... <span tal:replace="mydict/c/a" />
+ ... </div>
+ ... </tal:path-expression-testing>
... </div>
... """
@@ -117,7 +134,14 @@
<img alt="La Peña, oh La Peña" />
La Peña
<img alt="La Peña" />
- <img alt="Hello La Peña!" />
+ <img alt="Hello La Peña!" />
+ <BLANKLINE>
+ <div>
+ 1
+ 1
+ 2
+ </div>
+ <BLANKLINE>
</div>
Text templates
Modified: z3c.pt/trunk/z3c/pt/utils.py
===================================================================
--- z3c.pt/trunk/z3c/pt/utils.py 2008-03-16 18:43:59 UTC (rev 84713)
+++ z3c.pt/trunk/z3c/pt/utils.py 2008-03-16 18:44:45 UTC (rev 84714)
@@ -5,6 +5,7 @@
import sys
import cgi
import logging
+import expressions
# check if we're able to coerce unicode to str
try:
@@ -13,7 +14,10 @@
except UnicodeEncodeError:
unicode_required_flag = True
log = logging.getLogger('z3c.pt')
- log.info("Default system encoding is set to '%s'; the template engine will perform better if an encoding that coerces gracefully to unicode is used ('utf-8' recommended)." % sys.getdefaultencoding())
+ log.info("Default system encoding is set to '%s'; "
+ "the template engine will perform better if "
+ "an encoding that coerces gracefully to "
+ "unicode is used ('utf-8' recommended)." % sys.getdefaultencoding())
def handler(key=None):
def decorate(f):
@@ -36,7 +40,10 @@
def initialize_stream():
return StringIO()
-
+
+def initialize_traversal():
+ return expressions.PathTranslation.traverse
+
def getLanguage(request):
return ''
More information about the Checkins
mailing list