[Checkins] SVN: z3c.pt/trunk/ System variables are now defined in a configuration class.

Malthe Borch mborch at gmail.com
Thu Aug 21 09:34:44 EDT 2008


Log message for revision 90064:
  System variables are now defined in a configuration class.

Changed:
  U   z3c.pt/trunk/CHANGES.txt
  U   z3c.pt/trunk/src/z3c/pt/clauses.py
  U   z3c.pt/trunk/src/z3c/pt/config.py
  U   z3c.pt/trunk/src/z3c/pt/generation.py
  U   z3c.pt/trunk/src/z3c/pt/testing.py
  U   z3c.pt/trunk/src/z3c/pt/translation.py
  U   z3c.pt/trunk/src/z3c/pt/types.py

-=-
Modified: z3c.pt/trunk/CHANGES.txt
===================================================================
--- z3c.pt/trunk/CHANGES.txt	2008-08-21 13:28:30 UTC (rev 90063)
+++ z3c.pt/trunk/CHANGES.txt	2008-08-21 13:34:43 UTC (rev 90064)
@@ -4,6 +4,8 @@
 Version 1.0dev
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
+- System variables are now defined in a configuration class. [malthe]
+
 - Improve performance of codegen by not repeatedly calling
   an expensive "flatten" function. [chrism]
 

Modified: z3c.pt/trunk/src/z3c/pt/clauses.py
===================================================================
--- z3c.pt/trunk/src/z3c/pt/clauses.py	2008-08-21 13:28:30 UTC (rev 90063)
+++ z3c.pt/trunk/src/z3c/pt/clauses.py	2008-08-21 13:34:43 UTC (rev 90064)
@@ -7,11 +7,11 @@
 
 class Assign(object):
     """
-    >>> from z3c.pt.generation import CodeIO; stream = CodeIO()
-    >>> from z3c.pt.testing import pyexp
+    >>> from z3c.pt import testing
 
     We'll define some values for use in the tests.
-    
+
+    >>> _out, _write, stream = testing.setup_stream()
     >>> one = types.value("1")
     >>> bad_float = types.value("float('abc')")
     >>> abc = types.value("'abc'")
@@ -113,7 +113,10 @@
 
     def _assign(self, variable, value, stream):
         stream.annotate(value)
+        symbols = stream.symbols.as_dict()
         
+        if isinstance(value, types.template):
+            value = types.value(value % symbols)
         if isinstance(value, types.value):
             stream.write("%s = %s" % (variable, value))
         elif isinstance(value, types.join):
@@ -121,6 +124,8 @@
             _v_count = 0
             
             for part in value:
+                if isinstance(part, types.template):
+                    part = types.value(part % symbols)
                 if isinstance(part, (types.parts, types.join)):
                     _v = stream.save()
                     assign = Assign(part, _v)
@@ -149,100 +154,100 @@
 
 class Define(object):
     """
-      >>> from z3c.pt.generation import CodeIO; stream = CodeIO()
-      >>> from z3c.pt.testing import pyexp
-      
+    >>> from z3c.pt import testing
+
     Variable scope:
 
-      >>> define = Define("a", pyexp("b"))
-      >>> b = object()
-      >>> define.begin(stream)
-      >>> exec stream.getvalue()
-      >>> a is b
-      True
-      >>> del a
-      >>> define.end(stream)
-      >>> exec stream.getvalue()
-      >>> a
-      Traceback (most recent call last):
-          ...
-      NameError: name 'a' is not defined
-      >>> b is not None
-      True
+    >>> _out, _write, stream = testing.setup_stream()
+    >>> define = Define("a", testing.pyexp("b"))
+    >>> b = object()
+    >>> define.begin(stream)
+    >>> exec stream.getvalue()
+    >>> a is b
+    True
+    >>> del a
+    >>> define.end(stream)
+    >>> exec stream.getvalue()
+    >>> a
+    Traceback (most recent call last):
+        ...
+    NameError: name 'a' is not defined
+    >>> b is not None
+    True
 
     Multiple defines:
 
-      >>> stream = CodeIO()
-      >>> define1 = Define("a", pyexp("b"))
-      >>> define2 = Define("c", pyexp("d"))
-      >>> d = object()
-      >>> define1.begin(stream)
-      >>> define2.begin(stream)
-      >>> exec stream.getvalue()
-      >>> a is b and c is d
-      True
-      >>> define2.end(stream)
-      >>> define1.end(stream)
-      >>> del a; del c
-      >>> stream.scope[-1].remove('a'); stream.scope[-1].remove('c')
-      >>> exec stream.getvalue()
-      >>> a
-      Traceback (most recent call last):
-          ...
-      NameError: name 'a' is not defined
-      >>> c
-      Traceback (most recent call last):
-          ...
-      NameError: name 'c' is not defined
-      >>> b is not None and d is not None
-      True
+    >>> _out, _write, stream = testing.setup_stream()
+    >>> define1 = Define("a", testing.pyexp("b"))
+    >>> define2 = Define("c", testing.pyexp("d"))
+    >>> d = object()
+    >>> define1.begin(stream)
+    >>> define2.begin(stream)
+    >>> exec stream.getvalue()
+    >>> a is b and c is d
+    True
+    >>> define2.end(stream)
+    >>> define1.end(stream)
+    >>> del a; del c
+    >>> stream.scope[-1].remove('a'); stream.scope[-1].remove('c')
+    >>> exec stream.getvalue()
+    >>> a
+    Traceback (most recent call last):
+        ...
+    NameError: name 'a' is not defined
+    >>> c
+    Traceback (most recent call last):
+        ...
+    NameError: name 'c' is not defined
+    >>> b is not None and d is not None
+    True
 
     Tuple assignments:
 
