[Checkins] SVN: z3c.pt/trunk/src/z3c/pt/ Split out translation node from element class.

Malthe Borch mborch at gmail.com
Thu Aug 21 10:36:08 EDT 2008


Log message for revision 90069:
  Split out translation node from element class.

Changed:
  U   z3c.pt/trunk/src/z3c/pt/clauses.py
  U   z3c.pt/trunk/src/z3c/pt/etree.py
  U   z3c.pt/trunk/src/z3c/pt/genshi.py
  U   z3c.pt/trunk/src/z3c/pt/testing.py
  U   z3c.pt/trunk/src/z3c/pt/translation.py
  U   z3c.pt/trunk/src/z3c/pt/zpt.py

-=-
Modified: z3c.pt/trunk/src/z3c/pt/clauses.py
===================================================================
--- z3c.pt/trunk/src/z3c/pt/clauses.py	2008-08-21 14:32:56 UTC (rev 90068)
+++ z3c.pt/trunk/src/z3c/pt/clauses.py	2008-08-21 14:36:08 UTC (rev 90069)
@@ -424,11 +424,11 @@
         pass
 
 class Visit(object):
-    def __init__(self, element):
-        self.element = element
+    def __init__(self, node):
+        self.node = node
         
     def begin(self, stream):
-        self.element.visit(skip_macro=False)
+        self.node.visit(skip_macro=False)
 
     def end(self, stream):
         pass

Modified: z3c.pt/trunk/src/z3c/pt/etree.py
===================================================================
--- z3c.pt/trunk/src/z3c/pt/etree.py	2008-08-21 14:32:56 UTC (rev 90068)
+++ z3c.pt/trunk/src/z3c/pt/etree.py	2008-08-21 14:36:08 UTC (rev 90069)
@@ -198,7 +198,11 @@
         def getroottree(self):
             while self._parent is not None:
                 self = self._parent
-            return self
+            class roottree(object):
+                @classmethod
+                def getroot(cls):
+                    return self
+            return roottree
             
         def insert(self, position, element):
             element._parent = self

Modified: z3c.pt/trunk/src/z3c/pt/genshi.py
===================================================================
--- z3c.pt/trunk/src/z3c/pt/genshi.py	2008-08-21 14:32:56 UTC (rev 90068)
+++ z3c.pt/trunk/src/z3c/pt/genshi.py	2008-08-21 14:36:08 UTC (rev 90069)
@@ -12,10 +12,7 @@
 
     translator = expressions.PythonTranslation
     
-    class node(object):
-        def __init__(self, element):
-            self.element = element
-            
+    class node(translation.Node):
         @property
         def omit(self):
             if self.element.py_strip is not None:
@@ -62,6 +59,7 @@
                 self.element, config.XHTML_NS)
 
         translate = None
+        translation_name = None
         translation_domain = None
 
         @property
