[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