-      >>> stream = CodeIO()
-      >>> define = Define(types.declaration(('e', 'f')), pyexp("[1, 2]"))
-      >>> define.begin(stream)
-      >>> exec stream.getvalue()
-      >>> e == 1 and f == 2
-      True
-      >>> define.end(stream)
+    >>> _out, _write, stream = testing.setup_stream()
+    >>> define = Define(types.declaration(('e', 'f')), testing.pyexp("[1, 2]"))
+    >>> define.begin(stream)
+    >>> exec stream.getvalue()
+    >>> e == 1 and f == 2
+    True
+    >>> define.end(stream)
 
     Verify scope is preserved on tuple assignment:
 
-      >>> stream = CodeIO()
-      >>> e = None; f = None
-      >>> stream.scope[-1].add('e'); stream.scope[-1].add('f')
-      >>> stream.scope.append(set())
-      >>> define.begin(stream)
-      >>> define.end(stream)
-      >>> exec stream.getvalue()
-      >>> e is None and f is None
-      True
+    >>> _out, _write, stream = testing.setup_stream()
+    >>> e = None; f = None
+    >>> stream.scope[-1].add('e'); stream.scope[-1].add('f')
+    >>> stream.scope.append(set())
+    >>> define.begin(stream)
+    >>> define.end(stream)
+    >>> exec stream.getvalue()
+    >>> e is None and f is None
+    True
 
     Using semicolons in expressions within a define:
 
-      >>> stream = CodeIO()
-      >>> define = Define("a", pyexp("';'"))
-      >>> define.begin(stream)
-      >>> exec stream.getvalue()
-      >>> a
-      ';'
-      >>> define.end(stream)
+    >>> _out, _write, stream = testing.setup_stream()
+    >>> define = Define("a", testing.pyexp("';'"))
+    >>> define.begin(stream)
+    >>> exec stream.getvalue()
+    >>> a
+    ';'
+    >>> define.end(stream)
 
     Scope:
 
-      >>> stream = CodeIO()
-      >>> a = 1
-      >>> stream.scope[-1].add('a')
-      >>> stream.scope.append(set())
-      >>> define = Define("a", pyexp("2"))
-      >>> define.begin(stream)
-      >>> define.end(stream)
-      >>> exec stream.getvalue()
-      >>> a
-      1
-    
+    >>> _out, _write, stream = testing.setup_stream()
+    >>> a = 1
+    >>> stream.scope[-1].add('a')
+    >>> stream.scope.append(set())
+    >>> define = Define("a", testing.pyexp("2"))
+    >>> define.begin(stream)
+    >>> define.end(stream)
+    >>> exec stream.getvalue()
+    >>> a
+    1
     """
+    
     def __init__(self, declaration, expression, dictionary=None):
         if not isinstance(declaration, types.declaration):
             declaration = types.declaration((declaration,))
@@ -308,53 +313,51 @@
 
 class Condition(object):
     """
-      >>> from z3c.pt.generation import CodeIO
-      >>> from z3c.pt.testing import pyexp
-      >>> from StringIO import StringIO
-      
+    >>> from z3c.pt import testing
+
     Unlimited scope:
-    
-      >>> stream = CodeIO()
-      >>> true = Condition(pyexp("True"))
-      >>> false = Condition(pyexp("False"))
-      >>> true.begin(stream)
-      >>> stream.write("print 'Hello'")
-      >>> true.end(stream)
-      >>> false.begin(stream)
-      >>> stream.write("print 'Universe!'")
-      >>> false.end(stream)
-      >>> stream.write("print 'World!'")
-      >>> exec stream.getvalue()
-      Hello
-      World!
 
+    >>> _out, _write, stream = testing.setup_stream()
+    >>> true = Condition(testing.pyexp("True"))
+    >>> false = Condition(testing.pyexp("False"))
+    >>> true.begin(stream)
+    >>> stream.write("print 'Hello'")
+    >>> true.end(stream)
+    >>> false.begin(stream)
+    >>> stream.write("print 'Universe!'")
+    >>> false.end(stream)
+    >>> stream.write("print 'World!'")
+    >>> exec stream.getvalue()
+    Hello
+    World!
+
     Finalized limited scope:
 
-      >>> _out = StringIO(); _write = _out.write; stream = CodeIO()
-      >>> true = Condition(pyexp("True"), [Write(pyexp("'Hello'"))])
-      >>> false = Condition(pyexp("False"), [Write(pyexp("'Hallo'"))])
-      >>> true.begin(stream)
-      >>> true.end(stream)
-      >>> false.begin(stream)
-      >>> false.end(stream)
-      >>> exec stream.getvalue()
-      >>> _out.getvalue()
-      'Hello'
+    >>> _out, _write, stream = testing.setup_stream()
+    >>> true = Condition(testing.pyexp("True"), [Write(testing.pyexp("'Hello'"))])
+    >>> false = Condition(testing.pyexp("False"), [Write(testing.pyexp("'Hallo'"))])
+    >>> true.begin(stream)
+    >>> true.end(stream)
+    >>> false.begin(stream)
+    >>> false.end(stream)
+    >>> exec stream.getvalue()
+    >>> _out.getvalue()
+    'Hello'
 
     Open limited scope:
 
