[Checkins] SVN: z3c.pt/trunk/ Compiler moved out to chameleon.core and chameleon.zpt packages.

Malthe Borch mborch at gmail.com
Thu Oct 2 15:46:06 EDT 2008


Log message for revision 91672:
  Compiler moved out to chameleon.core and chameleon.zpt packages.

Changed:
  U   z3c.pt/trunk/CHANGES.txt
  U   z3c.pt/trunk/README.txt
  U   z3c.pt/trunk/benchmark/benchmark/tests.py
  U   z3c.pt/trunk/buildout.cfg
  U   z3c.pt/trunk/setup.py
  A   z3c.pt/trunk/src/z3c/pt/README.txt
  D   z3c.pt/trunk/src/z3c/pt/clauses.py
  D   z3c.pt/trunk/src/z3c/pt/codegen.py
  D   z3c.pt/trunk/src/z3c/pt/codegen.txt
  D   z3c.pt/trunk/src/z3c/pt/config.py
  U   z3c.pt/trunk/src/z3c/pt/configure.zcml
  D   z3c.pt/trunk/src/z3c/pt/doctypes.py
  D   z3c.pt/trunk/src/z3c/pt/etree.py
  U   z3c.pt/trunk/src/z3c/pt/expressions.py
  D   z3c.pt/trunk/src/z3c/pt/filecache.py
  D   z3c.pt/trunk/src/z3c/pt/generation.py
  D   z3c.pt/trunk/src/z3c/pt/genshi.py
  D   z3c.pt/trunk/src/z3c/pt/genshi.txt
  D   z3c.pt/trunk/src/z3c/pt/interfaces.py
  U   z3c.pt/trunk/src/z3c/pt/loader.py
  U   z3c.pt/trunk/src/z3c/pt/pagetemplate.py
  D   z3c.pt/trunk/src/z3c/pt/template.py
  D   z3c.pt/trunk/src/z3c/pt/template.txt
  D   z3c.pt/trunk/src/z3c/pt/testing.py
  U   z3c.pt/trunk/src/z3c/pt/tests/test_doctests.py
  D   z3c.pt/trunk/src/z3c/pt/tests/test_edgecases.py
  U   z3c.pt/trunk/src/z3c/pt/tests/view.pt
  D   z3c.pt/trunk/src/z3c/pt/tests/xinclude1.pt
  D   z3c.pt/trunk/src/z3c/pt/tests/xinclude2.pt
  D   z3c.pt/trunk/src/z3c/pt/tests/xinclude3.pt
  D   z3c.pt/trunk/src/z3c/pt/tests/xinclude4.pt
  U   z3c.pt/trunk/src/z3c/pt/texttemplate.py
  D   z3c.pt/trunk/src/z3c/pt/transformer.py
  D   z3c.pt/trunk/src/z3c/pt/translation.py
  D   z3c.pt/trunk/src/z3c/pt/translation.txt
  D   z3c.pt/trunk/src/z3c/pt/types.py
  D   z3c.pt/trunk/src/z3c/pt/utils.py
  D   z3c.pt/trunk/src/z3c/pt/zpt.py
  D   z3c.pt/trunk/src/z3c/pt/zpt.txt

-=-
Modified: z3c.pt/trunk/CHANGES.txt
===================================================================
--- z3c.pt/trunk/CHANGES.txt	2008-10-02 19:44:09 UTC (rev 91671)
+++ z3c.pt/trunk/CHANGES.txt	2008-10-02 19:46:03 UTC (rev 91672)
@@ -4,6 +4,10 @@
 Version 1.0dev
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
+  Package changes
+
+- Split out compiler to "Chameleon" package. [malthe]
+
   Backwards incompatibilities
 
 - Moved contents of ``z3c.pt.macro`` module into

Modified: z3c.pt/trunk/README.txt
===================================================================
--- z3c.pt/trunk/README.txt	2008-10-02 19:44:09 UTC (rev 91671)
+++ z3c.pt/trunk/README.txt	2008-10-02 19:46:03 UTC (rev 91672)
@@ -1,78 +1,10 @@
 Overview
---------
+========
 
-The z3c.pt package provides a fast template engine that supports the
-following dialects of the attribute template language:
+This package extends ``chameleon.zpt`` to provide application-level
+template support corresponding to ``zope.app.pagetemplate``, but using
+the fast Chameleon engine to compile templates into byte-code.
 
-* Zope TAL
-* Zope METAL
-* Zope i18n
-* Genshi
+For usage, see the README.txt file inside the package.
 
-Non-structural documents are supported through Genshi's variable
-interpolation syntax which is also available for XML templates.
 
-Casual benchmarks pegs it 16x more performant than the reference
-implementations for Zope TAL and Genshi.
-
-In a nutshell:
-
-* Templates are serialized and compiled into Python bytecode
-* Pluggable expression implementation
-
-
-Usage
------
-
-See README.txt inside package for general usage; to register the
-default expression types, load the package component configuration
-file (configure.zcml).
-
-
-Compiler notes
---------------
-
-The compiler is largely compatible with the targeted dialects. The TAL
-implementation is based on the 1.4 language specification* while the
-Genshi implementation is based on the documents for the 0.5 release**.
-
-Some notable changes:
-
-1. Tuple unpacking is allowed when defining variables:
-
-      tal:define="(a, b, c) [1, 2, 3]"
-
-2. Generators are allowed in tal:repeat statements. Note that the
-   repeat variable is not available in this case.
-
-      tal:repeat="i <some generator>"
-
-3. Attribute-access to dictionary entries is allowed in
-   Python-expressions, e.g.
-
-      dictionary.key
-
-   can be used instead of ``dictionary['key']``.
-
-4. Default expression type can be set using ``tal:default-expression``.
-   This is an alternative to providing the expression type before each
-   expression.
-
-5. The XPath select function provided to py:match-elements uses lxml
-   and requires the use of the default namespace prefix "xmlns".
-
-.. _TAL: http://wiki.zope.org/ZPT/TALSpecification14
-.. _Genshi: http://genshi.edgewall.org/wiki/Documentation/xml-templates.html
-
-
-Development
------------
-
-If you want to use the code directly from trunk (recommended only for
-development and testing usage), provide ``z3c.pt==dev`` as your
-dependency.
-
-svn://svn.zope.org/repos/main/z3c.pt/trunk#egg=z3c.pt-dev
-
-Want to contribute? Join #zope3-dev on Freenode IRC.
-

Modified: z3c.pt/trunk/benchmark/benchmark/tests.py
===================================================================
--- z3c.pt/trunk/benchmark/benchmark/tests.py	2008-10-02 19:44:09 UTC (rev 91671)
+++ z3c.pt/trunk/benchmark/benchmark/tests.py	2008-10-02 19:46:03 UTC (rev 91672)
@@ -11,8 +11,9 @@
 import zope.pagetemplate.pagetemplatefile
 import z3c.pt
 
-from z3c.pt import config
-from z3c.pt import filecache
+from chameleon.core import config
+from chameleon.core import filecache
+
 from z3c.pt import pagetemplate
 
 from lxml import etree
@@ -63,7 +64,7 @@
 
 class BenchmarkTestCase(BaseTestCase):
 
-    helloworld_z3c = pagetemplate.PageTemplate("""\
+    helloworld_z3c = pagetemplate.ZopePageTemplate("""\
     <div xmlns="http://www.w3.org/1999/xhtml">
     Hello World!
     </div>""")
@@ -86,7 +87,7 @@
     </tr>
     </table>""")
 
-    bigtable_path_z3c = pagetemplate.PageTemplate("""\
+    bigtable_path_z3c = pagetemplate.ZopePageTemplate("""\
     <table xmlns="http://www.w3.org/1999/xhtml"
     xmlns:tal="http://xml.zope.org/namespaces/tal"
     tal:default-expression="path">
@@ -229,7 +230,7 @@
     def testBigTablePathFile(self):
         table = self.table
 
-        z3cfile = pagetemplate.PageTemplateFile(
+        z3cfile = pagetemplate.ZopePageTemplateFile(
             self._testfile('bigtable_path_z3c.pt'))
 
         zopefile = zope.pagetemplate.pagetemplatefile.PageTemplateFile(

Modified: z3c.pt/trunk/buildout.cfg
===================================================================
--- z3c.pt/trunk/buildout.cfg	2008-10-02 19:44:09 UTC (rev 91671)
+++ z3c.pt/trunk/buildout.cfg	2008-10-02 19:46:03 UTC (rev 91672)
@@ -1,8 +1,6 @@
 [buildout]
-develop =
-    .
-    benchmark
-
+develop = . benchmark
+    
 parts =
     test
     test-nolxml

Modified: z3c.pt/trunk/setup.py
===================================================================
--- z3c.pt/trunk/setup.py	2008-10-02 19:44:09 UTC (rev 91671)
+++ z3c.pt/trunk/setup.py	2008-10-02 19:46:03 UTC (rev 91672)
@@ -9,6 +9,7 @@
     'zope.i18n >= 3.5',
     'zope.traversing',
     'zope.contentprovider',
+    'chameleon.zpt',
     ]
 
 if sys.version_info[:3] < (2,5,0):

Copied: z3c.pt/trunk/src/z3c/pt/README.txt (from rev 91339, z3c.pt/trunk/src/z3c/pt/template.txt)
===================================================================
--- z3c.pt/trunk/src/z3c/pt/README.txt	                        (rev 0)
+++ z3c.pt/trunk/src/z3c/pt/README.txt	2008-10-02 19:46:03 UTC (rev 91672)
@@ -0,0 +1,99 @@
+z3c.pt
+======
+
+This section demonstrates the high-level template classes. All page
+template classes in ``z3c.pt`` use path-expressions by default.
+
+Page templates
+--------------
+
+  >>> from z3c.pt.pagetemplate import ZopePageTemplate
+  >>> from z3c.pt.pagetemplate import ZopePageTemplateFile  
+
+The ``ZopePageTemplate`` class is initialized with a string.
+  
+  >>> print ZopePageTemplate("""\
+  ... <div xmlns="http://www.w3.org/1999/xhtml">
+  ...   Hello World!
+  ... </div>""")()
+  <div>
+    Hello World!
+  </div>
+
+The ``ZopePageTemplateFile`` class is initialized with an absolute
+path to a template file on disk.
+  
+  >>> from z3c.pt import tests
+  >>> path = tests.__path__[0]
+  >>> t = ZopePageTemplateFile(path+'/helloworld.pt')
+  >>> print t()
+  <div>
+    Hello World!
+  </div>
+
+  >>> import os
+  >>> t.filename.startswith(os.sep)
+  True
+
+View page templates
+-------------------
+
+  >>> from z3c.pt.pagetemplate import ViewPageTemplate
+  >>> from z3c.pt.pagetemplate import ViewPageTemplateFile
+  
+  >>> class View(object):
+  ...     request = u'request'
+  ...     context = u'context'
+  ...
+  ...     def __repr__(self):
+  ...         return 'view'
+  
+  >>> view = View()
+
+As before, we can initialize view page templates with a string (here
+incidentally loaded from disk).
+  
+  >>> template = ViewPageTemplate(
+  ...     open(path+'/view.pt').read())
+
+To render the template in the context of a view, we bind the template
+passing the view as an argument (view page templates derive from the
+``property``-class and are usually defined as an attribute on a view
+class).
+
+  >>> print template.bind(view)(test=u'test')
+  <div>
+    <span>view</span>
+    <span>context</span>
+    <span>request</span>
+    <span>test</span>
+  </div>
+  
+The exercise is similar for the file-based variant.
+  
+  >>> template = ViewPageTemplateFile(path+'/view.pt')
+  >>> print template.bind(view)(test=u'test')
+  <div>
+    <span>view</span>
+    <span>context</span>
+    <span>request</span>
+    <span>test</span>
+  </div>
+
+Text templates
+--------------
+
+  >>> from z3c.pt.texttemplate import ViewTextTemplate
+  >>> from z3c.pt.texttemplate import ViewTextTemplateFile
+  
+  >>> template = ViewTextTemplate(open(path+'/view.css').read())
+  >>> print template.bind(view)(color=u'#ccc')
+  #region {
+      background: #ccc;
+  }
+
+  >>> template = ViewTextTemplateFile(path+'/view.css')
+  >>> print template.bind(view)(color=u'#ccc')
+  #region {
+      background: #ccc;
+  }