@@ -162,6 +160,14 @@
         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."""
 

Modified: z3c.pt/trunk/src/z3c/pt/testing.py
===================================================================
--- z3c.pt/trunk/src/z3c/pt/testing.py	2008-08-21 14:32:56 UTC (rev 90068)
+++ z3c.pt/trunk/src/z3c/pt/testing.py	2008-08-21 14:36:08 UTC (rev 90069)
@@ -15,7 +15,7 @@
     return expressions.PythonTranslation.expression(string)
 
 def setup_stream():
-    class symbols(translation.Element.symbols):
+    class symbols(translation.Node.symbols):
         out = '_out'
         write = '_write'
 
@@ -74,10 +74,7 @@
     def update(self):
         translation.VariableInterpolation.update(self)
         
-    class node(object):
-        def __init__(self, element):
-            self.element = element
-
+    class node(translation.Node):
         def __getattr__(self, name):
             return None
 

Modified: z3c.pt/trunk/src/z3c/pt/translation.py
===================================================================
--- z3c.pt/trunk/src/z3c/pt/translation.py	2008-08-21 14:32:56 UTC (rev 90068)
+++ z3c.pt/trunk/src/z3c/pt/translation.py	2008-08-21 14:36:08 UTC (rev 90069)
@@ -12,78 +12,71 @@
 import config
 import etree
 
-class Element(etree.ElementBase):
-    """Base compiler element class.
+class Node(object):
+    """Element translation class.
 
-    This class represents an element in the template document tree. To
-    start compilation at this node, use the ``start`` method,
-    providing a code stream object.
+    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
+    
+    def __init__(self, element):
+        self.element = element
 
-    def start(self, stream):
-        self._stream = stream
-        self.visit()
-
+    @property
+    def stream(self):
+        return self.element.stream
+    
     def update(self):
-        pass
+        self.element.update()
     
     def begin(self):
         self.stream.scope.append(set())
-        self.stream.begin(self._serialize())
+        self.stream.begin(self.serialize())
         
     def end(self):
-        self.stream.end(self._serialize())
+        self.stream.end(self.serialize())
         self.stream.scope.pop()
 
     def body(self):
-        if not self.node.skip:
-            for element in self:
-                element.update()
+        if not self.skip:
+            for element in self.element:
+                element.node.update()
 
-            for element in self:
-                element.visit()
+            for element in self.element:
+                element.node.visit()
                     
     def visit(self, skip_macro=True):
         assert self.stream is not None, "Must use ``start`` method."
 
-        if skip_macro and (self.node.method or self.node.define_macro):
+        if skip_macro and (self.method or self.define_macro):
             return
 
-        for element in self:
+        for element in self.element:
             if not isinstance(element, Element):
-                self._wrap_literal(element)
+                self.wrap_literal(element)
 
         self.update()
         self.begin()
         self.body()
         self.end()
 
-    @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.")
-        
-                    
-    def _serialize(self):
+    def serialize(self):
         """Serialize element into clause-statements."""
 
         _ = []
 
         # i18n domain
-        if self.node.translation_domain is not None:
+        if self.translation_domain is not None:
             _.append(clauses.Define(
-                self.symbols.domain, types.value(repr(self.node.translation_domain))))
+                self.symbols.domain, types.value(repr(self.translation_domain))))
 
         # variable definitions
-        if self.node.define is not None:
-            for declaration, expression in self.node.define:
+        if self.define is not None:
+            for declaration, expression in self.define:
                 if declaration.global_scope:
                     _.append(clauses.Define(
                         declaration, expression, self.symbols.scope))
@@ -91,7 +84,7 @@
                     _.append(clauses.Define(declaration, expression))
 
         # macro method
-        for element in tuple(self):
+        for element in tuple(self.element):
             if not isinstance(element, Element):
                 continue
 
@@ -101,7 +94,7 @@
                 subclauses = []
                 subclauses.append(clauses.Method(
                     self.symbols.macro, macro.args))
-                subclauses.append(clauses.Visit(element))
+                subclauses.append(clauses.Visit(element.node))
                 _.append(clauses.Group(subclauses))
                 
                 # assign to variable
@@ -109,42 +102,42 @@
                     macro.name, types.parts((types.value(self.symbols.macro),))))
 
         # tag tail (deferred)
-        tail = self.tail
-        if tail and not self.node.fill_slot:
+        tail = self.element.tail
+        if tail and not self.fill_slot:
             if isinstance(tail, unicode):
                 tail = tail.encode('utf-8')
             _.append(clauses.Out(tail, defer=True))
 
         # condition
-        if self.node.condition is not None:
-            _.append(clauses.Condition(self.node.condition))
+        if self.condition is not None:
+            _.append(clauses.Condition(self.condition))
 
         # repeat
-        if self.node.repeat is not None:
-            variables, expression = self.node.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.node.content
+        content = self.content
 
         # macro slot definition
-        if self.node.define_slot:
+        if self.define_slot:
             # check if slot has been filled
-            variable = self.symbols.slot + self.node.define_slot
+            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.node.translate is not None
+        dynamic = content or self.translate is not None
 
         # static attributes are at the bottom of the food chain
-        attributes = self.node.static_attributes
+        attributes = self.static_attributes
 
         # dynamic attributes
-        attrs = self.node.dynamic_attributes or ()
+        attrs = self.dynamic_attributes or ()
         dynamic_attributes = tuple(attrs)
 
         for variables, expression in attrs:
@@ -156,7 +149,7 @@
             attributes[variable] = expression
 
         # translated attributes
-        translated_attributes = self.node.translated_attributes or ()
+        translated_attributes = self.translated_attributes or ()
         for variable, msgid in translated_attributes:
             if msgid:
                 if variable in dynamic_attributes:
@@ -183,20 +176,20 @@
             attributes[variable] = expression
 
         # tag
-        if self.node.omit is not True:
-            selfclosing = self.text is None and not dynamic and len(self) == 0
+        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.tag, attributes,
-                expression=self.node.dict_attributes, selfclosing=selfclosing,
-                cdata=self.node.cdata is not None)
-            if self.node.omit:
+                self.element.tag, attributes,
+                expression=self.dict_attributes, selfclosing=selfclosing,
+                cdata=self.cdata is not None)
+            if self.omit:
                 _.append(clauses.Condition(
-                    _not(self.node.omit), [tag], finalize=False))
+                    _not(self.omit), [tag], finalize=False))
             else:
                 _.append(tag)
 
         # tag text (if we're not replacing tag body)
-        text = self.text
         if text and not dynamic:
             if isinstance(text, unicode):
                 text = text.encode('utf-8')
@@ -204,7 +197,7 @@
 
         # dynamic content
         if content:
-            msgid = self.node.translate
+            msgid = self.translate
             if msgid is not None:
                 if msgid:
                     raise ValueError(
@@ -214,11 +207,11 @@
             _.append(clauses.Write(content))
 
         # use macro
-        elif self.node.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.xpath(
+            for element in self.element.xpath(
                 './/*[@metal:fill-slot]', namespaces={'metal': config.METAL_NS}):
                 variable = self.symbols.slot+element.node.fill_slot
                 kwargs.append((variable, variable))
@@ -227,12 +220,12 @@
                 subclauses.append(clauses.Define(
                     types.declaration((self.symbols.out, self.symbols.write)),
                     types.template('%(generation)s.initialize_stream()')))
-                subclauses.append(clauses.Visit(element))
+                subclauses.append(clauses.Visit(element.node))
                 subclauses.append(clauses.Assign(
                     types.template('%(out)s.getvalue()'), variable))
                 _.append(clauses.Group(subclauses))
                 
-            _.append(clauses.Assign(self.node.use_macro, self.symbols.metal))
+            _.append(clauses.Assign(self.use_macro, self.symbols.metal))
 
             # compute macro function arguments and create argument string
             arguments = ", ".join(
@@ -244,14 +237,14 @@
                 types.value("%s(%s)" % (self.symbols.metal, arguments))))
 
         # translate body
-        elif self.node.translate is not None:
-            msgid = self.node.translate
+        elif self.translate is not None:
+            msgid = self.translate
             if not msgid:
-                msgid = self._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 if e.i18n_name]
+            elements = [e for e in self.element if e.node.translation_name]
 
             if elements:
                 mapping = self.symbols.mapping
@@ -260,13 +253,13 @@
                 mapping = 'None'
 
             for element in elements:
-                name = element.i18n_name
+                name = element.node.translation_name
 
                 subclauses = []
                 subclauses.append(clauses.Define(
                     types.declaration((self.symbols.out, self.symbols.write)),
                     types.template('%(generation)s.initialize_stream()')))
-                subclauses.append(clauses.Visit(element))
+                subclauses.append(clauses.Visit(element.node))
                 subclauses.append(clauses.Assign(
                     types.template('%(out)s.getvalue()'),
                     "%s['%s']" % (mapping, name)))
@@ -285,10 +278,10 @@
                         [clauses.UnicodeWrite(result)]))
 
             subclauses = []
-            if self.text:
-                subclauses.append(clauses.Out(self.text.encode('utf-8')))
-            for element in self:
-                name = element.i18n_name
+            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))
@@ -299,25 +292,25 @@
 
         return _
 
-    def _wrap_literal(self, element):
-        index = self.index(element)
+    def wrap_literal(self, element):
+        index = self.element.index(element)
 
-        t = self.makeelement(utils.meta_attr('literal'))
+        t = self.element.makeelement(utils.meta_attr('literal'))
         t.attrib[utils.meta_attr('omit-tag')] = ''
         t.tail = element.tail
         t.text = unicode(element)
         for child in element.getchildren():
             t.append(child)
-        self.remove(element)
-        self.insert(index, t)
+        self.element.remove(element)
+        self.element.insert(index, t)
         t.update()
 
-    def _msgid(self):
+    def create_msgid(self):
         """Create an i18n msgid from the tag contents."""
 
-        out = StringIO(self.text)
-        for element in self:
-            name = element.i18n_name
+        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)
@@ -329,17 +322,29 @@
         
         return msgid
 
-    def _pull_attribute(self, name, default=None):
-        if name in self.attrib:
-            value = self.attrib[name]
-            del self.attrib[name]
-            return value
-        return default
+class Element(etree.ElementBase):
+    """Template element class.
+
+    To start translation at this element, use the ``start`` method,
+    providing a code stream object.
+    """
+
+    node = property(Node)
     
+    def start(self, stream):
+        self._stream = stream
+        self.node.visit()
+
     @property
-    def node(self):
-        return NotImplementedError("Must be provided by subclass.")
+    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'))
     
@@ -444,7 +449,7 @@
 
     # initialize code stream object
     stream = generation.CodeIO(
-        root.symbols, indentation=1, indentation_string="\t")
+        root.node.symbols, indentation=1, indentation_string="\t")
 
     # initialize variable scope
     stream.scope.append(set(

Modified: z3c.pt/trunk/src/z3c/pt/zpt.py
===================================================================
--- z3c.pt/trunk/src/z3c/pt/zpt.py	2008-08-21 14:32:56 UTC (rev 90068)
+++ z3c.pt/trunk/src/z3c/pt/zpt.py	2008-08-21 14:36:08 UTC (rev 90069)
@@ -13,10 +13,7 @@
     Implements the ZPT subset of the attribute template language.
     """
 
-    class node(object):
-        def __init__(self, element):
-            self.element = element
-            
+    class node(translation.Node):
         @property
         def omit(self):
             if self.element.tal_omit is not None:
@@ -71,6 +68,10 @@
             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
 



More information about the Checkins mailing list