-      >>> _out = StringIO(); _write = _out.write; stream = CodeIO()
-      >>> true = Condition(pyexp("True"), [Tag('div')], finalize=False)
-      >>> false = Condition(pyexp("False"), [Tag('span')], finalize=False)
-      >>> true.begin(stream)
-      >>> stream.out("Hello World!")
-      >>> true.end(stream)
-      >>> false.begin(stream)
-      >>> false.end(stream)
-      >>> exec stream.getvalue()
-      >>> _out.getvalue()
-      '<div>Hello World!</div>'
-          
+    >>> _out, _write, stream = testing.setup_stream()
+    >>> true = Condition(testing.pyexp("True"), [Tag('div')], finalize=False)
+    >>> false = Condition(testing.pyexp("False"), [Tag('span')], finalize=False)
+    >>> true.begin(stream)
+    >>> stream.out("Hello World!")
+    >>> true.end(stream)
+    >>> false.begin(stream)
+    >>> false.end(stream)
+    >>> exec stream.getvalue()
+    >>> _out.getvalue()
+    '<div>Hello World!</div>'
+
     """
       
     def __init__(self, value, clauses=None, finalize=True):
@@ -432,42 +435,40 @@
 
 class Tag(object):
     """
-      >>> from z3c.pt.generation import CodeIO
-      >>> from z3c.pt.testing import pyexp
-      >>> from StringIO import StringIO
+    >>> from z3c.pt import testing
 
-      Dynamic attribute:
-      
-      >>> _out = StringIO(); _write = _out.write; stream = CodeIO()
-      >>> tag = Tag('div', dict(alt=pyexp(repr('Hello World!'))))
-      >>> tag.begin(stream)
-      >>> stream.out('Hello Universe!')
-      >>> tag.end(stream)
-      >>> exec stream.getvalue()
-      >>> _out.getvalue()
-      '<div alt="Hello World!">Hello Universe!</div>'
+    Dynamic attribute:
 
-      Self-closing tag:
-      
-      >>> _out = StringIO(); _write = _out.write; stream = CodeIO()
-      >>> tag = Tag('br', {}, True)
-      >>> tag.begin(stream)
-      >>> tag.end(stream)
-      >>> exec stream.getvalue()
-      >>> _out.getvalue()
-      '<br />'
+    >>> _out, _write, stream = testing.setup_stream()
+    >>> tag = Tag('div', dict(alt=testing.pyexp(repr('Hello World!'))))
+    >>> tag.begin(stream)
+    >>> stream.out('Hello Universe!')
+    >>> tag.end(stream)
+    >>> exec stream.getvalue()
+    >>> _out.getvalue()
+    '<div alt="Hello World!">Hello Universe!</div>'
 
-      Unicode:
-      
-      >>> _out = StringIO(); _write = _out.write; stream = CodeIO()
-      >>> tag = Tag('div', dict(alt=pyexp(repr('La Pe\xc3\xb1a'))))
-      >>> tag.begin(stream)
-      >>> stream.out('Hello Universe!')
-      >>> tag.end(stream)
-      >>> exec stream.getvalue()
-      >>> _out.getvalue() == '<div alt="La Pe\xc3\xb1a">Hello Universe!</div>'
-      True
-            
+    Self-closing tag:
+
+    >>> _out, _write, stream = testing.setup_stream()
+    >>> tag = Tag('br', {}, True)
+    >>> tag.begin(stream)
+    >>> tag.end(stream)
+    >>> exec stream.getvalue()
+    >>> _out.getvalue()
+    '<br />'
+
+    Unicode:
+
+    >>> _out, _write, stream = testing.setup_stream()
+    >>> tag = Tag('div', dict(alt=testing.pyexp(repr('La Pe\xc3\xb1a'))))
+    >>> tag.begin(stream)
+    >>> stream.out('Hello Universe!')
+    >>> tag.end(stream)
+    >>> exec stream.getvalue()
+    >>> _out.getvalue() == '<div alt="La Pe\xc3\xb1a">Hello Universe!</div>'
+    True
+
     """
 
     def __init__(self, tag, attributes=None,
@@ -501,16 +502,17 @@
             self.attributes.items())
 
         if self.expression:
-            self.expression.begin(stream, '_exp')
+            self.expression.begin(stream, stream.symbols.tmp)
 
         names = ", ".join([repr(a) for a, e in static]+[repr(a) for a, v in dynamic])
         
         if self.expression:
             for attribute, expression in static:
-                stream.write("if '%s' not in _exp:" % attribute)
+                stream.write("if '%s' not in %s:" % (attribute, stream.symbols.tmp))
                 stream.indent()
                 stream.write(
-                    "_write(' %s=\"%s\"')" % (attribute, escape(expression, '"')))
+                    "%s(' %s=\"%s\"')" % (
+                    stream.symbols.write, attribute, escape(expression, '"')))
                 stream.outdent()
         else:
             for attribute, expression in static:
@@ -523,7 +525,8 @@
         temp2 = stream.save()
 
         if self.expression:
-            stream.write("for %s, %s in _exp.items():" % (temp, temp2))
+            stream.write("for %s, %s in %s.items():" % \
+                         (temp, temp2, stream.symbols.tmp))            
             stream.indent()
             if unicode_required_flag:
                 stream.write(
@@ -535,7 +538,8 @@
                     stream.write("%s = %s.encode('utf-8')" % (t, t))
                     stream.outdent()
                 stream.escape(temp2)
-                stream.write("_write(' %%s=\"%%s\"' %% (%s, %s))" % (temp, temp2))
+                stream.write("%s(' %%s=\"%%s\"' %% (%s, %s))" % \
+                             (stream.symbols.write, temp, temp2))
                 stream.outdent()
                 stream.write("elif %s is not None:" % temp2)
             else:
@@ -543,7 +547,8 @@
             stream.indent()
             stream.write("%s = str(%s)" % (temp2, temp2))
             stream.escape(temp2)
-            stream.write("_write(' %%s=\"%%s\"' %% (%s, %s))" % (temp, temp2))
+            stream.write("%s(' %%s=\"%%s\"' %% (%s, %s))" % \
+                         (stream.symbols.write, temp, temp2))
             stream.outdent()
             stream.outdent()
             
@@ -554,21 +559,21 @@
             if unicode_required_flag:
                 stream.write("if isinstance(%s, unicode):" % temp)
                 stream.indent()
-                stream.write("_write(' %s=\"')" % attribute)
-                stream.write("_esc = %s.encode('utf-8')" % temp)
-                stream.escape("_esc")
-                stream.write("_write(_esc)")
-                stream.write("_write('\"')")
+                stream.write("%s(' %s=\"')" % (stream.symbols.write, attribute))
+                stream.write("%s = %s.encode('utf-8')" % (stream.symbols.tmp, temp))
+                stream.escape(stream.symbols.tmp)
+                stream.write("%s(%s)" % (stream.symbols.write, stream.symbols.tmp))
+                stream.write("%s('\"')" % stream.symbols.write)
                 stream.outdent()
                 stream.write("elif %s is not None:" % temp)
             else:
                 stream.write("if %s is not None:" % temp)
             stream.indent()
-            stream.write("_write(' %s=\"')" % attribute)
-            stream.write("_esc = str(%s)" % temp)
-            stream.escape("_esc")
-            stream.write("_write(_esc)")
-            stream.write("_write('\"')")
+            stream.write("%s(' %s=\"')" % (stream.symbols.write, attribute))
+            stream.write("%s = str(%s)" % (stream.symbols.tmp, temp))
+            stream.escape(stream.symbols.tmp)
+            stream.write("%s(%s)" % (stream.symbols.write, stream.symbols.tmp))
+            stream.write("%s('\"')" % stream.symbols.write)
             stream.outdent()
             assign.end(stream)
 
@@ -589,64 +594,62 @@
 
 class Repeat(object):
     """