Deleted: z3c.pt/trunk/src/z3c/pt/clauses.py
===================================================================
--- z3c.pt/trunk/src/z3c/pt/clauses.py	2008-10-02 19:44:09 UTC (rev 91671)
+++ z3c.pt/trunk/src/z3c/pt/clauses.py	2008-10-02 19:46:03 UTC (rev 91672)
@@ -1,930 +0,0 @@
-from z3c.pt import types
-from z3c.pt import config
-from z3c.pt import etree
-from z3c.pt import utils
-
-class Assign(object):
-    """
-    >>> 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'")
-    >>> ghi = types.value("'ghi'")
-    >>> exclamation = types.value("'!'")
-        
-    Simple value assignment:
-    
-    >>> assign = Assign(one)
-    >>> assign.begin(stream, 'a')
-    >>> exec stream.getvalue()
-    >>> a == 1
-    True
-    >>> assign.end(stream)
-    
-    Try-except parts (bad, good):
-    
-    >>> assign = Assign(types.parts((bad_float, one)))
-    >>> assign.begin(stream, 'b')
-    >>> exec stream.getvalue()
-    >>> b == 1
-    True
-    >>> assign.end(stream)
-    
-    Try-except parts (good, bad):
-    
-    >>> assign = Assign(types.parts((one, bad_float)))
-    >>> assign.begin(stream, 'b')
-    >>> exec stream.getvalue()
-    >>> b == 1
-    True
-    >>> assign.end(stream)
-    
-    Join:
-
-    >>> assign = Assign(types.join((abc, ghi)))
-    >>> assign.begin(stream, 'b')
-    >>> exec stream.getvalue()
-    >>> b == 'abcghi'
-    True
-    >>> assign.end(stream)
-
-    Join with try-except parts:
-    
-    >>> assign = Assign(types.join((types.parts((bad_float, abc, ghi)), ghi)))
-    >>> assign.begin(stream, 'b')
-    >>> exec stream.getvalue()
-    >>> b == 'abcghi'
-    True
-    >>> assign.end(stream)
-    """
-
-    def __init__(self, parts, variable=None):
-        if not isinstance(parts, types.parts):
-            parts = types.parts((parts,))
-
-        self.parts = parts
-        self.variable = variable
-        
-    def begin(self, stream, variable=None):
-        """First n - 1 expressions must be try-except wrapped."""
-
-        variable = variable or self.variable
-
-        for value in self.parts[:-1]:
-            stream.write("try:")
-            stream.indent()
-
-            self._assign(variable, value, stream)
-            
-            stream.outdent()
-            stream.write("except Exception, e:")
-            stream.indent()
-
-        value = self.parts[-1]
-        self._assign(variable, value, stream)
-        
-        stream.outdent(len(self.parts)-1)
-
-    def _assign(self, variable, value, stream):
-        stream.annotate(value)
-        symbols = stream.symbols.as_dict()
-
-        if value.symbol_mapping:
-            stream.symbol_mapping.update(value.symbol_mapping)
-
-        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):
-            parts = []
-            _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)
-                    assign.begin(stream)
-                    assign.end(stream)
-                    _v_count +=1
-                    parts.append(_v)
-                elif isinstance(part, types.value):
-                    parts.append(part)
-                elif isinstance(part, unicode):
-                    if stream.encoding:
-                        parts.append(repr(part.encode(stream.encoding)))
-                    else:
-                        parts.append(repr(part))
-                elif isinstance(part, str):
-                    parts.append(repr(part))
-                else:
-                    raise ValueError("Not able to handle %s" % type(part))
-                    
-            format = "%s"*len(parts)
-
-            stream.write("%s = '%s' %% (%s)" % (variable, format, ",".join(parts)))
-            
-            for i in range(_v_count):
-                stream.restore()
-        
-    def end(self, stream):
-        pass
-
-class Define(object):
-    """
-    >>> from z3c.pt import testing
-
-    Variable scope:
-
-    >>> _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:
-
-    >>> _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:
-
-    >>> _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:
-
-    >>> _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:
-
-    >>> _out, _write, stream = testing.setup_stream()
-    >>> define = Define("a", testing.pyexp("';'"))
-    >>> define.begin(stream)
-    >>> exec stream.getvalue()
-    >>> a
-    ';'
-    >>> define.end(stream)
-
-    Scope:
-
-    >>> _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
-    """
-
-    assign = None
-    
-    def __init__(self, declaration, expression=None, dictionary=None):
-        if not isinstance(declaration, types.declaration):
-            declaration = types.declaration((declaration,))
-
-        if len(declaration) == 1:
-            variable = declaration[0]
-        else:
-            variable = u"(%s,)" % ", ".join(declaration)
-
-        if dictionary is not None:
-           variable = "%s['%s'] = %s" % (dictionary, variable, variable)
-
-        if expression is not None:
-            self.assign = Assign(expression, variable)
-            
-        self.declaration = declaration
-        self.dictionary = dictionary
-        
-    def begin(self, stream):
-        if self.declaration.global_scope:
-            # if the declaration belongs to a global scope, remove this
-            # symbol from previous scopes
-            for scope in stream.scope:
-                for variable in self.declaration:
-                    if variable in scope:
-                        scope.remove(variable)
-        else:
-            # save local variables already in in scope
-            for var in self.declaration:
-                temp = stream.save()
-
-                # If we didn't set the variable in this scope already
-                if var not in stream.scope[-1]:
-
-                    # we'll check if it's set in one of the older scopes
-                    for scope in stream.scope[:-1]:
-                        if var in scope:
-                            # in which case we back it up
-                            stream.write('%s = %s' % (temp, var))
-
-                    stream.scope[-1].add(var)
-
-        if self.assign is not None:
-            self.assign.begin(stream)
-
-    def end(self, stream):
-        if self.assign is not None:
-            self.assign.end(stream)
-
-        if not self.declaration.global_scope:
-            # restore the variables that were previously in scope
-            for var in reversed(self.declaration):
-                temp = stream.restore()
-
-                # If we set the variable in this scope already
-                if var in stream.scope[-1]:
-
-                    # we'll check if it's set in one of the older scopes
-                    for scope in stream.scope[:-1]:
-                        if var in scope:
-                            # in which case we restore it
-                            stream.write('%s = %s' % (var, temp))
-                            stream.scope[-1].remove(var)
-                            break
-                    else:
-                        stream.write("del %s" % var)
-
-class Condition(object):
-    """
-    >>> from z3c.pt import testing
-
-    Unlimited scope:
-
-    >>> _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, _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, _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):
-        self.assign = Assign(value)
-        self.clauses = clauses
-        self.finalize = finalize
-        
-    def begin(self, stream):
-        temp = stream.save()
-        self.assign.begin(stream, temp)
-        stream.write("if %s:" % temp)
-        stream.indent()
-        if self.clauses:
-            for clause in self.clauses:
-                clause.begin(stream)
-            if self.finalize:
-                for clause in reversed(self.clauses):
-                    clause.end(stream)
-            stream.outdent()
-        
-    def end(self, stream):
-        temp = stream.restore()
-
-        if self.clauses:
-            if not self.finalize:
-                stream.write("if %s:" % temp)
-                stream.indent()
-                for clause in reversed(self.clauses):
-                    clause.end(stream)
-                    stream.outdent()
-        else:
-            stream.outdent()
-        self.assign.end(stream)
-
-class Else(object):
-    def __init__(self, clauses=None):
-        self.clauses = clauses
-        
-    def begin(self, stream):
-        stream.write("else:")
-        stream.indent()
-        if self.clauses:
-            for clause in self.clauses:
-                clause.begin(stream)
-            for clause in reversed(self.clauses):
-                clause.end(stream)
-            stream.outdent()
-        
-    def end(self, stream):
-        if not self.clauses:
-            stream.outdent()
-
-class Group(object):
-    def __init__(self, clauses):
-        self.clauses = clauses
-        
-    def begin(self, stream):
-        for clause in self.clauses:
-            clause.begin(stream)
-        for clause in reversed(self.clauses):
-            clause.end(stream)
-
-    def end(self, stream):
-        pass
-
-class Visit(object):
-    def __init__(self, node):
-        self.node = node
-        
-    def begin(self, stream):
-        self.node.visit()
-
-    def end(self, stream):
-        pass
-
-class Tag(object):
-    """
-    >>> from z3c.pt import testing
-
-    Dynamic attribute:
-
-    >>> _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>'
-
-    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,
-                 selfclosing=False, expression=None, cdata=False):
-        self.tag = tag.split('}')[-1]
-        self.selfclosing = selfclosing
-        self.attributes = attributes or {}
-        self.expression = expression and Assign(expression)
-        self.cdata = cdata
-        
-    def begin(self, stream):
-        if self.cdata:
-            stream.out('<![CDATA['); return
-
-        stream.out('<%s' % self.tag)
-
-        static = filter(
-            lambda (attribute, value): \
-            not isinstance(value, types.expression),
-            self.attributes.items())
-
-        # sort static attribute alphabetically by name
-        static.sort(key=lambda (name, value): name)
-
-        dynamic = filter(
-            lambda (attribute, value): \
-            isinstance(value, types.expression),
-            self.attributes.items())
-
-        temp = stream.save()
-        temp2 = stream.save()
-        
-        if self.expression:
-            self.expression.begin(stream, stream.symbols.tmp)
-            # loop over all attributes
-            stream.write("for %s, %s in %s.items():" % \
-                         (temp, temp2, stream.symbols.tmp))            
-            stream.indent()
-
-            # only include attribute if expression is not None
-            stream.write("if %s is not None:" % temp2)                
-            stream.indent()
-
-            # if an encoding is specified, we need to check
-            # whether we're dealing with unicode strings or not,
-            # before writing out the attribute
-            if stream.encoding is not None:
-                # attribute name
-                stream.write("if isinstance(%s, unicode):" % temp)
-                stream.indent()
-                stream.write("%s = %s.encode('%s')" % (temp, temp, stream.encoding))
-                stream.outdent()
-
-                # attribute expression
-                stream.write("if isinstance(%s, unicode):" % temp2)
-                stream.indent()
-                stream.write("%s = %s.encode('%s')" % (temp2, temp2, stream.encoding))
-                stream.outdent()
-                stream.write("elif not isinstance(%s, str):" % temp2)
-            else:
-                stream.write("if not isinstance(%s, (str, unicode)):" % temp2)
-
-            # make sure this is a string
-            stream.indent()
-            stream.write("%s = str(%s)" % (temp2, temp2))
-            stream.outdent()
-                
-            # escape expression
-            stream.escape(temp2)
-
-            # write out
-            stream.write("%s(' %%s=\"%%s\"' %% (%s, %s))" % \
-                         (stream.symbols.write, temp, temp2))
-
-            stream.outdent()
-            stream.outdent()
-            
-        for attribute, value in dynamic:
-            assign = Assign(value)
-            assign.begin(stream, temp)
-
-            # only include attribute if expression is not ``None`` or ``False``
-            stream.write("if %s is not None and %s is not False:" % (temp, temp))
-            stream.indent()
-
-            # if an encoding is specified, we need to check
-            # whether we're dealing with unicode strings or not,
-            # before writing out the attribute
-            if stream.encoding is not None:
-                stream.write("if isinstance(%s, unicode):" % temp)
-                stream.indent()
-                stream.write("%s = %s.encode('%s')" % (temp, temp, stream.encoding))
-                stream.outdent()
-                stream.write("elif not isinstance(%s, str):" % temp)
-            else:
-                stream.write("if not isinstance(%s, (str, unicode)):" % temp)
-                
-            # make sure this is a string
-            stream.indent()
-            stream.write("%s = str(%s)" % (temp, temp))
-            stream.outdent()
-
-            # escape expression
-            stream.escape(temp)
-
-            # print attribute
-            stream.write("%s(' %s=\"'+%s+'\"')" % (
-                stream.symbols.write, attribute, temp))
-
-            stream.outdent()
-            assign.end(stream)
-
-        stream.restore()
-        stream.restore()
-
-        for attribute, expression in static:
-            if isinstance(expression, unicode) and stream.encoding:
-                expression = expression.encode(stream.encoding)
-
-            # escape expression
-            expression = utils.escape(expression, '"', stream.encoding)
-
-            # if there are dynamic expressions, we only want to write
-            # out static attributes if they're not in the dynamic
-            # expression dictionary
-            if self.expression:
-                stream.write("if '%s' not in %s:" % (attribute, stream.symbols.tmp))
-                stream.indent()
-                
-            stream.out(' %s="%s"' % (attribute, expression))
-
-            if self.expression:
-                stream.outdent()
-                
-        if self.selfclosing:
-            stream.out(" />")
-        else:
-            stream.out(">")
-
-    def end(self, stream):
-        if self.cdata:
-            stream.out(']]>'); return
-            
-        if not self.selfclosing:
-            stream.out('</%s>' % self.tag)
-
-class Repeat(object):
-    """
-    >>> from z3c.pt import testing
-
-    We need to set up the repeat object.
-
-    >>> from z3c.pt import utils
-    >>> repeat = utils.repeatdict()
-
-    Simple repeat loop and repeat data structure:
-
-    >>> _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.
-
-    >>> _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.
-
-    >>> _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)
-
-    """
-
-    def __init__(self, v, e, scope=(), repeatdict=True):
-        self.variable = v
-        self.expression = e
-        self.define = Define(v)
-        self.assign = Assign(e)
-        self.repeatdict = repeatdict
-
-    def begin(self, stream):
-        variable = self.variable
-
-        if self.repeatdict:
-            # initialize variable scope
-            self.define.begin(stream)
-
-            # assign iterator
-            iterator = stream.save()
-            self.assign.begin(stream, iterator)
-
-            # initialize iterator
-            stream.write("%s = repeat.insert('%s', %s)" % (
-                iterator, variable, iterator))
-
-            # loop
-            stream.write("try:")
-            stream.indent()
-            stream.write("%s = None" % variable)
-            stream.write("%s = %s.next()" % (variable, iterator))
-            stream.write("while True:")
-            stream.indent()
-        else:
-            stream.write("for %s in %s:" % (variable, self.expression))
-            stream.indent()
-
-    def end(self, stream):
-        # cook before leaving loop
-        stream.cook()
-
-        if self.repeatdict:
-            iterator = stream.restore()
-            stream.write("%s = %s.next()" % (self.variable, iterator))
-            
-        stream.out('\n')
-        stream.outdent()
-        
-        if self.repeatdict:
-            stream.outdent()
-            stream.write("except StopIteration:")
-            stream.indent()
-            stream.write("pass")
-            stream.outdent()
-
-            self.define.end(stream)
-            self.assign.end(stream)
-
-class Write(object):
-    """
-    >>> from z3c.pt import testing
-
-    Basic write:
-
-    >>> _out, _write, stream = testing.setup_stream()
-    >>> write = Write(testing.pyexp("'New York'"))
-    >>> write.begin(stream)
-    >>> write.end(stream)
-    >>> exec stream.getvalue()
-    >>> _out.getvalue()
-    'New York'
-
-    Try-except parts:
-
-    >>> _out, _write, stream = testing.setup_stream()
-    >>> write = Write(testing.pyexp("undefined | 'New Delhi'"))
-    >>> write.begin(stream)
-    >>> write.end(stream)
-    >>> exec stream.getvalue()
-    >>> _out.getvalue()
-    'New Delhi'
-
-    Unicode:
-
-    >>> _out, _write, stream = testing.setup_stream('utf-8')
-    >>> write = Write(types.value(repr('La Pe\xc3\xb1a'.decode('utf-8'))))
-    >>> write.begin(stream)
-    >>> write.end(stream)
-    >>> exec stream.getvalue()
-    >>> val = _out.getvalue()
-    >>> val == 'La Pe\xc3\xb1a'
-    True
-    >>> type(val) == str
-    True
-    """
-
-    value = assign = None
-    
-    def __init__(self, value):
-        self.assign = Assign(value)
-        self.structure = not isinstance(value, types.escape)
-        
-    def begin(self, stream):
-        temp = stream.save()
-        symbols = stream.symbols.as_dict()
-        value = self.value
-        
-        if isinstance(value, types.template):
-            value = types.value(value % symbols)
-
-        def write(template):
-            stream.write(template % symbols)
-            
-        if value:
-            expr = value
-        else:
-            self.assign.begin(stream, temp)
-            expr = temp
-
-        stream.write("%s = %s" % (stream.symbols.tmp, expr))
-        write("if %(tmp)s is not None:")
-        stream.indent()
-
-        if stream.encoding is not None:
-            write("if isinstance(%(tmp)s, unicode):")
-            stream.indent()
-            write("%%(tmp)s = %%(tmp)s.encode('%s')" % stream.encoding)
-            stream.outdent()
-            write("elif not isinstance(%(tmp)s, str):")
-        else:
-            write("if not isinstance(%(tmp)s, (str, unicode)):")
-            
-        # make sure this is a string
-        stream.indent()
-        write("%(tmp)s = str(%(tmp)s)")
-        stream.outdent()
-
-        if self.structure:
-            write("%(write)s(%(tmp)s)")
-        else:
-            stream.escape(stream.symbols.tmp)
-            write("%(write)s(%(tmp)s)")
-
-        stream.outdent()
-
-        # validate XML if enabled
-        if config.VALIDATION:
-            try:
-                _et = etree.import_elementtree()
-            except ImportError:
-                raise ImportError(
-                    "ElementTree (required when XML validation is enabled).")
-
-            stream.symbol_mapping[stream.symbols.validate] = etree.validate
-            write("%(validate)s(%(tmp)s)")
-
-    def end(self, stream):
-        if self.assign:
-            self.assign.end(stream)
-        stream.restore()
-
-class UnicodeWrite(Write):
-    """
-    >>> from z3c.pt import testing
-
-    Basic write:
-
-    >>> _out, _write, stream = testing.setup_stream()
-    >>> write = Write(types.value("'New York'"))
-    >>> write.begin(stream)
-    >>> write.end(stream)
-    >>> exec stream.getvalue()
-    >>> _out.getvalue()
-    'New York'
-
-    Unicode:
-
-    >>> _out, _write, stream = testing.setup_stream('utf-8')
-    >>> write = Write(types.value(repr(unicode('La Pe\xc3\xb1a', 'utf-8'))))
-    >>> write.begin(stream)
-    >>> write.end(stream)
-    >>> exec stream.getvalue()
-    >>> val = _out.getvalue()
-    >>> val == 'La Pe\xc3\xb1a'
-    True
-    >>> type(val) == str
-    True
-
-    Invalid:
-
-    >>> _out, _write, stream = testing.setup_stream()
-    >>> write = Write(types.value("None"))
-    >>> write.begin(stream)
-    >>> write.end(stream)
-    >>> exec stream.getvalue()
-    >>> _out.getvalue()
-    ''
-    """
-
-    def begin(self, stream):
-        temp = stream.save()
-
-        if self.value:
-            expr = self.value
-        else:
-            self.assign.begin(stream, temp)
-            expr = temp
-
-        stream.write("%s(%s)" % (stream.symbols.write, expr))
-
-class Out(object):
-    """
-    >>> from z3c.pt import testing
-      
-    >>> _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):
-        self.string = string
-        self.defer = defer
-        
-    def begin(self, stream):
-        if not self.defer:
-            stream.out(self.string)
-        
-    def end(self, stream):
-        stream.cook()
-        if self.defer:
-            stream.out(self.string)
-
-class Method(object):
-    """
-    >>> from z3c.pt import testing
-      
-    >>> _out, _write, stream = testing.setup_stream()
-    >>> _scope = {}
-    >>> method = Method('test', ('a', 'b', 'c'))
-    >>> method.begin(stream)
-    >>> stream.write('print a, b, c')
-    >>> method.end(stream)
-    >>> exec stream.getvalue()
-    >>> test(1, 2, 3)
-    1 2 3
-      
-    """
-
-    def __init__(self, name, args):
-        self.name = name
-        self.args = args
-
-    def begin(self, stream):
-        stream.write('def %s(%s):' % (self.name, ", ".join(self.args)))
-        stream.indent()
-
-    def end(self, stream):
-        stream.outdent()
-        assign = Assign(
-            types.value(self.name), "%s['%s']" % \
-            (stream.symbols.scope, self.name))
-        assign.begin(stream)
-        assign.end(stream)

Deleted: z3c.pt/trunk/src/z3c/pt/codegen.py
===================================================================
--- z3c.pt/trunk/src/z3c/pt/codegen.py	2008-10-02 19:44:09 UTC (rev 91671)
+++ z3c.pt/trunk/src/z3c/pt/codegen.py	2008-10-02 19:46:03 UTC (rev 91672)
@@ -1,190 +0,0 @@
-from compiler import ast, parse
-from compiler.pycodegen import ModuleCodeGenerator
-
-from transformer import ASTTransformer
-
-import __builtin__
-
-CONSTANTS = frozenset(['False', 'True', 'None', 'NotImplemented', 'Ellipsis'])
-UNDEFINED = object()
-
-def flatten(list):
-    """Flattens a potentially nested sequence into a flat list.
-    """
-    l = []
-    for elt in list:
-        t = type(elt)
-        if t is set or t is tuple or t is list or t is frozenset:
-            for elt2 in flatten(elt):
-                l.append(elt2)
-        else:
-            l.append(elt)
-    return l
-
-class Lookup(object):
-    """Abstract base class for variable lookup implementations."""
-
-    @classmethod
-    def globals(cls):
-        """Construct the globals dictionary to use as the execution context for
-        the expression or suite.
-        """
-        return {
-            '_lookup_attr': cls.lookup_attr,
-            '_lookup_name': cls.lookup_name,
-        }
-
-    @classmethod
-    def lookup_attr(cls, obj, key):
-        try:
-            return getattr(obj, key)
-        except AttributeError, e:
-            try:
-                return obj[key]
-            except (KeyError, TypeError):
-                raise e
-
-    @classmethod
-    def lookup_name(cls, data, name):
-        try:
-            return data[name]
-        except KeyError:
-            raise NameError(name)
-
-class TemplateASTTransformer(ASTTransformer):
-    """Concrete AST transformer that implements the AST transformations needed
-    for code embedded in templates.
-
-    """
-
-    def __init__(self, globals):
-        self.locals = [CONSTANTS]
-        builtin = dir(__builtin__)
-        self.locals.append(set(globals))
-        self.locals.append(set(builtin))
-        # self.names is an optimization for visitName (so we don't
-        # need to flatten the locals every time it's called)
-        self.names = set()
-        self.names.update(CONSTANTS)
-        self.names.update(builtin)
-        self.names.update(globals)
-
-    def visitConst(self, node):
-        #if isinstance(node.value, unicode):
-        #    return ast.Const(node.value.encode('utf-8'))
-        return node
-
-    def visitAssName(self, node):
-        if len(self.locals) > 1:
-            if node.flags == 'OP_ASSIGN':
-                self.locals[-1].add(node.name)
-                self.names.add(node.name)
-            else:
-                self.locals[-1].remove(node.name)
-                self.names.remove(node.name)
-        return node
-
-    def visitClass(self, node):
-        if len(self.locals) > 1:
-            self.locals[-1].add(node.name)
-            self.names.add(node.name)
-        self.locals.append(set())
-        try:
-            return ASTTransformer.visitClass(self, node)
-        finally:
-            self.locals.pop()
-
-    def visitFor(self, node):
-        self.locals.append(set())
-        try:
-            return ASTTransformer.visitFor(self, node)
-        finally:
-            self.locals.pop()
-
-    def visitFunction(self, node):
-        if len(self.locals) > 1:
-            self.locals[-1].add(node.name)
-            self.names.add(node.name)
-        self.locals.append(set(node.argnames))
-        self.names.update(node.argnames)
-        try:
-            return ASTTransformer.visitFunction(self, node)
-        finally:
-            self.locals.pop()
-
-    def visitGenExpr(self, node):
-        self.locals.append(set())
-        try:
-            return ASTTransformer.visitGenExpr(self, node)
-        finally:
-            self.locals.pop()
-
-    def visitLambda(self, node):
-        argnames = flatten(node.argnames)
-        self.names.update(argnames)
-        self.locals.append(set(argnames))
-        try:
-            return ASTTransformer.visitLambda(self, node)
-        finally:
-            self.locals.pop()
-
-    def visitListComp(self, node):
-        self.locals.append(set())
-        try:
-            return ASTTransformer.visitListComp(self, node)
-        finally:
-            self.locals.pop()
-
-    def visitName(self, node):
-        # If the name refers to a local inside a lambda, list comprehension, or
-        # generator expression, leave it alone
-        if not node.name in self.names:
-            # Otherwise, translate the name ref into a context lookup
-            func_args = [ast.Name('_scope'), ast.Const(node.name)]
-            node = ast.CallFunc(ast.Name('_lookup_name'), func_args)
-        return node
-
-    def visitGetattr(self, node):
-        """Get attribute with fallback to dictionary lookup.
-
-        Note: Variables starting with an underscore are exempt
-        (reserved for internal use).
-        """
-        
-        if hasattr(node.expr, 'name') and node.expr.name.startswith('_'):
-            return ast.Getattr(node.expr, node.attrname)
-
-        return ast.CallFunc(ast.Name('_lookup_attr'), [
-            self.visit(node.expr), ast.Const(node.attrname)
-            ])
-
-class Suite(object):
-    __slots__ = ['code', '_globals']
-
-    mode = 'exec'
-    
-    def __init__(self, source, globals=()):
-        """Create the code object from a string."""
-
-        if isinstance(source, unicode):
-            source = source.encode('utf-8')
-            
-        node = parse(source, self.mode)
-
-        # build tree
-        transform = TemplateASTTransformer(globals)
-        tree = transform.visit(node)
-        filename = tree.filename = '<script>'
-
-        # generate code
-        gen = ModuleCodeGenerator(tree)
-        gen.optimized = True
-
-        self._globals = Lookup.globals()
-        self.code = gen.getCode()
-
-    def __hash__(self):
-        return hash(self.code)
-
-    def __repr__(self):
-        return '%s(%r)' % (self.__class__.__name__, self.code)

Deleted: z3c.pt/trunk/src/z3c/pt/codegen.txt
===================================================================
--- z3c.pt/trunk/src/z3c/pt/codegen.txt	2008-10-02 19:44:09 UTC (rev 91671)
+++ z3c.pt/trunk/src/z3c/pt/codegen.txt	2008-10-02 19:46:03 UTC (rev 91672)
@@ -1,40 +0,0 @@
-Codegen
-=======
-
-The ``Codegen`` module is responsible for the low-level compilation
-of the page template.
-
-Suite
------
-
-The ``Suite`` class compiles a source code suite and makes a code
-object available.
-
-  >>> from z3c.pt.codegen import Suite
-  >>> suite = Suite("""\
-  ... print 'Hello World!'
-  ... """)
-  >>> exec suite.code in suite._globals
-  Hello World!
-
-Syntax extension: Dictionary lookup using dot operator
-------------------------------------------------------
-  
-We allow attribute access to dictionary entries to minimize verbosity
-in templates. It works by wrapping the get attribute nodes in a method
-that tries a dictionary lookup if attribute lookup failed.
-
-  >>> suite = Suite("""\
-  ... a = {'b': 1}
-  ... assert a['b'] == a.b
-  ... """)
-  >>> exec suite.code in suite._globals
-
-Syntax extension: Dynamic scoping
----------------------------------
-
-  >>> suite = Suite("""\
-  ... _scope = {'a': 1}
-  ... assert a == 1
-  ... """)
-  >>> exec suite.code in suite._globals

Deleted: z3c.pt/trunk/src/z3c/pt/config.py
===================================================================
--- z3c.pt/trunk/src/z3c/pt/config.py	2008-10-02 19:44:09 UTC (rev 91671)
+++ z3c.pt/trunk/src/z3c/pt/config.py	2008-10-02 19:46:03 UTC (rev 91672)
@@ -1,68 +0,0 @@
-import os
-
-# define which values are read as true
-TRUEVALS = ('y', 'yes', 't', 'true', 'on', '1')
-
-# in debug-mode, templates on disk are reloaded if they're modified
-DEBUG_MODE_KEY = 'Z3C_PT_DEBUG'
-DEBUG_MODE = os.environ.get(DEBUG_MODE_KEY, 'false')
-DEBUG_MODE = DEBUG_MODE.lower() in TRUEVALS
-
-# disable disk-cache to prevent the compiler from caching on disk
-DISK_CACHE_KEY = 'Z3C_PT_CACHE'
-DISK_CACHE = os.environ.get(DISK_CACHE_KEY, 'true')
-DISK_CACHE = DISK_CACHE.lower() in TRUEVALS
-CACHE_EXTENSION = "cache"
-
-# when validation is enabled, dynamically inserted content is
-# validated against the XHTML standard
-VALIDATION = DEBUG_MODE
-
-# use the disable-i18n flag to disable the translation machinery; this
-# will speed up templates that use internationalization
-DISABLE_I18N_KEY = 'Z3C_PT_DISABLE_I18N'
-DISABLE_I18N = os.environ.get(DISABLE_I18N_KEY, 'false')
-DISABLE_I18N = DISABLE_I18N.lower() in TRUEVALS
-
-# these definitions are standard---change at your own risk!
-XHTML_NS = "http://www.w3.org/1999/xhtml"
-TAL_NS = "http://xml.zope.org/namespaces/tal"
-META_NS = "http://xml.zope.org/namespaces/meta"
-METAL_NS = "http://xml.zope.org/namespaces/metal"
-XI_NS = "http://www.w3.org/2001/XInclude"
-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)
-
-# the symbols table below is used internally be the compiler
-class SYMBOLS(object):
-    # internal use only
-    init = '_init'
-    slot = '_slot'
-    metal = '_metal'
-    include = '_include'
-    macro = '_macro'
-    scope = '_scope'
-    out = '_out'
-    tmp = '_tmp'
-    write = '_write'
-    mapping = '_mapping'
-    result = '_result'
-    marker = '_marker'
-    domain = '_domain'
-    i18n_context = '_i18n_context'
-    attributes = '_attributes'
-    negotiate = '_negotiate'
-    translate = '_translate'
-    validate = '_validate'
-    path = '_path'
-
-    # advertised symbols
-    repeat = 'repeat'
-    language = 'target_language'
-    xincludes = 'xincludes'
-    
-    @classmethod
-    def as_dict(cls):
-        return dict((name, getattr(cls, name)) for name in dir(cls))
-            

Modified: z3c.pt/trunk/src/z3c/pt/configure.zcml
===================================================================
--- z3c.pt/trunk/src/z3c/pt/configure.zcml	2008-10-02 19:44:09 UTC (rev 91671)
+++ z3c.pt/trunk/src/z3c/pt/configure.zcml	2008-10-02 19:46:03 UTC (rev 91672)
@@ -1,35 +1,18 @@
 <configure package="z3c.pt"
-           xmlns="http://namespaces.zope.org/zope"
-           xmlns:zcml="http://namespaces.zope.org/zcml">
+           xmlns="http://namespaces.zope.org/zope">
 
   <include package="zope.component" file="meta.zcml" />
+
+  <include package="chameleon.core" />
+  <include package="chameleon.zpt" />
   
   <utility
-     name="python"
-     component=".expressions.python_translation" />
-
-  <utility
      name="path"
-     component=".expressions.path_translation" />
+     component=".expressions.path_translator" />
 
   <utility
      name="provider"
-     component=".expressions.provider_translation" />
+     component=".expressions.provider_translator" />
 
-  <adapter
-     name="string"
-     factory=".expressions.StringTranslation" />
-
-  <configure zcml:condition="installed zope.app.component">
-           
-      <include package="zope.app.component" file="meta.zcml" />
-      <include package="zope.app.security" file="meta.zcml" />
-      
-      <class class=".utils.repeatitem">
-        <allow interface=".interfaces.ITALESIterator" />
-      </class>
-    
-  </configure>
-  
 </configure>
  

Deleted: z3c.pt/trunk/src/z3c/pt/doctypes.py
===================================================================
--- z3c.pt/trunk/src/z3c/pt/doctypes.py	2008-10-02 19:44:09 UTC (rev 91671)
+++ z3c.pt/trunk/src/z3c/pt/doctypes.py	2008-10-02 19:46:03 UTC (rev 91672)
@@ -1,13 +0,0 @@
-def dt(name, pubid, system):
-    return '<!DOCTYPE %s PUBLIC "%s" "%s">' % (name, pubid, system)
-
-html_strict  = dt('HTML', '-//W3C//DTD HTML 4.01//EN',
-                  'http://www.w3.org/TR/html4/strict.dtd')
-html         = dt('HTML', '-//W3C//DTD HTML 4.01 Transitional//EN',
-                  'http://www.w3.org/TR/html4/loose.dtd')
-xhtml_strict = dt('html', '-//W3C//DTD XHTML 1.0 Strict//EN',
-                  'http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd')
-xhtml        = dt('html', '-//W3C//DTD XHTML 1.0 Transitional//EN',
-                  'http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd')
-no_doctype = ()
-

Deleted: z3c.pt/trunk/src/z3c/pt/etree.py
===================================================================
--- z3c.pt/trunk/src/z3c/pt/etree.py	2008-10-02 19:44:09 UTC (rev 91671)
+++ z3c.pt/trunk/src/z3c/pt/etree.py	2008-10-02 19:46:03 UTC (rev 91672)
@@ -1,320 +0,0 @@
-import htmlentitydefs
-import config
-import utils
-import cgi
-import copy
-import xml.parsers.expat
-from StringIO import StringIO
-
-class ValidationError(ValueError):
-    def __str__(self):
-        value, = self.args
-        return "Insertion of %s is not allowed." % \
-               repr(value)
-        
-def import_elementtree():
-    try:
-        import xml.etree.ElementTree as ET
-    except:
-        try:
-            import elementtree.ElementTree as ET
-        except ImportError:
-            import cElementTree as ET
-        
-    return ET
-
-def validate(string):
-    try:
-        import_elementtree().fromstring("<div>%s</div>" % string)
-    except xml.parsers.expat.ExpatError:
-        raise ValidationError(string)
-        
-class Parser(object):
-    element_mapping = utils.emptydict()
-
-    def parse(self, body):
-        return parse(body, self.element_mapping)
-        
-try:
-    import lxml.etree
-
-    class ElementBase(lxml.etree.ElementBase):
-        def tostring(self):
-            return lxml.etree.tostring(self)
-
-        def _convert_cdata_sections(self):
-            start = '<![CDATA['
-            end = ']]>'
-
-            text = self._raw_text or ""
-            tail = self._raw_tail or ""
-
-            if start in text:
-                before, rest = text.split(start, 1)
-                cdata, after = rest.split(end, 1)
-
-                element = self.makeelement(
-                    utils.xhtml_attr('cdata'))
-                element.attrib[utils.meta_attr('cdata')] = ""
-                element.text = cdata
-                element.tail = after
-                
-                self.text = before
-                self.insert(0, element)
-                element._convert_cdata_sections()
-                
-            if start in tail:
-                before, rest = tail.split(start, 1)
-                cdata, after = rest.split(end, 1)
-
-                element = self.makeelement(
-                    utils.xhtml_attr('cdata'))
-                element.attrib[utils.meta_attr('cdata')] = ""
-                self.addnext(element)
-
-                element.text = cdata
-                element.tail = after
-                self.tail = before
-                element._convert_cdata_sections()
-                
-        @property
-        def _raw_text(self):
-            """Return raw text.
-
-            CDATA sections are returned in their original formatting;
-            the routine relies on the fact that ``tostring`` will
-            output CDATA sections even though they're not present in
-            the .text-attribute.
-            """
-
-            if self.text in ("", None):
-                return self.text
-            
-            elements = tuple(self)
-            del self[:]
-            xml = lxml.etree.tostring(self, encoding='utf-8', with_tail=False)
-            self.extend(elements)
-                
-            element = self.makeelement(self.tag, nsmap=self.nsmap)
-            for attr, value in self.items():
-                element.attrib[attr] = value
-
-            html = lxml.etree.tostring(element)
-            tag = len(element.tag.split('}')[-1])+3
-            text = xml[len(html)-tag:-tag]
-
-            return text
-
-        @property
-        def _raw_tail(self):
-            """Return raw tail.
-
-            CDATA sections are returned in their original formatting;
-            the routine relies on the fact that ``tostring`` will
-            output CDATA sections even though they're not present in
-            the .tail-attribute.
-            """
-
-            if self.tail in ("", None):
-                return self.tail
-
-            elements = tuple(self)
-            del self[:]
-
-            parent = self.getparent()
-            if parent is None:
-                return self.tail
-            
-            length = len(lxml.etree.tostring(self, encoding='utf-8', with_tail=False))
-            
-            # wrap element
-            index = parent.index(self)
-            element = self.makeelement(self.tag, nsmap=self.nsmap)
-            element.append(self)
-            xml = lxml.etree.tostring(element, encoding='utf-8', with_tail=False)
-            self.extend(elements)
-            parent.insert(index, self)
-
-            ns = self.tag[self.tag.find('{')+1:self.tag.find('}')]
-            for prefix, namespace in self.nsmap.items():
-                if ns == namespace:
-                    if prefix is None:
-                        tag = len(self.tag) - len(ns)
-                    else:
-                        tag = len(self.tag) - len(ns) + len(prefix) + 1
-                    break
-            else:
-                raise ValueError(
-                    "Unable to determine tag length: %s." % self.tag)
-                
-            tail = xml[length+tag:-tag-1]
-            
-            return tail
-
-    def convert_cdata_section(node):
-        parent = node.getparent()
-        if parent is not None:
-            index = parent.index(node)
-            element = node.makeelement(node.tag, nsmap=node.nsmap)
-            element.append(node)
-            xml = lxml.etree.tostring(element, encoding='utf-8', with_tail=False)
-            parent.insert(index, node)
-        else:
-            xml = lxml.etree.tostring(node, encoding='utf-8', with_tail=False)
-            
-        if 'CDATA' in xml:
-            node._convert_cdata_sections()
-            for child in tuple(node):
-                convert_cdata_section(child)
-        
-    def parse(body, element_mapping):
-        lookup = lxml.etree.ElementNamespaceClassLookup()
-        parser = lxml.etree.XMLParser(resolve_entities=False, strip_cdata=False)
-        parser.setElementClassLookup(lookup)
-
-        # lxml 1.3-compatibility
-        try:
-            ns_lookup = lookup.get_namespace
-        except AttributeError:
-            ns_lookup = lxml.etree.Namespace
-
-        for key, mapping in element_mapping.items():
-            ns_lookup(key).update(mapping)
-        
-        tree = lxml.etree.parse(StringIO(body), parser)
-        root = tree.getroot()
-
-        convert_cdata_section(root)
-        
-        return root, tree.docinfo.doctype
-
-except ImportError:
-    ET = import_elementtree()
-    from pdis.xpath import XPath
-    
-    class ElementBase(object, ET._ElementInterface):
-        _parent = None
-        
-        def __new__(cls, tag, attrs=None):
-            return element_factory(tag, attrs)
-
-        def __init__(self, tag, attrs=None):
-            if attrs is None:
-                attrs = {}
-            
-            ET._ElementInterface.__init__(self, tag, attrs)
-            
-        def getparent(self):
-            return self._parent
-
-        def getroottree(self):
-            while self._parent is not None:
-                self = self._parent
-            class roottree(object):
-                @classmethod
-                def getroot(cls):
-                    return self
-            return roottree
-            
-        def insert(self, position, element):
-            element._parent = self
-            ET._ElementInterface.insert(self, position, element)
-
-        def tostring(self):
-            return ET.tostring(self)
-
-        def xpath(self, path, namespaces={}):
-            xpath = XPath(path, namespace_mapping=namespaces)
-            return xpath.evaluate(self)
-            
-        @property
-        def nsmap(self):
-            # TODO: Return correct namespace map
-            return {None: config.XHTML_NS}
-
-        @property
-        def prefix(self):
-            try:
-                ns, prefix = self.tag.split('}')
-            except:
-                return None
-            
-            for prefix, namespace in self.nsmap.items():
-                if namespace == ns:
-                    return prefix
-            
-    namespaces = {}
-    def ns_lookup(ns):
-        return namespaces.setdefault(ns, {})
-
-    class TreeBuilder(ET.TreeBuilder):
-        def start(self, tag, attrs):
-            if len(self._elem):
-                parent = self._elem[-1]
-            else:
-                parent = None
-            elem = ET.TreeBuilder.start(self, tag, attrs)
-            elem._parent = parent
-            elem.makeelement = self._factory
-            
-    class XMLParser(ET.XMLParser):
-        def __init__(self, **kwargs):
-            ET.XMLParser.__init__(self, **kwargs)
-
-            # this makes up for ET's lack of support for comments and
-            # processing instructions
-            self._parser.CommentHandler = self.handle_comment
-            self._parser.ProcessingInstructionHandler = self.handle_pi
-            self._parser.StartCdataSectionHandler = self.handle_cdata_start
-            self._parser.EndCdataSectionHandler = self.handle_cdata_end
-       
-        def doctype(self, name, pubid, system):
-            self.doctype = u'<!DOCTYPE %(name)s PUBLIC "%(pubid)s" "%(system)s">' % \
-                           dict(name=name, pubid=pubid, system=system)
-
-        def handle_comment(self, data):
-            name = utils.tal_attr('comment')
-            self._target.start(name, {})
-            self._target.data("<!-- %s -->" % data)
-            self._target.end(name)
-
-        def handle_pi(self, target, data):
-            name = utils.tal_attr('pi')
-            self._target.start(name, {})
-            self._target.data("<?%(target)s %(data)s?>" % dict(target=target, data=data))
-            self._target.end(name)
-
-        def handle_cdata_start(self):
-            self._target.start(utils.xhtml_attr('cdata'), {
-                utils.tal_attr('cdata'): ''})
-
-        def handle_cdata_end(self):
-            self._target.end(utils.xhtml_attr('cdata'))
-            
-    def parse(body, element_mapping):
-        def element_factory(tag, attrs=None, nsmap=None):
-            if attrs is None:
-                attrs = {}
-
-            if '{' in tag:
-                ns = tag[tag.find('{')+1:tag.find('}')]
-                ns_tag = tag[tag.find('}')+1:]
-            else:
-                ns = None
-                ns_tag = None
-
-            namespace = element_mapping[ns]
-            factory = namespace.get(ns_tag) or namespace.get(None) or ElementBase
-
-            element = object.__new__(factory)
-            element.__init__(tag, attrs)
-
-            return element
-        
-        target = TreeBuilder(element_factory=element_factory)
-        parser = XMLParser(target=target)
-        parser.entity = dict([(name, "&%s;" % name) for name in htmlentitydefs.entitydefs])
-        parser.feed(body)
-        root = parser.close()
-
-        return root, parser.doctype

Modified: z3c.pt/trunk/src/z3c/pt/expressions.py
===================================================================
--- z3c.pt/trunk/src/z3c/pt/expressions.py	2008-10-02 19:44:09 UTC (rev 91671)
+++ z3c.pt/trunk/src/z3c/pt/expressions.py	2008-10-02 19:46:03 UTC (rev 91672)
@@ -1,3 +1,6 @@
+import parser
+import re
+
 import zope.interface
 import zope.component
 
@@ -5,651 +8,16 @@
 from zope.contentprovider.interfaces import IContentProvider
 from zope.contentprovider.interfaces import ContentProviderLookupError
 
-import parser
-import re
+from chameleon.core import types
+from chameleon.zpt import expressions
 
-import interfaces
-import types
-import config
-import utils
-
 _marker = object()
 
-class ExpressionTranslation(object):
-    zope.interface.implements(interfaces.IExpressionTranslation)
+def identity(x):
+    return x
 
-    re_pragma = re.compile(r'^\s*(?P<pragma>[a-z]+):')
-    re_interpolation = re.compile(r'(?P<prefix>[^\\]\$|^\$)({((?P<expression>.*)})?|(?P<variable>[A-Za-z][A-Za-z0-9_]*))')
-    re_method = re.compile(r'^(?P<name>[A-Za-z0-9_]+)'
-                           '(\((?P<args>[A-Za-z0-9_]+\s*(,\s*[A-Za-z0-9_]+)*)\))?')
-
-    def name(self, string):
-        return string
-    
-    def search(self, string):
-        """
-        We need to implement a ``validate``-method. Let's define that an
-        expression is valid if it contains an odd number of
-        characters.
-        
-          >>> class MockExpressionTranslation(ExpressionTranslation):
-          ...     def validate(self, string):
-          ...         if len(string) % 2 == 0: raise SyntaxError()
-
-          >>> search = MockExpressionTranslation().search
-          >>> search("a")
-          'a'
-          >>> search("ab")
-          'a'
-          >>> search("abc")
-          'abc'
-          
-        """
-
-        left = 0
-        right = left + 1
-
-        current = None
-
-        while right <= len(string):
-            expression = string[left:right]
-
-            try:
-                e = self.validate(expression)
-                current = expression
-            except SyntaxError, e:
-                if right == len(string):
-                    if current is not None:
-                        return current
-
-                    raise e
-
-            right += 1
-
-        return current
-
-    def declaration(self, string):
-        """
-          >>> declaration = ExpressionTranslation().declaration
-
-        Single variable:
-
-          >>> declaration("variable")
-          declaration('variable')
-
-        Multiple variables:
-
-          >>> declaration("variable1, variable2")
-          declaration('variable1', 'variable2')
-
-        Repeat not allowed:
-
-          >>> declaration('repeat')
-          Traceback (most recent call last):
-          ...
-          ValueError: Invalid variable name 'repeat' (reserved).
-
-          >>> declaration('_disallowed')
-          Traceback (most recent call last):
-          ...
-          ValueError: Invalid variable name '_disallowed' (starts with an underscore).
-        """
-
-        variables = []
-        for var in string.split(', '):
-            var = var.strip()
-
-            if var in ('repeat',):
-                raise ValueError, "Invalid variable name '%s' (reserved)." % var
-
-            if var.startswith('_') and not var.startswith('_tmp'):
-                raise ValueError(
-                    "Invalid variable name '%s' (starts with an underscore)." % var)
-
-            variables.append(var)
-
-        return types.declaration(variables)
-
-    def mapping(self, string):
-        """
-          >>> mapping = ExpressionTranslation().mapping
-          
-          >>> mapping("abc def")
-          mapping(('abc', 'def'),)
-
-          >>> mapping("abc def;")
-          mapping(('abc', 'def'),)
-
-          >>> mapping("abc")
-          mapping(('abc', None),)
-
-          >>> mapping("abc;")
-          mapping(('abc', None),)
-
-          >>> mapping("abc; def ghi")
-          mapping(('abc', None), ('def', 'ghi'))
-
-        """
-
-        defs = string.split(';')
-        mappings = []
-        for d in defs:
-            d = d.strip()
-            if d == '':
-                continue
-
-            while '  ' in d:
-                d = d.replace('  ', ' ')
-
-            parts = d.split(' ')
-            if len(parts) == 1:
-                mappings.append((d, None))
-            elif len(parts) == 2:
-                mappings.append((parts[0], parts[1]))
-            else:
-                raise ValueError, "Invalid mapping (%s)." % string
-
-        return types.mapping(mappings)
-
-    def definitions(self, string):
-        """
-        
-        >>> class MockExpressionTranslation(ExpressionTranslation):
-        ...     def validate(self, string):
-        ...         if string == '' or ';' in string:
-        ...             raise SyntaxError()
-        ...
-        ...     def expression(self, string):
-        ...         self.validate(string)
-        ...         return types.value(string.strip())
-        
-        >>> definitions = MockExpressionTranslation().definitions
-        
-        Single define:
-        
-        >>> definitions("variable expression")
-        definitions((declaration('variable'), value('expression')),)
-        
-        Multiple defines:
-        
-        >>> definitions("variable1 expression1; variable2 expression2")
-        definitions((declaration('variable1'), value('expression1')),
-                    (declaration('variable2'), value('expression2')))
-        
-        Tuple define:
-        
-        >>> definitions("(variable1, variable2) (expression1, expression2)")
-        definitions((declaration('variable1', 'variable2'),
-                    value('(expression1, expression2)')),)
-
-        Global defines:
-
-        >>> definitions("global variable expression")
-        definitions((declaration('variable', global_scope=True), value('expression')),)
-
-        Space, the 'in' operator and '=' may be used to separate
-        variable from expression.
-
-        >>> definitions("variable in expression")
-        definitions((declaration('variable'), value('expression')),)        
-        
-        >>> definitions("variable1 = expression1; variable2 = expression2")
-        definitions((declaration('variable1'), value('expression1')),
-                    (declaration('variable2'), value('expression2')))
-
-        >>> definitions("variable1=expression1; variable2=expression2")
-        definitions((declaration('variable1'), value('expression1')),
-                    (declaration('variable2'), value('expression2')))
-        
-        A define clause that ends in a semicolon:
-        
-        >>> definitions("variable expression;")
-        definitions((declaration('variable'), value('expression')),)
-        
-        A define clause with a trivial expression (we do allow this):
-        
-        >>> definitions("variable")
-        definitions((declaration('variable'), None),)
-        
-        A proper define clause following one with a trivial expression:
-        
-        >>> definitions("variable1 expression; variable2")
-        definitions((declaration('variable1'), value('expression')),
-                    (declaration('variable2'), None))
-
-        """
-
-        string = string.replace('\n', '').strip()
-
-        defines = []
-        i = 0
-        while i < len(string):
-            global_scope = False
-            if string.startswith('global'):
-                global_scope = True
-                i += 6
-
-            while string[i] == ' ':
-                i += 1
-
-            # get variable definition
-            if string[i] == '(':
-                j = string.find(')', i+1)
-                if j == -1:
-                    raise ValueError, "Invalid variable tuple definition (%s)." % string
-                var = self.declaration(string[i+1:j])
-                j += 1
-            else:
-                j = string.find('=', i + 1)
-                k = string.find(' ', i + 1)
-                if k < j and k > -1 or j < 0:
-                    j = k
-                
-                if j < 0:
-                    var = self.declaration(string[i:])
-                    j = len(string)
-                else:
-                    var = self.declaration(string[i:j])
-
-            var.global_scope = global_scope
-            
-            # get expression
-            i = j + len(string) - j - len(string[j:].lstrip())
-
-            token = string[i:]
-            if token.startswith('=='):
-                raise ValueError("Invalid variable definition (%s)." % string)
-            elif token.startswith('='):
-                i += 1
-            elif token.startswith('in '):
-                i += 3
-
-            try:
-                expr = self.expression(string[i:])
-                j = -1
-            except SyntaxError, e:
-                expr = None
-                j = len(string)
-            
-            while j > i:
-                j = string.rfind(';', i, j)
-                if j < 0:
-                    raise e
-
-                try:
-                    expr = self.expression(string[i:j])
-                except SyntaxError, e:
-                    if string.rfind(';', i, j) > 0:
-                        continue
-                    raise e
-                
-                break
-                
-            defines.append((var, expr))
-
-            if j < 0:
-                break
-            
-            i = j + 1
-
-        return types.definitions(defines)
-
-    def definition(self, string):
-        defs = self.definitions(string)
-        if len(defs) != 1:
-            raise ValueError, "Multiple definitions not allowed."
-
-        return defs[0]
-
-    def output(self, string):
-        """
-        >>> class MockExpressionTranslation(ExpressionTranslation):
-        ...     def validate(self, string):
-        ...         return True
-        ...
-        ...     def translate(self, string):
-        ...         return types.value(string)
-
-        >>> output = MockExpressionTranslation().output
-
-        >>> output("context/title")
-        escape(value('context/title'),)
-
-        >>> output("context/pretty_title_or_id|context/title")
-        escape(value('context/pretty_title_or_id'), value('context/title'))
-
-        >>> output("structure context/title")
-        value('context/title')
-        
-        """
-        
-        if string.startswith('structure '):
-            return self.expression(string[len('structure'):])
-        
-        expression = self.expression(string)
-
-        if isinstance(expression, types.parts):
-            return types.escape(expression)
-
-        return types.escape((expression,))
-            
-    def expression(self, string):
-        """We need to implement the ``validate`` and
-        ``translate``-methods. 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 types.value(string)
-
-        >>> expression = MockExpressionTranslation().expression
-
-        >>> expression('a')
-        value('a')
-
-        >>> expression('a|b')
-        parts(value('a'), value('b'))
-    
-        """
-
-        string = string.replace('\n', '').strip()
-
-        if not string:
-            return types.parts()
-
-        parts = []
-
-        # default translator is ``self``
-        translator = self
-
-        i = j = 0
-        while i < len(string):
-            if translator is self:
-                match = self.re_pragma.match(string[i:])
-                if match is not None:
-                    pragma = match.group('pragma')
-
-                    translator = \
-                        zope.component.queryUtility(
-                            interfaces.IExpressionTranslation, name=pragma) or \
-                        zope.component.queryAdapter(
-                            self, interfaces.IExpressionTranslation, name=pragma)
-                    
-                    if translator is not None:
-                        i += match.end()
-                        continue
-
-                    translator = self
-
-            j = string.find('|', j + 1)
-            if j == -1:
-                j = len(string)
-
-            expr = string[i:j]
-
-            try:
-                translator.validate(expr)
-            except Exception, e:
-                if j < len(string):
-                    continue
-
-                # re-raise with traceback
-                translator.validate(expr)
-
-            value = translator.translate(expr)
-            parts.append(value)
-            translator = self
-            
-            i = j + 1
-
-        if len(parts) == 1:
-            return parts[0]
-
-        return types.parts(parts)
-
-    def interpolate(self, string):
-        """Search for an interpolation and return a match.
-
-        >>> class MockExpressionTranslation(ExpressionTranslation):
-        ...     def validate(self, string):
-        ...         if '}' in string: raise SyntaxError
-        ...
-        ...     def translate(self, string):
-        ...         return types.value(string)
-
-        >>> interpolate = MockExpressionTranslation().interpolate
-        
-        >>> interpolate('${abc}').group('expression')
-        'abc'
-
-        >>> interpolate(' ${abc}').group('expression')
-        'abc'
-
-        >>> interpolate('abc${def}').group('expression')
-        'def'
-
-        >>> interpolate('abc${def}ghi${jkl}').group('expression')
-        'def'
-
-        >>> interpolate('$abc').group('variable')
-        'abc'
-
-        >>> interpolate('${abc')
-        Traceback (most recent call last):
-          ...
-        SyntaxError: Interpolation expressions must be of the form ${<expression>} (${abc)
-        
-        """
-
-        m = self.re_interpolation.search(string)
-        if m is None:
-            return None
-
-        expression = m.group('expression')
-        variable = m.group('variable')
-        
-        if expression:
-            left = m.start()+len(m.group('prefix'))+1
-            right = string.find('}')
-
-            while right != -1:
-                match = string[left:right]
-                try:
-                    exp = self.expression(match)
-                    break
-                except SyntaxError:
-                    right = string.find('}', right)
-            else:
-                raise
-
-            string = string[:right+1]
-            return self.re_interpolation.search(string)
-
-        if m is None or (expression is None and variable is None):
-            raise SyntaxError(
-                "Interpolation expressions must be of the "
-                "form ${<expression>} (%s)" % string)
-
-        if expression and not m.group('expression'):
-            raise SyntaxError(expression)
-
-        return m
-
-    def method(self, string):
-        """Parse a method definition.
-
-        >>> method = ExpressionTranslation().method
-
-        >>> method('name')
-        name()
-
-        >>> method('name(a, b, c)')
-        name(a, b, c)
-        
-        """
-
-        m = self.re_method.match(string)
-        if m is None:
-            raise ValueError("Not a valid method definition (%s)." % string)
-
-        name = m.group('name')
-        args = [arg.strip() for arg in (m.group('args') or "").split(',') if arg]
-
-        return types.method(name, args)
-        
-class PythonTranslation(ExpressionTranslation):
-    def validate(self, string):
-        """We use the ``parser`` module to determine if
-        an expression is a valid python expression."""
-
-        if isinstance(string, unicode):
-            string = string.encode('utf-8')
-            
-        parser.expr(string.strip())
-
-    def translate(self, string):
-        if isinstance(string, str):
-            string = string.decode('utf-8')
-
-        return types.value(string.strip())
-
-python_translation = PythonTranslation()
-
-class StringTranslation(ExpressionTranslation):
-    zope.component.adapts(interfaces.IExpressionTranslation)
-
-    def __init__(self, translator):
-        self.translator = translator
-
-    def validate(self, string):
-        self.interpolate(string)
-        self.split(string)
-            
-    def translate(self, string):
-        return types.join(self.split(string))
-            
-    def split(self, string):
-        """Split up an interpolation string expression into parts that
-        are either unicode strings or ``value``-tuples.
-
-        >>> class MockTranslation(ExpressionTranslation):
-        ...     def validate(self, string):
-        ...         if '}' in string: raise SyntaxError
-        ...
-        ...     def translate(self, string):
-        ...         return types.value(string)
-        
-        >>> class MockStringTranslation(StringTranslation):
-        ...     pass
-        
-        >>> split = MockStringTranslation(MockTranslation()).split
-
-        >>> split("${abc}")
-        (value('abc'),)
-
-        >>> split(" ${abc}")
-        (' ', value('abc'))
-
-        >>> split("abc${def}")
-        ('abc', value('def'))
-
-        >>> split("${def}abc")
-        (value('def'), 'abc')
-
-        >>> split("abc${def}ghi")
-        ('abc', value('def'), 'ghi')
-
-        >>> split("abc${def}ghi${jkl}")
-        ('abc', value('def'), 'ghi', value('jkl'))
-
-        >>> split("abc${def | ghi}")
-        ('abc', parts(value('def '), value(' ghi')))
-
-        >>> print split(u"abc${ghi}")
-        (u'abc', value('ghi'))
-        
-        """
-
-        m = self.translator.interpolate(string)
-        if m is None:
-            return (self._unescape(string),)
-
-        prefix = m.group('prefix')
-        parts = []
-        
-        start = m.start() + len(prefix) - 1
-        if start > 0:
-            text = string[:start]
-            parts.append(self._unescape(text))
-
-        expression = m.group('expression')
-        variable = m.group('variable')
-
-        if expression:
-            parts.append(self.translator.expression(expression))
-        elif variable:
-            parts.append(self.translator.expression(variable))
-                
-        rest = string[m.end():]
-        if len(rest):
-            parts.extend(self.split(rest))
-
-        return tuple(parts)
-
-    def definitions(self, string):
-        """
-        
-        >>> definitions = StringTranslation(python_translation).definitions
-        
-        Semi-colon literal.
-        
-        >>> definitions("variable part1;; part2")
-        definitions((declaration('variable'), join('part1; part2',)),)
-
-        >>> definitions("variable1 part1;; part2; variable2 part3")
-        definitions((declaration('variable1'), join('part1; part2',)),
-                    (declaration('variable2'), join('part3',)))
-    
-        """
-
-        return super(StringTranslation, self).definitions(string)
-
-    def _unescape(self, string):
-        """
-        >>> unescape = StringTranslation(python_translation)._unescape
-        
-        >>> unescape('string:Hello World')
-        'string:Hello World'
-        
-        >>> unescape('; string:Hello World')
-        Traceback (most recent call last):
-         ...
-        SyntaxError: Semi-colons in string-expressions must be escaped.
-
-        >>> unescape(';; string:Hello World')
-        '; string:Hello World'
-
-        >>> unescape('string:Hello World;')
-        'string:Hello World;'
-        
-        """
-        
-        i = string.rfind(';')
-        if i < 0 or i == len(string) - 1:
-            return string
-        
-        j = string.rfind(';'+';')
-        if j < 0 or i != j + 1:
-            raise SyntaxError(
-                "Semi-colons in string-expressions must be escaped.")
-        
-        return string.replace(';;', ';')
-
 class ZopeTraverser(object):
-    def __init__(self, proxify=utils.identity):
+    def __init__(self, proxify=identity):
         self.proxify = proxify
 
     def __call__(self, base, request, call, *path_items):
@@ -681,20 +49,22 @@
 
         return base
 
-class PathTranslation(ExpressionTranslation):
+class PathTranslator(expressions.ExpressionTranslator):
     path_regex = re.compile(
         r'^((nocall|not):\s*)*([A-Za-z_][A-Za-z0-9_]*)'+
         r'(/[A-Za-z_ at -][A-Za-z0-9_ at -\\.]*)*$')
 
     path_traverse = ZopeTraverser()
 
+    symbol = '_path'
+    
     def validate(self, string):
         if not self.path_regex.match(string.strip()):
             raise SyntaxError("Not a valid path-expression.")
 
     def translate(self, string):
         """
-            >>> translate = PathTranslation().translate
+            >>> translate = PathTranslator().translate
             >>> translate("a/b")
             value("_path(a, request, True, 'b')")
 
@@ -740,16 +110,16 @@
 
         value = types.value(
             '%s(%s, request, %s, %s)' % \
-            (config.SYMBOLS.path, base, not nocall, ', '.join(components)))
+            (self.symbol, base, not nocall, ', '.join(components)))
 
         if negate:
             value = types.value('not(%s)' % value)
 
