Ticket #115: textinclude.diff
| File textinclude.diff, 8.9 KB (added by cmlenz, 16 years ago) |
|---|
-
genshi/template/base.py
279 279 EXPR = StreamEventKind('EXPR') 280 280 """Stream event kind representing a Python expression.""" 281 281 282 INCLUDE = StreamEventKind('INCLUDE') 283 """Stream event kind representing the inclusion of another template.""" 284 282 285 SUB = StreamEventKind('SUB') 283 286 """Stream event kind representing a nested stream to which one or more 284 287 directives should be applied. … … 320 323 except ParseError, e: 321 324 raise TemplateSyntaxError(e.msg, self.filepath, e.lineno, e.offset) 322 325 self.filters = [self._flatten, self._eval] 326 if loader: 327 self.filters.append(self._include) 323 328 324 329 def __repr__(self): 325 330 return '<%s "%s">' % (self.__class__.__name__, self.filename) … … 359 364 for event in substream: 360 365 yield event 361 366 else: 367 if kind is INCLUDE: 368 data = data[0], list(self._prepare(data[1])) 362 369 yield kind, data, pos 363 370 364 371 def generate(self, *args, **kwargs): … … 449 456 else: 450 457 yield event 451 458 459 def _include(self, stream, ctxt): 460 """Internal stream filter that performs inclusion of external 461 template files. 462 """ 463 from genshi.template.loader import TemplateNotFound 452 464 465 for event in stream: 466 if event[0] is INCLUDE: 467 href, fallback = event[1] 468 if not isinstance(href, basestring): 469 parts = [] 470 for subkind, subdata, subpos in self._eval(href, ctxt): 471 if subkind is TEXT: 472 parts.append(subdata) 473 href = u''.join([x for x in parts if x is not None]) 474 try: 475 tmpl = self.loader.load(href, relative_to=event[2][0], 476 cls=self.__class__) 477 for event in tmpl.generate(ctxt): 478 yield event 479 except TemplateNotFound: 480 if fallback is None: 481 raise 482 for filter_ in self.filters: 483 fallback = filter_(iter(fallback), ctxt) 484 for event in fallback: 485 yield event 486 else: 487 yield event 488 489 453 490 EXPR = Template.EXPR 491 INCLUDE = Template.INCLUDE 454 492 SUB = Template.SUB -
genshi/template/tests/text.py
12 12 # history and logs, available at http://genshi.edgewall.org/log/. 13 13 14 14 import doctest 15 import os 16 import shutil 17 import tempfile 15 18 import unittest 16 19 20 from genshi.template.loader import TemplateLoader 17 21 from genshi.template.text import TextTemplate 18 22 19 23 20 24 class TextTemplateTestCase(unittest.TestCase): 21 25 """Tests for text template processing.""" 22 26 27 def setUp(self): 28 self.dirname = tempfile.mkdtemp(suffix='markup_test') 29 30 def tearDown(self): 31 shutil.rmtree(self.dirname) 32 23 33 def test_escaping(self): 24 34 tmpl = TextTemplate('\\#escaped') 25 35 self.assertEqual('#escaped', str(tmpl.generate())) … … 74 84 75 85 """, tmpl.generate(items=range(3)).render('text')) 76 86 87 def test_include(self): 88 file1 = open(os.path.join(self.dirname, 'tmpl1.txt'), 'w') 89 try: 90 file1.write("Included\n") 91 finally: 92 file1.close() 77 93 94 file2 = open(os.path.join(self.dirname, 'tmpl2.txt'), 'w') 95 try: 96 file2.write("""----- Included data below this line ----- 97 #include tmpl1.txt 98 ----- Included data above this line -----""") 99 finally: 100 file2.close() 101 102 loader = TemplateLoader([self.dirname]) 103 tmpl = loader.load('tmpl2.txt', cls=TextTemplate) 104 self.assertEqual("""----- Included data below this line ----- 105 Included 106 ----- Included data above this line -----""", 107 tmpl.generate().render()) 108 78 109 def suite(): 79 110 suite = unittest.TestSuite() 80 111 suite.addTest(doctest.DocTestSuite(TextTemplate.__module__)) -
genshi/template/markup.py
21 21 from genshi.core import START, END, START_NS, END_NS, TEXT, PI, COMMENT 22 22 from genshi.input import XMLParser 23 23 from genshi.template.base import BadDirectiveError, Template, \ 24 TemplateSyntaxError, _apply_directives, SUB 24 TemplateSyntaxError, _apply_directives, \ 25 INCLUDE, SUB 25 26 from genshi.template.eval import Suite 26 27 from genshi.template.interpolation import interpolate 27 from genshi.template.loader import TemplateNotFound28 28 from genshi.template.directives import * 29 29 30 30 if sys.version_info < (2, 4): … … 50 50 EXEC = StreamEventKind('EXEC') 51 51 """Stream event kind representing a Python code suite to execute.""" 52 52 53 INCLUDE = StreamEventKind('INCLUDE')54 """Stream event kind representing the inclusion of another template."""55 56 53 DIRECTIVE_NAMESPACE = Namespace('http://genshi.edgewall.org/') 57 54 XINCLUDE_NAMESPACE = Namespace('http://www.w3.org/2001/XInclude') 58 55 … … 73 70 encoding=None, lookup='lenient'): 74 71 Template.__init__(self, source, basedir=basedir, filename=filename, 75 72 loader=loader, encoding=encoding, lookup=lookup) 76 77 73 self.filters += [self._exec, self._match] 78 if loader:79 self.filters.append(self._include)80 74 81 75 def _parse(self, source, encoding): 82 76 streams = [[]] # stacked lists of events of the "compiled" template … … 223 217 assert len(streams) == 1 224 218 return streams[0] 225 219 226 def _prepare(self, stream):227 for kind, data, pos in Template._prepare(self, stream):228 if kind is INCLUDE:229 data = data[0], list(self._prepare(data[1]))230 yield kind, data, pos231 232 220 def _exec(self, stream, ctxt): 233 221 """Internal stream filter that executes code in ``<?python ?>`` 234 222 processing instructions. … … 239 227 else: 240 228 yield event 241 229 242 def _include(self, stream, ctxt):243 """Internal stream filter that performs inclusion of external244 template files.245 """246 for event in stream:247 if event[0] is INCLUDE:248 href, fallback = event[1]249 if not isinstance(href, basestring):250 parts = []251 for subkind, subdata, subpos in self._eval(href, ctxt):252 if subkind is TEXT:253 parts.append(subdata)254 href = u''.join([x for x in parts if x is not None])255 try:256 tmpl = self.loader.load(href, relative_to=event[2][0])257 for event in tmpl.generate(ctxt):258 yield event259 except TemplateNotFound:260 if fallback is None:261 raise262 for filter_ in self.filters:263 fallback = filter_(iter(fallback), ctxt)264 for event in fallback:265 yield event266 else:267 yield event268 269 230 def _match(self, stream, ctxt, match_templates=None): 270 231 """Internal stream filter that applies any defined match templates 271 232 to the stream. … … 341 302 342 303 343 304 EXEC = MarkupTemplate.EXEC 344 INCLUDE = MarkupTemplate.INCLUDE -
genshi/template/text.py
15 15 16 16 import re 17 17 18 from genshi.template.base import BadDirectiveError, Template, SUB18 from genshi.template.base import BadDirectiveError, Template, INCLUDE, SUB 19 19 from genshi.template.directives import * 20 from genshi.template.directives import Directive, _apply_directives 20 21 from genshi.template.interpolation import interpolate 21 22 22 23 __all__ = ['TextTemplate'] … … 95 96 substream = stream[start_offset:] 96 97 stream[start_offset:] = [(SUB, ([directive], substream), 97 98 (self.filepath, lineno, 0))] 99 elif command == 'include': 100 pos = (self.filename, lineno, 0) 101 stream.append((INCLUDE, (value.strip(), []), pos)) 98 102 elif command != '#': 99 103 cls = self._dir_by_name.get(command) 100 104 if cls is None:
