[Checkins] SVN: z3c.pt/tags/0.2/ Tagging release.
Malthe Borch
mborch at gmail.com
Wed Dec 5 11:25:24 EST 2007
Log message for revision 82142:
Tagging release.
Changed:
A z3c.pt/tags/0.2/
D z3c.pt/tags/0.2/README.txt
A z3c.pt/tags/0.2/README.txt
D z3c.pt/tags/0.2/setup.py
A z3c.pt/tags/0.2/setup.py
D z3c.pt/tags/0.2/z3c/pt/BENCHMARKS.txt
A z3c.pt/tags/0.2/z3c/pt/BENCHMARKS.txt
D z3c.pt/tags/0.2/z3c/pt/README.txt
A z3c.pt/tags/0.2/z3c/pt/README.txt
D z3c.pt/tags/0.2/z3c/pt/VERSION.txt
A z3c.pt/tags/0.2/z3c/pt/VERSION.txt
A z3c.pt/tags/0.2/z3c/pt/codegen.py
A z3c.pt/tags/0.2/z3c/pt/codegen.txt
D z3c.pt/tags/0.2/z3c/pt/io.py
A z3c.pt/tags/0.2/z3c/pt/io.py
D z3c.pt/tags/0.2/z3c/pt/pagetemplate.py
A z3c.pt/tags/0.2/z3c/pt/pagetemplate.py
D z3c.pt/tags/0.2/z3c/pt/tal.py
A z3c.pt/tags/0.2/z3c/pt/tal.py
D z3c.pt/tags/0.2/z3c/pt/tal.txt
A z3c.pt/tags/0.2/z3c/pt/tal.txt
D z3c.pt/tags/0.2/z3c/pt/tests/test_doctests.py
A z3c.pt/tags/0.2/z3c/pt/tests/test_doctests.py
A z3c.pt/tags/0.2/z3c/pt/transformer.py
D z3c.pt/tags/0.2/z3c/pt/translate.txt
A z3c.pt/tags/0.2/z3c/pt/translation.py
A z3c.pt/tags/0.2/z3c/pt/translation.txt
-=-
Copied: z3c.pt/tags/0.2 (from rev 82100, z3c.pt/trunk)
Deleted: z3c.pt/tags/0.2/README.txt
===================================================================
--- z3c.pt/trunk/README.txt 2007-12-03 15:44:56 UTC (rev 82100)
+++ z3c.pt/tags/0.2/README.txt 2007-12-05 16:25:23 UTC (rev 82142)
@@ -1,13 +0,0 @@
-Overview
---------
-
-The z3c.pt package provides an alternative implementation of the TAL
-template language.
-
-In a nutshell:
-
- - Templates are JIT-compiled
- - Only python-expressions are supported
- - Depends only on lxml
-
-The METAL macro language is not supported; i18n is on the to-do.
Copied: z3c.pt/tags/0.2/README.txt (from rev 82141, z3c.pt/trunk/README.txt)
===================================================================
--- z3c.pt/tags/0.2/README.txt (rev 0)
+++ z3c.pt/tags/0.2/README.txt 2007-12-05 16:25:23 UTC (rev 82142)
@@ -0,0 +1,42 @@
+Overview
+--------
+
+The z3c.pt package provides an alternative implementation of the TAL
+template language.
+
+In a nutshell:
+
+ - Templates are JIT-compiled
+ - Only Python-expressions are supported
+ - Depends only on lxml
+
+The METAL macro language is not supported; i18n is on the to-do.
+
+Template and expression language
+--------------------------------
+
+The template and expression language is based loosely on the TAL 1.4
+specification*. Some notable changes:
+
+1. Only Python-expressions are allowed. Expressions can have
+ try-except fallbacks using the vertical bar syntax:
+
+ tal:content="<expression> | <first fallback> | <second fallback> | ..."
+
+2. Tuples are allowed in the tal:define statement:
+
+ tal:define="(a, b, c) [1, 2, 3]"
+
+3. Generators are allowed in tal:repeat statements. Note that the
+ repeat variable is not available in this case.
+
+ tal:repeat="i <some generator>"
+
+4. Attribute-access to dictionary entries is allowed, e.g.
+
+ dictionary.key
+
+ can be used instead of ``dictionary['key']``.
+
+*) http://wiki.zope.org/ZPT/TALSpecification14
+
Deleted: z3c.pt/tags/0.2/setup.py
===================================================================
--- z3c.pt/trunk/setup.py 2007-12-03 15:44:56 UTC (rev 82100)
+++ z3c.pt/tags/0.2/setup.py 2007-12-05 16:25:23 UTC (rev 82142)
@@ -1,32 +0,0 @@
-from setuptools import setup, find_packages
-import sys, os
-
-version = '0.1'
-
-setup(name='z3c.pt',
- version=version,
- description="An implementation of the TAL template language.",
- long_description=open("README.txt").read(),
- classifiers=[
- "Programming Language :: Python",
- "Topic :: Text Processing :: Markup :: HTML",
- "Topic :: Text Processing :: Markup :: XML",
- "Topic :: Software Development :: Libraries :: Python Modules",
- ],
- keywords='',
- author='Malthe Borch',
- author_email='mborch at gmail.com',
- url='',
- license='GPL',
- packages=find_packages(exclude=['ez_setup']),
- namespace_packages=['z3c'],
- include_package_data=True,
- zip_safe=False,
- install_requires=[
- 'setuptools',
- # -*- Extra requirements: -*-
- ],
- entry_points="""
- # -*- Entry points: -*-
- """,
- )
Copied: z3c.pt/tags/0.2/setup.py (from rev 82141, z3c.pt/trunk/setup.py)
===================================================================
--- z3c.pt/tags/0.2/setup.py (rev 0)
+++ z3c.pt/tags/0.2/setup.py 2007-12-05 16:25:23 UTC (rev 82142)
@@ -0,0 +1,33 @@
+from setuptools import setup, find_packages
+import sys, os
+
+version = '0.2'
+
+setup(name='z3c.pt',
+ version=version,
+ description="An implementation of the TAL template language.",
+ long_description=open("README.txt").read(),
+ classifiers=[
+ "Programming Language :: Python",
+ "Topic :: Text Processing :: Markup :: HTML",
+ "Topic :: Text Processing :: Markup :: XML",
+ "Topic :: Software Development :: Libraries :: Python Modules",
+ ],
+ keywords='',
+ author='Malthe Borch',
+ author_email='mborch at gmail.com',
+ url='',
+ license='GPL',
+ packages=find_packages(exclude=['ez_setup']),
+ namespace_packages=['z3c'],
+ include_package_data=True,
+ zip_safe=False,
+ install_requires=[
+ 'setuptools',
+ 'lxml',
+ # -*- Extra requirements: -*-
+ ],
+ entry_points="""
+ # -*- Entry points: -*-
+ """,
+ )
Deleted: z3c.pt/tags/0.2/z3c/pt/BENCHMARKS.txt
===================================================================
--- z3c.pt/trunk/z3c/pt/BENCHMARKS.txt 2007-12-03 15:44:56 UTC (rev 82100)
+++ z3c.pt/tags/0.2/z3c/pt/BENCHMARKS.txt 2007-12-05 16:25:23 UTC (rev 82142)
@@ -1,70 +0,0 @@
-Benchmarks
-==========
-
- zope.pagetemplate z3c.pt
-Hello World 4.482 1
-1000 x 10 table 4.540 1
-
-Source
-------
-
- >>> from z3c.pt import PageTemplate
- >>> from zope.pagetemplate.pagetemplate import PageTemplate as z3PageTemplate
-
-Hello World:
-
- >>> template = PageTemplate("""\
- ... <div xmlns="http://www.w3.org/1999/xhtml">
- ... Hello World!
- ... </div>""")
-
- >>> # for i in range(300000): a = template()
-
- >>> template = z3PageTemplate()
- >>> template.pt_edit("""\
- ... <div xmlns="http://www.w3.org/1999/xhtml">
- ... Hello World!
- ... </div>""", 'text/xhtml')
-
- >>> # for i in range(300000): a = template()
-
-1000 x 10 table:
-
- >>> table = [dict(a=1,b=2,c=3,d=4,e=5,f=6,g=7,h=8,i=9,j=10) \
- ... for x in range(1000)]
-
- >>> template = PageTemplate("""\
- ... <table xmlns="http://www.w3.org/1999/xhtml"
- ... xmlns:tal="http://xml.zope.org/namespaces/tal">
- ... <tr tal:repeat="row table">
- ... <td tal:repeat="c row.values()"
- ... tal:content="c" />
- ... </tr>
- ... </table>""")
-
- >>> # for i in range(20): a = template(table=table)
-
- >>> template = z3PageTemplate()
- >>> template.pt_edit("""\
- ... <table xmlns="http://www.w3.org/1999/xhtml"
- ... xmlns:tal="http://xml.zope.org/namespaces/tal">
- ... <tr tal:repeat="row options/table">
- ... <td tal:repeat="c python: row.values()"
- ... tal:content="c" />
- ... </tr>
- ... </table>""", 'text/xhtml')
-
- >>> # for i in range(20): a = template(table=table)
-
- >>> from StringIO import StringIO
- >>> def bigtable(table):
- ... out = StringIO()
- ... for row in table:
- ... out.write('<tr>')
- ... for c in row.values():
- ... out.write('<td>%s</td>' % c)
- ... out.write('</tr>')
- ... return out.getvalue()
-
- >>> # for i in range(20): a = bigtable(table=table)
-
Copied: z3c.pt/tags/0.2/z3c/pt/BENCHMARKS.txt (from rev 82102, z3c.pt/trunk/z3c/pt/BENCHMARKS.txt)
===================================================================
--- z3c.pt/tags/0.2/z3c/pt/BENCHMARKS.txt (rev 0)
+++ z3c.pt/tags/0.2/z3c/pt/BENCHMARKS.txt 2007-12-05 16:25:23 UTC (rev 82142)
@@ -0,0 +1,70 @@
+Benchmarks
+==========
+
+ zope.pagetemplate z3c.pt
+Hello World 4.482 1
+1000 x 10 table 4.513 1
+
+Source
+------
+
+ >>> from z3c.pt import PageTemplate
+ >>> from zope.pagetemplate.pagetemplate import PageTemplate as z3PageTemplate
+
+Hello World:
+
+ >>> template = PageTemplate("""\
+ ... <div xmlns="http://www.w3.org/1999/xhtml">
+ ... Hello World!
+ ... </div>""")
+
+ >>> # for i in range(300000): a = template()
+
+ >>> template = z3PageTemplate()
+ >>> template.pt_edit("""\
+ ... <div xmlns="http://www.w3.org/1999/xhtml">
+ ... Hello World!
+ ... </div>""", 'text/xhtml')
+
+ >>> # for i in range(300000): a = template()
+
+1000 x 10 table:
+
+ >>> table = [dict(a=1,b=2,c=3,d=4,e=5,f=6,g=7,h=8,i=9,j=10) \
+ ... for x in range(1000)]
+
+ >>> template = PageTemplate("""\
+ ... <table xmlns="http://www.w3.org/1999/xhtml"
+ ... xmlns:tal="http://xml.zope.org/namespaces/tal">
+ ... <tr tal:repeat="row table">
+ ... <td tal:repeat="c row.values()"
+ ... tal:content="c" />
+ ... </tr>
+ ... </table>""")
+
+ >>> for i in range(20): a = template(table=table)
+
+ >>> template = z3PageTemplate()
+ >>> template.pt_edit("""\
+ ... <table xmlns="http://www.w3.org/1999/xhtml"
+ ... xmlns:tal="http://xml.zope.org/namespaces/tal">
+ ... <tr tal:repeat="row options/table">
+ ... <td tal:repeat="c python: row.values()"
+ ... tal:content="c" />
+ ... </tr>
+ ... </table>""", 'text/xhtml')
+
+ >>> # for i in range(20): a = template(table=table)
+
+ >>> from StringIO import StringIO
+ >>> def bigtable(table):
+ ... out = StringIO()
+ ... for row in table:
+ ... out.write('<tr>')
+ ... for c in row.values():
+ ... out.write('<td>%s</td>' % c)
+ ... out.write('</tr>')
+ ... return out.getvalue()
+
+ >>> # for i in range(20): a = bigtable(table=table)
+
Deleted: z3c.pt/tags/0.2/z3c/pt/README.txt
===================================================================
--- z3c.pt/trunk/z3c/pt/README.txt 2007-12-03 15:44:56 UTC (rev 82100)
+++ z3c.pt/tags/0.2/z3c/pt/README.txt 2007-12-05 16:25:23 UTC (rev 82142)
@@ -1,34 +0,0 @@
-z3c.pt
-======
-
-Usage
------
-
-From a string:
-
- >>> from z3c.pt import PageTemplate
- >>> template = PageTemplate("""\
- ... <div xmlns="http://www.w3.org/1999/xhtml"
- ... xmlns:tal="http://xml.zope.org/namespaces/tal">
- ... Hello World!
- ... </div>
- ... """)
-
- >>> print template()
- <div>
- Hello World!
- </div>
-
-From a file:
-
- >>> from z3c.pt import PageTemplateFile
- >>> from z3c.pt import tests
- >>> filename = tests.__path__[0]+'/helloworld.pt'
-
- >>> template = PageTemplateFile(filename)
- >>> print template()
- <div>
- Hello World!
- </div>
-
-Keyword-parameters are passed on to the template namespace as-is.
Copied: z3c.pt/tags/0.2/z3c/pt/README.txt (from rev 82141, z3c.pt/trunk/z3c/pt/README.txt)
===================================================================
--- z3c.pt/tags/0.2/z3c/pt/README.txt (rev 0)
+++ z3c.pt/tags/0.2/z3c/pt/README.txt 2007-12-05 16:25:23 UTC (rev 82142)
@@ -0,0 +1,34 @@
+z3c.pt
+======
+
+Usage
+-----
+
+From a string:
+
+ >>> from z3c.pt import PageTemplate
+ >>> template = PageTemplate("""\
+ ... <div xmlns="http://www.w3.org/1999/xhtml"
+ ... xmlns:tal="http://xml.zope.org/namespaces/tal/python">
+ ... Hello World!
+ ... </div>
+ ... """)
+
+ >>> print template()
+ <div>
+ Hello World!
+ </div>
+
+From a file:
+
+ >>> from z3c.pt import PageTemplateFile
+ >>> from z3c.pt import tests
+ >>> filename = tests.__path__[0]+'/helloworld.pt'
+
+ >>> template = PageTemplateFile(filename)
+ >>> print template()
+ <div>
+ Hello World!
+ </div>
+
+Keyword-parameters are passed on to the template namespace as-is.
Deleted: z3c.pt/tags/0.2/z3c/pt/VERSION.txt
===================================================================
--- z3c.pt/trunk/z3c/pt/VERSION.txt 2007-12-03 15:44:56 UTC (rev 82100)
+++ z3c.pt/tags/0.2/z3c/pt/VERSION.txt 2007-12-05 16:25:23 UTC (rev 82142)
@@ -1 +0,0 @@
-0.1
Copied: z3c.pt/tags/0.2/z3c/pt/VERSION.txt (from rev 82141, z3c.pt/trunk/z3c/pt/VERSION.txt)
===================================================================
--- z3c.pt/tags/0.2/z3c/pt/VERSION.txt (rev 0)
+++ z3c.pt/tags/0.2/z3c/pt/VERSION.txt 2007-12-05 16:25:23 UTC (rev 82142)
@@ -0,0 +1 @@
+0.2
Copied: z3c.pt/tags/0.2/z3c/pt/codegen.py (from rev 82141, z3c.pt/trunk/z3c/pt/codegen.py)
===================================================================
--- z3c.pt/tags/0.2/z3c/pt/codegen.py (rev 0)
+++ z3c.pt/tags/0.2/z3c/pt/codegen.py 2007-12-05 16:25:23 UTC (rev 82142)
@@ -0,0 +1,63 @@
+from compiler import ast, parse
+from compiler.pycodegen import ModuleCodeGenerator
+
+from transformer import ASTTransformer
+
+marker = object()
+
+CONSTANTS = frozenset(['False', 'True', 'None', 'NotImplemented', 'Ellipsis'])
+
+class TemplateASTTransformer(ASTTransformer):
+ def __init__(self):
+ self.locals = [CONSTANTS]
+
+ def visitGetattr(self, node):
+ """
+ Allow fallback to dictionary lookup if attribute does not exist.
+
+ Variables starting with an underscore are exempt.
+
+ """
+
+ if hasattr(node.expr, 'name') and node.expr.name.startswith('_'):
+ return ast.Getattr(node.expr, node.attrname)
+
+ expr = self.visit(node.expr)
+ name = ast.Const(node.attrname)
+
+ # hasattr(obj, key) and getattr(obj, key) or not
+ # hasattr(obj, key) and obj[key]
+ return ast.Or([ast.And(
+ [ast.CallFunc(ast.Name('hasattr'), [expr, name], None, None),
+ ast.CallFunc(ast.Name('getattr'), [expr, name], None, None)]),
+ ast.And([
+ ast.Not(ast.CallFunc(ast.Name('hasattr'), [expr, name], None, None)),
+ ast.Subscript(expr, 'OP_APPLY', [name])])])
+
+class Suite(object):
+ __slots__ = ['code']
+
+ xform = TemplateASTTransformer
+ mode = 'exec'
+
+ def __init__(self, source):
+ """Create the code object from a string."""
+
+ node = parse(source, self.mode)
+
+ # build tree
+ transform = self.xform()
+ tree = transform.visit(node)
+ filename = tree.filename = '<script>'
+
+ # generate code
+ gen = ModuleCodeGenerator(tree)
+ gen.optimized = True
+
+ self.code = gen.getCode()
+
+ def __hash__(self):
+ return hash(self.code)
+
+ def __repr__(self):
+ return '%s(%r)' % (self.__class__.__name__, self.source)
Copied: z3c.pt/tags/0.2/z3c/pt/codegen.txt (from rev 82141, z3c.pt/trunk/z3c/pt/codegen.txt)
===================================================================
--- z3c.pt/tags/0.2/z3c/pt/codegen.txt (rev 0)
+++ z3c.pt/tags/0.2/z3c/pt/codegen.txt 2007-12-05 16:25:23 UTC (rev 82142)
@@ -0,0 +1,31 @@
+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
+ Hello World!
+
+AST transformations
+-------------------
+
+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
Deleted: z3c.pt/tags/0.2/z3c/pt/io.py
===================================================================
--- z3c.pt/trunk/z3c/pt/io.py 2007-12-03 15:44:56 UTC (rev 82100)
+++ z3c.pt/tags/0.2/z3c/pt/io.py 2007-12-05 16:25:23 UTC (rev 82142)
@@ -1,58 +0,0 @@
-from StringIO import StringIO
-
-class CodeIO(StringIO):
- """
- A high-level I/O class to write Python code to a stream.
- Indentation is managed using ``indent`` and ``outdent``.
-
- Convenience methods for keeping track of temporary
- variables.
-
- """
-
- variable_prefix = '_saved'
-
- def __init__(self, indentation_string="\t"):
- StringIO.__init__(self)
- self.indentation = 0
- self.indentation_string = indentation_string
- self.counter = 0
- self.queue = u''
-
- def save(self, variable=None):
- self.counter += 1
- if variable:
- self.write("%s%d = %s" % (self.variable_prefix, self.counter, variable))
- else:
- return "%s%d" % (self.variable_prefix, self.counter)
-
- def restore(self, variable=None):
- if variable:
- self.write("%s = %s%d" % (variable, self.variable_prefix, self.counter))
- else:
- return "%s%d" % (self.variable_prefix, self.counter)
-
- self.counter -= 1
-
- def indent(self, amount=1):
- self.indentation += amount
-
- def outdent(self, amount=1):
- self.indentation -= amount
-
- def out(self, string):
- self.queue += string
-
- def cook(self):
- if self.queue:
- queue = self.queue
- self.queue = ''
- self.write("_out.write('%s')" % queue)
-
- def write(self, string):
- self.cook()
- StringIO.write(self, self.indentation_string * self.indentation + string + '\n')
-
- def getvalue(self):
- self.cook()
- return StringIO.getvalue(self)
Copied: z3c.pt/tags/0.2/z3c/pt/io.py (from rev 82141, z3c.pt/trunk/z3c/pt/io.py)
===================================================================
--- z3c.pt/tags/0.2/z3c/pt/io.py (rev 0)
+++ z3c.pt/tags/0.2/z3c/pt/io.py 2007-12-05 16:25:23 UTC (rev 82142)
@@ -0,0 +1,58 @@
+from StringIO import StringIO
+
+class CodeIO(StringIO):
+ """
+ A high-level I/O class to write Python code to a stream.
+ Indentation is managed using ``indent`` and ``outdent``.
+
+ Convenience methods for keeping track of temporary
+ variables.
+
+ """
+
+ variable_prefix = '_saved'
+
+ def __init__(self, indentation=0, indentation_string="\t"):
+ StringIO.__init__(self)
+ self.indentation = indentation
+ self.indentation_string = indentation_string
+ self.counter = 0
+ self.queue = u''
+
+ def save(self, variable=None):
+ self.counter += 1
+ if variable:
+ self.write("%s%d = %s" % (self.variable_prefix, self.counter, variable))
+ else:
+ return "%s%d" % (self.variable_prefix, self.counter)
+
+ def restore(self, variable=None):
+ if variable:
+ self.write("%s = %s%d" % (variable, self.variable_prefix, self.counter))
+ else:
+ return "%s%d" % (self.variable_prefix, self.counter)
+
+ self.counter -= 1
+
+ def indent(self, amount=1):
+ self.indentation += amount
+
+ def outdent(self, amount=1):
+ self.indentation -= amount
+
+ def out(self, string):
+ self.queue += string
+
+ def cook(self):
+ if self.queue:
+ queue = self.queue
+ self.queue = ''
+ self.write("_out.write('%s')" % queue)
+
+ def write(self, string):
+ self.cook()
+ StringIO.write(self, self.indentation_string * self.indentation + string + '\n')
+
+ def getvalue(self):
+ self.cook()
+ return StringIO.getvalue(self)
Deleted: z3c.pt/tags/0.2/z3c/pt/pagetemplate.py
===================================================================
--- z3c.pt/trunk/z3c/pt/pagetemplate.py 2007-12-03 15:44:56 UTC (rev 82100)
+++ z3c.pt/tags/0.2/z3c/pt/pagetemplate.py 2007-12-05 16:25:23 UTC (rev 82142)
@@ -1,108 +0,0 @@
-import lxml.etree
-import StringIO
-
-import tal
-import io
-
-ns_lookup_table = [(f.__ns__, f) for f in (tal.define,
- tal.condition,
- tal.omit,
- tal.repeat,
- tal.attribute,
- tal.replace,
- tal.tag,
- tal.content)]
-
-class PageTemplate(object):
- def __init__(self, body):
- self.body = body
- self.render = None
-
- def translate(self):
- """Translates page template body to Python-code."""
-
- tree = lxml.etree.parse(StringIO.StringIO(self.body))
- root = tree.getroot()
-
- stream = io.CodeIO(indentation_string=' ')
-
- # imports and symbols
- stream.write("from cgi import escape as _escape")
- stream.write("from z3c.pt.tal import repeatdict as _repeatdict")
- stream.write("from StringIO import StringIO as _StringIO")
-
- stream.write("def render(**_kwargs):")
- stream.indent()
- stream.write("global _StringIO, _repeatdict, _escape")
- stream.write("repeat = _repeatdict()")
- stream.write("_attrs = {}")
- stream.write("_scope = _kwargs.keys()")
-
- # output
- stream.write("_out = _StringIO()")
-
- # set up keyword args
- stream.write("for _variable, _value in _kwargs.items():")
- stream.indent()
- stream.write("globals()[_variable] = _value")
- stream.outdent()
-
- # translate tree
- translate(root, stream)
-
- # output
- stream.write("return _out.getvalue()")
- stream.outdent()
-
- return stream.getvalue()
-
- def cook(self):
- exec self.translate()
- self.render = render
-
- @property
- def template(self):
- if self.render is None:
- self.cook()
-
- return self.render
-
- def __call__(self, **kwargs):
- return self.template(**kwargs)
-
-class PageTemplateFile(PageTemplate):
- def __init__(self, filename):
- self.filename = filename
- self.render = None
-
- @property
- def body(self):
- return open(self.filename, 'r').read()
-
-def translate(node, stream):
- keys = node.keys() + [None]
-
- handlers = [handler(node) for key, handler in ns_lookup_table \
- if key in keys]
-
- # remove namespace attributes
- for key, handler in ns_lookup_table:
- if key is not None and key in node.attrib:
- del node.attrib[key]
-
- # update node
- for handler in handlers:
- node = handler.update(node)
-
- # begin tag
- for handler in handlers:
- handler.begin(stream)
-
- # process children
- if node:
- for element in node:
- translate(element, stream)
-
- # end tag
- for handler in reversed(handlers):
- handler.end(stream)
Copied: z3c.pt/tags/0.2/z3c/pt/pagetemplate.py (from rev 82141, z3c.pt/trunk/z3c/pt/pagetemplate.py)
===================================================================
--- z3c.pt/tags/0.2/z3c/pt/pagetemplate.py (rev 0)
+++ z3c.pt/tags/0.2/z3c/pt/pagetemplate.py 2007-12-05 16:25:23 UTC (rev 82142)
@@ -0,0 +1,36 @@
+import translation
+import codegen
+
+class PageTemplate(object):
+ def __init__(self, body):
+ self.body = body
+ self.render = None
+
+ def cook(self):
+ source, _globals = translation.translate(self.body)
+ suite = codegen.Suite(source)
+
+ _locals = {}
+
+ exec suite.code in _globals, _locals
+
+ self.render = _locals['render']
+
+ @property
+ def template(self):
+ if self.render is None:
+ self.cook()
+
+ return self.render
+
+ def __call__(self, **kwargs):
+ return self.template(**kwargs)
+
+class PageTemplateFile(PageTemplate):
+ def __init__(self, filename):
+ self.filename = filename
+ self.render = None
+
+ @property
+ def body(self):
+ return open(self.filename, 'r').read()
Deleted: z3c.pt/tags/0.2/z3c/pt/tal.py
===================================================================
--- z3c.pt/trunk/z3c/pt/tal.py 2007-12-03 15:44:56 UTC (rev 82100)
+++ z3c.pt/tags/0.2/z3c/pt/tal.py 2007-12-05 16:25:23 UTC (rev 82142)
@@ -1,389 +0,0 @@
-import parser
-import cgi
-import xml.sax.saxutils
-
-def expression(string):
- """
- Python-expressions in try-except construct.
-
- Specification:
-
- expression :: = python_expression [ |* expression ]
- python_expresion ::= a python expression string
-
- *) Using | as logical or is not supported.
-
- """
-
- string = string.replace('\n', '')
-
- expression = []
-
- i = j = 0
- while i < len(string):
- j = string.find('|', j + 1)
- if j == -1:
- j = len(string)
-
- expr = string[i:j].lstrip()
-
- try:
- # we use the ``parser`` module to determine if
- # an expression is a valid python expression
- parser.expr(expr)
- except SyntaxError, e:
- if j < len(string):
- continue
-
- raise e
-
- expression.append(expr)
- i = j + 1
-
- return expression
-
-def definition(string):
- """
- TAL define-expression:
-
- Specification:
-
- argument ::= define_var [';' define_var]
- define_var ::= Name python_expression
-
- """
-
- string = string.replace('\n', '').strip()
-
- defines = []
-
- i = 0
- while i < len(string):
- while string[i] == ' ':
- i += 1
-
- # get variable name
- j = string.find(' ', i + 1)
- if j == -1:
- raise ValueError, "Invalid define clause (%s)." % string
-
- variable = string[i:j]
-
- if variable in ('repeat',):
- raise ValueError, "Invalid variable name '%s' (reserved)." % variable
-
- if variable.startswith('_'):
- raise ValueError, \
- "Invalid variable name '%s' (starts with an underscore)." % variable
- # get expression
- i = j
- while j < len(string):
- j = string.find(';', j+1)
- if j == -1:
- j = len(string)
-
- try:
- expr = expression(string[i:j])
- except SyntaxError, e:
- continue
- break
- else:
- raise e
-
- defines.append((variable, expr))
-
- i = j + 1
-
- return defines
-
-class repeatitem(object):
- def __init__(self, iterator, length):
- self.length = length
- self.iterator = iterator
-
- @property
- def index(self):
- return self.length - len(self.iterator) - 1
-
- @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 __setitem__(self, key, iterator):
- try:
- length = len(iterator)
- except TypeError:
- length = None
-
- dict.__setitem__(self, key, (iterator, length))
-
- def __getitem__(self, key):
- value, length = dict.__getitem__(self, key)
-
- if not isinstance(value, repeatitem):
- value = repeatitem(value, length)
- self.__setitem__(key, value)
-
- return value
-
-class Assign(object):
- def __init__(self, expression):
- self.expressions = expression
-
- def begin(self, stream, variable):
- """First n - 1 expressions must be try-except wrapped."""
-
- for expression in self.expressions[:-1]:
- stream.write("try:")
- stream.indent()
- stream.write("%s = %s" % (variable, expression))
- stream.outdent()
- stream.write("except Exception, e:")
- stream.indent()
-
- expression = self.expressions[-1]
- stream.write("%s = %s" % (variable, expression))
-
- def end(self, stream):
- stream.outdent(len(self.expressions)-1)
-
-class Define(object):
- def __init__(self, value):
- self.defines = [(v, Assign(e)) for v, e in definition(value)]
-
- def update(self, node):
- return node
-
- def begin(self, stream):
- variables = [v for (v, e) in self.defines]
-
- # save local variables already in scope
- save = stream.save()
- stream.write("%s = {}" % save)
- for var in variables:
- stream.write("if '%s' in _scope: %s['%s'] = %s" % (var, save, var, var))
- stream.write("else: _scope.append('%s')" % var)
-
- for variable, assign in self.defines:
- assign.begin(stream, variable)
- assign.end(stream)
-
- def end(self, stream):
- restore = stream.restore()
-
- for variable, expression in reversed(self.defines):
- # restore local variables previously in scope
- stream.write("if '%s' in %s:" % (variable, restore))
- stream.indent()
- stream.write("%s = %s['%s']" % (variable, restore, variable))
- stream.outdent()
- stream.write("else:")
- stream.indent()
- stream.write("del %s" % variable)
- stream.write("_scope.remove('%s')" % variable)
- stream.outdent()
-
-class Condition(object):
- def __init__(self, value):
- self.assign = Assign(expression(value))
-
- def update(self, node):
- return node
-
- def begin(self, stream):
- variable = '_condition'
-
- self.assign.begin(stream, variable)
- stream.write("if %s:" % variable)
- stream.indent()
-
- def end(self, stream):
- self.assign.end(stream)
- stream.outdent()
-
-class Repeat(object):
- def __init__(self, value):
- string = value.lstrip().replace('\n', '')
-
- space = string.find(' ')
- if space == -1:
- raise ValueError, "Invalid repeat clause (%s)." % value
-
- self.variable = string[:space]
- self.assign = Assign(expression(string[space:]))
-
- def update(self, node):
- return node
-
- def begin(self, stream):
- variable = self.variable
- iterator = stream.save()
-
- self.assign.begin(stream, iterator)
-
- # define variable scope
- self.define = Define("%s None" % self.variable)
- self.define.begin(stream)
-
- # initialize iterator
- stream.write("repeat['%s'] = %s = %s.__iter__()" % (variable, iterator, iterator))
-
- # loop
- stream.write("while %s:" % iterator)
- stream.indent()
- stream.write("%s = %s.next()" % (variable, iterator))
-
- def end(self, stream):
- # cook before leaving loop
- stream.cook()
-
- stream.outdent()
- self.define.end(stream)
- self.assign.end(stream)
- stream.restore()
-
-class Attribute(object):
- def __init__(self, value):
- self.attributes = definition(value)
-
- def update(self, node):
- for variable, expression in self.attributes:
- if variable in node.attrib:
- del node.attrib[variable]
-
- return node
-
- def begin(self, stream):
- stream.write("_attrs = {}")
- for variable, expression in self.attributes:
- assign = Assign(expression)
- assign.begin(stream, "_attrs['%s']" % variable)
- assign.end(stream)
-
- def end(self, stream):
- pass
-
-class Content(object):
- def __init__(self, value):
- self.assign = Assign(expression(value))
-
- def update(self, node):
- node.text = ''
- for element in node.getchildren():
- node.remove(element)
-
- return node
-
- def begin(self, stream):
- self.assign.begin(stream, '_content')
- stream.write("_out.write(_content)")
-
- def end(self, stream):
- self.assign.end(stream)
-
-class Replace(Content):
- def update(self, node):
- return None
-
-class Tag(object):
- def __init__(self, node):
- self.node = node
- self.tail = node.tail
-
- @property
- def tag(self):
- tag = self.node.tag
- if tag.startswith('{'):
- return tag[tag.find('}')+1:]
-
- return tag
-
- def update(self, node):
- self.node = node
- return node
-
- def begin(self, stream):
- if self.node is None:
- return
- stream.out('<%s' % self.tag)
- stream.write("for _name, _value in _attrs.items():")
- stream.indent()
- stream.write("""_out.write(' %s=\"%s\"' % (_name, _escape(_value, '\"')))""")
- stream.outdent()
- stream.write("_attrs.clear()")
- for name, value in self.node.attrib.items():
- stream.out(' %s=%s' % (name, xml.sax.saxutils.quoteattr(value)))
-
- if self.node.text is None:
- stream.out(' />')
- else:
- stream.out('>')
-
- text = self.node.text
- if text is not None:
- text = cgi.escape(text.replace('\n', '\\n'), '"')
- stream.out(text)
-
- def end(self, stream):
- if self.node is not None and self.node.text is not None:
- stream.out('</%s>' % self.tag)
-
- if self.tail is not None:
- tail = cgi.escape(self.tail.replace('\n', '\\n'), "'")
- stream.out(tail)
-
-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
-
- at handler("{http://xml.zope.org/namespaces/tal}define")
-def define(node, value):
- return Define(value)
-
- at handler("{http://xml.zope.org/namespaces/tal}condition")
-def condition(node, value):
- return Condition(value)
-
- at handler("{http://xml.zope.org/namespaces/tal}repeat")
-def repeat(node, value):
- return Repeat(value)
-
- at handler("{http://xml.zope.org/namespaces/tal}attributes")
-def attribute(node, value):
- return Attribute(value)
-
- at handler("{http://xml.zope.org/namespaces/tal}content")
-def content(node, value):
- return Content(value)
-
- at handler("{http://xml.zope.org/namespaces/tal}replace")
-def replace(node, value):
- return Replace(value)
-
- at handler("{http://xml.zope.org/namespaces/tal}omit-tag")
-def omit(node, value):
- raise NotImplemented, "The tal:omit-tag statement is not supported yet."
-
- at handler()
-def tag(node, value):
- return Tag(node)
Copied: z3c.pt/tags/0.2/z3c/pt/tal.py (from rev 82141, z3c.pt/trunk/z3c/pt/tal.py)
===================================================================
--- z3c.pt/tags/0.2/z3c/pt/tal.py (rev 0)
+++ z3c.pt/tags/0.2/z3c/pt/tal.py 2007-12-05 16:25:23 UTC (rev 82142)
@@ -0,0 +1,406 @@
+import parser
+import cgi
+import xml.sax.saxutils
+import itertools
+
+def expression(string):
+ """
+ Python-expressions in try-except construct.
+
+ Specification:
+
+ expression :: = python_expression [ |* expression ]
+ python_expresion ::= a python expression string
+
+ *) Using | as logical or is not supported.
+
+ """
+
+ string = string.replace('\n', '')
+
+ expression = []
+
+ i = j = 0
+ while i < len(string):
+ j = string.find('|', j + 1)
+ if j == -1:
+ j = len(string)
+
+ expr = string[i:j].lstrip()
+
+ try:
+ # we use the ``parser`` module to determine if
+ # an expression is a valid python expression
+ parser.expr(expr)
+ except SyntaxError, e:
+ if j < len(string):
+ continue
+
+ raise e
+
+ expression.append(expr)
+ i = j + 1
+
+ return expression
+
+def variable(string):
+ for var in string.split(', '):
+ var = var.strip()
+
+ if var in ('repeat',):
+ raise ValueError, "Invalid variable name '%s' (reserved)." % variable
+
+ if var.startswith('_'):
+ raise ValueError, \
+ "Invalid variable name '%s' (starts with an underscore)." % variable
+ yield var
+
+def definition(string):
+ """
+ TAL define-expression:
+
+ Specification:
+
+ argument ::= define_var [';' define_var]
+ define_var ::= Name python_expression
+
+ """
+
+ string = string.replace('\n', '').strip()
+
+ defines = []
+
+ i = 0
+ while i < len(string):
+ 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 = variable(string[i+1:j])
+ j += 1
+ else:
+ j = string.find(' ', i + 1)
+ if j == -1:
+ raise ValueError, "Invalid define clause (%s)." % string
+ var = variable(string[i:j])
+
+ # get expression
+ i = j
+ while j < len(string):
+ j = string.find(';', j+1)
+ if j == -1:
+ j = len(string)
+
+ try:
+ expr = expression(string[i:j])
+ except SyntaxError, e:
+ continue
+ break
+ else:
+ raise e
+
+ defines.append((list(var), expr))
+
+ i = j + 1
+
+ return defines
+
+class repeatitem(object):
+ def __init__(self, iterator, length):
+ self.length = length
+ self.iterator = iterator
+
+ @property
+ def index(self):
+ return self.length - len(self.iterator) - 1
+
+ @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 __setitem__(self, key, iterator):
+ try:
+ length = len(iterator)
+ except TypeError:
+ length = None
+
+ dict.__setitem__(self, key, (iterator, length))
+
+ def __getitem__(self, key):
+ value, length = dict.__getitem__(self, key)
+
+ if not isinstance(value, repeatitem):
+ value = repeatitem(value, length)
+ self.__setitem__(key, value)
+
+ return value
+
+class Assign(object):
+ def __init__(self, expression):
+ self.expressions = expression
+
+ def begin(self, stream, variable):
+ """First n - 1 expressions must be try-except wrapped."""
+
+ for expression in self.expressions[:-1]:
+ stream.write("try:")
+ stream.indent()
+ stream.write("%s = %s" % (variable, expression))
+ stream.outdent()
+ stream.write("except Exception, e:")
+ stream.indent()
+
+ expression = self.expressions[-1]
+ stream.write("%s = %s" % (variable, expression))
+
+ def end(self, stream):
+ stream.outdent(len(self.expressions)-1)
+
+class Define(object):
+ def __init__(self, value):
+ self.defines = [(v, Assign(e)) for v, e in definition(value)]
+ self.variables = list(itertools.chain(*[v for (v, e) in self.defines]))
+
+ def update(self, node):
+ return node
+
+ def begin(self, stream):
+ # save local variables already in scope
+ save = stream.save()
+ stream.write("%s = {}" % save)
+
+ for var in self.variables:
+ stream.write("if '%s' in _scope: %s['%s'] = %s" % (var, save, var, var))
+ stream.write("else: _scope.append('%s')" % var)
+
+ for variables, assign in self.defines:
+ if len(variables) == 1:
+ assign.begin(stream, variables[0])
+ else:
+ assign.begin(stream, u"(%s,)" % ", ".join(variables))
+ assign.end(stream)
+
+ def end(self, stream):
+ restore = stream.restore()
+
+ for variable in reversed(self.variables):
+ # restore local variables previously in scope
+ stream.write("if '%s' in %s:" % (variable, restore))
+ stream.indent()
+ stream.write("%s = %s['%s']" % (variable, restore, variable))
+ stream.outdent()
+ stream.write("else:")
+ stream.indent()
+ stream.write("del %s" % variable)
+ stream.write("_scope.remove('%s')" % variable)
+ stream.outdent()
+
+class Condition(object):
+ def __init__(self, value):
+ self.assign = Assign(expression(value))
+
+ def update(self, node):
+ return node
+
+ def begin(self, stream):
+ variable = '_condition'
+
+ self.assign.begin(stream, variable)
+ stream.write("if %s:" % variable)
+ stream.indent()
+
+ def end(self, stream):
+ self.assign.end(stream)
+ stream.outdent()
+
+class Repeat(object):
+ def __init__(self, value):
+ string = value.lstrip().replace('\n', '')
+
+ space = string.find(' ')
+ if space == -1:
+ raise ValueError, "Invalid repeat clause (%s)." % value
+
+ self.variable = string[:space]
+ self.assign = Assign(expression(string[space:]))
+
+ def update(self, node):
+ return node
+
+ def begin(self, stream):
+ variable = self.variable
+ iterator = stream.save()
+
+ self.assign.begin(stream, iterator)
+
+ # define variable scope
+ self.define = Define("%s None" % self.variable)
+ self.define.begin(stream)
+
+ # initialize iterator
+ stream.write("repeat['%s'] = %s = %s.__iter__()" % (variable, iterator, iterator))
+
+ # loop
+ stream.write("while %s:" % iterator)
+ stream.indent()
+ stream.write("%s = %s.next()" % (variable, iterator))
+
+ def end(self, stream):
+ # cook before leaving loop
+ stream.cook()
+
+ stream.outdent()
+ self.define.end(stream)
+ self.assign.end(stream)
+ stream.restore()
+
+class Attribute(object):
+ def __init__(self, value):
+ self.attributes = [(v, Assign(e)) for v, e in definition(value)]
+
+ def update(self, node):
+ for variables, expression in self.attributes:
+ for variable in variables:
+ if variable in node.attrib:
+ del node.attrib[variable]
+
+ return node
+
+ def begin(self, stream):
+ stream.write("_attrs = {}")
+ for variables, assign in self.attributes:
+ for variable in variables:
+ assign.begin(stream, "_attrs['%s']" % variable)
+ assign.end(stream)
+
+ def end(self, stream):
+ pass
+
+class Content(object):
+ def __init__(self, value):
+ self.assign = Assign(expression(value))
+
+ def update(self, node):
+ node.text = ''
+ for element in node.getchildren():
+ node.remove(element)
+
+ return node
+
+ def begin(self, stream):
+ self.assign.begin(stream, '_content')
+ stream.write("_out.write(_content)")
+
+ def end(self, stream):
+ self.assign.end(stream)
+
+class Replace(Content):
+ def update(self, node):
+ return None
+
+class Tag(object):
+ def __init__(self, node):
+ self.node = node
+ self.tail = node.tail
+
+ @property
+ def tag(self):
+ tag = self.node.tag
+ if tag.startswith('{'):
+ return tag[tag.find('}')+1:]
+
+ return tag
+
+ def update(self, node):
+ self.node = node
+ return node
+
+ def begin(self, stream):
+ if self.node is None:
+ return
+ stream.out('<%s' % self.tag)
+ stream.write("for _name, _value in _attrs.items():")
+ stream.indent()
+ stream.write("""_out.write(' %s=\"%s\"' % (_name, _escape(_value, '\"')))""")
+ stream.outdent()
+ stream.write("_attrs.clear()")
+ for name, value in self.node.attrib.items():
+ stream.out(' %s=%s' % (name, xml.sax.saxutils.quoteattr(value)))
+
+ if self.node.text is None:
+ stream.out(' />')
+ else:
+ stream.out('>')
+
+ text = self.node.text
+ if text is not None:
+ text = cgi.escape(text.replace('\n', '\\n'), '"')
+ stream.out(text)
+
+ def end(self, stream):
+ if self.node is not None and self.node.text is not None:
+ stream.out('</%s>' % self.tag)
+
+ if self.tail is not None:
+ tail = cgi.escape(self.tail.replace('\n', '\\n'), "'")
+ stream.out(tail)
+
+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
+
+ at handler("{http://xml.zope.org/namespaces/tal}define")
+def define(node, value):
+ return Define(value)
+
+ at handler("{http://xml.zope.org/namespaces/tal}condition")
+def condition(node, value):
+ return Condition(value)
+
+ at handler("{http://xml.zope.org/namespaces/tal}repeat")
+def repeat(node, value):
+ return Repeat(value)
+
+ at handler("{http://xml.zope.org/namespaces/tal}attributes")
+def attribute(node, value):
+ return Attribute(value)
+
+ at handler("{http://xml.zope.org/namespaces/tal}content")
+def content(node, value):
+ return Content(value)
+
+ at handler("{http://xml.zope.org/namespaces/tal}replace")
+def replace(node, value):
+ return Replace(value)
+
+ at handler("{http://xml.zope.org/namespaces/tal}omit-tag")
+def omit(node, value):
+ raise NotImplemented, "The tal:omit-tag statement is not supported yet."
+
+ at handler()
+def tag(node, value):
+ return Tag(node)
Deleted: z3c.pt/tags/0.2/z3c/pt/tal.txt
===================================================================
--- z3c.pt/trunk/z3c/pt/tal.txt 2007-12-03 15:44:56 UTC (rev 82100)
+++ z3c.pt/tags/0.2/z3c/pt/tal.txt 2007-12-05 16:25:23 UTC (rev 82142)
@@ -1,226 +0,0 @@
-TAL
-===
-
-Tests for the TAL language implementation.
-
- >>> from z3c.pt import tal
-
-expression
-----------
-
-Simple expression:
-
- >>> tal.expression("4 + 5")
- ['4 + 5']
-
-Complex expressions:
-
- >>> tal.expression("a.non_defined_method() | 1")
- ['a.non_defined_method() ', '1']
-
-Expression with non-semantic horizontal bar.
-
- >>> tal.expression("'|'")
- ["'|'"]
-
-Expression with non-semantic horizontal bar and semantic bar.
-
- >>> tal.expression("a.non_defined_method() | '|'")
- ['a.non_defined_method() ', "'|'"]
-
-Define
-------
-
- >>> from z3c.pt.io import CodeIO
- >>> stream = CodeIO()
- >>> _scope = []
-
-Variable scope:
-
- >>> define = tal.Define("a b")
- >>> b = object()
- >>> define.begin(stream)
- >>> exec stream.getvalue()
- >>> a is b
- True
- >>> del a
- >>> _scope.remove('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:
-
- >>> define = tal.Define("a b; c d")
- >>> d = object()
- >>> define.begin(stream)
- >>> exec stream.getvalue()
- >>> a is b and c is d
- True
- >>> define.end(stream)
- >>> del a; del c
- >>> _scope.remove('a'); _scope.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
-
-Using semicolons in expressions within a define:
-
- >>> define = tal.Define("a ';'")
- >>> define.begin(stream)
- >>> exec stream.getvalue()
- >>> a
- ';'
- >>> define.end(stream)
-
-Ending an define clause with a semicolon.
-
- >>> define = tal.Define("a 4 + 5;")
- >>> define.begin(stream)
- >>> exec stream.getvalue()
- >>> a
- 9
- >>> define.end(stream)
-
-Scope:
-
- >>> a = 1
- >>> define = tal.Define("a 2")
- >>> define.begin(stream)
- >>> define.end(stream)
- >>> exec stream.getvalue()
- >>> a
- 1
-
-Conditions
-----------
-
- >>> stream = CodeIO()
-
-True:
-
- >>> a = 0
- >>> condition = tal.Condition("True")
- >>> define = tal.Define("a 1")
- >>> condition.begin(stream)
- >>> define.begin(stream)
- >>> exec stream.getvalue()
- >>> a
- 1
- >>> define.end(stream)
- >>> condition.end(stream)
-
-False:
-
- >>> a = 0
- >>> condition = tal.Condition("False")
- >>> define = tal.Define("a 1")
- >>> condition.begin(stream)
- >>> define.begin(stream)
- >>> exec stream.getvalue()
- >>> a
- 0
- >>> define.end(stream)
- >>> condition.end(stream)
-
-Repeat
-------
-
- >>> from z3c.pt.tal import repeatdict as _repeat
- >>> repeat = _repeat()
-
- >>> stream = CodeIO()
-
- >>> _repeat = tal.Repeat("i 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())")
- >>> 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)
-
-Attribute
----------
-
- >>> from z3c.pt.tal import Attribute
- >>> stream = CodeIO()
-
- >>> attribute = Attribute("class 'plain'")
- >>> attribute.begin(stream)
- >>> attribute.end(stream)
- >>> exec stream.getvalue()
- >>> _attrs
- {'class': 'plain'}
- >>> del _attrs
-
-Attributes that are bound to expressions will be removed on ``update``:
-
- >>> from lxml.etree import Element
- >>> img = Element('img')
- >>> img.set('src', u'logo.gif')
- >>> img.set('class', u'stx')
- >>> img = attribute.update(img)
- >>> img.attrib
- {'src': 'logo.gif'}
-
-Content
--------
-
- >>> from z3c.pt.tal import Content
- >>> stream = CodeIO()
-
- >>> from StringIO import StringIO
- >>> _out = StringIO()
-
- >>> content = tal.Content(u"'Hello World!'")
- >>> content.begin(stream)
- >>> exec stream.getvalue()
- >>> _out.getvalue()
- 'Hello World!'
- >>> content.end(stream)
-
-Tag
----
-
-Define required global symbols.
-
- >>> from cgi import escape as _escape
- >>> _attrs = {}
-
- >>> stream = CodeIO()
- >>> br = Element('br')
- >>> tag = tal.Tag(br)
- >>> tag.begin(stream)
- >>> tag.end(stream)
- >>> _out = StringIO()
- >>> exec stream.getvalue()
- >>> _out.getvalue()
- '<br />'
-
- >>> stream = CodeIO()
- >>> div = Element('div')
- >>> div.text = ''
- >>> tag = tal.Tag(div)
- >>> tag.begin(stream)
- >>> tag.end(stream)
- >>> _out = StringIO()
- >>> exec stream.getvalue()
- >>> _out.getvalue()
- '<div></div>'
Copied: z3c.pt/tags/0.2/z3c/pt/tal.txt (from rev 82141, z3c.pt/trunk/z3c/pt/tal.txt)
===================================================================
--- z3c.pt/tags/0.2/z3c/pt/tal.txt (rev 0)
+++ z3c.pt/tags/0.2/z3c/pt/tal.txt 2007-12-05 16:25:23 UTC (rev 82142)
@@ -0,0 +1,267 @@
+TAL
+===
+
+Tests for the TAL language implementation.
+
+ >>> from z3c.pt import tal
+
+expression
+----------
+
+Simple expression:
+
+ >>> tal.expression("4 + 5")
+ ['4 + 5']
+
+Complex expressions:
+
+ >>> tal.expression("a.non_defined_method() | 1")
+ ['a.non_defined_method() ', '1']
+
+Expression with non-semantic horizontal bar.
+
+ >>> tal.expression("'|'")
+ ["'|'"]
+
+Expression with non-semantic horizontal bar and semantic bar.
+
+ >>> tal.expression("a.non_defined_method() | '|'")
+ ['a.non_defined_method() ', "'|'"]
+
+Assign
+------
+
+Simple assignment.
+
+ >>> from z3c.pt.io import CodeIO
+ >>> stream = CodeIO()
+ >>> _scope = []
+
+ >>> assign = tal.Assign(tal.expression("1"))
+ >>> assign.begin(stream, 'a')
+ >>> exec stream.getvalue()
+ >>> a == 1
+ True
+ >>> del a
+ >>> assign.end(stream)
+ >>> exec stream.getvalue()
+
+Define
+------
+
+Variable scope:
+
+ >>> stream = CodeIO()
+ >>> define = tal.Define("a b")
+ >>> b = object()
+ >>> define.begin(stream)
+ >>> exec stream.getvalue()
+ >>> a is b
+ True
+ >>> del a
+ >>> _scope.remove('a')
+ >>> define.end(stream)
+ >>> exec stream.getvalue()
+ >>> a
+ Traceback (most recent call last):
+ ...
+ NameError: name 'a' is not defined
+ >>> b is not None
+ True
+
+Multiple defines:
+
+ >>> stream = CodeIO()
+ >>> define = tal.Define("a b; c d")
+ >>> d = object()
+ >>> define.begin(stream)
+ >>> exec stream.getvalue()
+ >>> a is b and c is d
+ True
+ >>> define.end(stream)
+ >>> del a; del c
+ >>> _scope.remove('a'); _scope.remove('c')
+ >>> exec stream.getvalue()
+ >>> a
+ Traceback (most recent call last):
+ ...
+ NameError: name 'a' is not defined
+ >>> c
+ Traceback (most recent call last):
+ ...
+ NameError: name 'c' is not defined
+ >>> b is not None and d is not None
+ True
+
+Tuple assignments:
+
+ >>> stream = CodeIO()
+ >>> define = tal.Define("(e, f) [1, 2]")
+ >>> define.begin(stream)
+ >>> exec stream.getvalue()
+ >>> e == 1 and f == 2
+ True
+ >>> define.end(stream)
+
+Verify scope is preserved on tuple assignment:
+
+ >>> e = None; f = None
+ >>> _scope.append('e'); _scope.append('f')
+ >>> exec stream.getvalue()
+ >>> e is None and f is None
+ True
+
+Using semicolons in expressions within a define:
+
+ >>> stream = CodeIO()
+ >>> define = tal.Define("a ';'")
+ >>> define.begin(stream)
+ >>> exec stream.getvalue()
+ >>> a
+ ';'
+ >>> define.end(stream)
+
+Ending an define clause with a semicolon.
+
+ >>> stream = CodeIO()
+ >>> define = tal.Define("a 4 + 5;")
+ >>> define.begin(stream)
+ >>> exec stream.getvalue()
+ >>> a
+ 9
+ >>> define.end(stream)
+ >>> del a
+ >>> _scope.remove('a')
+ >>> exec stream.getvalue()
+
+Scope:
+
+ >>> stream = CodeIO()
+ >>> a = 1
+ >>> _scope.append('a')
+ >>> define = tal.Define("a 2")
+ >>> define.begin(stream)
+ >>> define.end(stream)
+ >>> exec stream.getvalue()
+ >>> a
+ 1
+
+Conditions
+----------
+
+ >>> stream = CodeIO()
+
+True:
+
+ >>> a = 0
+ >>> condition = tal.Condition("True")
+ >>> define = tal.Define("a 1")
+ >>> condition.begin(stream)
+ >>> define.begin(stream)
+ >>> exec stream.getvalue()
+ >>> a
+ 1
+ >>> define.end(stream)
+ >>> condition.end(stream)
+
+False:
+
+ >>> a = 0
+ >>> condition = tal.Condition("False")
+ >>> define = tal.Define("a 1")
+ >>> condition.begin(stream)
+ >>> define.begin(stream)
+ >>> exec stream.getvalue()
+ >>> a
+ 0
+ >>> define.end(stream)
+ >>> condition.end(stream)
+
+Repeat
+------
+
+ >>> from z3c.pt.tal import repeatdict as _repeat
+ >>> repeat = _repeat()
+
+ >>> stream = CodeIO()
+
+ >>> _repeat = tal.Repeat("i 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())")
+ >>> 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)
+
+Attribute
+---------
+
+ >>> from z3c.pt.tal import Attribute
+ >>> stream = CodeIO()
+
+ >>> attribute = Attribute("class 'plain'")
+ >>> attribute.begin(stream)
+ >>> attribute.end(stream)
+ >>> exec stream.getvalue()
+ >>> _attrs
+ {'class': 'plain'}
+ >>> del _attrs
+
+Attributes that are bound to expressions will be removed on ``update``:
+
+ >>> from lxml.etree import Element
+ >>> img = Element('img')
+ >>> img.set('src', u'logo.gif')
+ >>> img.set('class', u'stx')
+ >>> img = attribute.update(img)
+ >>> img.attrib
+ {'src': 'logo.gif'}
+
+Content
+-------
+
+ >>> from z3c.pt.tal import Content
+ >>> stream = CodeIO()
+
+ >>> from StringIO import StringIO
+ >>> _out = StringIO()
+
+ >>> content = tal.Content(u"'Hello World!'")
+ >>> content.begin(stream)
+ >>> exec stream.getvalue()
+ >>> _out.getvalue()
+ 'Hello World!'
+ >>> content.end(stream)
+
+Tag
+---
+
+Define required global symbols.
+
+ >>> from cgi import escape as _escape
+ >>> _attrs = {}
+
+ >>> stream = CodeIO()
+ >>> br = Element('br')
+ >>> tag = tal.Tag(br)
+ >>> tag.begin(stream)
+ >>> tag.end(stream)
+ >>> _out = StringIO()
+ >>> exec stream.getvalue()
+ >>> _out.getvalue()
+ '<br />'
+
+ >>> stream = CodeIO()
+ >>> div = Element('div')
+ >>> div.text = ''
+ >>> tag = tal.Tag(div)
+ >>> tag.begin(stream)
+ >>> tag.end(stream)
+ >>> _out = StringIO()
+ >>> exec stream.getvalue()
+ >>> _out.getvalue()
+ '<div></div>'
Deleted: z3c.pt/tags/0.2/z3c/pt/tests/test_doctests.py
===================================================================
--- z3c.pt/trunk/z3c/pt/tests/test_doctests.py 2007-12-03 15:44:56 UTC (rev 82100)
+++ z3c.pt/tags/0.2/z3c/pt/tests/test_doctests.py 2007-12-05 16:25:23 UTC (rev 82142)
@@ -1,23 +0,0 @@
-import zope.testing
-import unittest
-
-OPTIONFLAGS = (zope.testing.doctest.REPORT_ONLY_FIRST_FAILURE |
- zope.testing.doctest.ELLIPSIS |
-# zope.testing.doctest.REPORT_NDIFF |
- zope.testing.doctest.NORMALIZE_WHITESPACE)
-
-import zope.component.testing
-
-def test_suite():
- doctests = ['README.txt', 'BENCHMARKS.txt', 'tal.txt', 'translate.txt']
-
- return unittest.TestSuite((
- zope.testing.doctest.DocFileSuite(doctest,
- optionflags=OPTIONFLAGS,
- setUp=zope.component.testing.setUp,
- tearDown=zope.component.testing.tearDown,
- package="z3c.pt") for doctest in doctests
- ))
-
-if __name__ == '__main__':
- unittest.main(defaultTest='test_suite')
Copied: z3c.pt/tags/0.2/z3c/pt/tests/test_doctests.py (from rev 82141, z3c.pt/trunk/z3c/pt/tests/test_doctests.py)
===================================================================
--- z3c.pt/tags/0.2/z3c/pt/tests/test_doctests.py (rev 0)
+++ z3c.pt/tags/0.2/z3c/pt/tests/test_doctests.py 2007-12-05 16:25:23 UTC (rev 82142)
@@ -0,0 +1,22 @@
+import zope.testing
+import unittest
+
+OPTIONFLAGS = (zope.testing.doctest.REPORT_ONLY_FIRST_FAILURE |
+ zope.testing.doctest.ELLIPSIS |
+ zope.testing.doctest.NORMALIZE_WHITESPACE)
+
+import zope.component.testing
+
+def test_suite():
+ filesuites = ['README.txt', 'BENCHMARKS.txt', 'tal.txt', 'translation.txt', 'codegen.txt']
+
+ return unittest.TestSuite(
+ [zope.testing.doctest.DocFileSuite(doctest,
+ optionflags=OPTIONFLAGS,
+ setUp=zope.component.testing.setUp,
+ tearDown=zope.component.testing.tearDown,
+ package="z3c.pt") for doctest in filesuites]
+ )
+
+if __name__ == '__main__':
+ unittest.main(defaultTest='test_suite')
Copied: z3c.pt/tags/0.2/z3c/pt/transformer.py (from rev 82141, z3c.pt/trunk/z3c/pt/transformer.py)
===================================================================
--- z3c.pt/tags/0.2/z3c/pt/transformer.py (rev 0)
+++ z3c.pt/tags/0.2/z3c/pt/transformer.py 2007-12-05 16:25:23 UTC (rev 82142)
@@ -0,0 +1,235 @@
+from compiler import ast, parse
+
+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/tags/0.2/z3c/pt/translate.txt
===================================================================
--- z3c.pt/trunk/z3c/pt/translate.txt 2007-12-03 15:44:56 UTC (rev 82100)
+++ z3c.pt/tags/0.2/z3c/pt/translate.txt 2007-12-05 16:25:23 UTC (rev 82142)
@@ -1,60 +0,0 @@
-Translation
------------
-
- >>> from z3c.pt.pagetemplate import translate
- >>> from z3c.pt import io
-
-A few imports.
-
- >>> from lxml import etree
- >>> from StringIO import StringIO
-
-The following symbols are expected to be in the local symbol table.
-
- >>> from cgi import escape as _escape
- >>> from z3c.pt.tal import repeatdict as _repeat
- >>> repeat = _repeat()
- >>> _attrs = {}
-
-Example:
-
- >>> tree = etree.fromstring("""\
- ... <div xmlns="http://www.w3.org/1999/xhtml"
- ... xmlns:tal="http://xml.zope.org/namespaces/tal">
- ... <span tal:define="a 'abc'"
- ... tal:attributes="class 'def' + a"
- ... tal:content="a + 'ghi'" />
- ... <ul>
- ... <li tal:repeat="i range(5)">
- ... <span tal:replace="'Item ' + str(i) + ')'" />
- ... </li>
- ... </ul>
- ... </div>
- ... """)
-
- >>> stream = io.CodeIO(indentation_string=" ")
- >>> translate(tree, stream)
- >>> _out = StringIO()
- >>> _scope = []
- >>> exec stream.getvalue()
- >>> print _out.getvalue()
- <div>
- <span class="defabc">abcghi</span>
- <ul>
- <li>
- Item 0)
- </li>
- <li>
- Item 1)
- </li>
- <li>
- Item 2)
- </li>
- <li>
- Item 3)
- </li>
- <li>
- Item 4)
- </li>
- </ul>
- </div>
Copied: z3c.pt/tags/0.2/z3c/pt/translation.py (from rev 82141, z3c.pt/trunk/z3c/pt/translation.py)
===================================================================
--- z3c.pt/tags/0.2/z3c/pt/translation.py (rev 0)
+++ z3c.pt/tags/0.2/z3c/pt/translation.py 2007-12-05 16:25:23 UTC (rev 82142)
@@ -0,0 +1,76 @@
+from StringIO import StringIO
+import lxml.etree
+
+import cgi
+import tal
+import io
+
+ns_lookup_table = [(f.__ns__, f) for f in \
+ (tal.define,
+ tal.condition,
+ tal.omit,
+ tal.repeat,
+ tal.attribute,
+ tal.replace,
+ tal.tag,
+ tal.content)]
+
+wrapper = """\
+def render(**_kwargs):
+\trepeat = _repeatdict()
+\t_attrs = {}
+\t_scope = _kwargs.keys()
+\t_out = _StringIO()
+\t_globals = globals()
+\tfor _variable, _value in _kwargs.items():
+\t\t_globals[_variable] = _value
+%s
+\treturn _out.getvalue()
+"""
+
+def translate(body):
+ tree = lxml.etree.parse(StringIO(body))
+ root = tree.getroot()
+
+ stream = io.CodeIO(indentation=1, indentation_string="\t")
+ visit(root, stream)
+
+ source = wrapper % stream.getvalue()
+
+ _globals = dict(_StringIO=StringIO,
+ _repeatdict=tal.repeatdict,
+ _escape=cgi.escape)
+
+ return source, _globals
+
+def visit(node, stream):
+ """Translates a node and outputs to a code stream."""
+
+ keys = node.keys() + [None]
+
+ handlers = [handler(node) for key, handler in ns_lookup_table \
+ if key in keys]
+
+ # remove namespace attributes
+ for key, handler in ns_lookup_table:
+ if key is not None and key in node.attrib:
+ del node.attrib[key]
+
+ # update node
+ for handler in handlers:
+ node = handler.update(node)
+
+ # begin tag
+ for handler in handlers:
+ handler.begin(stream)
+
+ # process children
+ if node:
+ for element in node:
+ visit(element, stream)
+
+ # end tag
+ for handler in reversed(handlers):
+ handler.end(stream)
+
+ return stream
Copied: z3c.pt/tags/0.2/z3c/pt/translation.txt (from rev 82141, z3c.pt/trunk/z3c/pt/translation.txt)
===================================================================
--- z3c.pt/tags/0.2/z3c/pt/translation.txt (rev 0)
+++ z3c.pt/tags/0.2/z3c/pt/translation.txt 2007-12-05 16:25:23 UTC (rev 82142)
@@ -0,0 +1,45 @@
+Translation
+-----------
+
+ >>> from z3c.pt.translation import translate
+
+Example:
+
+ >>> body = """\
+ ... <div xmlns="http://www.w3.org/1999/xhtml"
+ ... xmlns:tal="http://xml.zope.org/namespaces/tal">
+ ... <span tal:define="a 'abc'"
+ ... tal:attributes="class 'def' + a"
+ ... tal:content="a + 'ghi'" />
+ ... <ul>
+ ... <li tal:repeat="i range(5)">
+ ... <span tal:replace="'Item ' + str(i) + ')'" />
+ ... </li>
+ ... </ul>
+ ... </div>
+ ... """
+
+ >>> source, _globals = translate(body)
+ >>> _locals = {}
+ >>> exec source in _globals, _locals
+ >>> print _locals['render']()
+ <div>
+ <span class="defabc">abcghi</span>
+ <ul>
+ <li>
+ Item 0)
+ </li>
+ <li>
+ Item 1)
+ </li>
+ <li>
+ Item 2)
+ </li>
+ <li>
+ Item 3)
+ </li>
+ <li>
+ Item 4)
+ </li>
+ </ul>
+ </div>
More information about the Checkins
mailing list