-      >>> from z3c.pt.generation import CodeIO
-      >>> from z3c.pt.testing import pyexp
+    >>> from z3c.pt import testing
 
     We need to set up the repeat object.
 
-      >>> from z3c.pt import utils
-      >>> repeat = utils.repeatdict()
+    >>> from z3c.pt import utils
+    >>> repeat = utils.repeatdict()
 
     Simple repeat loop and repeat data structure:
 
-      >>> from StringIO import StringIO
-      >>> _out = StringIO(); _write = _out.write; stream = CodeIO()
-      >>> _repeat = Repeat("i", pyexp("range(5)"))
-      >>> _repeat.begin(stream)
-      >>> stream.write("r = repeat['i']")
-      >>> stream.write(
-      ...     "print (i, r.index, r.start, r.end, r.number(), r.odd(), r.even())")
-      >>> _repeat.end(stream)
-      >>> exec stream.getvalue()
-      (0, 0, True, False, 1, False, True)
-      (1, 1, False, False, 2, True, False)
-      (2, 2, False, False, 3, False, True)
-      (3, 3, False, False, 4, True, False)
-      (4, 4, False, True, 5, False, True)
-      >>> _repeat.end(stream)
+    >>> _out, _write, stream = testing.setup_stream()
+    >>> _repeat = Repeat("i", testing.pyexp("range(5)"))
+    >>> _repeat.begin(stream)
+    >>> stream.write("r = repeat['i']")
+    >>> stream.write(
+    ...     "print (i, r.index, r.start, r.end, r.number(), r.odd(), r.even())")
+    >>> _repeat.end(stream)
+    >>> exec stream.getvalue()
+    (0, 0, True, False, 1, False, True)
+    (1, 1, False, False, 2, True, False)
+    (2, 2, False, False, 3, False, True)
+    (3, 3, False, False, 4, True, False)
+    (4, 4, False, True, 5, False, True)
+    >>> _repeat.end(stream)
 
     A repeat over an empty set.
 
-      >>> stream = CodeIO()
-      >>> _repeat = Repeat("j", pyexp("range(0)"))
-      >>> _repeat.begin(stream)
-      >>> _repeat.end(stream)
-      >>> exec stream.getvalue()
+    >>> _out, _write, stream = testing.setup_stream()
+    >>> _repeat = Repeat("j", testing.pyexp("range(0)"))
+    >>> _repeat.begin(stream)
+    >>> _repeat.end(stream)
+    >>> exec stream.getvalue()
 
     A repeat over a non-iterable raises an exception.
 
-      >>> stream = CodeIO()
-      >>> _repeat = Repeat("j", pyexp("None"))
-      >>> _repeat.begin(stream)
-      >>> _repeat.end(stream)
-      >>> exec stream.getvalue()
-      Traceback (most recent call last):
-       ...
-      TypeError: Can only repeat over an iterable object (None).
-      
+    >>> _out, _write, stream = testing.setup_stream()
+    >>> _repeat = Repeat("j", testing.pyexp("None"))
+    >>> _repeat.begin(stream)
+    >>> _repeat.end(stream)
+    >>> exec stream.getvalue()
+    Traceback (most recent call last):
+     ...
+    TypeError: Can only repeat over an iterable object (None).
+
     Simple for loop:
