Commits

Anonymous committed d0345c6

Text templates now default to rendering as plain text; it is no longer necessary to explicitly specify the "text" method to the `render()` or `serialize()` method of the generated markup stream. See tickets #62 and #118.

  • Participants
  • Parent commits 416e462
  • Branches trunk

Comments (0)

Files changed (10)

    which can speed up match templates in many cases, for example when a match
    template should only be applied once to a stream, or when it should not be
    applied recursively.
+ * Text templates now default to rendering as plain text; it is no longer
+   necessary to explicitly specify the "text" method to the `render()` or
+   `serialize()` method of the generated markup stream.
 
 
 Version 0.4.4

doc/templates.txt

   >>> from genshi.template import TextTemplate
   >>> tmpl = TextTemplate('Hello, $name!')
   >>> stream = tmpl.generate(name='world')
-  >>> print stream.render('text')
+  >>> print stream
   Hello, world!
 
 .. note:: If you want to use text templates, you should consider using the
     returns the complete generated text at once. Both accept various parameters
     that impact the way the stream is serialized.
     """
-    __slots__ = ['events']
+    __slots__ = ['events', 'serializer']
 
     START = StreamEventKind('START') #: a start tag
     END = StreamEventKind('END') #: an end tag
     PI = StreamEventKind('PI') #: processing instruction
     COMMENT = StreamEventKind('COMMENT') #: comment
 
-    def __init__(self, events):
+    def __init__(self, events, serializer=None):
         """Initialize the stream with a sequence of markup events.
         
         :param events: a sequence or iterable providing the events
+        :param serializer: the default serialization method to use for this
+                           stream
+
+        :note: Changed in 0.5: added the `serializer` argument
         """
         self.events = events #: The underlying iterable producing the events
+        self.serializer = serializer #: The default serializion method
 
     def __iter__(self):
         return iter(self.events)
         :return: the filtered stream
         :rtype: `Stream`
         """
-        return Stream(_ensure(function(self)))
+        return Stream(_ensure(function(self)), serializer=self.serializer)
 
     def filter(self, *filters):
         """Apply filters to the stream.
         """
         return reduce(operator.or_, (self,) + filters)
 
-    def render(self, method='xml', encoding='utf-8', **kwargs):
+    def render(self, method=None, encoding='utf-8', **kwargs):
         """Return a string representation of the stream.
         
         Any additional keyword arguments are passed to the serializer, and thus
         
         :param method: determines how the stream is serialized; can be either
                        "xml", "xhtml", "html", "text", or a custom serializer
-                       class
+                       class; if `None`, the default serialization method of
+                       the stream is used
         :param encoding: how the output string should be encoded; if set to
                          `None`, this method returns a `unicode` object
         :return: a `str` or `unicode` object
         :see: XMLSerializer, XHTMLSerializer, HTMLSerializer, TextSerializer
         """
         from genshi.output import encode
+        if method is None:
+            method = self.serializer or 'xml'
         generator = self.serialize(method=method, **kwargs)
         return encode(generator, method=method, encoding=encoding)
 
         
         :param method: determines how the stream is serialized; can be either
                        "xml", "xhtml", "html", "text", or a custom serializer
-                       class
+                       class; if `None`, the default serialization method of
+                       the stream is used
         :return: an iterator over the serialization results (`Markup` or
                  `unicode` objects, depending on the serialization method)
         :rtype: ``iterator``
         :see: XMLSerializer, XHTMLSerializer, HTMLSerializer, TextSerializer
         """
         from genshi.output import get_serializer
+        if method is None:
+            method = self.serializer or 'xml'
         return get_serializer(method, **kwargs)(_ensure(self))
 
     def __str__(self):

genshi/filters/transform.py

         transforms = self._mark(stream)
         for link in self.transforms:
             transforms = link(transforms)
-        return Stream(self._unmark(transforms))
+        return Stream(self._unmark(transforms),
+                      serializer=getattr(stream, 'serializer', None))
 
     def apply(self, function):
         """Apply a transformation to the stream.
                                  updateonly=True)
                 elif result:
                     yield result
-        return Stream(_generate())
+        return Stream(_generate(),
+                      serializer=getattr(stream, 'serializer', None))
 
     def test(self, ignore_context=False):
         """Returns a function that can be used to track whether the path matches

genshi/template/base.py

     directives should be applied.
     """
 