-        value.symbol_mapping[config.SYMBOLS.path] = self.path_traverse
+        value.symbol_mapping[self.symbol] = self.path_traverse
 
         return value
 
-path_translation = PathTranslation()
+path_translator = PathTranslator()
 
 def get_content_provider(context, request, view, name):
     cp = zope.component.queryMultiAdapter(
@@ -762,9 +132,7 @@
     cp.update()
     return cp.render()
     
-class ProviderTranslation(object):
-    zope.interface.implements(interfaces.IExpressionTranslation)
-    
+class ProviderTranslator(expressions.ExpressionTranslator):
     provider_regex = re.compile(r'^[A-Za-z][A-Za-z0-9_-]*$')
     symbol = '_get_content_provider'
     
@@ -779,4 +147,4 @@
         value.symbol_mapping[self.symbol] = get_content_provider
         return value
     
-provider_translation = ProviderTranslation()
+provider_translator = ProviderTranslator()

Deleted: z3c.pt/trunk/src/z3c/pt/filecache.py
===================================================================
--- z3c.pt/trunk/src/z3c/pt/filecache.py	2008-10-02 19:44:09 UTC (rev 91671)
+++ z3c.pt/trunk/src/z3c/pt/filecache.py	2008-10-02 19:46:03 UTC (rev 91672)
@@ -1,56 +0,0 @@
-import os
-import config
-import cPickle as pickle
-
-class TemplateCache(object):
-    def __init__(self, filename):
-        self.filename = filename
-        self.registry = {}
-        self.load()
-        
-    def __getitem__(self, key):
-        return self.registry[key]
-
-    def __setitem__(self, key, template):
-        self.registry[key] = template
-        self.save()
-
-    def __len__(self):
-        return len(self.registry)
-    
-    def get(self, key, default=None):
-        return self.registry.get(key, default)
-    
-    @property
-    def module_filename(self):
-        return self.filename + os.extsep + config.CACHE_EXTENSION
-    
-    def load(self):
-        try:
-            module_filename = self.module_filename
-            f = open(module_filename, 'rb')
-        except IOError:
-            return
-
-        try:
-            try:
-                self.registry = pickle.load(f)
-            except EOFError:
-                pass
-        finally:
-            f.close()
-        
-    def save(self):
-        try:
-            f = open(self.module_filename, 'wb')
-        except IOError:
-            return
-
-        try:
-            pickle.dump(self.registry, f, protocol=2)
-        finally:
-            f.close()
-
-    def purge(self):
-        self.registry = {}
-        self.save()

Deleted: z3c.pt/trunk/src/z3c/pt/generation.py
===================================================================
--- z3c.pt/trunk/src/z3c/pt/generation.py	2008-10-02 19:44:09 UTC (rev 91671)
+++ z3c.pt/trunk/src/z3c/pt/generation.py	2008-10-02 19:46:03 UTC (rev 91672)
@@ -1,166 +0,0 @@
-from zope.i18n import interpolate
-from zope.i18n import translate
-from zope.i18nmessageid import Message
-
-import utils
-import etree
-import expressions
-
-template_wrapper = """\
-def render(%(init)s, %(args)s%(extra)s%(language)s=None):
-\t%(out)s, %(write)s = %(init)s.initialize_stream()
-\t%(attributes)s, %(repeat)s = %(init)s.initialize_tal()
-\t%(scope)s = {}
-\t%(domain)s = None
-
-%(body)s
-\treturn %(out)s.getvalue()
-"""
-
-macro_wrapper = """\
-def render(%(init)s, %(kwargs)s%(extra)s):
-\t%(attributes)s, %(repeat)s = %(init)s.initialize_tal()
-\t%(domain)s = None
-%(body)s
-"""
-
-class marker(object):
-    pass
-
-def fast_translate(msgid, domain=None, mapping=None, context=None,
-                   target_language=None, default=None):
-    """This translation function does not attempt to negotiate a
-    language if ``None`` is passed."""
-    
-    if target_language is not None:
-        return translate(
-            msgid, domain=domain, mapping=mapping, context=context,
-            target_language=target_language, default=default)
-    
-    if isinstance(msgid, Message):
-        default = msgid.default
-        mapping = msgid.mapping
-
-    if default is None:
-        default = unicode(msgid)
-
-    if not isinstance(default, (str, unicode)):
-        return default
-    
-    return interpolate(default, mapping)
-
-def initialize_tal():
-    return ({}, utils.repeatdict())
-
-def initialize_stream():
-    out = BufferIO()
-    return (out, out.write)
-
-class BufferIO(list):
-    write = list.append
-
-    def getvalue(self):
-        return ''.join(self)
-
-class CodeIO(BufferIO):
-    """Stream buffer suitable for writing Python-code. This class is
-    used internally by the compiler to manage variable scopes, source
-    annotations and temporary variables."""
-
-    t_prefix = '_tmp'
-    v_prefix = '_var'
-
-    def __init__(self, symbols=None, encoding=None,
-                 indentation=0, indentation_string="\t"):
-        BufferIO.__init__(self)
-        self.symbols = symbols or object
-        self.symbol_mapping = {}
-        self.encoding = encoding
-        self.indentation = indentation
-        self.indentation_string = indentation_string
-        self.queue = ''
-        self.scope = [set()]
-        self.selectors = {}
-        self.annotations = {}
-        self._variables = {}
-        self.t_counter = 0
-        self.l_counter = 0
-
-    def save(self):
-        self.t_counter += 1
-        return "%s%d" % (self.t_prefix, self.t_counter)
-
-    def restore(self):
-        var = "%s%d" % (self.t_prefix, self.t_counter)
-        self.t_counter -= 1
-        return var
-
-    def indent(self, amount=1):
-        if amount > 0:
-            self.cook()
-            self.indentation += amount
-
-    def outdent(self, amount=1):
-        if amount > 0:
-            self.cook()
-            self.indentation -= amount
-
-    def annotate(self, item):
-        self.annotations[self.l_counter] = item
-
-    def out(self, string):
-        self.queue += string
-
-    def cook(self):
-        if self.queue:
-            queue = self.queue
-            self.queue = ''
-            self.write(
-                "%s(%s)" %
-                (self.symbols.write, repr(queue)))
-
-    def write(self, string):
-        if isinstance(string, unicode) and self.encoding:
-            string = string.encode(self.encoding)
-
-        self.l_counter += len(string.split('\n'))-1
-
-        self.cook()
-        BufferIO.write(self,
-            self.indentation_string * self.indentation + string + '\n')
-
-    def getvalue(self):
-        self.cook()
-        return BufferIO.getvalue(self)
-
-    def escape(self, variable):
-        self.write("if '&' in %s:" % variable)
-        self.indent()
-        self.write("%s = %s.replace('&', '&amp;')" % (variable, variable))
-        self.outdent()
-        self.write("if '<' in %s:" % variable)
-        self.indent()
-        self.write("%s = %s.replace('<', '&lt;')" % (variable, variable))
-        self.outdent()
-        self.write("if '>' in %s:" % variable)
-        self.indent()
-        self.write("%s = %s.replace('>', '&gt;')" % (variable, variable))
-        self.outdent()
-        self.write("if '\"' in %s:" % variable)
-        self.indent()
-        self.write("%s = %s.replace('\"', '&quot;')" % (variable, variable))
-        self.outdent()
-        
-    def begin(self, clauses):
-        if isinstance(clauses, (list, tuple)):
-            for clause in clauses:
-                self.begin(clause)
-        else:
-            clauses.begin(self)
-                
-    def end(self, clauses):
-        if isinstance(clauses, (list, tuple)):
-            for clause in reversed(clauses):
-                self.end(clause)
-        else:
-            clauses.end(self)

Deleted: z3c.pt/trunk/src/z3c/pt/genshi.py
===================================================================
--- z3c.pt/trunk/src/z3c/pt/genshi.py	2008-10-02 19:44:09 UTC (rev 91671)
+++ z3c.pt/trunk/src/z3c/pt/genshi.py	2008-10-02 19:46:03 UTC (rev 91672)
@@ -1,237 +0,0 @@
-import translation
-import expressions
-import utils
-import config
-import etree
-
-class GenshiElement(translation.Element, translation.VariableInterpolation):
-    """Genshi element.
-
-    Implements the Genshi subset of the attribute template language.
-    """
-
-    class node(translation.Node):
-        @property
-        def omit(self):
-            if self.element.py_strip is not None:
-                return self.element.py_strip or True
-            if self.element.meta_omit is not None:
-                return self.element.meta_omit or True
-            if self.element.py_replace or self.element.meta_replace:
-                return True
-            if self.element.xi_href:
-                return True
-            
-        @property
-        def define(self):
-            return self.element.py_with
-
-        @property
-        def condition(self):
-            return self.element.py_if
-
-        @property
-        def repeat(self):
-            return self.element.py_for
-
-        @property
-        def content(self):
-            return self.element.py_content or self.element.py_replace or \
-                   self.element.meta_replace
-
-        @property
-        def skip(self):
-            return bool(self.content)
-        
-        @property
-        def dict_attributes(self):
-            return self.element.py_attrs
-
-        @property
-        def dynamic_attributes(self):
-            return self.element.meta_attributes
-        
-        @property
-        def static_attributes(self):
-            return utils.get_attributes_from_namespace(
-                self.element, config.XHTML_NS)
-
-        @property
-        def macro(self):
-            return self.element.py_def
-
-        @property
-        def cdata(self):
-            return self.element.meta_cdata
-
-        @property
-        def include(self):
-            return self.element.xi_href
-
-        @property
-        def format(self):
-            return self.element.xi_parse
-        
-    node = property(node)
-
-    def update(self):
-        # Step 1: Convert py:choose, py:when, py:otherwise into
-        # tal:define, tal:condition
-        stream = self.stream
-        choose_expression = self._pull_attribute(utils.py_attr('choose'))
-        if choose_expression is not None:
-            choose_variable = stream.save()
-            
-            if choose_expression:
-                self._add_define(choose_variable, choose_expression)
-                
-            # select all elements that have the "py:when" controller,
-            # unless a "py:choose" expression sits in-between
-            variables = []
-            for element in self.xpath(
-                './*[@py:when]|.//*[not(@py:choose)]/*[@py:when]',
-                namespaces={'py': config.PY_NS}):
-
-                expression = element._pull_attribute(utils.py_attr('when'))
-                variable = stream.save()
-                variables.append(variable)
-
-                # add definition to ancestor
-                self._add_define(variable, expression)
-                
-                # add condition to element
-                if choose_expression:
-                    expression = "python: %s == %s" % (
-                        choose_variable, variable)
-                else:
-                    expression = "python: %s" % variable
-                    
-                element.attrib[utils.py_attr('if')] = expression
-
-            # process any "py:otherwise"-controllers
-            for element in self.xpath(
-                './*[@py:otherwise]|.//*[not(@py:choose)]/*[@py:otherwise]',
-                namespaces={'py': config.PY_NS}):
-                if choose_expression:
-                    expression = "python: %s not in %s" % (
-                        choose_variable, repr(tuple(variables)))
-                else:
-                    expression = "python: not(%s)" % " or ".join(variables)
-                    
-                element.attrib[utils.py_attr('if')] = expression
-
-        # Step 2: Process "py:match" macros
-        for element in self:
-            if getattr(element, 'py_match', None) is None:
-                continue
-            
-            nsmap = element.nsmap.copy()
-
-            # default namespace is not allowed in XPath
-            nsmap['xmlns'] = nsmap[None]
-            del nsmap[None]
-
-            # define macro
-            name = stream.save()
-            element.attrib[utils.py_attr('def')] = "%s(select)" % name
-
-            matches = self.getroottree().getroot().xpath(
-                element.py_match, namespaces=nsmap)
-            for match in matches:
-                # save reference to bound xpath-function
-                select = stream.save()
-                stream.selectors[select] = match.xpath
-
-                # replace matched element with macro
-                expression = "%s(%s)" % (name, select)
-                match.attrib[utils.py_attr('replace')] = expression
-
-                # save select-variable as element attribute
-                match.attrib[utils.meta_attr('select')] = select
-
-        # Step 3: Variable interpolation
-        translation.VariableInterpolation.update(self)        
-
-    def _add_define(self, variable, expression):
-        name = utils.py_attr('with')
-        define = "%s=%s; " % (variable, expression)
-
-        if name in self.attrib:
-            self.attrib[name] += define
-        else:
-            self.attrib[name] = define
-
-    def _pull_attribute(self, name, default=None):
-        attrib = self.attrib
-        if name in attrib:
-            value = attrib[name]
-            del attrib[name]
-            return value
-        return default    
-
-class XHTMLElement(GenshiElement):
-    """XHTML namespace element."""
-
-    py_if = utils.attribute(
-        utils.py_attr('if'), lambda p: p.expression)
-    py_for = utils.attribute(
-        utils.py_attr('for'), lambda p: p.definition)
-    py_with = utils.attribute(utils.py_attr('with'),
-        lambda p: expressions.python_translation.definitions)
-    py_choose = utils.attribute(
-        utils.py_attr('choose'), lambda p: p.expression)
-    py_when = utils.attribute(
-        utils.py_attr('when'), lambda p: p.expression)
-    py_match = utils.attribute(
-        utils.py_attr('match'))
-    py_def = utils.attribute(
-        utils.py_attr('def'), lambda p: p.method)
-    py_attrs = utils.attribute(
-        utils.py_attr('attrs'), lambda p: p.expression)
-    py_content = utils.attribute(
-        utils.py_attr('content'), lambda p: p.output)
-    py_replace = utils.attribute(
-        utils.py_attr('replace'), lambda p: p.output)
-    py_strip = utils.attribute(
-        utils.py_attr('strip'), lambda p: p.expression)
-    xi_href = None
-    xi_parse = None
-
-class MetaElement(XHTMLElement, translation.MetaElement):
-    pass
-
-class PyElement(XHTMLElement):
-    py_strip = utils.attribute("strip", lambda p: p.expression, u"")
-    
-class PyIfElement(PyElement):
-    py_if = utils.attribute("test", lambda p: p.expression)
-
-class PyForElement(PyElement):
-    py_for = utils.attribute("each", lambda p: p.definition)
-
-class PyWithElement(PyElement):
-    py_with = utils.attribute(
-        "vars", lambda p: expressions.python_translation.definitions)
-
-class PyDefElement(PyElement):
-    py_def = utils.attribute("function", lambda p: p.method)
-
-class PyMatchElement(PyElement):
-    py_match = utils.attribute("path")
-
-class XiIncludeElement(XHTMLElement):
-    xi_href = utils.attribute(
-        "href", lambda p: expressions.StringTranslation(p).expression)
-    xi_parse = utils.attribute("parse", default="xml")
-
-class GenshiParser(etree.Parser):
-    """ The parser implementation for Genshi templates """
-    element_mapping = {
-        config.XHTML_NS: {None: XHTMLElement},
-        config.META_NS: {None: MetaElement},
-        config.XI_NS: {'include': XiIncludeElement},
-        config.PY_NS: {'if': PyIfElement,
-                       'for': PyForElement,
-                       'def': PyDefElement,
-                       'with': PyWithElement,
-                       'match': PyMatchElement}}

Deleted: z3c.pt/trunk/src/z3c/pt/genshi.txt
===================================================================
--- z3c.pt/trunk/src/z3c/pt/genshi.txt	2008-10-02 19:44:09 UTC (rev 91671)
+++ z3c.pt/trunk/src/z3c/pt/genshi.txt	2008-10-02 19:46:03 UTC (rev 91672)
@@ -1,439 +0,0 @@
-Genshi
-======
-
-  >>> from z3c.pt.testing import render_genshi
-  
-py:if
-
-  >>> print render_genshi("""\
-  ... <div xmlns="http://www.w3.org/1999/xhtml"
-  ...      xmlns:py="http://genshi.edgewall.org/">
-  ...   <div py:if="False">
-  ...     <p>Bar</p>
-  ...   </div>
-  ...   <div py:if="True">
-  ...     <p>Foo</p>
-  ...   </div>
-  ...   <py:if test="False">
-  ...     <b>Bar</b>
-  ...   </py:if>
-  ...   <py:if test="True">
-  ...     <b>Foo</b>
-  ...   </py:if>
-  ... </div>""")
-  <div>
-    <div>
-      <p>Foo</p>
-    </div>
-  <BLANKLINE>
-      <b>Foo</b>
-  <BLANKLINE>
-  </div>
-
-py:choose, py:when, py:otherwise
-
-  >>> print render_genshi("""\
-  ... <div xmlns="http://www.w3.org/1999/xhtml"
-  ...      xmlns:py="http://genshi.edgewall.org/">
-  ...   <div py:choose="">
-  ...     <span py:when="0 == 1">0</span>
-  ...     <span py:when="1 == 1">1</span>
-  ...     <div>
-  ...       <span py:when="2 == 2">2</span>
-  ...       <span py:when="2 == 3">3</span>
-  ...       <div py:choose="1">
-  ...          <b py:when="1">3</b>
-  ...          <b py:when="2">4</b>
-  ...       </div>
-  ...     </div>
-  ...     <span py:otherwise="">3</span>
-  ...     <div py:choose="1">
-  ...       <span py:when="0">1</span>
-  ...       <span py:otherwise="">1</span>
-  ...     </div>
-  ...     <div py:choose="">
-  ...       <span py:when="0 == 1">1</span>
-  ...       <span py:otherwise="">2</span>
-  ...     </div>
-  ...   </div>
-  ... </div>""")
-  <div>
-    <div>
-      <span>1</span>
-      <div>
-        <span>2</span>
-        <div>
-           <b>3</b>
-           </div>
-      </div>
-      <div>
-        <span>1</span>
-      </div>
-      <div>
-        <span>2</span>
-      </div>
-    </div>
-  </div>
-
-py:for
-
-  >>> print render_genshi("""\
-  ... <ul xmlns="http://www.w3.org/1999/xhtml"
-  ...      xmlns:py="http://genshi.edgewall.org/">
-  ...   <li py:for="item in range(3)">${item}</li>
-  ...  <py:for each="item in range(3, 5)">
-  ...    <li>${item}</li>
-  ...  </py:for>
-  ... </ul>""")
-  <ul>
-    <li>0</li>
-  <li>1</li>
-  <li>2</li>
-  <li>3</li>
-  <li>4</li>
-  </ul>
-
-py:def
-
-  >>> print render_genshi("""\
-  ... <div xmlns="http://www.w3.org/1999/xhtml"
-  ...      xmlns:py="http://genshi.edgewall.org/">
-  ...  <p py:def="greeting(name)" class="greeting">
-  ...    Hello, ${name}!
-  ...  </p>
-  ...  ${greeting('world')}
-  ...  ${greeting('everyone else')}
-  ...  <py:def function="goodbye(name)">
-  ...    <p class="goodbye">Goodbye, ${name}!</p>
-  ...  </py:def>
-  ...  ${goodbye('world')}
-  ...  ${goodbye('everyone')}  
-  ... </div>""")
-  <div>
-   <p class="greeting">
-     Hello, world!
-   </p>
-  <BLANKLINE>
-   <p class="greeting">
-     Hello, everyone else!
-   </p>
-  <BLANKLINE>
-  <BLANKLINE>
-     <p class="goodbye">Goodbye, world!</p>
-  <BLANKLINE>
-  <BLANKLINE>
-  <BLANKLINE>
-     <p class="goodbye">Goodbye, everyone!</p>
-  <BLANKLINE>
-  <BLANKLINE>
-  </div>
-
-py:with
-
-  >>> def quote():
-  ...     return dict(author=u"Some name", quote=u"Some random quote")
-     
-  >>> print render_genshi("""\
-  ... <div xmlns="http://www.w3.org/1999/xhtml"
-  ...      xmlns:py="http://genshi.edgewall.org/">
-  ...   <span py:with="x=2; y=7; z=x+10">${x} ${y} ${z}</span>
-  ...   <py:with vars="x=4; y=3; z=x+5">${x} ${y} ${z}</py:with>
-  ...   <blockquote py:with="q=quote()">
-  ...       "${q["quote"]} <em>${q["author"]}</em>
-  ...   </blockquote>
-  ... </div>""", quote=quote)
-  <div>
-    <span>2 7 12</span>
-    4 3 9
-    <blockquote>
-        "Some random quote <em>Some name</em>
-    </blockquote>
-  </div>
-
-  
-py:attrs
-  
-  >>> print render_genshi("""\
-  ... <ul xmlns="http://www.w3.org/1999/xhtml"
-  ...     xmlns:py="http://genshi.edgewall.org/">
-  ...   <li class="expand" py:attrs="{'class': 'collapse'}">Bar</li>
-  ...   <li class="expand" py:attrs="d">Bar</li>
-  ... </ul>""", d=dict({'class': u'\u1234'}))
-  <ul>
-    <li class="collapse">Bar</li>
-    <li class="ሴ">Bar</li>
-  </ul>
-
-py:content, py:replace
-
-  >>> print render_genshi("""\
-  ... <div xmlns="http://www.w3.org/1999/xhtml"
-  ...      xmlns:py="http://genshi.edgewall.org/">
-  ...   <span py:content="'Hello, world!'" />
-  ...   <span py:replace="'Goodbye, world!'" />
-  ... </div>""")
-  <div>
-    <span>Hello, world!</span>
-    Goodbye, world!
-  </div>
-
-py:strip
-
-  >>> print render_genshi("""\
-  ... <div xmlns="http://www.w3.org/1999/xhtml"
-  ...      xmlns:py="http://genshi.edgewall.org/">
-  ...    <span py:strip="True"><b>foo</b></span>
-  ... </div>""")
-  <div>
-     <b>foo</b>
-  </div>
-
-py:match
-
-  >>> print render_genshi("""\
-  ... <div xmlns="http://www.w3.org/1999/xhtml"
-  ...      xmlns:py="http://genshi.edgewall.org/">
-  ...   <span py:match=".//xmlns:greeting">
-  ...     Hello, ${select('@name')[0]}!
-  ...   </span>
-  ...   <py:match path=".//xmlns:farewell">
-  ...      <span>Goodbye, ${select('@name')[0]}!</span>
-  ...   </py:match>
-  ...   <greeting name="dude" />
-  ...   <farewell name="dude" />
-  ... </div>""")
-  <div>
-    <span>
-      Hello, dude!
-    </span>
-  <BLANKLINE>
-  <BLANKLINE>
-       <span>Goodbye, dude!</span>
-  <BLANKLINE>
-  <BLANKLINE>
-  </div>
-
-:: Genshi variable interpolation (${<exp>} notation)
-
-  >>> print render_genshi("""\
-  ... <div xmlns="http://www.w3.org/1999/xhtml"
-  ...      xmlns:py="http://genshi.edgewall.org/">
-  ...   <span>inter${'pol' + 'ati'}on</span>is ${int('test') | 'convenient'}!
-  ...   <span>${'a'}${'b'}${'c'} ${'d'}</span>
-  ...   <span py:with="hello='Hello'" class="${hello} World!" />
-  ...   <span class="my-${'class'} item${'Last'}" />
-  ...   <a href="${ltr.href}" class="${ltr.iscurrent}">${ltr.letter}</a>
-  ...   <span style="position: ${'abs'}olute"
-  ...         class="my-${int('test') | 'class'} item${'Last'}" />
-  ... </div>""", ltr={'letter': 'A', 'href': '?title=A', 'iscurrent': 'current'})
-    <div>
-      <span>interpolation</span>is convenient!
-      <span>abc d</span>
-      <span class="Hello World!" />
-      <span class="my-class itemLast" />
-      <a href="?title=A" class="current">A</a>
-      <span style="position: absolute" class="my-class itemLast" />
-    </div>
-
-:: Simple variable names do not need { .. }. From `py:with specs`_.
-
-  >>> print render_genshi("""\
-  ... <div xmlns="http://www.w3.org/1999/xhtml"
-  ...      xmlns:py="http://genshi.edgewall.org/">
-  ...   <span py:with="y=7; z=x+10">$x $y $z</span>
-  ... </div>""", x=42)
-  <div>
-    <span>42 7 52</span>
-  </div>
-
-:: Genshi variable interpolation and unicode values
-    
-  >>> print render_genshi("""\
-  ... <div xmlns="http://www.w3.org/1999/xhtml">
-  ...   <img alt="${'La Peña'}" />
-  ...   <img alt="Hello ${'La Peña'}" />
-  ...   <img alt="La Peña, oh ${'La Peña'}" />
-  ...   ${unicode('La Pe\xc3\xb1a', 'utf-8').encode('utf-8')}
-  ...   <img alt="${unicode('La Pe\xc3\xb1a', 'utf-8').encode('utf-8')}" />
-  ...   <img alt="Hello ${unicode('La Pe\xc3\xb1a', 'utf-8').encode('utf-8')}!" />
-  ... </div>""", encoding='utf-8')
-    <div>
-      <img alt="La Peña" />
-      <img alt="Hello La Peña" />
-      <img alt="La Peña, oh La Peña" />
-      La Peña
-      <img alt="La Peña" />
-      <img alt="Hello La Peña!" />
-    </div>
-
-:: Unicode combined with attribute expansion
-
-  >>> print render_genshi("""\
-  ... <div xmlns="http://www.w3.org/1999/xhtml">
-  ...   <img alt="La Peña" />
-  ...   <img alt="${alt}" />
-  ... </div>""", alt=unicode("La Pe\xc3\xb1a", 'utf-8'))
-  <div>
-    <img alt="La Pe&ntilde;a" />
-    <img alt="La Peña" />
-  </div>
-
-:: Variables containing quotes
-  >>> print render_genshi("""\
-  ... <div xmlns="http://www.w3.org/1999/xhtml">
-  ...   <strong>"${quote}"</strong>
-  ... </div>""", quote="Hello, World!")
-    <div>
-      <strong>"Hello, World!"</strong>
-    </div>
-  
-:: Variables containing markup
-
-  >>> print render_genshi("""\
-  ... <div xmlns="http://www.w3.org/1999/xhtml">
-  ...   ${message}
-  ... </div>""", message="Hello, <em>World</em>!")
-    <div>
-      Hello, <em>World</em>!
-    </div>
-
-:: Variable expansion must preserve XML validity
-
-  >>> from z3c.pt import config
-  >>> config.VALIDATION = True
-  
-  >>> print render_genshi("""\
-  ... <div xmlns="http://www.w3.org/1999/xhtml">
-  ...   ${message}
-  ... </div>""", message="Hello, <em>World!")
-  Traceback (most recent call last):
-   ...
-  ValidationError: Insertion of 'Hello, <em>World!' is not allowed.
-  
-  >>> config.VALIDATION = False
-  
-:: Unless we are in a CDATA block
-
-  >>> print render_genshi("""\
-  ... <div xmlns="http://www.w3.org/1999/xhtml">
-  ... /* <![CDATA[ */
-  ...   ${message}
-  ... /* ]]> */
-  ... </div>""", message="Hello, <em>World!")
-    <div>
-      /* <![CDATA[ */
-      Hello, <em>World!
-      /* ]]> */
-    </div>
-
-:: HTML comments
-
-  >>> print render_genshi("""\
-  ... <div xmlns="http://www.w3.org/1999/xhtml"
-  ...      xmlns:py="http://genshi.edgewall.org/">
-  ...   <!-- a comment -->
-  ...   <!-- a multi-
-  ...        line comment -->
-  ...   <!-- a comment with an ${'expression'} -->
-  ... </div>""")
-  <div>
-    <!-- a comment -->
-    <!-- a multi-
-         line comment -->
-    <!-- a comment with an expression -->
-  </div>
-
-:: z3c.pt used to forget to output the ]; after the for loop
-
-  >>> print render_genshi("""\
-  ... <script xmlns="http://www.w3.org/1999/xhtml"
-  ...         xmlns:py="http://genshi.edgewall.org/"
-  ...         type="text/javascript">
-  ...  var brands = [
-  ...  <py:for each="brand in []">
-  ...    { value :  "${brand['id']}", "title" : "${brand['title']}" },
-  ...  </py:for>
-  ...  ];
-  ... </script>""")
-  <script type="text/javascript">
-  var brands = [
-  ];
-  </script>
-
-:: Strange looping behaviour
-
-  >>> brands=[dict(id=1, title="One"),
-  ...         dict(id=2, title="Two"),
-  ...         dict(id=3, title="Three")]
-  >>> print render_genshi("""\
-  ... <div xmlns="http://www.w3.org/1999/xhtml"
-  ...       xmlns:py="http://genshi.edgewall.org/">
-  ... <script type="text/javascript">
-  ... var brands = [
-  ...     <py:for each="brand in brands">
-  ...         { value :  "${brand['id']}", title : "${brand['title']}" },
-  ...     </py:for>
-  ...     ];
-  ...
-  ... $(document.ready(function() {
-  ...   alert("Hello, World");
-  ... });
-  ... </script>
-  ... </div>""", brands=brands)
-  <div>
-  <script type="text/javascript">
-    var brands = [
-      { value : "1", title : "One" },
-      { value : "2", title : "Two" },
-      { value : "3", title : "Three" },
-      ];
-  <BLANKLINE>
-  $(document.ready(function() {
-    alert("Hello, World");
-  });
-  </script>
-  </div>
-
-:: Very basic recursing
-
-  >>> print render_genshi("""\
-  ... <div xmlns="http://www.w3.org/1999/xhtml"
-  ...     xmlns:py="http://genshi.edgewall.org/">
-  ...   <ul py:def="rendermenu(menu)" py:if="menu">
-  ...     ${rendermenu([])}
-  ...   </ul>
-  ... </div>""")
-  <div>
-  </div>
-  
-:: Slightly more complex recursive function calls
- 
-  >>> print render_genshi("""\
-  ... <div xmlns="http://www.w3.org/1999/xhtml"
-  ...       xmlns:py="http://genshi.edgewall.org/">
-  ...   <ul py:def="rendermenu(menu)">
-  ...     <li py:for="entry in menu"
-  ...         py:attrs="{'class' : entry['current'] and 'current' or None}">
-  ...       <a py:attrs="dict(href=entry['url'])"
-  ...          py:content="entry['title']">Merken</a>
-  ...       ${rendermenu(entry.get('children', []))}
-  ...     </li>
-  ...   </ul>
-  ...   ${rendermenu(menu)}
-  ... </div>""", menu=[dict(title=u"Menu entry", url="/test", current=True)])
-  <div>
-    <ul>
-      <li class="current">
-        <a href="/test">Menu entry</a>
-        <ul>
-  <BLANKLINE>
-    </ul>
-  <BLANKLINE>
-      </li>
-  <BLANKLINE>
-    </ul>
-  <BLANKLINE>
-  </div>
-
-.. _py:with specs: http://genshi.edgewall.org/wiki/Documentation/0.4.x/xml-templates.html#py-with
-

Deleted: z3c.pt/trunk/src/z3c/pt/interfaces.py
===================================================================
--- z3c.pt/trunk/src/z3c/pt/interfaces.py	2008-10-02 19:44:09 UTC (rev 91671)
+++ z3c.pt/trunk/src/z3c/pt/interfaces.py	2008-10-02 19:46:03 UTC (rev 91672)
@@ -1,138 +0,0 @@
-from zope import interface
-
-class IExpressionTranslation(interface.Interface):
-    """This interface defines an expression translation utility."""
-    
-    def name(string):
-        """Should interpret ``string`` as a name. This method will
-        usually be the identity function."""
-    
-    def value(string):
-        """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
-        the provided string."""
-
-    def variable(string):
-        """A variable definition.
-        
-        Specification:
-        
-           variables :: = variable_name [, variables]
-
-        """
-        
-    def mapping(string):
-        """A mapping definition."""
-
-    def definition(string):
-        """A definition."""
-
-    def definitions(string):
-        """Multiple definitions.
-        
-        Specification:
-
-           argument ::= define_var [';' define_var]
-           define_var ::= Name python_expression
-           
-        """
-
-class ITALIterator(interface.Interface):
-    """A TAL iterator
-
-    Not to be confused with a Python iterator.
-    """
-
-    def next():
-        """Advance to the next value in the iteration, if possible
-
-        Return a true value if it was possible to advance and return
-        a false value otherwise.
-        """
-
-class ITALESIterator(ITALIterator):
-    """TAL Iterator provided by TALES
-
-    Values of this iterator are assigned to items in the repeat namespace.
-
-    For example, with a TAL statement like: tal:repeat="item items",
-    an iterator will be assigned to "repeat/item".  The iterator
-    provides a number of handy methods useful in writing TAL loops.
-
-    The results are undefined of calling any of the methods except
-    'length' before the first iteration.
-    """
-
-    def index():
-        """Return the position (starting with "0") within the iteration
-        """
-
-    def number():
-        """Return the position (starting with "1") within the iteration
-        """
-
-    def even():
-        """Return whether the current position is even
-        """
-
-    def odd():
-        """Return whether the current position is odd
-        """
-
-    def parity():
-        """Return 'odd' or 'even' depending on the position's parity
-
-        Useful for assigning CSS class names to table rows.
-        """
-
-    def start():
-        """Return whether the current position is the first position
-        """
-
-    def end():
-        """Return whether the current position is the last position
-        """
-
-    def letter():
-        """Return the position (starting with "a") within the iteration
-        """
-
-    def Letter():
-        """Return the position (starting with "A") within the iteration
-        """
-
-    def roman():
-        """Return the position (starting with "i") within the iteration
-        """
-
-    def Roman():
-        """Return the position (starting with "I") within the iteration
-        """
-
-    def item():
-        """Return the item at the current position
-        """
-
-    def length():
-        """Return the length of the sequence
-
-        Note that this may fail if the TAL iterator was created on a Python
-        iterator.
-        """

Modified: z3c.pt/trunk/src/z3c/pt/loader.py
===================================================================
--- z3c.pt/trunk/src/z3c/pt/loader.py	2008-10-02 19:44:09 UTC (rev 91671)
+++ z3c.pt/trunk/src/z3c/pt/loader.py	2008-10-02 19:46:03 UTC (rev 91672)
@@ -1,51 +1,15 @@
 import errno
 import os.path
+
 from z3c.pt.pagetemplate import PageTemplateFile
 from z3c.pt.texttemplate import TextTemplateFile
 
-def cache(func):
-    def load(self, *args):
-        template = self.registry.get(args)
-        if template is None:
-            self.registry[args] = template = func(self, *args)
-        return template
-    return load
-    
-class TemplateLoader(object):
-    """Template loader tool. To load templates using relative
-    filenames, pass a sequence of paths (or a single path) as
-    ``search_path``; if ``auto_reload`` is set, templates will be
-    reloaded when modified."""
+from chameleon.core import loader
 
-    def __init__(self, search_path=None, auto_reload=False, parser=None):
-        if search_path is None:
-            search_path = []
-        if isinstance(search_path, basestring):
-            search_path = [search_path]
-        self.search_path = search_path
-        self.auto_reload = auto_reload
-        self.parser = parser
-        self.registry = {}
-
-    @cache
-    def _load(self, filename, klass):
-        if os.path.isabs(filename):
-            return klass(filename, self.parser)
-
-        for path in self.search_path:
-            path = os.path.join(path, filename)
-            try:
-                return klass(
-                    path, self.parser, auto_reload=self.auto_reload)
-            except OSError, e:
-                if e.errno != errno.ENOENT:
-                    raise
-
-        raise ValueError("Can not find template %s" % filename)
-
+class TemplateLoader(loader.TemplateLoader):
     def load_page(self, filename):
-        return self._load(filename, PageTemplateFile)
+        return self.load(filename, PageTemplateFile)
 
     def load_text(self, filename):
-        return self._load(filename, TextTemplateFile)
+        return self.load(filename, TextTemplateFile)
 

Modified: z3c.pt/trunk/src/z3c/pt/pagetemplate.py
===================================================================
--- z3c.pt/trunk/src/z3c/pt/pagetemplate.py	2008-10-02 19:44:09 UTC (rev 91671)
+++ z3c.pt/trunk/src/z3c/pt/pagetemplate.py	2008-10-02 19:46:03 UTC (rev 91672)
@@ -1,62 +1,16 @@
-import zope.i18n
-
-import template
-import config
-import zpt
-import sys
 import os
+import sys
 
-def prepare_language_support(**kwargs):
-    target_language = kwargs.get('target_language')
+from chameleon.zpt.template import PageTemplate
+from chameleon.zpt.template import PageTemplateFile
+from chameleon.zpt.language import Parser
 
-    if config.DISABLE_I18N:
-        if target_language:
-            del kwargs['target_language']
-        return
-    
-    if not target_language:
-        context = kwargs.get(config.SYMBOLS.i18n_context)
-        target_language = zope.i18n.negotiate(context)
-
-        if target_language:
-            kwargs['target_language'] = target_language    
-
-class PageTemplate(template.BaseTemplate):
-    __doc__ = template.BaseTemplate.__doc__ # for Sphinx autodoc
-
-    default_parser = zpt.ZopePageTemplateParser()
-    
-    def __init__(self, body, parser=None, format=None, doctype=None):
-        if parser is None:
-            parser = self.default_parser
-        super(PageTemplate, self).__init__(body, parser, format, doctype)
-
-    def render(self, **kwargs):
-        prepare_language_support(**kwargs)
-        return super(PageTemplate, self).render(**kwargs)
-
-class PageTemplateFile(template.BaseTemplateFile):
-    __doc__ = template.BaseTemplateFile.__doc__ # for Sphinx autodoc
-
-    default_parser = zpt.ZopePageTemplateParser()
-    
-    def __init__(self, filename, parser=None, format=None,
-                 doctype=None, **kwargs):
-        if parser is None:
-            parser = self.default_parser
-        super(PageTemplateFile, self).__init__(filename, parser, format,
-                                               doctype, **kwargs)
-
-    def render(self, **kwargs):
-        prepare_language_support(**kwargs)
-        return super(PageTemplateFile, self).render(**kwargs)
-
 class ZopePageTemplate(PageTemplate):
-    default_parser = zpt.ZopePageTemplateParser(default_expression='path')
+    default_parser = Parser(default_expression='path')
 
 class ZopePageTemplateFile(PageTemplateFile):
-    default_parser = zpt.ZopePageTemplateParser(default_expression='path')
-
+    default_parser = Parser(default_expression='path')
+    
 class ViewPageTemplate(property):
     """Template class suitable for use with a Zope browser view; the
     variables ``view``, ``context`` and ``request`` variables are
@@ -65,8 +19,10 @@
     dictionary. Note that the default expression type for this class
     is 'path' (standard Zope traversal)."""
     
+    template_class = ZopePageTemplate
+
     def __init__(self, body, **kwargs):
-        self.template = ZopePageTemplate(body, **kwargs)
+        self.template = self.template_class(body, **kwargs)
         property.__init__(self, self.bind)
 
     def bind(self, view, request=None, macro=None, global_scope=True):
@@ -95,6 +51,8 @@
 class ViewPageTemplateFile(ViewPageTemplate):
     """If ``filename`` is a relative path, the module path of the
     class where the instance is used to get an absolute path."""
+
+    template_class = ZopePageTemplateFile
     
     def __init__(self, filename, path=None, content_type=None, **kwargs):
         if path is not None:
@@ -117,7 +75,7 @@
  	 
             filename = path + os.sep + filename
 
-        self.template = ZopePageTemplateFile(filename, **kwargs)
+        self.template = self.template_class(filename, **kwargs)
         property.__init__(self, self.bind)
 
     def __call__(self, view, **kwargs):

Deleted: z3c.pt/trunk/src/z3c/pt/template.py
===================================================================
--- z3c.pt/trunk/src/z3c/pt/template.py	2008-10-02 19:44:09 UTC (rev 91671)
+++ z3c.pt/trunk/src/z3c/pt/template.py	2008-10-02 19:46:03 UTC (rev 91672)
@@ -1,195 +0,0 @@
-import os
-import config
-import doctypes
-import filecache
-import translation
-
-class BaseTemplate(object):
-    """Constructs a template object using the template language
-    defined by ``parser`` (``ZopePageTemplateParser`` or
-    ``GenshiParser`` as of this writing). Must be passed an input
-    string as ``body``. The ``format`` parameter supports values 'xml'
-    and 'text'. Pass a value for ``encoding`` if you need to allow
-    strings that are not unicode or plain ASCII."""
-
-    compilers = {
-        'xml': translation.Compiler,
-        'text': translation.Compiler.from_text}
-
-    format = 'xml'
-    implicit_doctype = doctypes.xhtml
-    explicit_doctype = None
-    
-    def __init__(self, body, parser, format=None, doctype=None, encoding=None):
-        self.body = body
-        self.parser = parser        
-        self.signature = hash(body)
-        self.registry = {}
-        self.encoding = encoding
-        
-        if format is not None:
-            self.format = format
-
-        if doctype is not None:            
-            self.explicit_doctype = doctype
-        
-    @property
-    def macros(self):
-        return Macros(self.render_macro)
-
-    @property
-    def compiler(self):
-        return self.compilers[self.format](
-            self.body, self.parser,
-            implicit_doctype=self.implicit_doctype,
-            explicit_doctype=self.explicit_doctype,
-            encoding=self.encoding)
-
-    def cook(self, **kwargs):
-        return self.compiler(**kwargs)
-    
-    def cook_check(self, parameters, **kwargs):
-        key = tuple(parameters), \
-              tuple(item for item in kwargs.iteritems()), \
-              self.signature, self.explicit_doctype
-        template = self.registry.get(key, None)
-        if template is None:
-            template = self.cook(parameters=parameters, **kwargs)
-            self.registry[key] = template
-        return template
-
-    def render(self, **kwargs):
-        template = self.cook_check(parameters=kwargs)
-        return template.render(**kwargs)
-
-    def render_macro(self, macro, global_scope=False, parameters={}):
-        template = self.cook_check(
-            parameters=parameters, macro=macro, global_scope=global_scope)
-        return template.render(**parameters)
-    
-    def render_xinclude(self, **kwargs):
-        return self.render_macro("", parameters=kwargs)
-
-    def __repr__(self):
-        return u"<%s %d>" % (self.__class__.__name__, id(self))
-
-    def __call__(self, **kwargs):
-        return self.render(**kwargs)
-    
-class BaseTemplateFile(BaseTemplate):
-    """Constructs a template object using the template language
-    defined by ``parser``. Must be passed an absolute (or
-    current-working-directory-relative) filename as ``filename``. If
-    ``auto_reload`` is true, each time the template is rendered, it
-    will be recompiled if it has been changed since the last
-    rendering."""
-    
-    global_registry = {}
-    
-    def __init__(self, filename, parser, format=None,  doctype=None,
-                 auto_reload=False):
-        BaseTemplate.__init__(
-            self, None, parser, format=format, doctype=doctype)
-
-        self.auto_reload = auto_reload
-        self.filename = filename = os.path.abspath(
-            os.path.normpath(os.path.expanduser(filename)))
-
-        # make sure file exists
-        os.lstat(filename)
-
-        # read template
-        self.read()
-
-        # persist template registry on disk
-        if config.DISK_CACHE:
-            self.registry = self.global_registry.setdefault(
-                filename, filecache.TemplateCache(filename))
-
-        self.xincludes = XIncludes(
-            self.global_registry, os.path.dirname(filename), self.clone)
-        
-    def clone(self, filename, format=None):
-        cls = type(self)
-        return cls(
-            filename, self.parser, format=format,
-            doctype=self.explicit_doctype, auto_reload=self.auto_reload)
-        
-    def _get_filename(self):
-        return getattr(self, '_filename', None)
-
-    def _set_filename(self, filename):
-        self._filename = filename
-        self._v_last_read = False
-
-    filename = property(_get_filename, _set_filename)
-
-    def read(self):
-        filename = self.filename
-        mtime = self.mtime()
-        fd = open(filename, 'r')
-        self.body = body = fd.read()
-        fd.close()
-        self.signature = filename, mtime
-        self._v_last_read = mtime
-
-    def cook(self, **kwargs):
-        template = self.compiler(**kwargs)
-
-        if config.DEBUG_MODE:
-            filename = "%s.py" % self.filename
-            f = open(filename, 'w')
-            f.write(template.source)
-            f.close()
-
-        return template
-
-    def cook_check(self, **kwargs):
-        if self.auto_reload and self._v_last_read != self.mtime():
-            self.read()
-
-        return BaseTemplate.cook_check(self, **kwargs)
-
-    def render(self, **kwargs):
-        kwargs[config.SYMBOLS.xincludes] = self.xincludes
-        return super(BaseTemplateFile, self).render(**kwargs)
-
-    def mtime(self):
-        try:
-            return os.path.getmtime(self.filename)
-        except (IOError, OSError):
-            return 0
-
-    def __repr__(self):
-        return u"<%s %s>" % (self.__class__.__name__, self.filename)
-
-class XIncludes(object):
-    """Dynamic XInclude registry providing a ``get``-method that will
-    resolve a filename to a template instance. Format must be
-    explicitly provided."""
-    
-    def __init__(self, registry, relpath, factory):
-        self.registry = registry
-        self.relpath = relpath
-        self.factory = factory
-
-    def get(self, filename, format):
-        if not os.path.isabs(filename):
-            filename = os.path.join(self.relpath, filename)        
-        template = self.registry.get(filename)
-        if template is not None:
-            return template
-        return self.factory(filename, format=format)
-    
-class Macro(object):
-    def __init__(self, render):
-        self.render = render
-
-class Macros(object):
-    def __init__(self, render_macro):
-        self.render = render_macro
-
-    def __getitem__(self, name):
-        def render(**kwargs):
-            return self.render(name, parameters=kwargs)
-        return Macro(render)

Deleted: z3c.pt/trunk/src/z3c/pt/template.txt
===================================================================
--- z3c.pt/trunk/src/z3c/pt/template.txt	2008-10-02 19:44:09 UTC (rev 91671)
+++ z3c.pt/trunk/src/z3c/pt/template.txt	2008-10-02 19:46:03 UTC (rev 91672)
@@ -1,288 +0,0 @@
-Template classes
-================
-
-This section demonstrates the high-level template classes.
-
-z3c.pt.pagetemplate.PageTemplate
---------------------------------
-
-  >>> from z3c.pt.pagetemplate import PageTemplate
-  >>> from z3c.pt.testing import mock_parser
-  
-  >>> print PageTemplate("""\
-  ... <div xmlns="http://www.w3.org/1999/xhtml">
-  ...   Hello World!
-  ... </div>""")()
-  <div>
-    Hello World!
-  </div>
-
-z3c.pt.pagetemplate.PageTemplateFile
-------------------------------------
-
-  >>> from z3c.pt.pagetemplate import PageTemplateFile
-  >>> from z3c.pt import tests
-  >>> path = tests.__path__[0]
-  >>> t = PageTemplateFile(path+'/helloworld.pt')
-  >>> print t()
-  <div>
-    Hello World!
-  </div>
-
-  >>> import os
-  >>> t.filename.startswith(os.sep)
-  True
-
-z3c.pt.pagetemplate.ViewPageTemplate
-------------------------------------
-
-  >>> from z3c.pt.pagetemplate import ViewPageTemplate
-  
-  >>> class ViewPageTemplateView(object):
-  ...     __call__ = ViewPageTemplate(
-  ...          open(path+'/view.pt').read())
-  ...     request = u'request'
-  ...     context = u'context'
-
-  >>> view = ViewPageTemplateView()
-    
-  >>> print view(test=u'test')
-  <div>
-    <span>&lt;ViewPageTemplateView object at ...&gt;</span>
-    <span>context</span>
-    <span>request</span>
-    <span>test</span>
-  </div>
-
-z3c.pt.pagetemplate.ViewPageTemplateFile
-----------------------------------------
-
-  >>> from z3c.pt.pagetemplate import ViewPageTemplateFile
-  
-  >>> class ViewPageTemplateView(object):
-  ...     __call__ = ViewPageTemplateFile(path+'/view.pt')
-  ...     request = u'request'
-  ...     context = u'context'
-
-  >>> view = ViewPageTemplateView()
-
-  >>> print view(test=u'test')
-  <div>
-    <span>&lt;ViewPageTemplateView object at ...&gt;</span>
-    <span>context</span>
-    <span>request</span>
-    <span>test</span>
-  </div>
-
-z3c.pt.texttemplate.ViewTextTemplate
-------------------------------------
-
-  >>> from z3c.pt.texttemplate import ViewTextTemplate
-  
-  >>> class ViewTextTemplateView(object):
-  ...     __call__ = ViewTextTemplate(open(path+'/view.css').read())
-  ...     request = u'request'
-  ...     context = u'context'
-
-  >>> view = ViewTextTemplateView()
-
-  >>> print view(color=u'#ccc')
-  #region {
-      background: #ccc;
-  }
-
-z3c.pt.texttemplate.ViewTextTemplateFile
-----------------------------------------
-
-  >>> from z3c.pt.texttemplate import ViewTextTemplateFile
-  
-  >>> class ViewTextTemplateView(object):
-  ...     __call__ = ViewTextTemplateFile(path+'/view.css')
-  ...     request = u'request'
-  ...     context = u'context'
-
-  >>> view = ViewTextTemplateView()
-
-  >>> print view(color=u'#ccc')
-  #region {
-      background: #ccc;
-  }
-
-Compiler integration
---------------------
-
-Certain constructs require close collaboration between the template
-compiler and the page template classes.
-
-py:match integration
-
-  >>> from z3c.pt.genshi import GenshiParser
-  
-  >>> print PageTemplate("""\
-  ... <div xmlns="http://www.w3.org/1999/xhtml"
-  ...      xmlns:py="http://genshi.edgewall.org/">
-  ...   <py:match path=".//xmlns:greeting">Hello ${select('@name')[0]}!</py:match>
-  ...   <greeting name="World" />
-  ... </div>
-  ... """, parser=GenshiParser())()
-  <div>
-    Hello World!
-  <BLANKLINE>
-  </div>
-
-metal:define-macro, metal:use-macro
-
-  >>> template1 = PageTemplate("""\
-  ... <div xmlns="http://www.w3.org/1999/xhtml"
-  ...      xmlns:tal="http://xml.zope.org/namespaces/tal"
-  ...      xmlns:metal="http://xml.zope.org/namespaces/metal">
-  ...   <div metal:define-macro="greeting">
-  ...     Hello, ${name}!
-  ...     <span tal:define="global name 'earth'">
-  ...       Hello, ${name}!
-  ...     </span>
-  ...     Hello, ${name}!
-  ...   </div>
-  ... </div>""")
-
-  >>> template2 = PageTemplate("""\
-  ... <div xmlns="http://www.w3.org/1999/xhtml"
-  ...      xmlns:tal="http://xml.zope.org/namespaces/tal"
-  ...      xmlns:metal="http://xml.zope.org/namespaces/metal">
-  ...   <div tal:define="name 'world'">
-  ...     <div metal:use-macro="template1.macros['greeting']" />
-  ...     Hello, ${name}!
-  ...   </div>
-  ...   Hello, ${name}!
-  ... </div>""")
-
-  >>> print template2(template1=template1)
-  <div>
-    <div>
-      <div>
-      Hello, world!
-      <span>
-        Hello, earth!
-      </span>
-      Hello, earth!
-    </div>
-  <BLANKLINE>
-      Hello, world!
-    </div>
-    Hello, earth!
-  </div>
-
-metal:define-macro, metal:use-macro, metal:define-slot, metal:fill-slot
-
-  >>> main = PageTemplate("""\
-  ... <html xmlns="http://www.w3.org/1999/xhtml"
-  ...       xmlns:tal="http://xml.zope.org/namespaces/tal"
-  ...       xmlns:metal="http://xml.zope.org/namespaces/metal"
-  ...       metal:define-macro="master">
-  ...   <div metal:define-slot="content">
-  ...       I will be replaced
-  ...   </div>
-  ... </html>""")
-
-  >>> content = PageTemplate("""\
-  ... <div xmlns="http://www.w3.org/1999/xhtml"
-  ...      xmlns:tal="http://xml.zope.org/namespaces/tal"
-  ...      xmlns:metal="http://xml.zope.org/namespaces/metal"
-  ...      metal:use-macro="main.macros['master']">
-  ...   <div metal:fill-slot="content">
-  ...       I replace you.
-  ...   </div>
-  ... </div>""")
-
-  >>> print content(main=main)
-  <html>
-    <div>
-         I replace you.
-    </div>
-  </html>
-
-xi:include
-
-  >>> from z3c.pt.template import BaseTemplateFile
-  >>> template1 = BaseTemplateFile(path+"/xinclude1.pt", mock_parser)
-  >>> print template1()
-  <div>
-    <div>
-    <span>Hello, world!</span>
-    </div>
-  </div>
-
-:: XInclude in Genshi
-
-When using XInclude-statements in Genshi, macro-definitions are
-carried over from the included template. This is demonstrated below.
-
-  >>> template2 = BaseTemplateFile(path+"/xinclude3.pt", GenshiParser())
-  >>> print template2()
-  <div>
-  <BLANKLINE>
-  <BLANKLINE>
-    <p class="greeting">
-      Hello, world!
-    </p>
-  <BLANKLINE>
-  </div>
-
-Before we proceed, we reduce and restore the underlying byte-code
-template.
-  
-  >>> from cPickle import dumps, loads
-  >>> for registry in (template1.registry, template2.registry):
-  ...     for key, bct in registry.items():
-  ...         registry[key] = loads(dumps(bct))
-
-  >>> print template2()
-  <div>
-  <BLANKLINE>
-  <BLANKLINE>
-    <p class="greeting">
-      Hello, world!
-    </p>
-  <BLANKLINE>
-  </div>
-  
-  
-Error handling
---------------
-
-When an exception is raised which does not expose a bug in the TAL
-translation machinery, we expect the exception to contain the part of
-the template source that caused the exception.
-
-Exception while evaluating expression:
-
-  >>> PageTemplate("""\
-  ... <div xmlns="http://www.w3.org/1999/xhtml"
-  ...      xmlns:tal="http://xml.zope.org/namespaces/tal">
-  ...   <span tal:content="range()" />
-  ... </div>""").render()
-  Traceback (most recent call last):
-    ...
-  TypeError: range expected at least 1 arguments, got 0
-
-Exception while evaluating definition:
-
-  >>> PageTemplate("""\
-  ... <div xmlns="http://www.w3.org/1999/xhtml"
-  ...      xmlns:tal="http://xml.zope.org/namespaces/tal">
-  ...   <span tal:define="dummy range()" />
-  ... </div>""").render()
-  Traceback (most recent call last):
-    ...
-  TypeError: range expected at least 1 arguments, got 0
-
-Exception while evaluating interpolation:
-
-  >>> PageTemplate("""\
-  ... <div xmlns="http://www.w3.org/1999/xhtml"
-  ...      xmlns:tal="http://xml.zope.org/namespaces/tal">
-  ...   <span>${range()}</span>
-  ... </div>""").render()
-  Traceback (most recent call last):
-    ...
-  TypeError: range expected at least 1 arguments, got 0