+  
+    >>> _out, _write, stream = testing.setup_stream()
+    >>> _for = Repeat("i", testing.pyexp("range(3)"), repeatdict=False)
+    >>> _for.begin(stream)
+    >>> stream.write("print i")
+    >>> _for.end(stream)
+    >>> exec stream.getvalue()
+    0
+    1
+    2
+    >>> _for.end(stream)
 
-      >>> stream = CodeIO()
-      >>> _for = Repeat("i", pyexp("range(3)"), repeatdict=False)
-      >>> _for.begin(stream)
-      >>> stream.write("print i")
-      >>> _for.end(stream)
-      >>> exec stream.getvalue()
-      0
-      1
-      2
-      >>> _for.end(stream)
-
     """
 
     def __init__(self, v, e, scope=(), repeatdict=True):
@@ -701,14 +704,12 @@
 
 class Write(object):
     """
-    >>> from z3c.pt.generation import CodeIO
-    >>> from z3c.pt.testing import pyexp
-    >>> from StringIO import StringIO
+    >>> from z3c.pt import testing
 
     Basic write:
-    
-    >>> _out = StringIO(); _write = _out.write; stream = CodeIO()
-    >>> write = Write(pyexp("'New York'"))
+
+    >>> _out, _write, stream = testing.setup_stream()
+    >>> write = Write(testing.pyexp("'New York'"))
     >>> write.begin(stream)
     >>> write.end(stream)
     >>> exec stream.getvalue()
@@ -717,8 +718,8 @@
 
     Try-except parts:
 
-    >>> _out = StringIO(); _write = _out.write; stream = CodeIO()
-    >>> write = Write(pyexp("undefined | 'New Delhi'"))
+    >>> _out, _write, stream = testing.setup_stream()
+    >>> write = Write(testing.pyexp("undefined | 'New Delhi'"))
     >>> write.begin(stream)
     >>> write.end(stream)
     >>> exec stream.getvalue()
@@ -727,7 +728,7 @@
 
     Unicode:
 
-    >>> _out = StringIO(); _write = _out.write; stream = CodeIO()
+    >>> _out, _write, stream = testing.setup_stream()
     >>> write = Write(types.value("unicode('La Pe\xc3\xb1a', 'utf-8')"))
     >>> write.begin(stream)
     >>> write.end(stream)
@@ -752,44 +753,34 @@
     def begin(self, stream):
         temp = stream.save()
 
+        def write(template):
+            stream.write(template % stream.symbols.as_dict())
+            
         if self.value:
             expr = self.value
         else:
             self.assign.begin(stream, temp)
             expr = temp
 
-        stream.write("_urf = %s" % expr)
-
-        stream.write("if _urf is not None:")
+        stream.write("%s = %s" % (stream.symbols.tmp, expr))
+        write("if %(tmp)s is not None:")
         stream.indent()
         if unicode_required_flag:
-            stream.write("if isinstance(_urf, unicode):")
+            write("if isinstance(%(tmp)s, unicode):")
             stream.indent()
-            stream.write("_urf = _urf.encode('utf-8')")
+            write("%(tmp)s = %(tmp)s.encode('utf-8')")
             stream.outdent()
-            stream.write("else:")
+            write("else:")
             stream.indent()
-            stream.write("_urf = str(_urf)")
+            write("%(tmp)s = str(%(tmp)s)")
             stream.outdent()
         else:
-            stream.write("_urf = str(_urf)")
+            write("%(tmp)s = str(%(tmp)s)")
         if self.structure:
-            stream.write("_write(_urf)")
+            write("%(write)s(%(tmp)s)")
         else:
-            # Inlined escape function
-            stream.write("if '&' in _urf:")
-            stream.indent()
-            stream.write("_urf = _urf.replace('&', '&amp;')")
-            stream.outdent()
-            stream.write("if '<' in _urf:")
-            stream.indent()
-            stream.write("_urf = _urf.replace('<', '&lt;')")
-            stream.outdent()
-            stream.write("if '>' in _urf:")
-            stream.indent()
-            stream.write("_urf = _urf.replace('>', '&gt;')")
-            stream.outdent()
-            stream.write("_write(_urf)")
+            stream.escape(stream.symbols.tmp)
+            write("%(write)s(%(tmp)s)")
         stream.outdent()
 
         # validate XML if enabled
@@ -802,7 +793,7 @@
 
             stream.write("import z3c.pt.etree")
             stream.write("_ET = z3c.pt.etree.import_elementtree()")
-            stream.write("_ET.fromstring('<div>%s</div>' % _urf)")
+            write("_ET.fromstring('<div>%%s</div>' %% %(tmp)s)")
 
     def end(self, stream):
         if self.assign:
