changeset 334:2fdf34945dfd experimental-compiler

got a few more unit tests working. need to figure out path.select() better
author zzzeek
date Wed, 08 Nov 2006 00:55:13 +0000
parents d8fc236ca3d8
children 6cc2eabf73b8
files genshi/codegen/adapters.py genshi/codegen/generator.py genshi/codegen/interp.py genshi/codegen/output.py genshi/codegen/tests/template.py
diffstat 5 files changed, 46 insertions(+), 7 deletions(-) [+]
line wrap: on
line diff
--- a/genshi/codegen/adapters.py
+++ b/genshi/codegen/adapters.py
@@ -63,7 +63,10 @@
 class InlineQName(unicode):
     """creates a QName-like object from a START event"""
     def __new__(cls, event):
-        self = unicode.__new__(cls, u'{%s}%s' % (event[1][0], event[1][1]))
+        if event[1][0] is not None:
+            self = unicode.__new__(cls, u'{%s}%s' % (event[1][0], event[1][1]))
+        else:
+            self = unicode.__new__(cls, u'%s' % (event[1][1]))
         self.namespace = event[1][0]
         self.localname = event[1][1]
         return self
--- a/genshi/codegen/generator.py
+++ b/genshi/codegen/generator.py
@@ -112,7 +112,7 @@
 class Generator(object):
     """given a Template, generates Python modules (as strings or code objects)
     optimized to a particular Serializer."""
-    def __init__(self, template, method='html', serializer=None, strip_whitespace=False, filters=None):
+    def __init__(self, template, method='html', serializer=None, strip_whitespace=False, compress_empty=False, filters=None):
         self.template = template
         self.serializer = serializer or ({
                 'xml':   serialize.XMLSerializeFilter,
@@ -122,6 +122,8 @@
                
         self.code = self._generate_module()
         self.filters = filters or []
+        if compress_empty:
+            self.filters.append(output.EmptyTagFilter())
         if strip_whitespace:
             self.filters.append(output.PostWhitespaceFilter())
     def generate(self, *args, **kwargs):
@@ -164,7 +166,8 @@
             expr = parse(expr, "eval")
         visitor.walk(expr, self)
     def visitName(self, node, *args, **kwargs):
-        self.identifiers.add(node.name)
+        if node.name not in __builtins__:
+            self.identifiers.add(node.name)
 
 class PythonGenerator(object):
     def __init__(self, stream, serializer):
--- a/genshi/codegen/interp.py
+++ b/genshi/codegen/interp.py
@@ -56,7 +56,7 @@
                 #for filter_ in self.filters[3:]:
                 #    content = filter_(content, ctxt)
                 content = list(content)
-                
+
                 for test in [mt[0] for mt in match_templates]:
                     test(tail[0][0:3], namespaces, ctxt, updateonly=True)
 
@@ -70,12 +70,24 @@
         else:
             yield event
 
+# TODO: this adds too much overhead
+def _ensure(stream):
+    """Ensure that every item on the stream is actually an inline event."""
+    for event in stream:
+        if type(event) is not tuple:
+            if hasattr(event, 'totuple'):
+                event = event.totuple()
+            else:
+                event = TEXT, unicode(event), (None, -1, -1), unicode(event)
+        yield event
+
 def evaluate(result, pos):
     if result is not None:
         if isinstance(result, basestring):
             yield TEXT, result, pos, result
         elif hasattr(result, '__iter__'):
-            for event in result:
+            substream = _ensure(result)
+            for event in substream:
                 yield event
         else:
             yield TEXT, unicode(result), pos, result
--- a/genshi/codegen/output.py
+++ b/genshi/codegen/output.py
@@ -12,6 +12,27 @@
                         END_CDATA, PI, COMMENT, XML_NAMESPACE
 
 
+class EmptyTagFilter(object):
+    """Combines `START` and `STOP` events into `EMPTY` events for elements that
+    have no contents.
+    """
+    EMPTY = StreamEventKind('EMPTY')
+
+    def __call__(self, stream):
+        prev = (None, None, None, None)
+        for kind, data, pos, literal in stream:
+            if prev[0] is START:
+                if kind is END:
+                    prev = EMPTY, prev[1], prev[2], prev[3][:-1] + '/>'
+                    yield prev
+                    continue
+                else:
+                    yield prev
+            if kind is not START:
+                yield kind, data, pos, literal
+            prev = kind, data, pos, literal
+EMPTY = EmptyTagFilter.EMPTY
+
 class PostWhitespaceFilter(object):
     """A filter that removes extraneous ignorable white space from the
     stream."""
--- a/genshi/codegen/tests/template.py
+++ b/genshi/codegen/tests/template.py
@@ -12,8 +12,8 @@
 
 class MarkupTemplateAdapter(object):
     def __init__(self, text):
-        self.generator = Generator(RealMarkupTemplate(text), strip_whitespace=True)
-        print u''.join(self.generator._generate_code_events())
+        self.generator = Generator(RealMarkupTemplate(text), strip_whitespace=True, compress_empty=True)
+        #print u''.join(self.generator._generate_code_events())
     def generate(self, *args, **kwargs):
         return self.generator.generate(*args, **kwargs)
 
Copyright (C) 2012-2017 Edgewall Software