annotate genshi/template/markup.py @ 605:bc5faca93699

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.
author cmlenz
date Mon, 27 Aug 2007 19:04:20 +0000
parents 509b3a5e765e
children 9ada030ad986
rev   line source
336
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
1 # -*- coding: utf-8 -*-
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
2 #
408
49a3bae5a8bb Update copyright year for files modified this year.
cmlenz
parents: 407
diff changeset
3 # Copyright (C) 2006-2007 Edgewall Software
336
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
4 # All rights reserved.
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
5 #
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
6 # This software is licensed as described in the file COPYING, which
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
7 # you should have received as part of this distribution. The terms
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
8 # are also available at http://genshi.edgewall.org/wiki/License.
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
9 #
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
10 # This software consists of voluntary contributions made by many
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
11 # individuals. For the exact contribution history, see the revision
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
12 # history and logs, available at http://genshi.edgewall.org/log/.
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
13
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
14 """Markup templating engine."""
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
15
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
16 from itertools import chain
405
bd5da099c113 Support for Python code blocks using the `<?python ?>` processing instruction. Closes #84.
cmlenz
parents: 400
diff changeset
17 import sys
336
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
18
363
caf7b68ab5dc Parse template includes at parse time to avoid some runtime overhead.
cmlenz
parents: 362
diff changeset
19 from genshi.core import Attrs, Namespace, Stream, StreamEventKind
405
bd5da099c113 Support for Python code blocks using the `<?python ?>` processing instruction. Closes #84.
cmlenz
parents: 400
diff changeset
20 from genshi.core import START, END, START_NS, END_NS, TEXT, PI, COMMENT
336
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
21 from genshi.input import XMLParser
400
8dd0d34a9fb7 Renamed `genshi.template.core` to `genshi.template.base`, mainly to avoid confusion with `genshi.core`.
cmlenz
parents: 381
diff changeset
22 from genshi.template.base import BadDirectiveError, Template, \
475
bb939ed3058c Added include directive for text templates (#115). Thanks to Alastair for the original patch.
cmlenz
parents: 442
diff changeset
23 TemplateSyntaxError, _apply_directives, \
bb939ed3058c Added include directive for text templates (#115). Thanks to Alastair for the original patch.
cmlenz
parents: 442
diff changeset
24 INCLUDE, SUB
405
bd5da099c113 Support for Python code blocks using the `<?python ?>` processing instruction. Closes #84.
cmlenz
parents: 400
diff changeset
25 from genshi.template.eval import Suite
407
ea71a51e0258 Move string interpolation code into separate module (`genshi.template.interpolation`).
cmlenz
parents: 405
diff changeset
26 from genshi.template.interpolation import interpolate
336
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
27 from genshi.template.directives import *
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
28
405
bd5da099c113 Support for Python code blocks using the `<?python ?>` processing instruction. Closes #84.
cmlenz
parents: 400
diff changeset
29 if sys.version_info < (2, 4):
bd5da099c113 Support for Python code blocks using the `<?python ?>` processing instruction. Closes #84.
cmlenz
parents: 400
diff changeset
30 _ctxt2dict = lambda ctxt: ctxt.frames[0]
bd5da099c113 Support for Python code blocks using the `<?python ?>` processing instruction. Closes #84.
cmlenz
parents: 400
diff changeset
31 else:
bd5da099c113 Support for Python code blocks using the `<?python ?>` processing instruction. Closes #84.
cmlenz
parents: 400
diff changeset
32 _ctxt2dict = lambda ctxt: ctxt
bd5da099c113 Support for Python code blocks using the `<?python ?>` processing instruction. Closes #84.
cmlenz
parents: 400
diff changeset
33
425
5b248708bbed Try to use proper reStructuredText for docstrings throughout.
cmlenz
parents: 422
diff changeset
34 __all__ = ['MarkupTemplate']
5b248708bbed Try to use proper reStructuredText for docstrings throughout.
cmlenz
parents: 422
diff changeset
35 __docformat__ = 'restructuredtext en'
5b248708bbed Try to use proper reStructuredText for docstrings throughout.
cmlenz
parents: 422
diff changeset
36
336
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
37
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
38 class MarkupTemplate(Template):
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
39 """Implementation of the template language for XML-based templates.
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
40
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
41 >>> tmpl = MarkupTemplate('''<ul xmlns:py="http://genshi.edgewall.org/">
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
42 ... <li py:for="item in items">${item}</li>
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
43 ... </ul>''')
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
44 >>> print tmpl.generate(items=[1, 2, 3])
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
45 <ul>
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
46 <li>1</li><li>2</li><li>3</li>
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
47 </ul>
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
48 """
405
bd5da099c113 Support for Python code blocks using the `<?python ?>` processing instruction. Closes #84.
cmlenz
parents: 400
diff changeset
49 EXEC = StreamEventKind('EXEC')
427
68a8308309b9 More API documentation.
cmlenz
parents: 425
diff changeset
50 """Stream event kind representing a Python code suite to execute."""
68a8308309b9 More API documentation.
cmlenz
parents: 425
diff changeset
51
363
caf7b68ab5dc Parse template includes at parse time to avoid some runtime overhead.
cmlenz
parents: 362
diff changeset
52 DIRECTIVE_NAMESPACE = Namespace('http://genshi.edgewall.org/')
caf7b68ab5dc Parse template includes at parse time to avoid some runtime overhead.
cmlenz
parents: 362
diff changeset
53 XINCLUDE_NAMESPACE = Namespace('http://www.w3.org/2001/XInclude')
336
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
54
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
55 directives = [('def', DefDirective),
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
56 ('match', MatchDirective),
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
57 ('when', WhenDirective),
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
58 ('otherwise', OtherwiseDirective),
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
59 ('for', ForDirective),
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
60 ('if', IfDirective),
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
61 ('choose', ChooseDirective),
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
62 ('with', WithDirective),
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
63 ('replace', ReplaceDirective),
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
64 ('content', ContentDirective),
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
65 ('attrs', AttrsDirective),
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
66 ('strip', StripDirective)]
605
bc5faca93699 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.
cmlenz
parents: 602
diff changeset
67 serializer = 'xml'
336
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
68
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
69 def __init__(self, source, basedir=None, filename=None, loader=None,
545
6e21c89d9255 Support for Python code blocks in templates can now be disabled. Closes #123.
cmlenz
parents: 520
diff changeset
70 encoding=None, lookup='lenient', allow_exec=True):
336
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
71 Template.__init__(self, source, basedir=basedir, filename=filename,
545
6e21c89d9255 Support for Python code blocks in templates can now be disabled. Closes #123.
cmlenz
parents: 520
diff changeset
72 loader=loader, encoding=encoding, lookup=lookup,
6e21c89d9255 Support for Python code blocks in templates can now be disabled. Closes #123.
cmlenz
parents: 520
diff changeset
73 allow_exec=allow_exec)
496
782931585925 Fix bug introduced in [575]: includes weren't being processed inside match templates.
cmlenz
parents: 475
diff changeset
74 # Make sure the include filter comes after the match filter
782931585925 Fix bug introduced in [575]: includes weren't being processed inside match templates.
cmlenz
parents: 475
diff changeset
75 if loader:
782931585925 Fix bug introduced in [575]: includes weren't being processed inside match templates.
cmlenz
parents: 475
diff changeset
76 self.filters.remove(self._include)
405
bd5da099c113 Support for Python code blocks using the `<?python ?>` processing instruction. Closes #84.
cmlenz
parents: 400
diff changeset
77 self.filters += [self._exec, self._match]
496
782931585925 Fix bug introduced in [575]: includes weren't being processed inside match templates.
cmlenz
parents: 475
diff changeset
78 if loader:
782931585925 Fix bug introduced in [575]: includes weren't being processed inside match templates.
cmlenz
parents: 475
diff changeset
79 self.filters.append(self._include)
336
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
80
374
ca46dc9c7761 `MarkupTemplate`s can now be instantiated from markup streams, in addition to strings and file-like objects. Thanks to David Fraser for the patch. Closes #69.
cmlenz
parents: 364
diff changeset
81 def _parse(self, source, encoding):
381
a6c2a9cd2e92 Fix for #80: fallback only shown when the template to include wasn't found. In addition, the nesting of includes and fallback content should work correctly, and directives/expressions/etc inside fallback content are processed. Thanks to Christian Boos for the original patch and unit tests.
cmlenz
parents: 374
diff changeset
82 streams = [[]] # stacked lists of events of the "compiled" template
336
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
83 dirmap = {} # temporary mapping of directives to elements
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
84 ns_prefix = {}
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
85 depth = 0
590
880b1a75d046 Fix includes so that they again raise an exception when the included template is not found and no fallback has been provided.
cmlenz
parents: 552
diff changeset
86 fallbacks = []
880b1a75d046 Fix includes so that they again raise an exception when the included template is not found and no fallback has been provided.
cmlenz
parents: 552
diff changeset
87 includes = []
336
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
88
374
ca46dc9c7761 `MarkupTemplate`s can now be instantiated from markup streams, in addition to strings and file-like objects. Thanks to David Fraser for the patch. Closes #69.
cmlenz
parents: 364
diff changeset
89 if not isinstance(source, Stream):
434
e065d7906b68 * Better method to propogate the full path to the template file on parse errors. Supersedes r513.
cmlenz
parents: 427
diff changeset
90 source = XMLParser(source, filename=self.filename,
374
ca46dc9c7761 `MarkupTemplate`s can now be instantiated from markup streams, in addition to strings and file-like objects. Thanks to David Fraser for the patch. Closes #69.
cmlenz
parents: 364
diff changeset
91 encoding=encoding)
ca46dc9c7761 `MarkupTemplate`s can now be instantiated from markup streams, in addition to strings and file-like objects. Thanks to David Fraser for the patch. Closes #69.
cmlenz
parents: 364
diff changeset
92
ca46dc9c7761 `MarkupTemplate`s can now be instantiated from markup streams, in addition to strings and file-like objects. Thanks to David Fraser for the patch. Closes #69.
cmlenz
parents: 364
diff changeset
93 for kind, data, pos in source:
381
a6c2a9cd2e92 Fix for #80: fallback only shown when the template to include wasn't found. In addition, the nesting of includes and fallback content should work correctly, and directives/expressions/etc inside fallback content are processed. Thanks to Christian Boos for the original patch and unit tests.
cmlenz
parents: 374
diff changeset
94 stream = streams[-1]
336
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
95
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
96 if kind is START_NS:
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
97 # Strip out the namespace declaration for template directives
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
98 prefix, uri = data
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
99 ns_prefix[prefix] = uri
363
caf7b68ab5dc Parse template includes at parse time to avoid some runtime overhead.
cmlenz
parents: 362
diff changeset
100 if uri not in (self.DIRECTIVE_NAMESPACE,
caf7b68ab5dc Parse template includes at parse time to avoid some runtime overhead.
cmlenz
parents: 362
diff changeset
101 self.XINCLUDE_NAMESPACE):
336
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
102 stream.append((kind, data, pos))
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
103
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
104 elif kind is END_NS:
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
105 uri = ns_prefix.pop(data, None)
363
caf7b68ab5dc Parse template includes at parse time to avoid some runtime overhead.
cmlenz
parents: 362
diff changeset
106 if uri and uri not in (self.DIRECTIVE_NAMESPACE,
caf7b68ab5dc Parse template includes at parse time to avoid some runtime overhead.
cmlenz
parents: 362
diff changeset
107 self.XINCLUDE_NAMESPACE):
336
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
108 stream.append((kind, data, pos))
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
109
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
110 elif kind is START:
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
111 # Record any directive attributes in start tags
363
caf7b68ab5dc Parse template includes at parse time to avoid some runtime overhead.
cmlenz
parents: 362
diff changeset
112 tag, attrs = data
336
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
113 directives = []
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
114 strip = False
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
115
363
caf7b68ab5dc Parse template includes at parse time to avoid some runtime overhead.
cmlenz
parents: 362
diff changeset
116 if tag in self.DIRECTIVE_NAMESPACE:
336
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
117 cls = self._dir_by_name.get(tag.localname)
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
118 if cls is None:
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
119 raise BadDirectiveError(tag.localname, self.filepath,
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
120 pos[1])
552
5458a4e8814c For directives used as elements, pass all attributes without a namespace to the directive class. This enables adding optional extra attributes to directives.
cmlenz
parents: 545
diff changeset
121 args = dict([(name.localname, value) for name, value
5458a4e8814c For directives used as elements, pass all attributes without a namespace to the directive class. This enables adding optional extra attributes to directives.
cmlenz
parents: 545
diff changeset
122 in attrs if not name.namespace])
5458a4e8814c For directives used as elements, pass all attributes without a namespace to the directive class. This enables adding optional extra attributes to directives.
cmlenz
parents: 545
diff changeset
123 directives.append((cls, args, ns_prefix.copy(), pos))
336
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
124 strip = True
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
125
363
caf7b68ab5dc Parse template includes at parse time to avoid some runtime overhead.
cmlenz
parents: 362
diff changeset
126 new_attrs = []
caf7b68ab5dc Parse template includes at parse time to avoid some runtime overhead.
cmlenz
parents: 362
diff changeset
127 for name, value in attrs:
caf7b68ab5dc Parse template includes at parse time to avoid some runtime overhead.
cmlenz
parents: 362
diff changeset
128 if name in self.DIRECTIVE_NAMESPACE:
336
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
129 cls = self._dir_by_name.get(name.localname)
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
130 if cls is None:
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
131 raise BadDirectiveError(name.localname,
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
132 self.filepath, pos[1])
362
0910d5978f45 Follow-up to [431]: directives are no longer instantiated directly at parse time, but instead by the `attach()` method of the directive class (which replaces the `prepare()` method).
cmlenz
parents: 336
diff changeset
133 directives.append((cls, value, ns_prefix.copy(), pos))
336
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
134 else:
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
135 if value:
442
ff7c72b52fb2 Back out [510] and instead implement configurable error handling modes. The default is the old 0.3.x behaviour, but more strict error handling is available as an option.
cmlenz
parents: 434
diff changeset
136 value = list(interpolate(value, self.basedir,
ff7c72b52fb2 Back out [510] and instead implement configurable error handling modes. The default is the old 0.3.x behaviour, but more strict error handling is available as an option.
cmlenz
parents: 434
diff changeset
137 pos[0], pos[1], pos[2],
ff7c72b52fb2 Back out [510] and instead implement configurable error handling modes. The default is the old 0.3.x behaviour, but more strict error handling is available as an option.
cmlenz
parents: 434
diff changeset
138 lookup=self.lookup))
336
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
139 if len(value) == 1 and value[0][0] is TEXT:
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
140 value = value[0][1]
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
141 else:
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
142 value = [(TEXT, u'', pos)]
363
caf7b68ab5dc Parse template includes at parse time to avoid some runtime overhead.
cmlenz
parents: 362
diff changeset
143 new_attrs.append((name, value))
caf7b68ab5dc Parse template includes at parse time to avoid some runtime overhead.
cmlenz
parents: 362
diff changeset
144 new_attrs = Attrs(new_attrs)
336
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
145
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
146 if directives:
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
147 index = self._dir_order.index
362
0910d5978f45 Follow-up to [431]: directives are no longer instantiated directly at parse time, but instead by the `attach()` method of the directive class (which replaces the `prepare()` method).
cmlenz
parents: 336
diff changeset
148 directives.sort(lambda a, b: cmp(index(a[0]), index(b[0])))
336
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
149 dirmap[(depth, tag)] = (directives, len(stream), strip)
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
150
363
caf7b68ab5dc Parse template includes at parse time to avoid some runtime overhead.
cmlenz
parents: 362
diff changeset
151 if tag in self.XINCLUDE_NAMESPACE:
caf7b68ab5dc Parse template includes at parse time to avoid some runtime overhead.
cmlenz
parents: 362
diff changeset
152 if tag.localname == 'include':
caf7b68ab5dc Parse template includes at parse time to avoid some runtime overhead.
cmlenz
parents: 362
diff changeset
153 include_href = new_attrs.get('href')
caf7b68ab5dc Parse template includes at parse time to avoid some runtime overhead.
cmlenz
parents: 362
diff changeset
154 if not include_href:
caf7b68ab5dc Parse template includes at parse time to avoid some runtime overhead.
cmlenz
parents: 362
diff changeset
155 raise TemplateSyntaxError('Include misses required '
422
95089b6e37ca More work to include absolute file paths in exceptions.
cmlenz
parents: 421
diff changeset
156 'attribute "href"',
95089b6e37ca More work to include absolute file paths in exceptions.
cmlenz
parents: 421
diff changeset
157 self.filepath, *pos[1:])
590
880b1a75d046 Fix includes so that they again raise an exception when the included template is not found and no fallback has been provided.
cmlenz
parents: 552
diff changeset
158 includes.append(include_href)
381
a6c2a9cd2e92 Fix for #80: fallback only shown when the template to include wasn't found. In addition, the nesting of includes and fallback content should work correctly, and directives/expressions/etc inside fallback content are processed. Thanks to Christian Boos for the original patch and unit tests.
cmlenz
parents: 374
diff changeset
159 streams.append([])
363
caf7b68ab5dc Parse template includes at parse time to avoid some runtime overhead.
cmlenz
parents: 362
diff changeset
160 elif tag.localname == 'fallback':
590
880b1a75d046 Fix includes so that they again raise an exception when the included template is not found and no fallback has been provided.
cmlenz
parents: 552
diff changeset
161 streams.append([])
880b1a75d046 Fix includes so that they again raise an exception when the included template is not found and no fallback has been provided.
cmlenz
parents: 552
diff changeset
162 fallbacks.append(streams[-1])
363
caf7b68ab5dc Parse template includes at parse time to avoid some runtime overhead.
cmlenz
parents: 362
diff changeset
163
caf7b68ab5dc Parse template includes at parse time to avoid some runtime overhead.
cmlenz
parents: 362
diff changeset
164 else:
caf7b68ab5dc Parse template includes at parse time to avoid some runtime overhead.
cmlenz
parents: 362
diff changeset
165 stream.append((kind, (tag, new_attrs), pos))
caf7b68ab5dc Parse template includes at parse time to avoid some runtime overhead.
cmlenz
parents: 362
diff changeset
166
336
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
167 depth += 1
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
168
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
169 elif kind is END:
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
170 depth -= 1
363
caf7b68ab5dc Parse template includes at parse time to avoid some runtime overhead.
cmlenz
parents: 362
diff changeset
171
590
880b1a75d046 Fix includes so that they again raise an exception when the included template is not found and no fallback has been provided.
cmlenz
parents: 552
diff changeset
172 if fallbacks and data == self.XINCLUDE_NAMESPACE['fallback']:
880b1a75d046 Fix includes so that they again raise an exception when the included template is not found and no fallback has been provided.
cmlenz
parents: 552
diff changeset
173 assert streams.pop() is fallbacks[-1]
363
caf7b68ab5dc Parse template includes at parse time to avoid some runtime overhead.
cmlenz
parents: 362
diff changeset
174 elif data == self.XINCLUDE_NAMESPACE['include']:
590
880b1a75d046 Fix includes so that they again raise an exception when the included template is not found and no fallback has been provided.
cmlenz
parents: 552
diff changeset
175 fallback = None
880b1a75d046 Fix includes so that they again raise an exception when the included template is not found and no fallback has been provided.
cmlenz
parents: 552
diff changeset
176 if len(fallbacks) == len(includes):
880b1a75d046 Fix includes so that they again raise an exception when the included template is not found and no fallback has been provided.
cmlenz
parents: 552
diff changeset
177 fallback = fallbacks.pop()
880b1a75d046 Fix includes so that they again raise an exception when the included template is not found and no fallback has been provided.
cmlenz
parents: 552
diff changeset
178 streams.pop() # discard anything between the include tags
880b1a75d046 Fix includes so that they again raise an exception when the included template is not found and no fallback has been provided.
cmlenz
parents: 552
diff changeset
179 # and the fallback element
381
a6c2a9cd2e92 Fix for #80: fallback only shown when the template to include wasn't found. In addition, the nesting of includes and fallback content should work correctly, and directives/expressions/etc inside fallback content are processed. Thanks to Christian Boos for the original patch and unit tests.
cmlenz
parents: 374
diff changeset
180 stream = streams[-1]
590
880b1a75d046 Fix includes so that they again raise an exception when the included template is not found and no fallback has been provided.
cmlenz
parents: 552
diff changeset
181 stream.append((INCLUDE, (includes.pop(), fallback), pos))
363
caf7b68ab5dc Parse template includes at parse time to avoid some runtime overhead.
cmlenz
parents: 362
diff changeset
182 else:
caf7b68ab5dc Parse template includes at parse time to avoid some runtime overhead.
cmlenz
parents: 362
diff changeset
183 stream.append((kind, data, pos))
336
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
184
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
185 # If there have have directive attributes with the corresponding
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
186 # start tag, move the events inbetween into a "subprogram"
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
187 if (depth, data) in dirmap:
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
188 directives, start_offset, strip = dirmap.pop((depth, data))
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
189 substream = stream[start_offset:]
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
190 if strip:
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
191 substream = substream[1:-1]
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
192 stream[start_offset:] = [(SUB, (directives, substream),
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
193 pos)]
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
194
405
bd5da099c113 Support for Python code blocks using the `<?python ?>` processing instruction. Closes #84.
cmlenz
parents: 400
diff changeset
195 elif kind is PI and data[0] == 'python':
545
6e21c89d9255 Support for Python code blocks in templates can now be disabled. Closes #123.
cmlenz
parents: 520
diff changeset
196 if not self.allow_exec:
6e21c89d9255 Support for Python code blocks in templates can now be disabled. Closes #123.
cmlenz
parents: 520
diff changeset
197 raise TemplateSyntaxError('Python code blocks not allowed',
6e21c89d9255 Support for Python code blocks in templates can now be disabled. Closes #123.
cmlenz
parents: 520
diff changeset
198 self.filepath, *pos[1:])
405
bd5da099c113 Support for Python code blocks using the `<?python ?>` processing instruction. Closes #84.
cmlenz
parents: 400
diff changeset
199 try:
601
9ae986bcba9a Simplify implementation of `py:with` directive by compiling to a `Suite`, instead of manually breaking up the statement and compiling each part to an `Expression`. Also, the first line of code in a `Suite` is now stored as the "function name" of the bytecode, so that it shows up in tracebacks.
cmlenz
parents: 590
diff changeset
200 suite = Suite(data[1], self.filepath, pos[1],
442
ff7c72b52fb2 Back out [510] and instead implement configurable error handling modes. The default is the old 0.3.x behaviour, but more strict error handling is available as an option.
cmlenz
parents: 434
diff changeset
201 lookup=self.lookup)
405
bd5da099c113 Support for Python code blocks using the `<?python ?>` processing instruction. Closes #84.
cmlenz
parents: 400
diff changeset
202 except SyntaxError, err:
bd5da099c113 Support for Python code blocks using the `<?python ?>` processing instruction. Closes #84.
cmlenz
parents: 400
diff changeset
203 raise TemplateSyntaxError(err, self.filepath,
bd5da099c113 Support for Python code blocks using the `<?python ?>` processing instruction. Closes #84.
cmlenz
parents: 400
diff changeset
204 pos[1] + (err.lineno or 1) - 1,
bd5da099c113 Support for Python code blocks using the `<?python ?>` processing instruction. Closes #84.
cmlenz
parents: 400
diff changeset
205 pos[2] + (err.offset or 0))
bd5da099c113 Support for Python code blocks using the `<?python ?>` processing instruction. Closes #84.
cmlenz
parents: 400
diff changeset
206 stream.append((EXEC, suite, pos))
bd5da099c113 Support for Python code blocks using the `<?python ?>` processing instruction. Closes #84.
cmlenz
parents: 400
diff changeset
207
336
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
208 elif kind is TEXT:
442
ff7c72b52fb2 Back out [510] and instead implement configurable error handling modes. The default is the old 0.3.x behaviour, but more strict error handling is available as an option.
cmlenz
parents: 434
diff changeset
209 for kind, data, pos in interpolate(data, self.basedir, pos[0],
ff7c72b52fb2 Back out [510] and instead implement configurable error handling modes. The default is the old 0.3.x behaviour, but more strict error handling is available as an option.
cmlenz
parents: 434
diff changeset
210 pos[1], pos[2],
ff7c72b52fb2 Back out [510] and instead implement configurable error handling modes. The default is the old 0.3.x behaviour, but more strict error handling is available as an option.
cmlenz
parents: 434
diff changeset
211 lookup=self.lookup):
336
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
212 stream.append((kind, data, pos))
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
213
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
214 elif kind is COMMENT:
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
215 if not data.lstrip().startswith('!'):
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
216 stream.append((kind, data, pos))
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
217
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
218 else:
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
219 stream.append((kind, data, pos))
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
220
381
a6c2a9cd2e92 Fix for #80: fallback only shown when the template to include wasn't found. In addition, the nesting of includes and fallback content should work correctly, and directives/expressions/etc inside fallback content are processed. Thanks to Christian Boos for the original patch and unit tests.
cmlenz
parents: 374
diff changeset
221 assert len(streams) == 1
a6c2a9cd2e92 Fix for #80: fallback only shown when the template to include wasn't found. In addition, the nesting of includes and fallback content should work correctly, and directives/expressions/etc inside fallback content are processed. Thanks to Christian Boos for the original patch and unit tests.
cmlenz
parents: 374
diff changeset
222 return streams[0]
a6c2a9cd2e92 Fix for #80: fallback only shown when the template to include wasn't found. In addition, the nesting of includes and fallback content should work correctly, and directives/expressions/etc inside fallback content are processed. Thanks to Christian Boos for the original patch and unit tests.
cmlenz
parents: 374
diff changeset
223
405
bd5da099c113 Support for Python code blocks using the `<?python ?>` processing instruction. Closes #84.
cmlenz
parents: 400
diff changeset
224 def _exec(self, stream, ctxt):
425
5b248708bbed Try to use proper reStructuredText for docstrings throughout.
cmlenz
parents: 422
diff changeset
225 """Internal stream filter that executes code in ``<?python ?>``
5b248708bbed Try to use proper reStructuredText for docstrings throughout.
cmlenz
parents: 422
diff changeset
226 processing instructions.
405
bd5da099c113 Support for Python code blocks using the `<?python ?>` processing instruction. Closes #84.
cmlenz
parents: 400
diff changeset
227 """
bd5da099c113 Support for Python code blocks using the `<?python ?>` processing instruction. Closes #84.
cmlenz
parents: 400
diff changeset
228 for event in stream:
bd5da099c113 Support for Python code blocks using the `<?python ?>` processing instruction. Closes #84.
cmlenz
parents: 400
diff changeset
229 if event[0] is EXEC:
bd5da099c113 Support for Python code blocks using the `<?python ?>` processing instruction. Closes #84.
cmlenz
parents: 400
diff changeset
230 event[1].execute(_ctxt2dict(ctxt))
bd5da099c113 Support for Python code blocks using the `<?python ?>` processing instruction. Closes #84.
cmlenz
parents: 400
diff changeset
231 else:
bd5da099c113 Support for Python code blocks using the `<?python ?>` processing instruction. Closes #84.
cmlenz
parents: 400
diff changeset
232 yield event
bd5da099c113 Support for Python code blocks using the `<?python ?>` processing instruction. Closes #84.
cmlenz
parents: 400
diff changeset
233
336
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
234 def _match(self, stream, ctxt, match_templates=None):
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
235 """Internal stream filter that applies any defined match templates
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
236 to the stream.
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
237 """
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
238 if match_templates is None:
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
239 match_templates = ctxt._match_templates
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
240
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
241 tail = []
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
242 def _strip(stream):
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
243 depth = 1
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
244 while 1:
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
245 event = stream.next()
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
246 if event[0] is START:
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
247 depth += 1
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
248 elif event[0] is END:
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
249 depth -= 1
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
250 if depth > 0:
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
251 yield event
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
252 else:
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
253 tail[:] = [event]
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
254 break
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
255
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
256 for event in stream:
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
257
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
258 # We (currently) only care about start and end events for matching
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
259 # We might care about namespace events in the future, though
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
260 if not match_templates or (event[0] is not START and
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
261 event[0] is not END):
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
262 yield event
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
263 continue
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
264
602
509b3a5e765e Add runtime optimization hints for match templates.
cmlenz
parents: 601
diff changeset
265 for idx, (test, path, template, hints, namespaces, directives) \
509b3a5e765e Add runtime optimization hints for match templates.
cmlenz
parents: 601
diff changeset
266 in enumerate(match_templates):
336
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
267
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
268 if test(event, namespaces, ctxt) is True:
602
509b3a5e765e Add runtime optimization hints for match templates.
cmlenz
parents: 601
diff changeset
269 if 'match_once' in hints:
509b3a5e765e Add runtime optimization hints for match templates.
cmlenz
parents: 601
diff changeset
270 del match_templates[idx]
509b3a5e765e Add runtime optimization hints for match templates.
cmlenz
parents: 601
diff changeset
271 idx -= 1
336
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
272
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
273 # Let the remaining match templates know about the event so
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
274 # they get a chance to update their internal state
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
275 for test in [mt[0] for mt in match_templates[idx + 1:]]:
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
276 test(event, namespaces, ctxt, updateonly=True)
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
277
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
278 # Consume and store all events until an end event
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
279 # corresponding to this start event is encountered
602
509b3a5e765e Add runtime optimization hints for match templates.
cmlenz
parents: 601
diff changeset
280 inner = _strip(stream)
509b3a5e765e Add runtime optimization hints for match templates.
cmlenz
parents: 601
diff changeset
281 if 'match_once' not in hints \
509b3a5e765e Add runtime optimization hints for match templates.
cmlenz
parents: 601
diff changeset
282 and 'not_recursive' not in hints:
509b3a5e765e Add runtime optimization hints for match templates.
cmlenz
parents: 601
diff changeset
283 inner = self._match(inner, ctxt, [match_templates[idx]])
509b3a5e765e Add runtime optimization hints for match templates.
cmlenz
parents: 601
diff changeset
284 content = list(self._include(chain([event], inner, tail),
509b3a5e765e Add runtime optimization hints for match templates.
cmlenz
parents: 601
diff changeset
285 ctxt))
336
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
286
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
287 for test in [mt[0] for mt in match_templates]:
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
288 test(tail[0], namespaces, ctxt, updateonly=True)
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
289
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
290 # Make the select() function available in the body of the
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
291 # match template
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
292 def select(path):
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
293 return Stream(content).select(path, namespaces, ctxt)
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
294 ctxt.push(dict(select=select))
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
295
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
296 # Recursively process the output
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
297 template = _apply_directives(template, ctxt, directives)
602
509b3a5e765e Add runtime optimization hints for match templates.
cmlenz
parents: 601
diff changeset
298 remaining = match_templates
509b3a5e765e Add runtime optimization hints for match templates.
cmlenz
parents: 601
diff changeset
299 if 'match_once' not in hints:
509b3a5e765e Add runtime optimization hints for match templates.
cmlenz
parents: 601
diff changeset
300 remaining = remaining[:idx] + remaining[idx + 1:]
336
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
301 for event in self._match(self._eval(self._flatten(template,
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
302 ctxt),
602
509b3a5e765e Add runtime optimization hints for match templates.
cmlenz
parents: 601
diff changeset
303 ctxt), ctxt, remaining):
336
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
304 yield event
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
305
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
306 ctxt.pop()
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
307 break
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
308
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
309 else: # no matches
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
310 yield event
363
caf7b68ab5dc Parse template includes at parse time to avoid some runtime overhead.
cmlenz
parents: 362
diff changeset
311
caf7b68ab5dc Parse template includes at parse time to avoid some runtime overhead.
cmlenz
parents: 362
diff changeset
312
405
bd5da099c113 Support for Python code blocks using the `<?python ?>` processing instruction. Closes #84.
cmlenz
parents: 400
diff changeset
313 EXEC = MarkupTemplate.EXEC
Copyright (C) 2012-2017 Edgewall Software