@@ -811,12 +802,11 @@
 
 class UnicodeWrite(Write):
     """
-    >>> from z3c.pt.generation import CodeIO
-    >>> from StringIO import StringIO
+    >>> from z3c.pt import testing
 
     Basic write:
 
-    >>> _out = StringIO(); _write = _out.write; stream = CodeIO()
+    >>> _out, _write, stream = testing.setup_stream()
     >>> write = Write(types.value("'New York'"))
     >>> write.begin(stream)
     >>> write.end(stream)
@@ -826,7 +816,7 @@
 
     Unicode:
 
-    >>> _out = StringIO(); _write = _out.write; stream = CodeIO()
+    >>> _out, _write, stream = testing.setup_stream()
     >>> write = Write(types.value("unicode('La Pe\xc3\xb1a', 'utf-8')"))
     >>> write.begin(stream)
     >>> write.end(stream)
@@ -839,7 +829,7 @@
 
     Invalid:
 
-    >>> _out = StringIO(); _write = _out.write; stream = CodeIO()
+    >>> _out, _write, stream = testing.setup_stream()
     >>> write = Write(types.value("None"))
     >>> write.begin(stream)
     >>> write.end(stream)
@@ -857,21 +847,19 @@
             self.assign.begin(stream, temp)
             expr = temp
 
-        stream.write("_write(%s)" % expr)
+        stream.write("%s(%s)" % (stream.symbols.write, expr))
 
 class Out(object):
     """
-      >>> from z3c.pt.generation import CodeIO
-      >>> from z3c.pt.testing import pyexp
-      >>> from StringIO import StringIO
+    >>> from z3c.pt import testing
       
-      >>> _out = StringIO(); _write = _out.write; stream = CodeIO()
-      >>> out = Out('Hello World!')
-      >>> out.begin(stream)
-      >>> out.end(stream)
-      >>> exec stream.getvalue()
-      >>> _out.getvalue()
-      'Hello World!'      
+    >>> _out, _write, stream = testing.setup_stream()
+    >>> out = Out('Hello World!')
+    >>> out.begin(stream)
+    >>> out.end(stream)
+    >>> exec stream.getvalue()
+    >>> _out.getvalue()
+    'Hello World!'
     """
     
     def __init__(self, string, defer=False):

Modified: z3c.pt/trunk/src/z3c/pt/config.py
===================================================================
--- z3c.pt/trunk/src/z3c/pt/config.py	2008-08-21 13:28:30 UTC (rev 90063)
+++ z3c.pt/trunk/src/z3c/pt/config.py	2008-08-21 13:34:43 UTC (rev 90064)
@@ -21,3 +21,29 @@
 I18N_NS = "http://xml.zope.org/namespaces/i18n"
 PY_NS = "http://genshi.edgewall.org"
 NS_MAP = dict(py=PY_NS, tal=TAL_NS, metal=METAL_NS)
+
+class SYMBOLS(object):
+    slot = '_slot'
+    metal = '_metal'
+    macro = '_macro'
+    scope = '_scope'
+    out = '_out'
+    tmp = '_tmp'
+    write = '_write'
+    mapping = '_mapping'
+    result = '_result'
+    marker = '_marker'
+    domain = '_domain'
+    context = '_context'
+    attributes = '_attributes'
+    negotiate = '_negotiate'
+    translate = '_translate'
+    path = '_path'
+    repeat = 'repeat'
+    language = 'target_language'
+    generation = 'generation'
+
+    @classmethod
+    def as_dict(cls):
+        return dict((name, getattr(cls, name)) for name in dir(cls))
+            

Modified: z3c.pt/trunk/src/z3c/pt/generation.py
===================================================================
--- z3c.pt/trunk/src/z3c/pt/generation.py	2008-08-21 13:28:30 UTC (rev 90063)
+++ z3c.pt/trunk/src/z3c/pt/generation.py	2008-08-21 13:34:43 UTC (rev 90064)
@@ -10,23 +10,24 @@
 from z3c.pt.config import DISABLE_I18N
 
 template_wrapper = """\
-def render(%(args)s%(extra)starget_language=None):
-\tglobal generation
+def render(%(args)s%(extra)s%(language)s=None):
+\tglobal %(generation)s
 
-\t_out, _write = generation.initialize_stream()
-\t_attributes, repeat = generation.initialize_tal()
-\t_domain, _negotiate, _translate = generation.initialize_i18n()
-\t_marker = generation.initialize_helpers()
-\t_path = generation.initialize_traversal()
-\t_scope = {}
-\t_target_language = _negotiate(_context, target_language)
+\t%(out)s, %(write)s = generation.initialize_stream()
+\t%(attributes)s, %(repeat)s = generation.initialize_tal()
+\t%(domain)s, %(negotiate)s, %(translate)s = generation.initialize_i18n()
+\t%(marker)s = %(generation)s.initialize_helpers()
+\t%(path)s = %(generation)s.initialize_traversal()
+\t%(scope)s = {}
+
+\t%(language)s = %(negotiate)s(%(context)s, %(language)s)
 %(code)s
-\treturn _out.getvalue()
+\treturn %(out)s.getvalue()
 """
 
 macro_wrapper = """\
 def render(%(kwargs)s%(extra)s):
