[Checkins] SVN: z3c.pt/trunk/ Engine now uses cStringIO.

Malthe Borch mborch at gmail.com
Fri Feb 22 17:37:52 EST 2008


Log message for revision 84148:
  Engine now uses cStringIO.

Changed:
  U   z3c.pt/trunk/docs/HISTORY.txt
  U   z3c.pt/trunk/setup.py
  U   z3c.pt/trunk/z3c/pt/BENCHMARKS.txt
  U   z3c.pt/trunk/z3c/pt/clauses.py
  U   z3c.pt/trunk/z3c/pt/expressions.py
  U   z3c.pt/trunk/z3c/pt/io.py
  U   z3c.pt/trunk/z3c/pt/translation.py
  U   z3c.pt/trunk/z3c/pt/translation.txt
  U   z3c.pt/trunk/z3c/pt/utils.py

-=-
Modified: z3c.pt/trunk/docs/HISTORY.txt
===================================================================
--- z3c.pt/trunk/docs/HISTORY.txt	2008-02-22 22:36:51 UTC (rev 84147)
+++ z3c.pt/trunk/docs/HISTORY.txt	2008-02-22 22:37:52 UTC (rev 84148)
@@ -1,11 +1,12 @@
 Changelog
 ---------
 
-Version 0.4 - in development
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+Version 0.4 - February 22, 2008
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
+- Engine now uses cStringIO yielding a 2.5x performance
+  improvement. Unicode is now handled correctly.
 
-
 Version 0.3 - December 23, 2007
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 

Modified: z3c.pt/trunk/setup.py
===================================================================
--- z3c.pt/trunk/setup.py	2008-02-22 22:36:51 UTC (rev 84147)
+++ z3c.pt/trunk/setup.py	2008-02-22 22:37:52 UTC (rev 84148)
@@ -1,6 +1,6 @@
 from setuptools import setup, find_packages
 