Deleted: z3c.pt/trunk/src/z3c/pt/testing.py
===================================================================
--- z3c.pt/trunk/src/z3c/pt/testing.py	2008-10-02 19:44:09 UTC (rev 91671)
+++ z3c.pt/trunk/src/z3c/pt/testing.py	2008-10-02 19:46:03 UTC (rev 91672)
@@ -1,136 +0,0 @@
-import translation
-import template
-import generation
-import expressions
-import doctypes
-import etree
-import config
-import utils
-
-import zpt
-import genshi
-
-from StringIO import StringIO
-from cPickle import dumps, loads
-
-class TestCompiler(translation.Compiler):
-    def __call__(self, *args, **kwargs):
-        template = translation.Compiler.__call__(self, *args, **kwargs)
-        template = loads(dumps(template))
-        return template
-
-def pyexp(string):
-    return expressions.python_translation.expression(string)
-
-def setup_stream(encoding=None):
-    class symbols(translation.Node.symbols):
-        out = '_out'
-        write = '_write'
-
-    out = StringIO()
-    write = out.write
-    stream = generation.CodeIO(symbols, encoding=encoding)
-    return out, write, stream
-
-def compile_xhtml(body, **kwargs):
-    compiler = TestCompiler(
-        body, mock_parser, implicit_doctype=doctypes.xhtml)
-    return compiler(parameters=sorted(kwargs.keys()))
-
-def render_xhtml(body, **kwargs):
-    template = compile_xhtml(body, **kwargs)
-    return template.render(**kwargs)    
-    
-def render_text(body, **kwargs):
-    compiler = TestCompiler.from_text(
-        body, mock_parser, implicit_doctype=doctypes.xhtml)
-    template = compiler(parameters=sorted(kwargs.keys()))
-    return template.render(**kwargs)    
-
-def render_zpt(body, **kwargs):
-    compiler = TestCompiler(
-        body, zpt.ZopePageTemplateParser(), implicit_doctype=doctypes.xhtml)
-    template = compiler(parameters=sorted(kwargs.keys()))
-    return template.render(**kwargs)    
-
-def render_genshi(body, encoding=None, **kwargs):
-    compiler = TestCompiler(
-        body, genshi.GenshiParser(),
-        encoding=encoding, implicit_doctype=doctypes.xhtml)
-    template = compiler(parameters=sorted(kwargs.keys()))
-    kwargs.update(template.selectors)
-    return template.render(**kwargs)    
-
-class MockTemplate(object):
-    def __init__(self, body, parser):
-        self.body = body
-        self.parser = parser
-
-    @property
-    def macros(self):
-        def render(name, parameters={}):
-            compiler = TestCompiler(self.body, self.parser)
-            template = compiler(macro=name, parameters=parameters)
-            return template.render(**parameters)
-        return template.Macros(render)
-
-class MockElement(translation.Element, translation.VariableInterpolation):
-    translator = expressions.python_translation
-    
-    def update(self):
-        translation.VariableInterpolation.update(self)
-        
-    class node(translation.Node):
-        def __getattr__(self, name):
-            return None
-
-        @property
-        def static_attributes(self):
-            return utils.get_attributes_from_namespace(
-                self.element, config.XHTML_NS)
-
-        @property
-        def omit(self):
-            if self.element.meta_omit is not None:
-                return self.element.meta_omit or True
-            if self.content:
-                return True
-            if self.include:
-                return True
-
-        @property
-        def content(self):
-            return self.element.meta_replace
-        
-        @property
-        def cdata(self):
-            return self.element.meta_cdata
-
-        @property
-        def include(self):
-            return self.element.xi_href
-
-        @property
-        def format(self):
-            return self.element.xi_parse
-
-    node = property(node)
-
-    xi_href = None
-    xi_parse = None
-
-class MockMetaElement(MockElement, translation.MetaElement):
-    pass
-    
-class MockXiElement(MockElement):
-    xi_href = utils.attribute(
-        "href", lambda p: expressions.StringTranslation(p).expression)
-    xi_parse = utils.attribute("parse", default="xml")
-
-class MockParser(etree.Parser):
-    element_mapping = {
-        config.XHTML_NS: {None: MockElement},
-        config.META_NS: {None: MockMetaElement},
-        config.XI_NS: {None: MockXiElement}}
-
-mock_parser = MockParser()