-\tglobal generation
+\tglobal %(generation)s
 %(code)s
 """
 
@@ -67,44 +68,6 @@
 def initialize_traversal():
     return expressions.PathTranslation.traverse
 
-class Generator(object):
-    def __init__(self, params, wrapper):
-        self.params = list(params)
-        self.wrapper = wrapper
-        self.stream = CodeIO(indentation=1, indentation_string="\t")
-
-        # initialize variable scope
-        self.stream.scope.append(set(('_out', '_write', '_scope') + tuple(params)))
-
-    def __call__(self):
-        params = self.params
-        extra = ''
-
-        # prepare args
-        args = ', '.join(params)
-        if args:
-            args += ', '
-
-        # prepare kwargs
-        kwargs = ', '.join("%s=None" % param for param in params)
-        if kwargs:
-            kwargs += ', '
-            
-        # prepare selectors
-        for selector in self.stream.selectors:
-            extra += '%s=None, ' % selector
-
-        # we need to ensure we have _context for the i18n handling in
-        # the arguments. the default template implementations pass
-        # this in explicitly.
-        if '_context' not in params:
-            extra += '_context=None, '
-
-        code = self.stream.getvalue()
-        return self.wrapper % dict(
-            args=args, kwargs=kwargs, extra=extra, code=code), \
-            {'generation': z3c.pt.generation}
-
 class BufferIO(list):
     write = list.append
 
@@ -127,8 +90,9 @@
     t_prefix = '_tmp'
     v_prefix = '_var'
 
-    def __init__(self, indentation=0, indentation_string="\t"):
+    def __init__(self, symbols=None, indentation=0, indentation_string="\t"):
         BufferIO.__init__(self)
+        self.symbols = symbols or object
         self.indentation = indentation
         self.indentation_string = indentation_string
         self.queue = ''
@@ -169,8 +133,9 @@
         if self.queue:
             queue = self.queue
             self.queue = ''
-            self.write("_write('%s')" %
-                       queue.replace('\n', '\\n').replace("'", "\\'"))
+            self.write(
+                "%s('%s')" %
+                (self.symbols.write, queue.replace('\n', '\\n').replace("'", "\\'")))
 
     def write(self, string):
         if isinstance(string, unicode):

Modified: z3c.pt/trunk/src/z3c/pt/testing.py
===================================================================
--- z3c.pt/trunk/src/z3c/pt/testing.py	2008-08-21 13:28:30 UTC (rev 90063)
+++ z3c.pt/trunk/src/z3c/pt/testing.py	2008-08-21 13:34:43 UTC (rev 90064)
@@ -1,4 +1,5 @@
 import translation
+import generation
 import expressions
 import macro
 import etree
@@ -8,9 +9,21 @@
 import zpt
 import genshi
 
+from StringIO import StringIO
+
 def pyexp(string):
     return expressions.PythonTranslation.expression(string)
 
+def setup_stream():
+    class symbols(translation.Element.symbols):
+        out = '_out'
+        write = '_write'
+
+    out = StringIO()
+    write = out.write
+    stream = generation.CodeIO(symbols)
+    return out, write, stream
+
 def cook(generator, **kwargs):
     source, _globals = generator()
     _locals = {}

Modified: z3c.pt/trunk/src/z3c/pt/translation.py
===================================================================
--- z3c.pt/trunk/src/z3c/pt/translation.py	2008-08-21 13:28:30 UTC (rev 90063)
+++ z3c.pt/trunk/src/z3c/pt/translation.py	2008-08-21 13:34:43 UTC (rev 90064)
@@ -15,16 +15,13 @@
 class Element(etree.ElementBase):
     """Base compiler element class.
 