+    serializer = None
+
     def __init__(self, source, basedir=None, filename=None, loader=None,
                  encoding=None, lookup='lenient', allow_exec=True):
         """Initialize a template from either a string, a file-like object, or
         stream = self.stream
         for filter_ in self.filters:
             stream = filter_(iter(stream), ctxt)
-        return Stream(stream)
+        return Stream(stream, self.serializer)
 
     def _eval(self, stream, ctxt):
         """Internal stream filter that evaluates any expressions in `START` and

genshi/template/markup.py

                   ('content', ContentDirective),
                   ('attrs', AttrsDirective),
                   ('strip', StripDirective)]
+    serializer = 'xml'
 
     def __init__(self, source, basedir=None, filename=None, loader=None,
                  encoding=None, lookup='lenient', allow_exec=True):

genshi/template/tests/directives.py

         """)
         self.assertEqual("""
                       Hi, you!
+
         """, str(tmpl.generate()))
 
     def test_function_with_star_args(self):

genshi/template/tests/text.py

           * 0
           * 1
           * 2
-""", tmpl.generate(items=range(3)).render('text'))
+""", tmpl.generate(items=range(3)).render())
 
     def test_empty_lines2(self):
         tmpl = OldTextTemplate("""Your items:
 
           * 2
 
-""", tmpl.generate(items=range(3)).render('text'))
+""", tmpl.generate(items=range(3)).render())
 
     def test_include(self):
         file1 = open(os.path.join(self.dirname, 'tmpl1.txt'), 'w')
   * 0
   * 1
   * 2
-""", tmpl.generate(items=range(3)).render('text'))
+""", tmpl.generate(items=range(3)).render())
 
     def test_empty_lines2(self):
         tmpl = NewTextTemplate("""Your items:
 
   * 2
 
-""", tmpl.generate(items=range(3)).render('text'))
+""", tmpl.generate(items=range(3)).render())
 
     def test_include(self):
         file1 = open(os.path.join(self.dirname, 'tmpl1.txt'), 'w')
         try:
-            file1.write("Included\n")
+            file1.write("Included")
         finally:
             file1.close()
 

genshi/template/text.py

     ...  * ${'Item %d' % item}
     ... {% end %}
     ... ''')
-    >>> print tmpl.generate(name='Joe', items=[1, 2, 3]).render('text')
+    >>> print tmpl.generate(name='Joe', items=[1, 2, 3]).render()
     Dear Joe,
     <BLANKLINE>
     <BLANKLINE>
     ...  * $item
     ... {% end %}\
     ... ''')
-    >>> print tmpl.generate(name='Joe', items=[1, 2, 3]).render('text')
+    >>> print tmpl.generate(name='Joe', items=[1, 2, 3]).render()
     Dear Joe,
     <BLANKLINE>
     We have the following items for you:
     ...  * $item
     ... {% end %}\
     ... ''')
-    >>> print tmpl.generate(name='Joe', items=[1, 2, 3]).render('text')
+    >>> print tmpl.generate(name='Joe', items=[1, 2, 3]).render()
     Dear Joe,
     <BLANKLINE>
     {# This is a comment #}
                   ('if', IfDirective),
                   ('choose', ChooseDirective),
                   ('with', WithDirective)]
+    serializer = 'text'
 
     _DIRECTIVE_RE = r'((?<!\\)%s\s*(\w+)\s*(.*?)\s*%s|(?<!\\)%s.*?%s)'
     _ESCAPE_RE = r'\\\n|\\(\\)|\\(%s)|\\(%s)'
     ... 
     ... All the best,
     ... Foobar''')
-    >>> print tmpl.generate(name='Joe', items=[1, 2, 3]).render('text')
+    >>> print tmpl.generate(name='Joe', items=[1, 2, 3]).render()
     Dear Joe,
     <BLANKLINE>
     We have the following items for you:
                   ('if', IfDirective),
                   ('choose', ChooseDirective),
                   ('with', WithDirective)]
+    serializer = 'text'
 
     _DIRECTIVE_RE = re.compile(r'(?:^[ \t]*(?<!\\)#(end).*\n?)|'
                                r'(?:^[ \t]*(?<!\\)#((?:\w+|#).*)\n?)',