Edgewall Software

Changeset 726


Ignore:
Timestamp:
Aug 28, 2007, 1:20:47 AM (16 years ago)
Author:
cmlenz
Message:
  • XInclude elements in markup templates now support the parse attribute; when set to "xml" (the default), the include is processed as before, but when set to "text", the included template is parsed as a text template using the new syntax (ticket #101).
  • If an include is found when parsing a template, but no template loader has been specified, a TemplateSyntaxError is raised.
Location:
trunk
Files:
7 edited

Legend:

Unmodified
Added
Removed
  • trunk/ChangeLog

    r725 r726  
    3030   necessary to explicitly specify the "text" method to the `render()` or
    3131   `serialize()` method of the generated markup stream.
     32 * XInclude elements in markup templates now support the `parse` attribute; when
     33   set to "xml" (the default), the include is processed as before, but when set
     34   to "text", the included template is parsed as a text template using the new
     35   syntax (ticket #101).
     36 * If an include is found when parsing a template, but no template loader has
     37   been specified, a `TemplateSyntaxError` is raised.
    3238
    3339
  • trunk/doc/xml-templates.txt

    r718 r726  
    602602.. _`xinclude specification`: http://www.w3.org/TR/xinclude/
    603603
     604
     605Dynamic Includes
     606================
     607
    604608Incudes in Genshi are fully dynamic: Just like normal attributes, the `href`
    605609attribute accepts expressions, and directives_ can be used on the
     
    613617
    614618
     619Including Text Templates
     620========================
     621
     622The ``parse`` attribute of the ``<xi:include>`` element can be used to specify
     623whether the included template is an XML template or a text template (using the
     624new syntax added in Genshi 0.5):
     625
     626.. code-block:: genshi
     627
     628  <xi:include href="myscript.js" parse="text" />
     629
     630This example would load the ``myscript.js`` file as a ``NewTextTemplate``. See
     631`text templates`_ for details on the syntax of text templates.
     632
     633.. _`text templates`: text-templates.html
     634
     635
    615636.. _comments:
    616637
  • trunk/genshi/template/base.py

    r725 r726  
    4040    """Base exception class for errors related to template processing."""
    4141
    42     def __init__(self, message, filename='<string>', lineno=-1, offset=-1):
     42    def __init__(self, message, filename=None, lineno=-1, offset=-1):
    4343        """Create the exception.
    4444       
     
    4949        :param offset: the column number at which the error occurred
    5050        """
     51        if filename is None:
     52            filename = '<string>'
    5153        self.msg = message #: the error message string
    5254        if filename != '<string>' or lineno >= 0:
     
    6365    """
    6466
    65     def __init__(self, message, filename='<string>', lineno=-1, offset=-1):
     67    def __init__(self, message, filename=None, lineno=-1, offset=-1):
    6668        """Create the exception
    6769       
     
    8587    """
    8688
    87     def __init__(self, name, filename='<string>', lineno=-1):
     89    def __init__(self, name, filename=None, lineno=-1):
    8890        """Create the exception
    8991       
     
    334336        self.allow_exec = allow_exec
    335337
     338        self.filters = [self._flatten, self._eval, self._exec]
     339        if loader:
     340            self.filters.append(self._include)
     341
    336342        if isinstance(source, basestring):
    337343            source = StringIO(source)
     
    342348        except ParseError, e:
    343349            raise TemplateSyntaxError(e.msg, self.filepath, e.lineno, e.offset)
    344         self.filters = [self._flatten, self._eval, self._exec]
    345         if loader:
    346             self.filters.append(self._include)
    347350
    348351    def __repr__(self):
     
    387390            else:
    388391                if kind is INCLUDE:
    389                     href, fallback = data
     392                    href, cls, fallback = data
    390393                    if isinstance(href, basestring) and \
    391394                            not getattr(self.loader, 'auto_reload', True):
     
    395398                        try:
    396399                            tmpl = self.loader.load(href, relative_to=pos[0],
    397                                                     cls=self.__class__)
     400                                                    cls=cls or self.__class__)
    398401                            for event in tmpl.stream:
    399402                                yield event
     
    514517        for event in stream:
    515518            if event[0] is INCLUDE:
    516                 href, fallback = event[1]
     519                href, cls, fallback = event[1]
    517520                if not isinstance(href, basestring):
    518521                    parts = []
     
    523526                try:
    524527                    tmpl = self.loader.load(href, relative_to=event[2][0],
    525                                             cls=self.__class__)
     528                                            cls=cls or self.__class__)
    526529                    for event in tmpl.generate(ctxt):
    527530                        yield event
  • trunk/genshi/template/markup.py

    r725 r726  
    2525from genshi.template.interpolation import interpolate
    2626from genshi.template.directives import *
     27from genshi.template.text import NewTextTemplate
    2728
    2829__all__ = ['MarkupTemplate']
     
    142143
    143144                if tag in self.XINCLUDE_NAMESPACE:
     145                    if self._include not in self.filters:
     146                        raise TemplateSyntaxError('Include found but no '
     147                                                  'template loader specified',
     148                                                  self.filepath, *pos[1:])
    144149                    if tag.localname == 'include':
    145150                        include_href = new_attrs.get('href')
     
    148153                                                      'attribute "href"',
    149154                                                      self.filepath, *pos[1:])
    150                         includes.append(include_href)
     155                        includes.append((include_href, new_attrs.get('parse')))
    151156                        streams.append([])
    152157                    elif tag.localname == 'fallback':
     
    171176                                  # and the fallback element
    172177                    stream = streams[-1]
    173                     stream.append((INCLUDE, (includes.pop(), fallback), pos))
     178                    href, parse = includes.pop()
     179                    try:
     180                        cls = {
     181                            'xml': MarkupTemplate,
     182                            'text': NewTextTemplate
     183                        }[parse or 'xml']
     184                    except KeyError:
     185                        raise TemplateSyntaxError('Invalid value for "parse" '
     186                                                  'attribute of include',
     187                                                  self.filepath, *pos[1:])
     188                    stream.append((INCLUDE, (href, cls, fallback), pos))
    174189                else:
    175190                    stream.append((kind, data, pos))
  • trunk/genshi/template/tests/markup.py

    r704 r726  
    245245        </Test>""", str(tmpl.generate()))
    246246
     247    def test_include_without_loader(self):
     248        xml = """<html xmlns:xi="http://www.w3.org/2001/XInclude">
     249          <xi:include href="oops.html" />
     250        </html>"""
     251        self.assertRaises(TemplateSyntaxError, MarkupTemplate, xml)
     252
    247253    def test_include_in_loop(self):
    248254        dirname = tempfile.mkdtemp(suffix='genshi_test')
  • trunk/genshi/template/tests/text.py

    r725 r726  
    1818import unittest
    1919
     20from genshi.template.base import TemplateSyntaxError
    2021from genshi.template.loader import TemplateLoader
    2122from genshi.template.text import OldTextTemplate, NewTextTemplate
     
    111112            ----- Included data above this line -----""",
    112113                         tmpl.generate().render())
     114
     115    def test_include_without_loader(self):
     116        text = '#include "oops.html"'
     117        self.assertRaises(TemplateSyntaxError, OldTextTemplate, text)
    113118
    114119
     
    232237----- Included data above this line -----""", tmpl.generate().render())
    233238
     239    def test_include_without_loader(self):
     240        text = '{% include "oops.html" %}'
     241        self.assertRaises(TemplateSyntaxError, NewTextTemplate, text)
     242
    234243
    235244def suite():
  • trunk/genshi/template/text.py

    r725 r726  
    2929import re
    3030
    31 from genshi.template.base import BadDirectiveError, Template, EXEC, INCLUDE, SUB
     31from genshi.template.base import BadDirectiveError, Template, \
     32                                 TemplateSyntaxError, EXEC, INCLUDE, SUB
    3233from genshi.template.eval import Suite
    3334from genshi.template.directives import *
     
    187188
    188189            if command == 'include':
     190                if self._include not in self.filters:
     191                    raise TemplateSyntaxError('Include found but no template '
     192                                              'loader specified', self.filepath,
     193                                              lineno)
    189194                pos = (self.filename, lineno, 0)
    190                 stream.append((INCLUDE, (value.strip(), []), pos))
     195                stream.append((INCLUDE, (value.strip(), None, []), pos))
    191196
    192197            elif command == 'python':
     
    307312                                              (self.filepath, lineno, 0))]
    308313            elif command == 'include':
     314                if self._include not in self.filters:
     315                    raise TemplateSyntaxError('Include found but no template '
     316                                              'loader specified', self.filepath,
     317                                              lineno)
    309318                pos = (self.filename, lineno, 0)
    310                 stream.append((INCLUDE, (value.strip(), []), pos))
     319                stream.append((INCLUDE, (value.strip(), None, []), pos))
    311320            elif command != '#':
    312321                cls = self._dir_by_name.get(command)
Note: See TracChangeset for help on using the changeset viewer.