-    This class represents a node in the template tree. To start
-    compilation at this node, use the ``start`` method, providing a
-    code stream object.
+    This class represents an element in the template document tree. To
+    start compilation at this node, use the ``start`` method,
+    providing a code stream object.
     """
 
-    metal_slot_prefix = '_fill'
-    metal_variable = '_metal'
-    macro_variable = '_macro'
-    scope_variable = '_scope'
-    
+    symbols = config.SYMBOLS
+
     def start(self, stream):
         self._stream = stream
         self.visit()
@@ -82,14 +79,14 @@
         # i18n domain
         if self.node.translation_domain is not None:
             _.append(clauses.Define(
-                "_domain", types.value(repr(self.node.translation_domain))))
+                self.symbols.domain, types.value(repr(self.node.translation_domain))))
 
         # variable definitions
         if self.node.define is not None:
             for declaration, expression in self.node.define:
                 if declaration.global_scope:
                     _.append(clauses.Define(
-                        declaration, expression, self.scope_variable))
+                        declaration, expression, self.symbols.scope))
                 else:
                     _.append(clauses.Define(declaration, expression))
 
@@ -103,13 +100,13 @@
                 # define macro
                 subclauses = []
                 subclauses.append(clauses.Method(
-                    self.macro_variable, macro.args))
+                    self.symbols.macro, macro.args))
                 subclauses.append(clauses.Visit(element))
                 _.append(clauses.Group(subclauses))
                 
                 # assign to variable
                 _.append(clauses.Define(
-                    macro.name, types.parts((types.value(self.macro_variable),))))
+                    macro.name, types.parts((types.value(self.symbols.macro),))))
 
         # tag tail (deferred)
         tail = self.tail
@@ -136,7 +133,7 @@
         # macro slot definition
         if self.node.define_slot:
             # check if slot has been filled
-            variable = self.metal_slot_prefix + self.node.define_slot
+            variable = self.symbols.slot + self.node.define_slot
             if variable in itertools.chain(*self.stream.scope):
                 content = types.value(variable)
 
@@ -223,19 +220,19 @@
             kwargs = []
             for element in self.xpath(
                 './/*[@metal:fill-slot]', namespaces={'metal': config.METAL_NS}):
-                variable = self.metal_slot_prefix+element.node.fill_slot
+                variable = self.symbols.slot+element.node.fill_slot
                 kwargs.append((variable, variable))
                 
                 subclauses = []
                 subclauses.append(clauses.Define(
-                    types.declaration(('_out', '_write')),
-                    types.value('generation.initialize_stream()')))
+                    types.declaration((self.symbols.out, self.symbols.write)),
+                    types.template('%(generation)s.initialize_stream()')))
                 subclauses.append(clauses.Visit(element))
                 subclauses.append(clauses.Assign(
-                    types.value('_out.getvalue()'), variable))
+                    types.template('%(out)s.getvalue()'), variable))
                 _.append(clauses.Group(subclauses))
                 
-            _.append(clauses.Assign(self.node.use_macro, self.metal_variable))
+            _.append(clauses.Assign(self.node.use_macro, self.symbols.metal))
 
             # compute macro function arguments and create argument string
             arguments = ", ".join(
@@ -244,7 +241,7 @@
                 tuple("%s=%s" % kwarg for kwarg in kwargs))
                 
             _.append(clauses.Write(
-                types.value("%s(%s)" % (self.metal_variable, arguments))))
+                types.value("%s(%s)" % (self.symbols.metal, arguments))))
 
         # translate body
         elif self.node.translate is not None:
@@ -257,7 +254,7 @@
             elements = [e for e in self if e.i18n_name]
 
             if elements:
-                mapping = '_mapping'
+                mapping = self.symbols.mapping
                 _.append(clauses.Assign(types.value('{}'), mapping))
             else:
                 mapping = 'None'
@@ -267,23 +264,23 @@
 
                 subclauses = []
                 subclauses.append(clauses.Define(
-                    types.declaration(('_out', '_write')),
-                    types.value('generation.initialize_stream()')))
+                    types.declaration((self.symbols.out, self.symbols.write)),
+                    types.template('%(generation)s.initialize_stream()')))
                 subclauses.append(clauses.Visit(element))
                 subclauses.append(clauses.Assign(
-                    types.value('_out.getvalue()'),
+                    types.template('%(out)s.getvalue()'),
                     "%s['%s']" % (mapping, name)))
 
                 _.append(clauses.Group(subclauses))
 
             _.append(clauses.Assign(
                 _translate(types.value(repr(msgid)), mapping=mapping,
-                           default='_marker'), '_result'))
+                           default=self.symbols.marker), self.symbols.result))
 
             # write translation to output if successful, otherwise
             # fallback to default rendition; 
-            result = types.value('_result')
-            condition = types.value('_result is not _marker')
+            result = types.value(self.symbols.result)
+            condition = types.template('%(result)s is not %(marker)s')
             _.append(clauses.Condition(condition,
                         [clauses.UnicodeWrite(result)]))
 
@@ -444,9 +441,16 @@
         wrapper = generation.macro_wrapper
     else:
         wrapper = generation.template_wrapper
-    generator = generation.Generator(params, wrapper)
-    stream = generator.stream
 
+    # initialize code stream object
+    stream = generation.CodeIO(
+        root.symbols, indentation=1, indentation_string="\t")
+
+    # initialize variable scope
+    stream.scope.append(set(
+        (stream.symbols.out, stream.symbols.write, stream.symbols.scope) + \
+        tuple(params)))
+
     # output doctype if any
     if doctype and isinstance(doctype, (str, unicode)):
         dt = (doctype +'\n').encode('utf-8')
@@ -456,9 +460,47 @@
         stream.end([doctype])
         stream.scope.pop()
 
+    # start generation
     root.start(stream)
-    return generator
 
+    extra = ''
+
+    # prepare args
+    args = ', '.join(params)
+    if args:
+        args += ', '
+
+    # prepare kwargs
+    kwargs = ', '.join("%s=None" % param for param in params)
+    if kwargs:
+        kwargs += ', '
+
+    # prepare selectors
+    for selector in stream.selectors:
+        extra += '%s=None, ' % selector
+
+    # we need to ensure we have _context for the i18n handling in
+    # the arguments. the default template implementations pass
+    # this in explicitly.
+    if stream.symbols.context not in params:
+        extra += '%s=None, ' % stream.symbols.context
+
+    code = stream.getvalue()
+
+    class generator(object):
+        @property
+        def stream(self):
+            return stream
+        
+        def __call__(self):
+            parameters = dict(
+                args=args, kwargs=kwargs, extra=extra, code=code)
+            parameters.update(stream.symbols.__dict__)
+
+            return wrapper % parameters, {stream.symbols.generation: generation}
+
+    return generator()
+
 def translate_text(body, parser, *args, **kwargs):
     root, doctype = parser.parse("<html xmlns='%s'></html>" % config.XHTML_NS)
     root.text = body
@@ -466,9 +508,10 @@
     return translate_etree(root, doctype=doctype, *args, **kwargs)
     
 def _translate(value, mapping=None, default=None):
-    format = ("_translate(%s, domain=_domain, mapping=%s, context=_context, "
-              "target_language=_target_language, default=%s)")
-    return types.value(format % (value, mapping, default))
+    format = "_translate(%s, domain=%%(domain)s, mapping=%s, context=%%(context)s, " \
+             "target_language=%%(language)s, default=%s)"
+    return types.template(
+        format % (value, mapping, default))
 
 def _not(value):
     return types.value("not (%s)" % value)

Modified: z3c.pt/trunk/src/z3c/pt/types.py
===================================================================
--- z3c.pt/trunk/src/z3c/pt/types.py	2008-08-21 13:28:30 UTC (rev 90063)
+++ z3c.pt/trunk/src/z3c/pt/types.py	2008-08-21 13:34:43 UTC (rev 90064)
@@ -9,6 +9,10 @@
     def __repr__(self):
         return 'value(%s)' % str.__repr__(self)
 
+class template(value):
+    def __repr__(self):
+        return 'template(%s)' % str.__repr__(self)
+
 class join(tuple, expression):
     def __repr__(self):
         return 'join'+tuple.__repr__(self)



More information about the Checkins mailing list