Modified: z3c.pt/trunk/src/z3c/pt/tests/test_doctests.py
===================================================================
--- z3c.pt/trunk/src/z3c/pt/tests/test_doctests.py	2008-10-02 19:44:09 UTC (rev 91671)
+++ z3c.pt/trunk/src/z3c/pt/tests/test_doctests.py	2008-10-02 19:46:03 UTC (rev 91672)
@@ -6,26 +6,20 @@
 
 import zope.component.testing
 import zope.configuration.xmlconfig
+import z3c.pt
 
-import z3c.pt.config
+from chameleon.core import config
 
 def setUp(suite):
     zope.component.testing.setUp(suite)
     zope.configuration.xmlconfig.XMLConfig('configure.zcml', z3c.pt)()
 
 def test_suite():
-    filesuites = ('zpt.txt', 'genshi.txt', 'template.txt',
-                  'i18n.txt', 'codegen.txt', 'translation.txt')
-    testsuites = ('z3c.pt.translation', 'z3c.pt.clauses', 'z3c.pt.expressions')
+    filesuites = 'README.txt',
 
-    z3c.pt.config.DISK_CACHE = False
+    config.DISK_CACHE = False
     
     return unittest.TestSuite(
-        [zope.testing.doctest.DocTestSuite(
-        doctest, optionflags=OPTIONFLAGS,
-        setUp=setUp, tearDown=zope.component.testing.tearDown) \
-         for doctest in testsuites] + 
-        
         [zope.testing.doctest.DocFileSuite(
         doctest, optionflags=OPTIONFLAGS,
         setUp=setUp, tearDown=zope.component.testing.tearDown,

Deleted: z3c.pt/trunk/src/z3c/pt/tests/test_edgecases.py
===================================================================
--- z3c.pt/trunk/src/z3c/pt/tests/test_edgecases.py	2008-10-02 19:44:09 UTC (rev 91671)
+++ z3c.pt/trunk/src/z3c/pt/tests/test_edgecases.py	2008-10-02 19:46:03 UTC (rev 91672)
@@ -1,204 +0,0 @@
-import unittest
-
-from zope.component.testing import PlacelessSetup
-
-class TestNumericEntityPlusUnicodeParameterInsertedLiterally(unittest.TestCase,
-                                                             PlacelessSetup):
-    # See also
-    # http://groups.google.com/group/z3c_pt/browse_thread/thread/aea963d25a1778d0?hl=en
-    def setUp(self):
-        PlacelessSetup.setUp(self)
-
-    def tearDown(self):
-        PlacelessSetup.tearDown(self)
-            
-    def test_it(self):
-        import z3c.pt
-        from zope.configuration import xmlconfig
-        xmlconfig.file('configure.zcml', z3c.pt)
-        from z3c.pt.pagetemplate import PageTemplate
-        body = u"""\
-        <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
-        "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
-        <html xmlns="http://www.w3.org/1999/xhtml">
-        ${foo} &#169;
-        </html>
-        """
-        expected = u"""\
-        <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
-        "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
-        <html xmlns="http://www.w3.org/1999/xhtml">
-        foo \xa9
-        </html>"""
-        t = PageTemplate(body)
-        self.assertEqual(norm(t.render(foo=u'foo')), norm(expected))
-
-class TestUnicodeAttributeLiteral(unittest.TestCase, PlacelessSetup):
-    def setUp(self):
-        PlacelessSetup.setUp(self)
-
-    def tearDown(self):
-        PlacelessSetup.tearDown(self)
-    
-    def test_it(self):
-        import z3c.pt
-        from zope.configuration import xmlconfig
-        xmlconfig.file('configure.zcml', z3c.pt)
-        from z3c.pt.pagetemplate import PageTemplate
-        body = u"""\
-        <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
-        "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
-        <html xmlns="http://www.w3.org/1999/xhtml">
-        <div id="${foo}"/>
-        </html>
-        """
-        expected = u"""\
-        <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
-        "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
-        <html xmlns="http://www.w3.org/1999/xhtml">
-        <div id="\xa9"/>
-        </html>"""
-        t = PageTemplate(body)
-        c = unicode('\xc2\xa9', 'utf-8')
-        self.assertEqual(norm(t.render(foo=c)), norm(expected))
-
-    def test_torture(self):
-        import z3c.pt
-        from z3c.pt.genshi import GenshiParser
-        from zope.configuration import xmlconfig
-        xmlconfig.file('configure.zcml', z3c.pt)
-        from z3c.pt.pagetemplate import PageTemplate
-        body = u"""\
-        <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
-        "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
-        <html xmlns="http://www.w3.org/1999/xhtml"
-        xmlns:py="http://genshi.edgewall.org/">
-        <title>\xa9</title>
-        <div id="${foo}" py:attrs="dict(label=foo)"/>
-        </html>
-        """
-        expected = u"""\
-        <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
-        "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
-        <html xmlns="http://www.w3.org/1999/xhtml">
-        <title>\xa9</title>
-        <div label="\xa9" id="\xa9"/>
-        </html>"""
-        t = PageTemplate(body, parser=GenshiParser())
-        c = unicode('\xc2\xa9', 'utf-8')
-        self.assertEqual(norm(t.render(foo=c)), norm(expected))
-
-class TestZCMLActionsPickleable(unittest.TestCase, PlacelessSetup):
-    # see also
-    # http://groups.google.com/group/z3c_pt/browse_thread/thread/bd0cc94b5fd40ae0?hl=en
-    def setUp(self):
-        PlacelessSetup.setUp(self)
-
-    def tearDown(self):
-        PlacelessSetup.tearDown(self)
-            
-    def test_registry_actions_can_be_pickled_and_unpickled(self):
-        from z3c import pt as package
-        from zope.configuration import config
-        from zope.configuration import xmlconfig
-        context = config.ConfigurationMachine()
-        xmlconfig.registerCommonDirectives(context)
-        context.package = package
-        xmlconfig.include(context, 'configure.zcml', package)
-        context.execute_actions(clear=False)
-        actions = context.actions
-        import pickle
-        dumped = pickle.dumps(actions, -1)
-        new = pickle.loads(dumped)
-        self.assertEqual(len(actions), len(new))
-
-class TestExplicitDoctypes(unittest.TestCase, PlacelessSetup):
-    def setUp(self):
-        PlacelessSetup.setUp(self)
-
-    def tearDown(self):
-        PlacelessSetup.tearDown(self)
-
-    def test_doctype_declared_in_constructor_adds_doctype(self):
-        import z3c.pt
-        from zope.configuration import xmlconfig
-        xmlconfig.file('configure.zcml', z3c.pt)
-        from z3c.pt.pagetemplate import PageTemplate
-        from z3c.pt import doctypes
-        body = u"""\
-        <html xmlns="http://www.w3.org/1999/xhtml">
-        </html>
-        """
-        expected = u"""\
-        <!DOCTYPE html PUBLIC"-//W3C//DTD XHTML 1.0 Strict//EN"
-        "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
-        <html xmlns="http://www.w3.org/1999/xhtml">
-        </html>"""
-        t = PageTemplate(body, doctype=doctypes.xhtml_strict)
-        self.assertEqual(norm(t.render()), norm(expected))
-
-    def test_doctype_declared_in_constructor_overrides_template_doctype(self):
-        import z3c.pt
-        from zope.configuration import xmlconfig
-        xmlconfig.file('configure.zcml', z3c.pt)
-        from z3c.pt.pagetemplate import PageTemplate
-        from z3c.pt import doctypes
-        body = u"""\
-        <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
-        "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
-        <html xmlns="http://www.w3.org/1999/xhtml">
-        </html>
-        """
-        expected = u"""\
-        <!DOCTYPE html PUBLIC"-//W3C//DTD XHTML 1.0 Strict//EN"
-        "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
-        <html xmlns="http://www.w3.org/1999/xhtml">
-        </html>"""
-        t = PageTemplate(body, doctype=doctypes.xhtml_strict)
-        self.assertEqual(norm(t.render()), norm(expected))
-
-    def test_doctype_assigned_to_instance_overrides_constructor_doctype(self):
-        import z3c.pt
-        from zope.configuration import xmlconfig
-        xmlconfig.file('configure.zcml', z3c.pt)
-        from z3c.pt.pagetemplate import PageTemplate
-        from z3c.pt import doctypes
-        body = u"""\
-        <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
-        "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
-        <html xmlns="http://www.w3.org/1999/xhtml">
-        </html>
-        """
-        expected = u"""\
-        <!DOCTYPE HTML PUBLIC"-//W3C//DTD HTML4.01 Transitional//EN"
-        "http://www.w3.org/TR/html4/loose.dtd">
-        <html xmlns="http://www.w3.org/1999/xhtml">
-        </html>"""
-        t = PageTemplate(body, doctype=doctypes.html)
-        t.doctype = doctypes.html
-        self.assertEqual(norm(t.render()), norm(expected))
-
-    def test_no_doctype_overrides_parsed_doctype(self):
-        import z3c.pt
-        from zope.configuration import xmlconfig
-        xmlconfig.file('configure.zcml', z3c.pt)
-        from z3c.pt.pagetemplate import PageTemplate
-        from z3c.pt import doctypes
-        body = u"""\
-        <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
-        "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
-        <html xmlns="http://www.w3.org/1999/xhtml">
-        </html>
-        """
-        expected = u"""\
-        <html xmlns="http://www.w3.org/1999/xhtml">
-        </html>"""
-        t = PageTemplate(body, doctype=doctypes.no_doctype)
-        self.assertEqual(norm(t.render()), norm(expected))
-
-def norm(s):
-    return s.replace(' ', '').replace('\n', '')
-
-def test_suite():
-    import sys
-    return unittest.findTestCases(sys.modules[__name__])

Modified: z3c.pt/trunk/src/z3c/pt/tests/view.pt
===================================================================
--- z3c.pt/trunk/src/z3c/pt/tests/view.pt	2008-10-02 19:44:09 UTC (rev 91671)
+++ z3c.pt/trunk/src/z3c/pt/tests/view.pt	2008-10-02 19:46:03 UTC (rev 91672)
@@ -1,6 +1,6 @@
 <div xmlns="http://www.w3.org/1999/xhtml"
      xmlns:tal="http://xml.zope.org/namespaces/tal">
-  <span tal:content="nocall: view" />
+  <span tal:content="view" />
   <span tal:content="context" />
   <span tal:content="request" />
   <span tal:content="options/test" />

Deleted: z3c.pt/trunk/src/z3c/pt/tests/xinclude1.pt
===================================================================
--- z3c.pt/trunk/src/z3c/pt/tests/xinclude1.pt	2008-10-02 19:44:09 UTC (rev 91671)
+++ z3c.pt/trunk/src/z3c/pt/tests/xinclude1.pt	2008-10-02 19:46:03 UTC (rev 91672)
@@ -1,4 +0,0 @@
-<div xmlns="http://www.w3.org/1999/xhtml"
-     xmlns:xi="http://www.w3.org/2001/XInclude">
-  <xi:include href="xinclude${1+1}.pt" />
-</div>

Deleted: z3c.pt/trunk/src/z3c/pt/tests/xinclude2.pt
===================================================================
--- z3c.pt/trunk/src/z3c/pt/tests/xinclude2.pt	2008-10-02 19:44:09 UTC (rev 91671)
+++ z3c.pt/trunk/src/z3c/pt/tests/xinclude2.pt	2008-10-02 19:46:03 UTC (rev 91672)
@@ -1,3 +0,0 @@
-<div xmlns="http://www.w3.org/1999/xhtml">
-  <span>Hello, world!</span>
-</div>

Deleted: z3c.pt/trunk/src/z3c/pt/tests/xinclude3.pt
===================================================================
--- z3c.pt/trunk/src/z3c/pt/tests/xinclude3.pt	2008-10-02 19:44:09 UTC (rev 91671)
+++ z3c.pt/trunk/src/z3c/pt/tests/xinclude3.pt	2008-10-02 19:46:03 UTC (rev 91672)
@@ -1,6 +0,0 @@
-<div xmlns="http://www.w3.org/1999/xhtml"
-     xmlns:py="http://genshi.edgewall.org/"
-     xmlns:xi="http://www.w3.org/2001/XInclude">
-  <xi:include href="xinclude${4}.pt" />
-  ${greeting('world')}
-</div>

Deleted: z3c.pt/trunk/src/z3c/pt/tests/xinclude4.pt
===================================================================
--- z3c.pt/trunk/src/z3c/pt/tests/xinclude4.pt	2008-10-02 19:44:09 UTC (rev 91671)
+++ z3c.pt/trunk/src/z3c/pt/tests/xinclude4.pt	2008-10-02 19:46:03 UTC (rev 91672)
@@ -1,7 +0,0 @@
-<div xmlns="http://www.w3.org/1999/xhtml"
-     xmlns:py="http://genshi.edgewall.org/"
-     py:strip="">
-  <p py:def="greeting(name)" class="greeting">
-    Hello, ${name}!
-  </p>
-</div>

Modified: z3c.pt/trunk/src/z3c/pt/texttemplate.py
===================================================================
--- z3c.pt/trunk/src/z3c/pt/texttemplate.py	2008-10-02 19:44:09 UTC (rev 91671)
+++ z3c.pt/trunk/src/z3c/pt/texttemplate.py	2008-10-02 19:46:03 UTC (rev 91672)
@@ -1,5 +1,4 @@
 import pagetemplate
-import translation
 
 class TextTemplate(pagetemplate.PageTemplate):
     __doc__ = pagetemplate.PageTemplate.__doc__ # for Sphinx autodoc
@@ -9,21 +8,10 @@
     __doc__ = pagetemplate.PageTemplateFile.__doc__ # for Sphinx autodoc
     format = 'text'
 
-class ViewTextTemplate(property):
-    def __init__(self, body):
-        self.template = TextTemplate(body)
-        property.__init__(self, self.render)
-
-    def render(self, view):
-        def template(**kwargs):
-            return self.template.render(view=view,
-                                        context=view.context,
-                                        request=view.request,
-                                        _context=view.request,
-                                        options=kwargs)
-        return template        
-    
-class ViewTextTemplateFile(ViewTextTemplate):
-    def __init__(self, filename):
-        self.template = TextTemplateFile(filename)
-        property.__init__(self, self.render)
+class ViewTextTemplate(pagetemplate.ViewPageTemplate):
+    __doc__ = pagetemplate.ViewPageTemplate.__doc__ # for Sphinx autodoc
+    template_class = TextTemplate
+        
+class ViewTextTemplateFile(pagetemplate.ViewPageTemplateFile):
+    __doc__ = pagetemplate.ViewPageTemplateFile.__doc__ # for Sphinx autodoc
+    template_class = TextTemplateFile

Deleted: z3c.pt/trunk/src/z3c/pt/transformer.py
===================================================================
--- z3c.pt/trunk/src/z3c/pt/transformer.py	2008-10-02 19:44:09 UTC (rev 91671)
+++ z3c.pt/trunk/src/z3c/pt/transformer.py	2008-10-02 19:46:03 UTC (rev 91672)
@@ -1,235 +0,0 @@
-from compiler import ast
-
-class ASTTransformer(object):
-    """General purpose base class for AST transformations.
-    
-    Every visitor method can be overridden to return an AST node that has been
-    altered or replaced in some way.
-    """
-
-    def visit(self, node):
-        if node is None:
-            return None
-        if type(node) is tuple:
-            return tuple([self.visit(n) for n in node])
-        visitor = getattr(self, 'visit%s' % node.__class__.__name__,
-                          self._visitDefault)
-        return visitor(node)
-
-    def _clone(self, node, *args):
-        lineno = getattr(node, 'lineno', None)
-        node = node.__class__(*args)
-        if lineno is not None:
-            node.lineno = lineno
-        if isinstance(node, (ast.Class, ast.Function, ast.GenExpr, ast.Lambda)):
-            node.filename = '<string>' # workaround for bug in pycodegen
-        return node
-
-    def _visitDefault(self, node):
-        return node
-
-    def visitExpression(self, node):
-        return self._clone(node, self.visit(node.node))
-
-    def visitModule(self, node):
-        return self._clone(node, node.doc, self.visit(node.node))
-
-    def visitStmt(self, node):
-        return self._clone(node, [self.visit(x) for x in node.nodes])
-
-    # Classes, Functions & Accessors
-
-    def visitCallFunc(self, node):
-        return self._clone(node, self.visit(node.node),
-            [self.visit(x) for x in node.args],
-            node.star_args and self.visit(node.star_args) or None,
-            node.dstar_args and self.visit(node.dstar_args) or None
-        )
-
-    def visitClass(self, node):
-        return self._clone(node, node.name, [self.visit(x) for x in node.bases],
-            node.doc, self.visit(node.code)
-        )
-
-    def visitFunction(self, node):
-        args = []
-        if hasattr(node, 'decorators'):
-            args.append(self.visit(node.decorators))
-        return self._clone(node, *args + [
-            node.name,
-            node.argnames,
-            [self.visit(x) for x in node.defaults],
-            node.flags,
-            node.doc,
-            self.visit(node.code)
-        ])
-
-    def visitGetattr(self, node):
-        return self._clone(node, self.visit(node.expr), node.attrname)
-
-    def visitLambda(self, node):
-        node = self._clone(node, node.argnames,
-            [self.visit(x) for x in node.defaults], node.flags,
-            self.visit(node.code)
-        )
-        return node
-
-    def visitSubscript(self, node):
-        return self._clone(node, self.visit(node.expr), node.flags,
-            [self.visit(x) for x in node.subs]
-        )
-
-    # Statements
-
-    def visitAssert(self, node):
-        return self._clone(node, self.visit(node.test), self.visit(node.fail))
-
-    def visitAssign(self, node):
-        return self._clone(node, [self.visit(x) for x in node.nodes],
-            self.visit(node.expr)
-        )
-
-    def visitAssAttr(self, node):
-        return self._clone(node, self.visit(node.expr), node.attrname,
-            node.flags
-        )
-
-    def visitAugAssign(self, node):
-        return self._clone(node, self.visit(node.node), node.op,
-            self.visit(node.expr)
-        )
-
-    def visitDecorators(self, node):
-        return self._clone(node, [self.visit(x) for x in node.nodes])
-
-    def visitExec(self, node):
-        return self._clone(node, self.visit(node.expr), self.visit(node.locals),
-            self.visit(node.globals)
-        )
-
-    def visitFor(self, node):
-        return self._clone(node, self.visit(node.assign), self.visit(node.list),
-            self.visit(node.body), self.visit(node.else_)
-        )
-
-    def visitIf(self, node):
-        return self._clone(node, [self.visit(x) for x in node.tests],
-            self.visit(node.else_)
-        )
-
-    def _visitPrint(self, node):
-        return self._clone(node, [self.visit(x) for x in node.nodes],
-            self.visit(node.dest)
-        )
-    visitPrint = visitPrintnl = _visitPrint
-
-    def visitRaise(self, node):
-        return self._clone(node, self.visit(node.expr1), self.visit(node.expr2),
-            self.visit(node.expr3)
-        )
-
-    def visitReturn(self, node):
-        return self._clone(node, self.visit(node.value))
-
-    def visitTryExcept(self, node):
-        return self._clone(node, self.visit(node.body), self.visit(node.handlers),
-            self.visit(node.else_)
-        )
-
-    def visitTryFinally(self, node):
-        return self._clone(node, self.visit(node.body), self.visit(node.final))
-
-    def visitWhile(self, node):
-        return self._clone(node, self.visit(node.test), self.visit(node.body),
-            self.visit(node.else_)
-        )
-
-    def visitWith(self, node):
-        return self._clone(node, self.visit(node.expr),
-            [self.visit(x) for x in node.vars], self.visit(node.body)
-        )
-
-    def visitYield(self, node):
-        return self._clone(node, self.visit(node.value))
-
-    # Operators
-
-    def _visitBoolOp(self, node):
-        return self._clone(node, [self.visit(x) for x in node.nodes])
-    visitAnd = visitOr = visitBitand = visitBitor = visitBitxor = _visitBoolOp
-    visitAssTuple = visitAssList = _visitBoolOp
-
-    def _visitBinOp(self, node):
-        return self._clone(node,
-            (self.visit(node.left), self.visit(node.right))
-        )
-    visitAdd = visitSub = _visitBinOp
-    visitDiv = visitFloorDiv = visitMod = visitMul = visitPower = _visitBinOp
-    visitLeftShift = visitRightShift = _visitBinOp
-
-    def visitCompare(self, node):
-        return self._clone(node, self.visit(node.expr),
-            [(op, self.visit(n)) for op, n in  node.ops]
-        )
-
-    def _visitUnaryOp(self, node):
-        return self._clone(node, self.visit(node.expr))
-    visitUnaryAdd = visitUnarySub = visitNot = visitInvert = _visitUnaryOp
-    visitBackquote = visitDiscard = _visitUnaryOp
-
-    def visitIfExp(self, node):
-        return self._clone(node, self.visit(node.test), self.visit(node.then),
-            self.visit(node.else_)
-        )
-
-    # Identifiers, Literals and Comprehensions
-
-    def visitDict(self, node):
-        return self._clone(node, 
-            [(self.visit(k), self.visit(v)) for k, v in node.items]
-        )
-
-    def visitGenExpr(self, node):
-        return self._clone(node, self.visit(node.code))
-
-    def visitGenExprFor(self, node):
-        return self._clone(node, self.visit(node.assign), self.visit(node.iter),
-            [self.visit(x) for x in node.ifs]
-        )
-
-    def visitGenExprIf(self, node):
-        return self._clone(node, self.visit(node.test))
-
-    def visitGenExprInner(self, node):
-        quals = [self.visit(x) for x in node.quals]
-        return self._clone(node, self.visit(node.expr), quals)
-
-    def visitKeyword(self, node):
-        return self._clone(node, node.name, self.visit(node.expr))
-
-    def visitList(self, node):
-        return self._clone(node, [self.visit(n) for n in node.nodes])
-
-    def visitListComp(self, node):
-        quals = [self.visit(x) for x in node.quals]
-        return self._clone(node, self.visit(node.expr), quals)
-
-    def visitListCompFor(self, node):
-        return self._clone(node, self.visit(node.assign), self.visit(node.list),
-            [self.visit(x) for x in node.ifs]
-        )
-
-    def visitListCompIf(self, node):
-        return self._clone(node, self.visit(node.test))
-
-    def visitSlice(self, node):
-        return self._clone(node, self.visit(node.expr), node.flags,
-            node.lower and self.visit(node.lower) or None,
-            node.upper and self.visit(node.upper) or None
-        )
-
-    def visitSliceobj(self, node):
-        return self._clone(node, [self.visit(x) for x in node.nodes])
-
-    def visitTuple(self, node):
-        return self._clone(node, [self.visit(n) for n in node.nodes])

Deleted: z3c.pt/trunk/src/z3c/pt/translation.py
===================================================================
--- z3c.pt/trunk/src/z3c/pt/translation.py	2008-10-02 19:44:09 UTC (rev 91671)
+++ z3c.pt/trunk/src/z3c/pt/translation.py	2008-10-02 19:46:03 UTC (rev 91672)
@@ -1,770 +0,0 @@
-from StringIO import StringIO
-
-import generation
-import expressions
-import codegen
-import clauses
-import doctypes
-import itertools
-import types
-import utils
-import config
-import etree
-import marshal
-import htmlentitydefs
-
-class Node(object):
-    """Element translation class.
-
-    This class implements the translation node for an element in the
-    template document tree.
-
-    It's used internally by the translation machinery.
-    """
-
-    symbols = config.SYMBOLS
-
-    translate = None
-    translation_name = None
-    translation_domain = None
-    translated_attributes = None
-    skip = None
-    cdata = None
-    omit = None
-    define = None
-    macro = None
-    use_macro = None
-    define_macro = None
-    fill_slot = None
-    define_slot = None
-    condition = None
-    repeat = None
-    content = None
-    include = None
-    format = None
-    dict_attributes = None
-    static_attributes = utils.emptydict()
-    dynamic_attributes = utils.emptydict()
-    
-    def __init__(self, element):
-        self.element = element
-
-    @property
-    def stream(self):
-        return self.element.stream
-    
-    def update(self):
-        self.element.update()
-    
-    def begin(self):
-        self.stream.scope.append(set())
-        self.stream.begin(self.serialize())
-        
-    def end(self):
-        self.stream.end(self.serialize())
-        self.stream.scope.pop()
-
-    def body(self):
-        if not self.skip:
-            for element in self.element:
-                element.node.update()
-
-            for element in self.element:
-                element.node.visit()
-                    
-    def visit(self):
-        assert self.stream is not None, "Must use ``start`` method."
-
-        for element in self.element:
-            if not isinstance(element, Element):
-                self.wrap_literal(element)
-
-        self.update()
-        self.begin()
-        self.body()
-        self.end()
-
-    def serialize(self):
-        """Serialize element into clause-statements."""
-
-        _ = []
-
-        # i18n domain
-        if self.translation_domain is not None:
-            _.append(clauses.Define(
-                self.symbols.domain, types.value(repr(self.translation_domain))))
-
-        # variable definitions
-        if self.define is not None:
-            for declaration, expression in self.define:
-                if declaration.global_scope:
-                    _.append(clauses.Define(
-                        declaration, expression, self.symbols.scope))
-                else:
-                    _.append(clauses.Define(declaration, expression))
-
-        # macro method
-        macro = self.macro
-        if macro is not None:
-            _.append(clauses.Method(
-                macro.name, macro.args))
-                
-        # tag tail (deferred)
-        tail = self.element.tail
-        if tail and not self.fill_slot:
-            if isinstance(tail, unicode) and self.stream.encoding:
-                tail = tail.encode(self.stream.encoding)
-            _.append(clauses.Out(tail, defer=True))
-
-        # condition
-        if self.condition is not None:
-            _.append(clauses.Condition(self.condition))
-
-        # repeat
-        if self.repeat is not None:
-            variables, expression = self.repeat
-            if len(variables) != 1:
-                raise ValueError(
-                    "Cannot unpack more than one variable in a "
-                    "repeat statement.")
-            _.append(clauses.Repeat(variables[0], expression))
-
-        content = self.content
-
-        # macro slot definition
-        if self.define_slot:
-            # check if slot has been filled
-            variable = self.symbols.slot + self.define_slot
-            if variable in itertools.chain(*self.stream.scope):
-                content = types.value(variable)
-
-        # set dynamic content flag
-        dynamic = content or self.translate is not None
-
-        # static attributes are at the bottom of the food chain
-        attributes = utils.odict()
-        attributes.update(self.static_attributes)
-
-        # dynamic attributes
-        dynamic_attrs = self.dynamic_attributes or ()
-        dynamic_attr_names = []
-        
-        for variables, expression in dynamic_attrs:
-            if len(variables) != 1:
-                raise ValueError("Tuple definitions in assignment clause "
-                                     "is not supported.")
-
-            variable = variables[0]
-            attributes[variable] = expression
-            dynamic_attr_names.append(variable)
-
-        # translated attributes
-        translated_attributes = self.translated_attributes or ()
-        for variable, msgid in translated_attributes:
-            if msgid:
-                if variable in dynamic_attr_names:
-                    raise ValueError(
-                        "Message id not allowed in conjunction with "
-                        "a dynamic attribute.")
-
-                value = types.value('"%s"' % msgid)
-
-                if variable in attributes:
-                    default = '"%s"' % attributes[variable]
-                    expression = self.translate_expression(value, default=default)
-                else:
-                    expression = self.translate_expression(value)
-            else:
-                if variable in dynamic_attr_names or variable in attributes:
-                    text = '"%s"' % attributes[variable]
-                    expression = self.translate_expression(text)
-                else:
-                    raise ValueError("Must be either static or dynamic "
-                                     "attribute when no message id "
-                                     "is supplied.")
-
-            attributes[variable] = expression
-
-        # tag
-        text = self.element.text
-        if self.omit is not True:
-            selfclosing = text is None and not dynamic and len(self.element) == 0
-            tag = clauses.Tag(
-                self.element.tag, attributes,
-                expression=self.dict_attributes, selfclosing=selfclosing,
-                cdata=self.cdata is not None)
-            if self.omit:
-                _.append(clauses.Condition(
-                    types.value("not (%s)" % self.omit), [tag], finalize=False))
-            else:
-                _.append(tag)
-
-        # tag text (if we're not replacing tag body)
-        if text and not dynamic and not self.use_macro:
-            if isinstance(text, unicode) and self.stream.encoding:
-                text = text.encode(self.stream.encoding)
-            _.append(clauses.Out(text))
-
-        # dynamic content
-        if content:
-            msgid = self.translate
-            if msgid is not None:
-                if msgid:
-                    raise ValueError(
-                        "Can't use message id with dynamic content translation.")
-
-                _.append(clauses.Assign(content, self.symbols.tmp))
-                content = self.translate_expression(
-                    types.value(self.symbols.tmp))
-                
-            _.append(clauses.Write(content))
-
-        # include
-        elif self.include:
-            # compute macro function arguments and create argument string
-            arguments = ", ".join(
-                ("%s=%s" % (arg, arg) for arg in \
-                 itertools.chain(*self.stream.scope)))
-
-            # XInclude's are similar to METAL macros, except the macro
-            # is always defined as the entire template.
-
-            # first we compute the filename expression and write it to
-            # an internal variable
-            _.append(clauses.Assign(self.include, self.symbols.include))
-
-            # call template
-            _.append(clauses.Write(
-                types.template(
-                "%%(xincludes)s.get(%%(include)s, %s).render_xinclude(%s)" % \
-                (repr(self.format), arguments))))
-            
-        # use macro
-        elif self.use_macro:
-            # for each fill-slot element, create a new output stream
-            # and save value in a temporary variable
-            kwargs = []
-            for element in self.element.xpath(
-                './/*[@metal:fill-slot] | .//metal:*[@fill-slot]',
-                namespaces={'metal': config.METAL_NS}):
-                if element.node.fill_slot is None:
-                    # XXX this should not be necessary, but the above
-                    # xpath expression finds non-"metal:fill-slot"
-                    # nodes somehow on my system; this is perhaps due
-                    # to a bug in the libxml2 version I'm using; we
-                    # work around it by just skipping the element.
-                    # (chrism)
-                    continue
-
-                variable = self.symbols.slot+element.node.fill_slot
-                kwargs.append((variable, variable))
-                
-                subclauses = []
-                subclauses.append(clauses.Define(
-                    types.declaration((self.symbols.out, self.symbols.write)),
-                    types.template('%(init)s.initialize_stream()')))
-                subclauses.append(clauses.Visit(element.node))
-                subclauses.append(clauses.Assign(
-                    types.template('%(out)s.getvalue()'), variable))
-                _.append(clauses.Group(subclauses))
-                
-            _.append(clauses.Assign(self.use_macro, self.symbols.metal))
-
-            # compute macro function arguments and create argument string
-            if 'xmlns' in self.element.attrib:
-                kwargs.append(('include_ns_attribute', repr(True)))
-                
-            arguments = ", ".join(
-                tuple("%s=%s" % (arg, arg) for arg in \
-                      itertools.chain(*self.stream.scope))+
-                tuple("%s=%s" % kwarg for kwarg in kwargs))
-
-            _.append(clauses.Write(
-                types.value("%s.render(%s)" % (self.symbols.metal, arguments))))
-
-        # translate body
-        elif self.translate is not None:
-            msgid = self.translate
-            if not msgid:
-                msgid = self.create_msgid()
-
-            # for each named block, create a new output stream
-            # and use the value in the translation mapping dict
-            elements = [e for e in self.element if e.node.translation_name]
-
-            if elements:
-                mapping = self.symbols.mapping
-                _.append(clauses.Assign(types.value('{}'), mapping))
-            else:
-                mapping = 'None'
-
-            for element in elements:
-                name = element.node.translation_name
-
-                subclauses = []
-                subclauses.append(clauses.Define(
-                    types.declaration((self.symbols.out, self.symbols.write)),
-                    types.template('%(init)s.initialize_stream()')))
-                subclauses.append(clauses.Visit(element.node))
-                subclauses.append(clauses.Assign(
-                    types.template('%(out)s.getvalue()'),
-                    "%s['%s']" % (mapping, name)))
-
-                _.append(clauses.Group(subclauses))
-
-            _.append(clauses.Assign(
-                self.translate_expression(
-                types.value(repr(msgid)), mapping=mapping,
-                default=self.symbols.marker), self.symbols.result))
-
-            # write translation to output if successful, otherwise
-            # fallback to default rendition; 
-            result = types.value(self.symbols.result)
-            result.symbol_mapping[self.symbols.marker] = generation.marker
-            condition = types.template('%(result)s is not %(marker)s')
-            _.append(clauses.Condition(condition,
-                        [clauses.UnicodeWrite(result)]))
-
-            subclauses = []
-            if self.element.text:
-                subclauses.append(clauses.Out(self.element.text.encode('utf-8')))
-            for element in self.element:
-                name = element.node.translation_name
-                if name:
-                    value = types.value("%s['%s']" % (mapping, name))
-                    subclauses.append(clauses.Write(value))
-                else:
-                    subclauses.append(clauses.Out(element.tostring()))
-            if subclauses:
-                _.append(clauses.Else(subclauses))
-
-        return _
-
-    def wrap_literal(self, element):
-        index = self.element.index(element)
-
-        t = self.element.makeelement(utils.meta_attr('literal'))
-        t.attrib['omit-tag'] = ''
-        t.tail = element.tail
-        t.text = unicode(element)
-        for child in element.getchildren():
-            t.append(child)
-        self.element.remove(element)
-        self.element.insert(index, t)
-        t.update()
-
-    def create_msgid(self):
-        """Create an i18n msgid from the tag contents."""
-
-        out = StringIO(self.element.text)
-        for element in self.element:
-            name = element.node.translation_name
-            if name:
-                out.write("${%s}" % name)
-                out.write(element.tail)
-            else:
-                out.write(element.tostring())
-
-        msgid = out.getvalue().strip()
-        msgid = msgid.replace('  ', ' ').replace('\n', '')
-        
-        return msgid
-
-    def translate_expression(self, value, mapping=None, default=None):
-        format = "%%(translate)s(%s, domain=%%(domain)s, mapping=%s, " \
-                 "target_language=%%(language)s, default=%s)"
-        template = types.template(
-            format % (value, mapping, default))
-
-        # add translate-method to symbol mapping
-        translate = generation.fast_translate
-        template.symbol_mapping[config.SYMBOLS.translate] = translate
-
-        return template
-    
-class Element(etree.ElementBase):
-    """Template element class.
-
-    To start translation at this element, use the ``start`` method,
-    providing a code stream object.
-    """
-
-    translator = expressions.python_translation
-    
-    class node(Node):
-        @property
-        def omit(self):
-            if self.element.meta_omit is not None:
-                return self.element.meta_omit or True
-            if self.element.meta_replace:
-                return True
-
-        @property
-        def content(self):
-            return self.element.meta_replace
-
-    node = property(node)
-    
-    def start(self, stream):
-        self._stream = stream
-        self.node.visit()
-
-    def update(self):
-        pass
-    
-    @property
-    def stream(self):
-        while self is not None:
-            try:
-                return self._stream
-            except AttributeError:
-                self = self.getparent()
-
-        raise ValueError("Can't locate stream object.")
-
-    meta_cdata = utils.attribute(
-        utils.meta_attr('cdata'))
-    
-    meta_omit = utils.attribute(
-        utils.meta_attr('omit-tag'))
-
-    meta_attributes =  utils.attribute(
-        utils.meta_attr('attributes'), lambda p: p.definitions)
-
-    meta_replace = utils.attribute(
-        utils.meta_attr('replace'), lambda p: p.output)
-
-class MetaElement(Element):
-    meta_cdata = utils.attribute('cdata')
-    
-    meta_omit = True
-    
-    meta_attributes =  utils.attribute(
-        'attributes', lambda p: p.definitions)
-    meta_replace = utils.attribute(
-        'replace', lambda p: p.output)
-
-class NativeAttributePrefixSupport:
-    """Element mix-in which allows native attributes to appear with
-    namespace prefix.
-
-    >>> class MockElement(NativeAttributePrefixSupport):
-    ...     nsmap = {'prefix1': 'ns1'}
-    ...     prefix = 'prefix1'
-    ...     attrib = {'{ns1}attr1': '1', 'attr2': '2', '{ns2}attr3': '3'}
-
-    >>> element = MockElement()
-    >>> element.update()
-    >>> keys = utils.get_attributes_from_namespace(element, 'ns1').keys()
-    >>> tuple(sorted(keys))
-    ('attr1', 'attr2')
-    """
-    
-    def update(self):
-        namespace = self.nsmap[self.prefix]
-        for name, value in self.attrib.items():
-            if name.startswith('{%s}' % namespace):
-                del self.attrib[name]
-                name = name.split('}')[-1]
-                self.attrib[name] = value
-    
-class VariableInterpolation:
-    def update(self):
-        translator = self.translator
-        
-        if self.text is not None:
-            while self.text:
-                text = self.text
-                m = translator.interpolate(text)
-                if m is None:
-                    break
-
-                t = self.makeelement(utils.meta_attr('interpolation'))
-                expression = "structure " + \
-                             (m.group('expression') or m.group('variable'))
-                t.attrib['replace'] = expression
-                t.tail = text[m.end():]
-                self.insert(0, t)
-                t.update()
-
-                if m.start() == 0:
-                    self.text = text[2-len(m.group('prefix')):m.start()+1]
-                else:
-                    self.text = text[:m.start()+1]
-
-        if self.tail is not None:
-            while self.tail:
-                m = translator.interpolate(self.tail)
-                if m is None:
-                    break
-
-                t = self.makeelement(utils.meta_attr('interpolation'))
-                expression = "structure " + \
-                             (m.group('expression') or m.group('variable'))
-                t.attrib['replace'] = expression
-                t.tail = self.tail[m.end():]
-                parent = self.getparent()
-                parent.insert(parent.index(self)+1, t)
-                t.update()
-                                
-                self.tail = self.tail[:m.start()+len(m.group('prefix'))-1]
-
-        for name in utils.get_attributes_from_namespace(self, config.XHTML_NS):
-            value = self.attrib[name]
-
-            if translator.interpolate(value):
-                del self.attrib[name]
-
-                attributes = utils.meta_attr('attributes')
-                expr = '%s string:%s' % (name, value)
-                if attributes in self.attrib:
-                    self.attrib[attributes] += '; %s' % expr
-                else:
-                    self.attrib[attributes] = expr
-
-class Compiler(object):
-    """Template compiler. ``implicit_doctype`` will be used as the
-    document type if the template does not define one
-    itself. ``explicit_doctype`` may be used to explicitly set a
-    doctype regardless of what the template defines."""
-
-    doctype = None
-    implicit_doctype = ""
-    
-    def __init__(self, body, parser, implicit_doctype=None,
-                 explicit_doctype=None, encoding=None):
-        # documents without a document type declaration are augmented
-        # with default namespace declarations and proper XML entity
-        # definitions; this represents a 'convention' over
-        # 'configuration' approach to template documents
-        no_doctype_declaration = '<!DOCTYPE' not in body
-
-        # add default namespace declaration if no explicit document
-        # type has been set
-        if implicit_doctype and explicit_doctype is None and \
-               no_doctype_declaration:
-            body = """\
-            <meta:declare-ns
-            xmlns="%s" xmlns:tal="%s" xmlns:metal="%s" xmlns:i18n="%s"
-            xmlns:py="%s" xmlns:xinclude="%s" xmlns:meta="%s"
-            >%s</meta:declare-ns>""" % (
-                config.XHTML_NS, config.TAL_NS,
-                config.METAL_NS, config.I18N_NS,
-                config.PY_NS, config.XI_NS, config.META_NS,
-                body)
-
-        # prepend the implicit doctype to the document source and add
-        # entity definitions
-        if implicit_doctype and no_doctype_declaration:
-            entities = "".join((
-                '<!ENTITY %s "&#%s;">' % (name, text) for (name, text) in \
-                htmlentitydefs.name2codepoint.items()))
-
-            implicit_doctype = implicit_doctype[:-1] + '  [ %s ]>' % entities
-            self.implicit_doctype = implicit_doctype
-            body = implicit_doctype + "\n" + body
-
-        # parse document
-        self.root, parsed_doctype = parser.parse(body)
-
-        # explicit document type has priority
-        if explicit_doctype is not None:
-            self.doctype = explicit_doctype
-        elif parsed_doctype and not no_doctype_declaration:
-            self.doctype = parsed_doctype
-            
-        self.parser = parser
-
-        if utils.coerces_gracefully(encoding):
-            self.encoding = None
-        else:
-            self.encoding = encoding
-        
-    @classmethod
-    def from_text(cls, body, parser, **kwargs):
-        compiler = Compiler(
-            "<html xmlns='%s'></html>" % config.XHTML_NS, parser,
-            implicit_doctype=None, encoding=kwargs.get('encoding'))
-        compiler.root.text = body
-        compiler.root.attrib[utils.meta_attr('omit-tag')] = ""
-        return compiler
-
-    def __call__(self, macro=None, global_scope=True, parameters=()):
-        if not isinstance(self.root, Element):
-            raise ValueError(
-                "Must define valid namespace for tag: '%s.'" % self.root.tag)
-
-        # if macro is non-trivial, start compilation at the element
-        # where the macro is defined
-        if macro:
-            elements = self.root.xpath(
-                'descendant-or-self::*[@metal:define-macro="%s"] |'
-                'descendant-or-self::metal:*[@define-macro="%s"]' % (macro, macro),
-                namespaces={'metal': config.METAL_NS})
-
-            if not elements:
-                raise ValueError("Macro not found: %s." % macro)
-
-            self.root = element = elements[0]
-
-            # remove attribute from tag
-            if element.nsmap[element.prefix] == config.METAL_NS:
-                del element.attrib['define-macro']
-            else:
-                del element.attrib[utils.metal_attr('define-macro')]
-                
-        if macro is None or 'include_ns_attribute' in parameters:
-            # add namespace attribute to 
-            namespace = self.root.tag.split('}')[0][1:]
-            self.root.attrib['xmlns'] = namespace
-        
-        if global_scope:
-            wrapper = generation.template_wrapper
-        else:
-            wrapper = generation.macro_wrapper
-            
-        # initialize code stream object
-        stream = generation.CodeIO(
-            self.root.node.symbols, encoding=self.encoding,
-            indentation=1, indentation_string="\t")
-
-        # initialize variable scope
-        stream.scope.append(set(
-            (stream.symbols.out, stream.symbols.write, stream.symbols.scope) + \
-            tuple(parameters)))
-
-        # output doctype if any
-        if self.doctype and not macro:
-            doctype = self.doctype + '\n'
-            if self.encoding:
-                doctype = doctype.encode(self.encoding)
-            out = clauses.Out(doctype)
-            stream.scope.append(set())
-            stream.begin([out])
-            stream.end([out])
-            stream.scope.pop()
-
-        # start generation
-        self.root.start(stream)
-        body = stream.getvalue()
-
-        # remove namespace declaration
-        if 'xmlns' in self.root.attrib:
-            del self.root.attrib['xmlns']
-        
-        # prepare args
-        ignore = 'target_language',
-        args = ', '.join((param for param in parameters if param not in ignore))
-        if args:
-            args += ', '
-
-        # prepare kwargs
-        kwargs = ', '.join("%s=None" % param for param in parameters)
-        if kwargs:
-            kwargs += ', '
-
-        # prepare selectors
-        extra = ''
-        for selector in stream.selectors:
-            extra += '%s=None, ' % selector
-
-        # wrap generated Python-code in function definition
-        mapping = dict(
-            args=args, kwargs=kwargs, extra=extra, body=body)
-        mapping.update(stream.symbols.__dict__)
-        source = wrapper % mapping
-
-        # serialize document
-        xmldoc = self.implicit_doctype + "\n" + self.root.tostring()
-
-        return ByteCodeTemplate(
-            source, stream.symbol_mapping,
-            xmldoc, self.parser, self.root)
-
-class ByteCodeTemplate(object):
-    """Template compiled to byte-code."""
-
-    def __init__(self, source, symbols, xmldoc, parser, tree):
-        # compile code
-        suite = codegen.Suite(source, globals=symbols)
-        suite._globals.update(symbols)
-        
-        # execute code
-        _locals = {}
-        exec suite.code in suite._globals, _locals
-
-        # keep state
-        self.func = _locals['render']
-        self.source = source
-        self.symbols = symbols
-        self.xmldoc = xmldoc
-        self.parser = parser
-        self.tree = tree
-            
-    def __reduce__(self):
-        reconstructor, (cls, base, state), kwargs = \
-                       GhostedByteCodeTemplate(self).__reduce__()
-        return reconstructor, (ByteCodeTemplate, base, state), kwargs
-
-    def __setstate__(self, state):
-        self.__dict__.update(GhostedByteCodeTemplate.rebuild(state))
-
-    def __repr__(self):
-        return '<%s parser="%s">' % \
-               (type(self).__name__, str(type(self.parser)).split("'")[1])
-
-    def render(self, *args, **kwargs):
-        kwargs.update(self.selectors)
-        return self.func(generation, *args, **kwargs)
-
-    @property
-    def selectors(self):
-        selectors = getattr(self, '_selectors', None)
-        if selectors is not None:
-            return selectors
-
-        self._selectors = selectors = {}
-        for element in self.tree.xpath(
-            './/*[@meta:select]', namespaces={'meta': config.META_NS}):
-            name = element.attrib[utils.meta_attr('select')]
-            selectors[name] = element.xpath
-
-        return selectors
-
-class GhostedByteCodeTemplate(object):
-    suite = codegen.Suite("def render(): pass")
-    
-    def __init__(self, template):
-        self.code = marshal.dumps(template.func.func_code)
-        self.defaults = len(template.func.func_defaults or ())
-        self.symbols = template.symbols
-        self.source = template.source
-        self.xmldoc = template.xmldoc
-        self.parser = template.parser
-        
-    @classmethod
-    def rebuild(cls, state):
-        symbols = state['symbols']
-        source = state['source']
-        xmldoc = state['xmldoc']
-        parser = state['parser']
-        tree, doctype = parser.parse(xmldoc)        
-
-        _locals = {}
-        _globals = symbols.copy()
-        _globals.update(cls.suite._globals)
-        exec cls.suite.code in _globals, _locals
-        
-        func = _locals['render']
-        func.func_defaults = ((None,)*state['defaults']) or None
-        func.func_code = marshal.loads(state['code'])
-
-        return dict(
-            func=func,
-            symbols=symbols,
-            source=source,
-            xmldoc=xmldoc,
-            parser=parser,
-            tree=tree)
-
-            

Deleted: z3c.pt/trunk/src/z3c/pt/translation.txt
===================================================================
--- z3c.pt/trunk/src/z3c/pt/translation.txt	2008-10-02 19:44:09 UTC (rev 91671)
+++ z3c.pt/trunk/src/z3c/pt/translation.txt	2008-10-02 19:46:03 UTC (rev 91672)
@@ -1,197 +0,0 @@
-Translation
-===========
-
-This document contains functional template tests.
-
-  >>> from z3c.pt.testing import render_xhtml
-
-XHTML
------
-
-:: Plain HTML document
-
-  >>> print render_xhtml("""\
-  ... <div xmlns="http://www.w3.org/1999/xhtml">
-  ...   Hello World!
-  ... </div>""")
-    <div>
-      Hello World!
-    </div>
-
-:: Setting DOCTYPE
-
-  >>> print render_xhtml("""\
-  ... <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" 
-  ...    "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
-  ... <html xmlns="http://www.w3.org/1999/xhtml">
-  ...   Hello World!
-  ... </html>""")
-    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
-    <html xmlns="http://www.w3.org/1999/xhtml">
-      Hello World!
-    </html>
-
-:: Unicode 
-
-  >>> print render_xhtml("""\
-  ... <div xmlns="http://www.w3.org/1999/xhtml">
-  ...   La Peña
-  ...   <img alt="La Peña" />
-  ... </div>""")
-    <div>
-      La Peña
-      <img alt="La Pe&ntilde;a" />
-    </div>
-
-:: CDATA blocks
-  >>> print render_xhtml("""\
-  ... <div xmlns="http://www.w3.org/1999/xhtml">
-  ...   /* <![CDATA[ */
-  ...   This is protected
-  ...   /* ]]> */
-  ...   <span>Not protected</span> <![CDATA[ This is protected ]]>
-  ... </div>""")
-    <div>
-      /* <![CDATA[ */
-      This is protected
-      /* ]]> */
-      <span>Not protected</span> <![CDATA[ This is protected ]]>
-    </div>
-
-Literals
---------
-
-:: Named entities output literally
-
-  >>> print render_xhtml("""\
-  ... <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" 
-  ...    "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
-  ... <html xmlns="http://www.w3.org/1999/xhtml">
-  ...   Hello &nbsp; World!
-  ... </html>""")
-    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
-    <html xmlns="http://www.w3.org/1999/xhtml">
-      Hello &nbsp; World!
-    </html>
-
-:: Although not XML-compliant, named entities are accepted even
-   without a document type declaration.
-    
-  >>> print render_xhtml("""\
-  ... <html xmlns="http://www.w3.org/1999/xhtml">
-  ...   Hello &nbsp; World!
-  ...   <a href="localhost" title="Singing &amp; Dancing"
-  ...   >&rarr;</a>
-  ...   <span class="&rarr;" />
-  ... </html>""")
-    <html>
-      Hello &nbsp; World!
-      <a href="localhost" title="Singing &amp; Dancing">&rarr;</a>
-      <span class="&rarr;" />
-    </html>
-
-:: Processing instructions output literally
-
-  >>> print render_xhtml("""\
-  ... <html xmlns="http://www.w3.org/1999/xhtml">
-  ...   <?xml-stylesheet href="classic.xsl" type="text/xml"?>
-  ...   Hello World!
-  ... </html>""")
-    <html>
-      <?xml-stylesheet href="classic.xsl" type="text/xml"?>
-      Hello World!
-    </html>
-
-:: Literal comments (without embedded expressions) output literally
-
-  >>> print render_xhtml("""\
-  ... <html xmlns="http://www.w3.org/1999/xhtml">
-  ...   <!-- hello world -->
-  ... </html>""")
-    <html>
-      <!-- hello world -->
-    </html>
-  
-Text templates
---------------
-
-  >>> from z3c.pt.testing import render_text
-
-An example with a CSS stylesheet document:
-  
-  >>> css = """\
-  ... #some-region {
-  ...    background: url(${'http://nohost/plone'}/logo.gif) no-repeat;
-  ... }"""
-
-  >>> print render_text(css)
-  #some-region {
-     background: url(http://nohost/plone/logo.gif) no-repeat;
-  }
-
-A javascript document that prints out HTML:
-
-  >>> js = """\
-  ... print '<div class="description">Hello ${'World!'}</div>';"""
-
-  >>> print render_text(js)
-  print '<div class="description">Hello World!</div>';
-
-Ghosted templates
------------------
-
-To facilitate disk-caching, template instances can be pickled.
-
-  >>> from z3c.pt.testing import compile_xhtml
-  >>> template = compile_xhtml("""\
-  ... <div xmlns="http://www.w3.org/1999/xhtml">
-  ...   Hello World!
-  ... </div>""")
-
-  >>> from pickle import dumps, loads
-  >>> pickle = dumps(template)
-  >>> template = loads(pickle)
-
-Check that we're getting a template object back.
-  
-  >>> template
-  <ByteCodeTemplate parser="z3c.pt.testing.MockParser">
-
-Let's try and render the template.
- 
-  >>> print template.render()
-  <div>
-    Hello World!
-  </div>
-
-  
-Error handling
---------------
-
-This section demonstrates how the package handles templates that
-contain errors.
-
-:: Malformed syntax
-
-We expect the xml-parser to raise an exception.
-  
-  >>> body = '<div xmlns="http://www.w3.org/1999/xhtml"'
-  >>> render_xhtml(body)
-  Traceback (most recent call last):
-    ...
-  XMLSyntaxError: ...
-
-:: Missing namespace definition
-
-If a document type is provided, namespaces must be declared.
-
-  >>> body = """\
-  ... <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
-  ...                       "http://www.w3.org/TR/html4/loose.dtd">
-  ... <div xmlns="http://www.w3.org/1999/xhtml" tal:content="'Hello World'" />
-  ... """
-
-  >>> print render_xhtml(body)
-  Traceback (most recent call last):
-    ...
-  XMLSyntaxError: Namespace prefix tal for content on div is not defined...

Deleted: z3c.pt/trunk/src/z3c/pt/types.py
===================================================================
--- z3c.pt/trunk/src/z3c/pt/types.py	2008-10-02 19:44:09 UTC (rev 91671)
+++ z3c.pt/trunk/src/z3c/pt/types.py	2008-10-02 19:46:03 UTC (rev 91672)
@@ -1,59 +0,0 @@
-from utils import emptydict
-
-class expression:
-    symbol_mapping = emptydict()
-
-class parts(tuple, expression):
-    def __repr__(self):
-        return 'parts'+tuple.__repr__(self)
-
-class value(unicode, expression):
-    def __init__(self, *args):
-        super(value, self).__init__(*args)
-        self.symbol_mapping = {}
-
-    def __repr__(self):
-        try:
-            r = repr(self.encode())
-        except UnicodeEncodeError:
-            r = unicode.__repr__(self)
-            
-        return "value(%s)" % r        
-
-class template(value):
-    def __repr__(self):
-        return 'template(%s)' % str.__repr__(self)
-
-class join(tuple, expression):
-    def __repr__(self):
-        return 'join'+tuple.__repr__(self)
-
-class declaration(tuple):
-    global_scope = False
-    
-    def __repr__(self):
-        items = map(repr, self)
-        if self.global_scope:
-            items.append('global_scope=%s' % repr(self.global_scope))
-        return 'declaration(%s)' % ', '.join(items)
-
-class mapping(tuple):
-    def __repr__(self):
-        return 'mapping'+tuple.__repr__(self)
-
-class definitions(tuple):
-    def __repr__(self):
-        return 'definitions'+tuple.__repr__(self)
-
-class escape(parts):
-    def __repr__(self):
-        return 'escape'+tuple.__repr__(self)
-
-class method(object):
-    def __init__(self, name, args):
-        self.name = name
-        self.args = args
-
-    def __repr__(self):
-        return "%s(%s)" % (self.name, ", ".join(arg for arg in self.args))
-        

Deleted: z3c.pt/trunk/src/z3c/pt/utils.py
===================================================================
--- z3c.pt/trunk/src/z3c/pt/utils.py	2008-10-02 19:44:09 UTC (rev 91671)
+++ z3c.pt/trunk/src/z3c/pt/utils.py	2008-10-02 19:46:03 UTC (rev 91672)
@@ -1,256 +0,0 @@
-from zope import interface
-
-import sys
-import config
-import logging
-import interfaces
-import htmlentitydefs
-import re, string
-
-from UserDict import UserDict
-
-# 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
-    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())
-
-def coerces_gracefully(encoding):
-    if encoding != sys.getdefaultencoding() and unicode_required_flag:
-        return False
-    return True
-
-s_counter = 0
-
-def handler(key=None):
-    def decorate(f):
-        def g(node):
-            if key is None:
-                return f(node, None)
-            return f(node, node.get(key))
-        g.__ns__ = key
-        return g
-    return decorate
-
-def attribute(ns, factory=None, default=None, encoding=None):
-    def get(self):
-        value = self.attrib.get(ns)
-        if value is not None:
-            if encoding or self.stream.encoding:
-                value = value.encode(encoding or self.stream.encoding)
-            if factory is None:
-                return value
-            f = factory(self.translator)
-            return f(value)
-        elif default is not None:
-            return default
-    def set(self, value):
-        self.attrib[ns] = value
-    return property(get, set)
-
-def escape(string, quote=None, encoding=None):
-    if not isinstance(string, unicode) and encoding:
-        string = string.decode(encoding)
-    else:
-        encoding = None
-
-    table = htmlentitydefs.codepoint2name
-    def get(char):
-        key = ord(char)
-        if key in table:
-            return '&%s;' % table[key]
-        return char
-    
-    string = "".join(map(get, string))
-
-    if quote is not None:
-        string = string.replace(quote, '\\'+quote)
-
-    if encoding:
-        string = string.encode(encoding)
-        
-    return string
-
-def identity(x):
-    return x
-
-class scope(list):
-    def __init__(self, *args):
-        global s_counter
-        self.hash = s_counter
-        s_counter += 1
-
-    def __hash__(self):
-        return self.hash
-
-class emptydict(dict):
-    def __setitem__(self, key, value):
-        raise TypeError("Read-only dictionary does not support assignment.")
-    
-class repeatitem(object):
-    interface.implements(interfaces.ITALESIterator)
-    
-    def __init__(self, iterator, length):
-        self.length = length
-        self.iterator = iterator
-        
-    @property
-    def index(self):
-        try:
-            length = len(self.iterator)
-        except TypeError:
-            length = self.iterator.__length_hint__()
-        except:
-            raise TypeError("Unable to determine length.")
-
-        try:
-            return self.length - length - 1
-        except TypeError:
-            return None
-            
-    @property
-    def start(self):
-        return self.index == 0
-
-    @property
-    def end(self):
-        return self.index == self.length - 1
-
-    def number(self):
-        return self.index + 1
-
-    def odd(self):
-        return bool(self.index % 2)
-
-    def even(self):
-        return not self.odd()
-
-class repeatdict(dict):
-    def insert(self, key, iterable):
-        try:
-            length = len(iterable)
-        except TypeError:
-            length = None
-            
-        try:
-            # We used to do iterable.__iter__() but, e.g. BTreeItems
-            # objects are iterable (via __getitem__) but don't possess
-            # an __iter__.  call iter(iterable) instead to determine
-            # iterability.
-            iterator = iter(iterable)
-        except TypeError:
-            raise TypeError(
-                "Can only repeat over an iterable object (%s)." % iterable)
-        
-        self[key] = (iterator, length)
-        return iterator
-        
-    def __getitem__(self, key):
-        value, length = dict.__getitem__(self, key)
-
-        if not isinstance(value, repeatitem):
-            value = repeatitem(value, length)
-            self[key] = (value, length)
-            
-        return value
-
-class odict(UserDict):
-    def __init__(self, dict = None):
-        self._keys = []
-        UserDict.__init__(self, dict)
-
-    def __delitem__(self, key):
-        UserDict.__delitem__(self, key)
-        self._keys.remove(key)
-
-    def __setitem__(self, key, item):
-        """Case insensitive set item."""
-        
-        keys = tuple(key.lower() for key in self._keys)
-        _key = key.lower()
-        if _key in keys:
-            for k in self._keys:
-                if k.lower() == _key:
-                    self._keys.remove(k)
-                    key = k
-                    break
-                
-        UserDict.__setitem__(self, key, item)
-        self._keys.append(key)
-
-    def clear(self):
-        UserDict.clear(self)
-        self._keys = []
-
-    def copy(self):
-        dict = UserDict.copy(self)
-        dict._keys = self._keys[:]
-        return dict
-
-    def items(self):
-        return zip(self._keys, self.values())
-
-    def keys(self):
-        return self._keys
-
-    def popitem(self):
-        try:
-            key = self._keys[-1]
-        except IndexError:
-            raise KeyError('dictionary is empty')
-
-        val = self[key]
-        del self[key]
-
-        return (key, val)
-
-    def setdefault(self, key, failobj = None):
-        UserDict.setdefault(self, key, failobj)
-        if key not in self._keys: self._keys.append(key)
-
-    def update(self, dict):
-        UserDict.update(self, dict)
-        for key in dict.keys():
-            if key not in self._keys: self._keys.append(key)
-
-    def values(self):
-        return map(self.get, self._keys)
-    
-def get_attributes_from_namespace(element, namespace):
-    if element.nsmap.get(element.prefix) == namespace:
-        return dict([
-            (name, value) for (name, value) in element.attrib.items() \
-            if '{' not in name])
-
-    return dict([
-        (name, value) for (name, value) in element.attrib.items() \
-        if name.startswith('{%s}' % namespace)])
-
-def get_namespace(element):
-    if '}' in element.tag:
-        return element.tag.split('}')[0][1:]
-    return element.nsmap[None]
-
-def xhtml_attr(name):
-    return "{%s}%s" % (config.XHTML_NS, name)
-
-def tal_attr(name):
-    return "{%s}%s" % (config.TAL_NS, name)
-
-def meta_attr(name):
-    return "{%s}%s" % (config.META_NS, name)
-
-def metal_attr(name):
-    return "{%s}%s" % (config.METAL_NS, name)
-
-def i18n_attr(name):
-    return "{%s}%s" % (config.I18N_NS, name)
-
-def py_attr(name):
-    return "{%s}%s" % (config.PY_NS, name)

Deleted: z3c.pt/trunk/src/z3c/pt/zpt.py
===================================================================
--- z3c.pt/trunk/src/z3c/pt/zpt.py	2008-10-02 19:44:09 UTC (rev 91671)
+++ z3c.pt/trunk/src/z3c/pt/zpt.py	2008-10-02 19:46:03 UTC (rev 91672)
@@ -1,231 +0,0 @@
-from zope import component
-
-import translation
-import interfaces
-import itertools
-import utils
-import config
-import etree
-
-class ZopePageTemplateElement(
-    translation.Element, translation.VariableInterpolation,
-    translation.NativeAttributePrefixSupport):
-    """Zope Page Template element.
-
-    Implements the ZPT subset of the attribute template language.
-    """
-
-    class node(translation.Node):
-        @property
-        def omit(self):
-            if self.element.tal_omit is not None:
-                return self.element.tal_omit or True
-            if self.element.meta_omit is not None:
-                return self.element.meta_omit or True
-            if self.element.tal_replace or self.element.meta_replace:
-                return True
-            if self.element.metal_use or self.element.metal_fillslot:
-                return True
-            
-        @property
-        def define(self):
-            return self.element.tal_define
-
-        @property
-        def condition(self):
-            return self.element.tal_condition
-
-        @property
-        def repeat(self):
-            return self.element.tal_repeat
-
-        @property
-        def content(self):
-            return self.element.tal_content or self.element.tal_replace or \
-                   self.element.meta_replace
-
-        @property
-        def skip(self):
-            if self.define_slot:
-                variable = self.symbols.slot + self.define_slot
-                if variable in itertools.chain(*self.stream.scope):
-                    return True
-
-            return self.content or \
-                   self.use_macro or self.translate is not None
-
-        @property
-        def dynamic_attributes(self):
-            return (self.element.tal_attributes or ()) + \
-                   (self.element.meta_attributes or ())
-
-        @property
-        def translated_attributes(self):
-            return self.element.i18n_attributes
-        
-        @property
-        def static_attributes(self):
-            return utils.get_attributes_from_namespace(
-                self.element, config.XHTML_NS)
-            
-        @property
-        def translate(self):
-            return self.element.i18n_translate
-
-        @property
-        def translation_name(self):
-            return self.element.i18n_name
-
-        @property
-        def translation_domain(self):
-            return self.element.i18n_domain
-
-        @property
-        def use_macro(self):
-            return self.element.metal_use
-        
-        @property
-        def define_macro(self):
-            return self.element.metal_define
-
-        @property
-        def define_slot(self):
-            return self.element.metal_defineslot
-
-        @property
-        def fill_slot(self):
-            return self.element.metal_fillslot        
-
-        @property
-        def cdata(self):
-            return self.element.meta_cdata
-
-        @property
-        def default_expression(self):
-            return self.element.tal_default_expression
-
-    node = property(node)
-
-    @property
-    def translator(self):
-        while self.node.default_expression is None:
-            self = self.getparent()
-            if self is None:
-                raise ValueError("Default expression not set.")
-            
-        return component.getUtility(
-            interfaces.IExpressionTranslation, name=self.node.default_expression)
-
-    def update(self):
-        translation.NativeAttributePrefixSupport.update(self)    
-        translation.VariableInterpolation.update(self)        
-
-class XHTMLElement(ZopePageTemplateElement):
-    """XHTML namespace element."""
-
-    tal_define = utils.attribute(
-        utils.tal_attr('define'), lambda p: p.definitions)
-    tal_condition = utils.attribute(
-        utils.tal_attr('condition'), lambda p: p.expression)
-    tal_repeat = utils.attribute(
-        utils.tal_attr('repeat'), lambda p: p.definition)
-    tal_attributes = utils.attribute(
-        utils.tal_attr('attributes'), lambda p: p.definitions)
-    tal_content = utils.attribute(
-        utils.tal_attr('content'), lambda p: p.output)
-    tal_replace = utils.attribute(
-        utils.tal_attr('replace'), lambda p: p.output)
-    tal_omit = utils.attribute(
-        utils.tal_attr('omit-tag'), lambda p: p.expression)
-    tal_default_expression = utils.attribute(
-        utils.tal_attr('default-expression'), encoding='ascii')
-    metal_define = utils.attribute(
-        utils.metal_attr('define-macro'), lambda p: p.method)
-    metal_use = utils.attribute(
-        utils.metal_attr('use-macro'), lambda p: p.expression)
-    metal_fillslot = utils.attribute(
-        utils.metal_attr('fill-slot'))
-    metal_defineslot = utils.attribute(
-        utils.metal_attr('define-slot'))
-    i18n_translate = utils.attribute(
-        utils.i18n_attr('translate'))
-    i18n_attributes = utils.attribute(
-        utils.i18n_attr('attributes'), lambda p: p.mapping)
-    i18n_domain = utils.attribute(
-        utils.i18n_attr('domain'))
-    i18n_name = utils.attribute(
-        utils.i18n_attr('name'))
-
-class MetaElement(XHTMLElement, translation.MetaElement):
-    pass
-
-class TALElement(ZopePageTemplateElement):
-    """TAL namespace element."""
-    
-    tal_define = utils.attribute("define", lambda p: p.definitions)
-    tal_condition = utils.attribute("condition", lambda p: p.expression)
-    tal_replace = utils.attribute("replace", lambda p: p.output)
-    tal_repeat = utils.attribute("repeat", lambda p: p.definition)
-    tal_attributes = utils.attribute("attributes", lambda p: p.expression)
-    tal_content = utils.attribute("content", lambda p: p.output)
-    tal_omit = utils.attribute("omit-tag", lambda p: p.expression, u"")
-    tal_default_expression = utils.attribute(
-        'default-expression')
-    tal_cdata = utils.attribute("cdata")
-
-    metal_define = None
-    metal_use = None
-    metal_fillslot = None
-    metal_defineslot = None
-    i18n_domain = None
-    i18n_translate = None
-    i18n_attributes = None
-    
-class METALElement(ZopePageTemplateElement):
-    """METAL namespace element."""
-
-    tal_define = None
-    tal_condition = None
-    tal_replace = None
-    tal_content = None
-    tal_repeat = None
-    tal_attributes = None
-    tal_omit = True
-    tal_default_expression = None
-    tal_cdata = None
-    metal_define = utils.attribute('define-macro', lambda p: p.method)
-    metal_use = utils.attribute('use-macro', lambda p: p.expression)
-    metal_fillslot = utils.attribute('fill-slot')
-    metal_defineslot = utils.attribute('define-slot')
-    i18n_domain = None
-    i18n_translate = None
-    i18n_attributes = None
-
-class ZopePageTemplateParser(etree.Parser):
-    """ The parser implementation for ZPT """
-    element_mapping = {
-        config.XHTML_NS: {None: XHTMLElement},
-        config.META_NS: {None: MetaElement},
-        config.TAL_NS: {None: TALElement},
-        config.METAL_NS: {None: METALElement}}
-
-    default_expression = 'python'
-
-    def __init__(self, default_expression=None):
-        if default_expression is not None:
-            self.default_expression = default_expression
-
-    def parse(self, body):
-        root, doctype = super(ZopePageTemplateParser, self).parse(body)
-        # if a default expression is not set explicitly in the
-        # template, use the TAL-attribute ``default-expression``
-        # to set it
-        if utils.get_namespace(root) == config.TAL_NS:
-            tag = 'default-expression'
-        else:
-            tag = utils.tal_attr('default-expression')
-
-        if not root.attrib.get(tag):
-            root.attrib[tag] = self.default_expression
-
-        return root, doctype

Deleted: z3c.pt/trunk/src/z3c/pt/zpt.txt
===================================================================
--- z3c.pt/trunk/src/z3c/pt/zpt.txt	2008-10-02 19:44:09 UTC (rev 91671)
+++ z3c.pt/trunk/src/z3c/pt/zpt.txt	2008-10-02 19:46:03 UTC (rev 91672)
@@ -1,409 +0,0 @@
-Zope Page Templates (ZPT)
-=========================
-
-  >>> from z3c.pt.testing import render_zpt
-
-TAL
----
-  
-:: Namespace elements
-
-  >>> print render_zpt("""\
-  ... <tal:block xmlns:tal="http://xml.zope.org/namespaces/tal">
-  ...   Hello, world!
-  ... </tal:block>""")
-  <BLANKLINE>
-    Hello, world!
-  <BLANKLINE>
-
-tal:define, tal:attributes, tal:contents    
-  
-  >>> print render_zpt("""\
-  ... <div xmlns="http://www.w3.org/1999/xhtml"
-  ...      xmlns:tal="http://xml.zope.org/namespaces/tal">
-  ...   <span id="test"
-  ...         class="dummy"
-  ...         onclick=""
-  ...         tal:define="a 'abc'"
-  ...         tal:attributes="class 'def' + a; style 'hij'; onClick 'alert();'"
-  ...         tal:content="a + 'ghi'" />
-  ...   <span tal:replace="'Hello World!'">Hello <b>Universe</b>!</span>
-  ...   <span tal:replace="'Hello World!'"><b>Hello Universe!</b></span>
-  ...   <span tal:content="None" />
-  ... </div>""")
-    <div>
-      <span class="defabc" style="hij" onclick="alert();" id="test">abcghi</span>
-      Hello World!
-      Hello World!
-      <span></span>
-    </div>
-
-tal:attributes 'checked' and 'selected' toggles
-
-  >>> print render_zpt("""\
-  ... <div xmlns="http://www.w3.org/1999/xhtml"
-  ...      xmlns:tal="http://xml.zope.org/namespaces/tal">
-  ...   <option tal:attributes="selected True"/>
-  ...   <option tal:attributes="selected None"/>
-  ...   <input tal:attributes="checked True"/>
-  ...   <input tal:attributes="checked False"/>
-  ... </div>""")
-    <div>
-       <option selected="True" />
-       <option />
-       <input checked="True" />
-       <input />
-    </div>
-
-tal:repeat
-    
-  >>> print render_zpt("""\
-  ... <div xmlns="http://www.w3.org/1999/xhtml"
-  ...      xmlns:tal="http://xml.zope.org/namespaces/tal">
-  ...   <ul>
-  ...     <li tal:repeat="i range(5)"><span tal:replace="'Item ' + str(i) + ')'" /></li>
-  ...   </ul>
-  ... </div>""")
-    <div>
-      <ul>
-        <li>Item 0)</li>
-        <li>Item 1)</li>
-        <li>Item 2)</li>
-        <li>Item 3)</li>
-        <li>Item 4)</li>
-      </ul>
-    </div>
-
-tal:repeat (repeat-variable)
-
-  >>> print render_zpt("""\
-  ... <div xmlns="http://www.w3.org/1999/xhtml"
-  ...      xmlns:tal="http://xml.zope.org/namespaces/tal">
-  ...   <ul>
-  ...     <li tal:repeat="i range(3)"><span tal:replace="str(i) + ' ' + str(repeat['i'].even())" /></li>
-  ...   </ul>
-  ... </div>""")
-    <div>
-      <ul>
-        <li>0 True</li>
-        <li>1 False</li>
-        <li>2 True</li>
-      </ul>
-    </div>
-
-tal:condition
-
-  >>> print render_zpt("""\
-  ... <div xmlns="http://www.w3.org/1999/xhtml"
-  ...      xmlns:tal="http://xml.zope.org/namespaces/tal">
-  ...   <div tal:condition="True">
-  ...     Show me!
-  ...   </div>
-  ...   <div tal:condition="False">
-  ...     Do not show me!
-  ...   </div>
-  ... </div>""")
-    <div>
-      <div>
-        Show me!
-      </div>
-    </div>
-
-:: HTML comments
-
-  >>> print render_zpt("""\
-  ... <div xmlns="http://www.w3.org/1999/xhtml"
-  ...      xmlns:tal="http://xml.zope.org/namespaces/tal">
-  ...   <!-- a comment -->
-  ...   <!-- a multi-
-  ...        line comment -->
-  ...   <!-- a comment with an ${'expression'} -->
-  ... </div>""")
-    <div>
-      <!-- a comment -->
-      <!-- a multi-
-           line comment -->
-      <!-- a comment with an expression -->
-    </div>
-
-:: TAL elements with namespace prefix
-
-  >>> print render_zpt("""\
-  ... <div xmlns="http://www.w3.org/1999/xhtml"
-  ...      xmlns:tal="http://xml.zope.org/namespaces/tal">
-  ...   <tal:example replace="'Hello World!'" />
-  ...   <tal:example tal:replace="'Hello World!'" />
-  ...   <tal:div content="'Hello World!'" />
-  ...   <tal:multiple repeat="i range(3)" replace="i" />
-  ...   <tal:div condition="True">True</tal:div>
-  ... </div>""")
-    <div>
-      Hello World!
-      Hello World!
-      Hello World!
-      0
-      1
-      2
-      True
-    </div>
-
-tal:omit-tag
-
-  >>> print render_zpt("""\
-  ... <div xmlns="http://www.w3.org/1999/xhtml"
-  ...      xmlns:tal="http://xml.zope.org/namespaces/tal">
-  ...   <p tal:omit-tag="">No paragraph here.</p>
-  ...   <p tal:omit-tag="True">No paragraph here either.</p>
-  ...   <p tal:omit-tag="False">A paragraph here.</p>
-  ... </div>""")
-    <div>
-      No paragraph here.
-      No paragraph here either.
-      <p>A paragraph here.</p>
-    </div>
-
-:: Unicode with dynamic attributes and content
-    
-  >>> print render_zpt("""\
-  ... <div xmlns="http://www.w3.org/1999/xhtml"
-  ...      xmlns:tal="http://xml.zope.org/namespaces/tal">
-  ...   <img tal:attributes="title '%sHello%s' % (chr(60), chr(62))" />
-  ...   <span tal:replace="structure '%sbr /%s' % (chr(60), chr(62))" />
-  ...   <span tal:replace="'%sbr /%s' % (chr(60), chr(62))" />
-  ...   <span tal:content="unicode('La Pe\xc3\xb1a', 'utf-8')" />
-  ... </div>""")
-    <div>
-      <img title="&lt;Hello&gt;" />
-      <br />
-      &lt;br /&gt;
-      <span>La Peña</span>
-    </div>
-
-:: Using the "path:" expression
-
-  >>> class Test(object):
-  ...     greeting = u'Hello'
-  
-  >>> print render_zpt("""\
-  ... <div xmlns="http://www.w3.org/1999/xhtml"
-  ...      xmlns:tal="http://xml.zope.org/namespaces/tal">
-  ...   <span tal:replace="path: test1/greeting" />
-  ...   <span tal:replace="path: test2/greeting" />
-  ... </div>""", request=object(),
-  ... test1={'greeting': u'Hello'}, test2=Test())
-  <div>
-    Hello
-    Hello
-  </div>
-
-:: Using the "string:" expression
-
-  >>> print render_zpt("""\
-  ... <div xmlns="http://www.w3.org/1999/xhtml"
-  ...      xmlns:tal="http://xml.zope.org/namespaces/tal">
-  ...   <span tal:replace="string:${greeting}, world!" />
-  ...   <img tal:attributes="alt string:Leonardo da Vinci;; Musee du Louvre, 1503;
-  ...                        title string:Mona Lisa" />
-  ... </div>""", request=object(), greeting=u'Hello')
-  <div>
-    Hello, world!
-    <img alt="Leonardo da Vinci; Musee du Louvre, 1503" title="Mona Lisa" />
-  </div>
-
-:: Using the "provider:" expression
-
-  >>> class Context(object): pass
-  >>> class Request(object): pass
-  >>> class View(object): pass
-
-This directive renders a content provider; let's define and register a
-content provider which allows us to verify the functionality of the
-expression.
-  
-  >>> from zope.contentprovider.interfaces import IContentProvider
-  >>> from zope import component
-  >>> from zope import interface
-    
-  >>> class DummyContentProvider(object):
-  ...     component.adapts(Context, Request, View)
-  ...     interface.implements(IContentProvider)
-  ...
-  ...     def __init__(self, context, request, view):
-  ...         self.context = context
-  ...         self.request = request
-  ...         self.view = view
-  ...
-  ...     def update(self):
-  ...         self.updated = True
-  ...
-  ...     def render(self):
-  ...         return type(self.context), type(self.request), \
-  ...                type(self.view), self.updated
-
-  >>> component.provideAdapter(
-  ...     DummyContentProvider, name="test")
-  
-  >>> print render_zpt("""\
-  ... <div xmlns="http://www.w3.org/1999/xhtml"
-  ...      xmlns:tal="http://xml.zope.org/namespaces/tal">
-  ...   <span tal:replace="structure provider:test" />
-  ... </div>""", context=Context(), request=Request(), view=View())
-  <div>
-    (<class 'Context'>, <class 'Request'>, <class 'View'>, True)
-  </div>
-
-:: Setting the default expression
-
-  >>> print render_zpt("""\
-  ... <div xmlns="http://www.w3.org/1999/xhtml"
-  ...      xmlns:tal="http://xml.zope.org/namespaces/tal">
-  ...   <div tal:default-expression="path">
-  ...     <span tal:replace="test/greeting" />
-  ...   </div>
-  ... </div>""", request=object(), test={'greeting': u'Hello'})
-  <div>
-    <div>
-      Hello
-    </div>
-  </div>
-
-:: Using different expressions with try-except operator (|)
-  
-  >>> print render_zpt("""\
-  ... <div xmlns="http://www.w3.org/1999/xhtml"
-  ...      xmlns:tal="http://xml.zope.org/namespaces/tal">
-  ...   <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" />
-  ...          <span tal:replace="python: 5+5" />
-  ...       </div>
-  ...       <span tal:replace="path: mydict/a" />
-  ...       <span tal:replace="python: 1+1" />
-  ...       <span tal:replace="path: mydict/b|True" />
-  ...       <span tal:replace="int('a')|path: mydict/a" />
-  ...   </tal:path-expression-testing>
-  ... </div>""")
-  <div>
-  <BLANKLINE>
-        <div>
-           1
-           1
-           2
-           10
-        </div>
-        1
-        2
-        True
-        1
-  <BLANKLINE>
-  </div>
-
-:: Using TAL pragmas "nocall" and "structure"
-
-  >>> print render_zpt("""\
-  ... <div xmlns="http://www.w3.org/1999/xhtml"
-  ...      xmlns:tal="http://xml.zope.org/namespaces/tal">
-  ...   <span tal:default-expression="path"
-  ...         tal:replace="structure nocall: dir" />
-  ...   <span tal:replace="structure dir" />
-  ... </div>""", request=object())
-    <div>
-      <built-in function dir>
-      <built-in function dir>
-    </div>
-
-METAL
------
-
-metal:define-macro, metal:use-macro
-
-  >>> body = """\
-  ... <div xmlns="http://www.w3.org/1999/xhtml"
-  ...      xmlns:tal="http://xml.zope.org/namespaces/tal"
-  ...      xmlns:metal="http://xml.zope.org/namespaces/metal">
-  ...   <div class="greeting" metal:define-macro="greeting">
-  ...     Hello, ${name|string:earth}!
-  ...   </div>
-  ...   <div tal:define="name 'world'">
-  ...     <div metal:use-macro="template.macros['greeting']" />
-  ...   </div>  
-  ... </div>"""
-
-  >>> from z3c.pt.testing import MockTemplate
-  >>> from z3c.pt.zpt import ZopePageTemplateParser
-
-  >>> template = MockTemplate(body, ZopePageTemplateParser())
-  >>> print render_zpt(body, template=template)
-  <div>
-    <div class="greeting">
-      Hello, earth!
-    </div>
-    <div>
-      <div class="greeting">
-      Hello, world!
-    </div>
-  <BLANKLINE>
-    </div>  
-  </div>
-
-metal:define-slot, metal:fill-slot
-
-  >>> body = """\
-  ... <div xmlns="http://www.w3.org/1999/xhtml"
-  ...      xmlns:tal="http://xml.zope.org/namespaces/tal"
-  ...      xmlns:metal="http://xml.zope.org/namespaces/metal">
-  ...   <div metal:define-macro="greeting">
-  ...     Hey, <span class="name" metal:define-slot="name">
-  ...     a <em>stranger!</em></span>
-  ...   </div>
-  ...   <div metal:use-macro="template.macros['greeting']">
-  ...     This will be omitted
-  ...     <span metal:fill-slot="name">earth!</span>
-  ...   </div>
-  ...   <div metal:use-macro="template.macros['greeting']">
-  ...     <div>
-  ...       <metal:earth fill-slot="name">earth!</metal:earth>
-  ...     </div>
-  ...   </div>
-  ...   <div metal:use-macro="template.macros['greeting']">
-  ...     <!-- display fallback greeting -->
-  ...   </div>
-  ...   <div metal:use-macro="template.macros['greeting']">
-  ...     <span metal:fill-slot="dummy">dummy!</span>
-  ...   </div>
-  ... </div>"""
-
-  >>> from z3c.pt.testing import MockTemplate
-  
-  >>> template = MockTemplate(body, ZopePageTemplateParser())
-  >>> print render_zpt(body, template=template)
-  <div>
-    <div>
-      Hey, <span class="name">
-      a <em>stranger!</em></span>
-    </div>
-    <div>
-      Hey, <span class="name">earth!</span>
-    </div>
-  <BLANKLINE>
-    <div>
-      Hey, <span class="name">earth!</span>
-    </div>
-  <BLANKLINE>
-    <div>
-      Hey, <span class="name">
-      a <em>stranger!</em></span>
-    </div>
-  <BLANKLINE>
-    <div>
-      Hey, <span class="name">
-      a <em>stranger!</em></span>
-    </div>
-  <BLANKLINE>
-  </div>
-
-



More information about the Checkins mailing list