[Checkins] SVN: z3c.pt/trunk/ Added support for expression
interpolation in document content.
Malthe Borch
mborch at gmail.com
Sat Feb 23 09:56:19 EST 2008
Log message for revision 84184:
Added support for expression interpolation in document content.
Changed:
U z3c.pt/trunk/setup.py
U z3c.pt/trunk/z3c/pt/expressions.py
U z3c.pt/trunk/z3c/pt/translation.py
U z3c.pt/trunk/z3c/pt/translation.txt
-=-
Modified: z3c.pt/trunk/setup.py
===================================================================
--- z3c.pt/trunk/setup.py 2008-02-23 14:49:10 UTC (rev 84183)
+++ z3c.pt/trunk/setup.py 2008-02-23 14:56:19 UTC (rev 84184)
@@ -1,6 +1,6 @@
from setuptools import setup, find_packages
-version = '0.4.3'
+version = '0.5dev'
setup(name='z3c.pt',
version=version,
Modified: z3c.pt/trunk/z3c/pt/expressions.py
===================================================================
--- z3c.pt/trunk/z3c/pt/expressions.py 2008-02-23 14:49:10 UTC (rev 84183)
+++ z3c.pt/trunk/z3c/pt/expressions.py 2008-02-23 14:56:19 UTC (rev 84184)
@@ -2,7 +2,45 @@
def name(string):
return string
+
+def search(string):
+ """
+ Extracts the longest valid Python-expression from the beginning of
+ the provided string..
+ >>> search("'Hello World'")
+ "'Hello World'"
+
+ >>> search("'Hello World'}")
+ "'Hello World'"
+
+ >>> search("'Hello World' + '")
+ "'Hello World' "
+
+ """
+
+ left = 0
+ right = left + 1
+
+ current = None
+
+ while right <= len(string):
+ expression = string[left:right]
+
+ try:
+ e = value(expression)
+ current = expression
+ except SyntaxError, e:
+ if right == len(string):
+ if current is not None:
+ return current
+
+ raise e
+
+ right += 1
+
+ return current
+
def value(string):
"""
Specification:
Modified: z3c.pt/trunk/z3c/pt/translation.py
===================================================================
--- z3c.pt/trunk/z3c/pt/translation.py 2008-02-23 14:49:10 UTC (rev 84183)
+++ z3c.pt/trunk/z3c/pt/translation.py 2008-02-23 14:56:19 UTC (rev 84184)
@@ -1,11 +1,20 @@
from StringIO import StringIO
import lxml.etree
+import re
import io
import utils
import expressions
import clauses
+# set up namespace
+lookup = lxml.etree.ElementNamespaceClassLookup()
+parser = lxml.etree.XMLParser()
+parser.setElementClassLookup(lookup)
+
+xhtml = lxml.etree.Namespace('http://www.w3.org/1999/xhtml')
+tal = lxml.etree.Namespace('http://xml.zope.org/namespaces/tal')
+
wrapper = """\
def render(%starget_language=None):
\tglobal utils
@@ -20,6 +29,7 @@
%s
\treturn _out.getvalue().decode('utf-8')
"""
+interpolation_regex = re.compile(r'([^\\]\$|^\$){(?P<expression>.*)}')
def attribute(ns, factory):
def get(self):
@@ -28,6 +38,25 @@
return factory(value)
return property(get)
+def interpolate(string):
+ m = interpolation_regex.search(string)
+ if m is None:
+ return None
+
+ left = m.start()
+ exp = expressions.search(string[left+3:])
+ right = left+4+len(exp)
+
+ m = interpolation_regex.search(string[:right])
+
+ if m is None:
+ interpolation = string[left:right]
+ raise SyntaxError(
+ "Interpolation expressions must of the "
+ "form ${<expression>} (%s)" % interpolation)
+
+ return m
+
class Element(lxml.etree.ElementBase):
def begin(self, stream):
stream.scope.append(set())
@@ -41,6 +70,8 @@
skip = self.replace or self.content or self.i18n_translate is not None
if not skip:
for element in self:
+ element.interpolate()
+ for element in self:
element.visit(stream)
def visit(self, stream):
@@ -48,6 +79,35 @@
self.body(stream)
self.end(stream)
+ def interpolate(self):
+ # interpolate text
+ if self.text is not None:
+ while self.text:
+ m = interpolate(self.text)
+ if m is None:
+ break
+
+ t = parser.makeelement(
+ '{http://xml.zope.org/namespaces/tal}interpolation')
+ t.attrib['replace'] = m.group('expression')
+ t.tail = self.text[m.end():]
+ self.insert(0, t)
+ self.text = self.text[:m.start()+1]
+
+ # interpolate tail
+ if self.tail is not None:
+ while self.tail:
+ m = interpolate(self.tail)
+ if m is None:
+ break
+
+ t = parser.makeelement(
+ '{http://xml.zope.org/namespaces/tal}interpolation')
+ t.attrib['replace'] = m.group('expression')
+ t.tail = self.tail[m.end():]
+ self.getparent().append(t)
+ self.tail = self.tail[:m.start()+1]
+
def clauses(self):
_ = []
@@ -282,14 +342,6 @@
return attributes
-# set up namespace
-lookup = lxml.etree.ElementNamespaceClassLookup()
-parser = lxml.etree.XMLParser()
-parser.setElementClassLookup(lookup)
-
-xhtml = lxml.etree.Namespace('http://www.w3.org/1999/xhtml')
-tal = lxml.etree.Namespace('http://xml.zope.org/namespaces/tal')
-
xhtml[None] = Element
tal[None] = TALElement
Modified: z3c.pt/trunk/z3c/pt/translation.txt
===================================================================
--- z3c.pt/trunk/z3c/pt/translation.txt 2008-02-23 14:49:10 UTC (rev 84183)
+++ z3c.pt/trunk/z3c/pt/translation.txt 2008-02-23 14:56:19 UTC (rev 84184)
@@ -40,6 +40,7 @@
... <span tal:content="None" />
... <span tal:attributes="class lambda: 'Hello'"
... tal:content="lambda: 'World'" />
+ ... <span>Inter${'pol' + 'ati'}on</span>is ${int('test') | 'convenient'}!
... </div>
... """ % (u'La Pe\xf1a').encode('utf-8')
@@ -78,6 +79,7 @@
<span>La Peña</span>
<span></span>
<span class="Hello">World</span>
+ <span>Interpolation</span>is convenient!
</div>
Error handling
More information about the Checkins
mailing list