[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