-version = '0.3.3'
+version = '0.4'
 
 setup(name='z3c.pt',
       version=version,

Modified: z3c.pt/trunk/z3c/pt/BENCHMARKS.txt
===================================================================
--- z3c.pt/trunk/z3c/pt/BENCHMARKS.txt	2008-02-22 22:36:51 UTC (rev 84147)
+++ z3c.pt/trunk/z3c/pt/BENCHMARKS.txt	2008-02-22 22:37:52 UTC (rev 84148)
@@ -1,13 +1,27 @@
 Benchmarks
 ==========
 
-                  zope.pagetemplate     z3c.pt
-Hello World       3.55                  1     
-1000 x 10 table   6.02                  1
+These benchmarks should not be taken too seriously but they do give an
+idea of how this package measures up to Zope's default TAL
+engine. Also included is a comparison to a pure python implementation.
 
-Source
-------
+Results
+-------
 
+                  zope.pagetemplate     z3c.pt    pure python
+Hello World        3.6                  1         0.02        
+1000 x 10 table   14.0                  1         0.63
+
+There's a setup cost in using a template language which explains the
+50x factor in the 'Hello World' benchmark versus a pure python
+implementation.
+
+Certainly a specialized implementation will always be faster. But
+there's still some room for improvement.
+
+Benchmark source code
+---------------------
+
   >>> from z3c.pt import PageTemplate
   >>> from zope.pagetemplate.pagetemplate import PageTemplate as z3PageTemplate
 
@@ -18,7 +32,7 @@
   ...   Hello World!
   ... </div>""")
 
-  >>> # for i in range(300000): a = template()
+  >>> # for i in range(90000): a = template()
 
   >>> template = z3PageTemplate()
   >>> template.pt_edit("""\
@@ -26,8 +40,16 @@
   ...   Hello World!
   ... </div>""", 'text/xhtml')
 
-  >>> # for i in range(300000): a = template()  
+  >>> # for i in range(90000): a = template()  
 
+  >>> def hello_world():
+  ...     return u"""\
+  ... <div>
+  ...   Hello World!
+  ... </div>"""
+
+  >>> for i in range(9000000): a = hello_world()
+
 1000 x 10 table:
   
   >>> table = [dict(a=1,b=2,c=3,d=4,e=5,f=6,g=7,h=8,i=9,j=10) \
@@ -68,9 +90,10 @@
   ...   for row in table:
   ...      out.write('<tr>')
   ...      for c in row.values():
-  ...         out.write('<td>%s</td>' % c)
+  ...         d = c+1
+  ...         out.write('<td><span class="column-%d">%s</span></td>' % (d, d))
   ...      out.write('</tr>')
   ...   return out.getvalue()
   
-  >>> # for i in range(20): a = bigtable(table=table)
+  >>> # for i in range(40): a = bigtable(table=table)
 

Modified: z3c.pt/trunk/z3c/pt/clauses.py
===================================================================
--- z3c.pt/trunk/z3c/pt/clauses.py	2008-02-22 22:36:51 UTC (rev 84147)
+++ z3c.pt/trunk/z3c/pt/clauses.py	2008-02-22 22:37:52 UTC (rev 84148)
@@ -1,5 +1,7 @@
 from expressions import value
 
+from utils import unicode_required_flag
+
 class Assign(object):
     """
       >>> from z3c.pt.io import CodeIO; stream = CodeIO()
@@ -464,11 +466,24 @@
         temp = stream.save()
                 
         if self.count == 1:
-            stream.write("_out.write(%s)" % self.expressions[0])
+            expr = self.expressions[0]
         else:
             self.assign.begin(stream, temp)
-            stream.write("_out.write(%s)" % temp)
-        
+            expr = temp
+
+        if unicode_required_flag:
+            stream.write("_urf = %s" % expr)
+            stream.write("try:")
+            stream.indent()
+            stream.write("_out.write(str(_urf))")
+            stream.outdent()
+            stream.write("except TypeError:")
+            stream.indent()
+            stream.write("_out.write(unicode(_urf, 'utf-8'))")
+            stream.outdent()
+        else:
+            stream.write("_out.write(str(%s))" % expr)
+            
     def end(self, stream):
         if self.count != 1:
             self.assign.end(stream)

Modified: z3c.pt/trunk/z3c/pt/expressions.py
===================================================================
--- z3c.pt/trunk/z3c/pt/expressions.py	2008-02-22 22:36:51 UTC (rev 84147)
+++ z3c.pt/trunk/z3c/pt/expressions.py	2008-02-22 22:37:52 UTC (rev 84148)
@@ -50,13 +50,13 @@
         try:
             # we use the ``parser`` module to determine if
             # an expression is a valid python expression
-            parser.expr(expr)
+            parser.expr(expr.encode('utf-8'))
         except SyntaxError, e:
             if j < len(string):
                 continue
 
             raise e
-
+            
         expressions.append(expr)
         i = j + 1
 

Modified: z3c.pt/trunk/z3c/pt/io.py
===================================================================
--- z3c.pt/trunk/z3c/pt/io.py	2008-02-22 22:36:51 UTC (rev 84147)
+++ z3c.pt/trunk/z3c/pt/io.py	2008-02-22 22:37:52 UTC (rev 84148)
@@ -25,7 +25,6 @@
         self.scope = [set()]
         
         self._variables = {}
-
         self.t_counter = 0
 
     def save(self):
@@ -58,7 +57,8 @@
         
     def write(self, string):
         self.cook()
-        StringIO.write(self, self.indentation_string * self.indentation + string + '\n')
+        StringIO.write(
+            self, self.indentation_string * self.indentation + string + '\n')
 
     def getvalue(self):
         self.cook()

Modified: z3c.pt/trunk/z3c/pt/translation.py
===================================================================
--- z3c.pt/trunk/z3c/pt/translation.py	2008-02-22 22:36:51 UTC (rev 84147)
+++ z3c.pt/trunk/z3c/pt/translation.py	2008-02-22 22:37:52 UTC (rev 84148)
@@ -18,7 +18,7 @@
 
 \t_target_language = target_language
 %s
-\treturn _out.getvalue()
+\treturn _out.getvalue().decode('utf-8')
 """
 
 def attribute(ns, factory):

Modified: z3c.pt/trunk/z3c/pt/translation.txt
===================================================================
--- z3c.pt/trunk/z3c/pt/translation.txt	2008-02-22 22:36:51 UTC (rev 84147)
+++ z3c.pt/trunk/z3c/pt/translation.txt	2008-02-22 22:37:52 UTC (rev 84148)
@@ -35,8 +35,9 @@
   ...   <p tal:omit-tag="True">No paragraph here either.</p>
   ...   <p tal:omit-tag="False">A paragraph here.</p>
   ...   <span tal:replace="'Hello World!'">Hello Universe!</span>
+  ...   <span tal:content="'%s'" />
   ... </div>
-  ... """
+  ... """ % (u'La Pe\xf1a').encode('utf-8')
 
   >>> print render(body)
   <div>
@@ -60,7 +61,7 @@
     </ul>
     Hello World!
     <div>Hello World!</div>
-  <BLANKLINE>
+    0
     1
     2
     3
@@ -69,6 +70,7 @@
     No paragraph here either.
     <p>A paragraph here.</p>
     Hello World!
+    <span>La Peña</span>
   </div>
     
 Error handling

Modified: z3c.pt/trunk/z3c/pt/utils.py
===================================================================
--- z3c.pt/trunk/z3c/pt/utils.py	2008-02-22 22:36:51 UTC (rev 84147)
+++ z3c.pt/trunk/z3c/pt/utils.py	2008-02-22 22:37:52 UTC (rev 84148)
@@ -1,8 +1,19 @@
 import zope.i18n
 
+from cStringIO import StringIO
+
+import sys
 import cgi
-from StringIO import StringIO
+import logging
 
+# check if we're able to coerce unicode to str
+try:
+    str(u'La Pe\xf1a')
+    unicode_required_flag = False
+except UnicodeEncodeError:
+    unicode_required_flag = True    
+    logging.warn("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).")
+
 def handler(key=None):
     def decorate(f):
         def g(node):



More information about the Checkins mailing list