annotate genshi/template/markup.py @ 798:c690de5abafd stable-0.5.x

Ported [914], [970], and [971] to 0.5.x branch.
author cmlenz
date Thu, 15 Jan 2009 23:50:09 +0000
parents cf0a0a066aec
children 1b6968d31089 98a1b03bbc89
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 #
719
09a90feb9269 Fix copyright years.
cmlenz
parents: 715
diff changeset
3 # Copyright (C) 2006-2008 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
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
17
636
e0f12a6f3612 Follow-up to [751]: applying the optimization to text templates was actually slowing them down, so only do it for markup templates.
cmlenz
parents: 629
diff changeset
18 from genshi.core import Attrs, Markup, Namespace, Stream, StreamEventKind
405
bd5da099c113 Support for Python code blocks using the `<?python ?>` processing instruction. Closes #84.
cmlenz
parents: 400
diff changeset
19 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
20 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
21 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
22 TemplateSyntaxError, _apply_directives, \
609
237050080827 Add support for Python code blocks in text templates using the new syntax.
cmlenz
parents: 606
diff changeset
23 EXEC, INCLUDE, SUB
405
bd5da099c113 Support for Python code blocks using the `<?python ?>` processing instruction. Closes #84.
cmlenz
parents: 400
diff changeset
24 from genshi.template.eval import Suite
407
ea71a51e0258 Move string interpolation code into separate module (`genshi.template.interpolation`).
cmlenz
parents: 405
diff changeset
25 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
26 from genshi.template.directives import *
610
6a37018199fd * 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).
cmlenz
parents: 609
diff changeset
27 from genshi.template.text import NewTextTemplate
336
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
28
425
5b248708bbed Try to use proper reStructuredText for docstrings throughout.
cmlenz
parents: 422
diff changeset
29 __all__ = ['MarkupTemplate']
5b248708bbed Try to use proper reStructuredText for docstrings throughout.
cmlenz
parents: 422
diff changeset
30 __docformat__ = 'restructuredtext en'
5b248708bbed Try to use proper reStructuredText for docstrings throughout.
cmlenz
parents: 422
diff changeset
31
336
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
32
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
33 class MarkupTemplate(Template):
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
34 """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
35
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
36 >>> 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
37 ... <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
38 ... </ul>''')
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
39 >>> 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
40 <ul>
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
41 <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
42 </ul>
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
43 """
427
68a8308309b9 More API documentation.
cmlenz
parents: 425
diff changeset
44
363
caf7b68ab5dc Parse template includes at parse time to avoid some runtime overhead.
cmlenz
parents: 362
diff changeset
45 DIRECTIVE_NAMESPACE = Namespace('http://genshi.edgewall.org/')
caf7b68ab5dc Parse template includes at parse time to avoid some runtime overhead.
cmlenz
parents: 362
diff changeset
46 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
47
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
48 directives = [('def', DefDirective),
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
49 ('match', MatchDirective),
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
50 ('when', WhenDirective),
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
51 ('otherwise', OtherwiseDirective),
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
52 ('for', ForDirective),
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
53 ('if', IfDirective),
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
54 ('choose', ChooseDirective),
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
55 ('with', WithDirective),
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
56 ('replace', ReplaceDirective),
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
57 ('content', ContentDirective),
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
58 ('attrs', AttrsDirective),
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
59 ('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
60 serializer = 'xml'
636
e0f12a6f3612 Follow-up to [751]: applying the optimization to text templates was actually slowing them down, so only do it for markup templates.
cmlenz
parents: 629
diff changeset
61 _number_conv = Markup
336
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
62
715
09715f868a73 Enable pickling of `Template` and `Code` objects.
cmlenz
parents: 714
diff changeset
63 def _init_filters(self):
09715f868a73 Enable pickling of `Template` and `Code` objects.
cmlenz
parents: 714
diff changeset
64 Template._init_filters(self)
496
782931585925 Fix bug introduced in [575]: includes weren't being processed inside match templates.
cmlenz
parents: 475
diff changeset
65 # Make sure the include filter comes after the match filter
715
09715f868a73 Enable pickling of `Template` and `Code` objects.
cmlenz
parents: 714
diff changeset
66 if self.loader:
496
782931585925 Fix bug introduced in [575]: includes weren't being processed inside match templates.
cmlenz
parents: 475
diff changeset
67 self.filters.remove(self._include)
609
237050080827 Add support for Python code blocks in text templates using the new syntax.
cmlenz
parents: 606
diff changeset
68 self.filters += [self._match]
715
09715f868a73 Enable pickling of `Template` and `Code` objects.
cmlenz
parents: 714
diff changeset
69 if self.loader:
496
782931585925 Fix bug introduced in [575]: includes weren't being processed inside match templates.
cmlenz
parents: 475
diff changeset
70 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
71
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
72 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
73 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
74 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
75 ns_prefix = {}
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
76 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
77 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
78 includes = []
336
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
79
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
80 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
81 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
82 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
83
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
84 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
85 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
86
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
87 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
88 # 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
89 prefix, uri = data
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
90 ns_prefix[prefix] = uri
363
caf7b68ab5dc Parse template includes at parse time to avoid some runtime overhead.
cmlenz
parents: 362
diff changeset
91 if uri not in (self.DIRECTIVE_NAMESPACE,
caf7b68ab5dc Parse template includes at parse time to avoid some runtime overhead.
cmlenz
parents: 362
diff changeset
92 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
93 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
94
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
95 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
96 uri = ns_prefix.pop(data, None)
363
caf7b68ab5dc Parse template includes at parse time to avoid some runtime overhead.
cmlenz
parents: 362
diff changeset
97 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
98 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
99 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
100
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
101 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
102 # 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
103 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
104 directives = []
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
105 strip = False
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
106
363
caf7b68ab5dc Parse template includes at parse time to avoid some runtime overhead.
cmlenz
parents: 362
diff changeset
107 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
108 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
109 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
110 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
111 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
112 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
113 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
114 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
115 strip = True
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
116
363
caf7b68ab5dc Parse template includes at parse time to avoid some runtime overhead.
cmlenz
parents: 362
diff changeset
117 new_attrs = []
caf7b68ab5dc Parse template includes at parse time to avoid some runtime overhead.
cmlenz
parents: 362
diff changeset
118 for name, value in attrs:
caf7b68ab5dc Parse template includes at parse time to avoid some runtime overhead.
cmlenz
parents: 362
diff changeset
119 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
120 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
121 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
122 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
123 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
124 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
125 else:
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
126 if value:
714
7e6496bde18a The `Template` class and its subclasses, as well as the interpolation API, now take an `filepath` parameter instead of `basedir`. Closes #207. Thanks to Waldemar Kornewald for the patch.
cmlenz
parents: 700
diff changeset
127 value = list(interpolate(value, self.filepath,
7e6496bde18a The `Template` class and its subclasses, as well as the interpolation API, now take an `filepath` parameter instead of `basedir`. Closes #207. Thanks to Waldemar Kornewald for the patch.
cmlenz
parents: 700
diff changeset
128 pos[1], pos[2],
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
129 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
130 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
131 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
132 else:
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
133 value = [(TEXT, u'', pos)]
363
caf7b68ab5dc Parse template includes at parse time to avoid some runtime overhead.
cmlenz
parents: 362
diff changeset
134 new_attrs.append((name, value))
caf7b68ab5dc Parse template includes at parse time to avoid some runtime overhead.
cmlenz
parents: 362
diff changeset
135 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
136
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
137 if directives:
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
138 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
139 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
140 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
141
363
caf7b68ab5dc Parse template includes at parse time to avoid some runtime overhead.
cmlenz
parents: 362
diff changeset
142 if tag in self.XINCLUDE_NAMESPACE:
caf7b68ab5dc Parse template includes at parse time to avoid some runtime overhead.
cmlenz
parents: 362
diff changeset
143 if tag.localname == 'include':
caf7b68ab5dc Parse template includes at parse time to avoid some runtime overhead.
cmlenz
parents: 362
diff changeset
144 include_href = new_attrs.get('href')
caf7b68ab5dc Parse template includes at parse time to avoid some runtime overhead.
cmlenz
parents: 362
diff changeset
145 if not include_href:
caf7b68ab5dc Parse template includes at parse time to avoid some runtime overhead.
cmlenz
parents: 362
diff changeset
146 raise TemplateSyntaxError('Include misses required '
422
95089b6e37ca More work to include absolute file paths in exceptions.
cmlenz
parents: 421
diff changeset
147 'attribute "href"',
95089b6e37ca More work to include absolute file paths in exceptions.
cmlenz
parents: 421
diff changeset
148 self.filepath, *pos[1:])
610
6a37018199fd * 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).
cmlenz
parents: 609
diff changeset
149 includes.append((include_href, new_attrs.get('parse')))
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
150 streams.append([])
363
caf7b68ab5dc Parse template includes at parse time to avoid some runtime overhead.
cmlenz
parents: 362
diff changeset
151 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
152 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
153 fallbacks.append(streams[-1])
363
caf7b68ab5dc Parse template includes at parse time to avoid some runtime overhead.
cmlenz
parents: 362
diff changeset
154
caf7b68ab5dc Parse template includes at parse time to avoid some runtime overhead.
cmlenz
parents: 362
diff changeset
155 else:
caf7b68ab5dc Parse template includes at parse time to avoid some runtime overhead.
cmlenz
parents: 362
diff changeset
156 stream.append((kind, (tag, new_attrs), pos))
caf7b68ab5dc Parse template includes at parse time to avoid some runtime overhead.
cmlenz
parents: 362
diff changeset
157
336
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
158 depth += 1
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
159
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
160 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
161 depth -= 1
363
caf7b68ab5dc Parse template includes at parse time to avoid some runtime overhead.
cmlenz
parents: 362
diff changeset
162
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
163 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
164 assert streams.pop() is fallbacks[-1]
363
caf7b68ab5dc Parse template includes at parse time to avoid some runtime overhead.
cmlenz
parents: 362
diff changeset
165 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
166 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
167 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
168 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
169 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
170 # 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
171 stream = streams[-1]
610
6a37018199fd * 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).
cmlenz
parents: 609
diff changeset
172 href, parse = includes.pop()
6a37018199fd * 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).
cmlenz
parents: 609
diff changeset
173 try:
6a37018199fd * 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).
cmlenz
parents: 609
diff changeset
174 cls = {
6a37018199fd * 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).
cmlenz
parents: 609
diff changeset
175 'xml': MarkupTemplate,
6a37018199fd * 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).
cmlenz
parents: 609
diff changeset
176 'text': NewTextTemplate
6a37018199fd * 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).
cmlenz
parents: 609
diff changeset
177 }[parse or 'xml']
6a37018199fd * 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).
cmlenz
parents: 609
diff changeset
178 except KeyError:
6a37018199fd * 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).
cmlenz
parents: 609
diff changeset
179 raise TemplateSyntaxError('Invalid value for "parse" '
6a37018199fd * 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).
cmlenz
parents: 609
diff changeset
180 'attribute of include',
6a37018199fd * 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).
cmlenz
parents: 609
diff changeset
181 self.filepath, *pos[1:])
6a37018199fd * 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).
cmlenz
parents: 609
diff changeset
182 stream.append((INCLUDE, (href, cls, fallback), pos))
363
caf7b68ab5dc Parse template includes at parse time to avoid some runtime overhead.
cmlenz
parents: 362
diff changeset
183 else:
caf7b68ab5dc Parse template includes at parse time to avoid some runtime overhead.
cmlenz
parents: 362
diff changeset
184 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
185
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
186 # 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
187 # 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
188 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
189 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
190 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
191 if strip:
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
192 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
193 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
194 pos)]
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
195
405
bd5da099c113 Support for Python code blocks using the `<?python ?>` processing instruction. Closes #84.
cmlenz
parents: 400
diff changeset
196 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
197 if not self.allow_exec:
6e21c89d9255 Support for Python code blocks in templates can now be disabled. Closes #123.
cmlenz
parents: 520
diff changeset
198 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
199 self.filepath, *pos[1:])
405
bd5da099c113 Support for Python code blocks using the `<?python ?>` processing instruction. Closes #84.
cmlenz
parents: 400
diff changeset
200 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
201 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
202 lookup=self.lookup)
405
bd5da099c113 Support for Python code blocks using the `<?python ?>` processing instruction. Closes #84.
cmlenz
parents: 400
diff changeset
203 except SyntaxError, err:
bd5da099c113 Support for Python code blocks using the `<?python ?>` processing instruction. Closes #84.
cmlenz
parents: 400
diff changeset
204 raise TemplateSyntaxError(err, self.filepath,
bd5da099c113 Support for Python code blocks using the `<?python ?>` processing instruction. Closes #84.
cmlenz
parents: 400
diff changeset
205 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
206 pos[2] + (err.offset or 0))
bd5da099c113 Support for Python code blocks using the `<?python ?>` processing instruction. Closes #84.
cmlenz
parents: 400
diff changeset
207 stream.append((EXEC, suite, pos))
bd5da099c113 Support for Python code blocks using the `<?python ?>` processing instruction. Closes #84.
cmlenz
parents: 400
diff changeset
208
336
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
209 elif kind is TEXT:
714
7e6496bde18a The `Template` class and its subclasses, as well as the interpolation API, now take an `filepath` parameter instead of `basedir`. Closes #207. Thanks to Waldemar Kornewald for the patch.
cmlenz
parents: 700
diff changeset
210 for kind, data, pos in interpolate(data, self.filepath, pos[1],
7e6496bde18a The `Template` class and its subclasses, as well as the interpolation API, now take an `filepath` parameter instead of `basedir`. Closes #207. Thanks to Waldemar Kornewald for the patch.
cmlenz
parents: 700
diff changeset
211 pos[2], 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
767
e694d3ad8e61 Ported [892] to 0.5.x branch.
cmlenz
parents: 759
diff changeset
224 def _match(self, stream, ctxt, start=0, end=None, **vars):
336
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
225 """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
226 to the stream.
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
227 """
767
e694d3ad8e61 Ported [892] to 0.5.x branch.
cmlenz
parents: 759
diff changeset
228 match_templates = ctxt._match_templates
336
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
229
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
230 tail = []
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
231 def _strip(stream):
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
232 depth = 1
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
233 while 1:
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
234 event = stream.next()
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
235 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
236 depth += 1
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
237 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
238 depth -= 1
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
239 if depth > 0:
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
240 yield event
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
241 else:
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
242 tail[:] = [event]
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
243 break
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
244
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
245 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
246
798
c690de5abafd Ported [914], [970], and [971] to 0.5.x branch.
cmlenz
parents: 772
diff changeset
247 # We (currently) only care about start events for matching
336
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
248 # We might care about namespace events in the future, though
798
c690de5abafd Ported [914], [970], and [971] to 0.5.x branch.
cmlenz
parents: 772
diff changeset
249 if not match_templates or event[0] is not START:
336
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
250 yield event
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
251 continue
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
252
602
509b3a5e765e Add runtime optimization hints for match templates.
cmlenz
parents: 601
diff changeset
253 for idx, (test, path, template, hints, namespaces, directives) \
509b3a5e765e Add runtime optimization hints for match templates.
cmlenz
parents: 601
diff changeset
254 in enumerate(match_templates):
767
e694d3ad8e61 Ported [892] to 0.5.x branch.
cmlenz
parents: 759
diff changeset
255 if idx < start or end is not None and idx >= end:
759
63ab16fadccd Ported [884] back to 0.5.x branch.
cmlenz
parents: 719
diff changeset
256 continue
336
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 if test(event, namespaces, ctxt) is True:
602
509b3a5e765e Add runtime optimization hints for match templates.
cmlenz
parents: 601
diff changeset
259 if 'match_once' in hints:
509b3a5e765e Add runtime optimization hints for match templates.
cmlenz
parents: 601
diff changeset
260 del match_templates[idx]
509b3a5e765e Add runtime optimization hints for match templates.
cmlenz
parents: 601
diff changeset
261 idx -= 1
336
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
262
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
263 # 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
264 # 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
265 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
266 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
267
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
268 # 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
269 # corresponding to this start event is encountered
767
e694d3ad8e61 Ported [892] to 0.5.x branch.
cmlenz
parents: 759
diff changeset
270 pre_end = idx + 1
694
812671b40022 Match templates are now applied in a more controlled fashion: in the order they are declared in the template source, all match templates up to (and including) the matching template itself are applied to the matched content, whereas the match templates declared after the matching template are only applied to the generated content. Fixes #186. Many thanks to Matt Chaput for reporting the problem and providing a test case.
cmlenz
parents: 650
diff changeset
271 if 'match_once' not in hints and 'not_recursive' in hints:
767
e694d3ad8e61 Ported [892] to 0.5.x branch.
cmlenz
parents: 759
diff changeset
272 pre_end -= 1
700
8d079cee6822 Add option for unbuffered match template processing, which could cause excessive memory usage. Closes #190.
cmlenz
parents: 694
diff changeset
273 inner = _strip(stream)
767
e694d3ad8e61 Ported [892] to 0.5.x branch.
cmlenz
parents: 759
diff changeset
274 if pre_end > 0:
e694d3ad8e61 Ported [892] to 0.5.x branch.
cmlenz
parents: 759
diff changeset
275 inner = self._match(inner, ctxt, end=pre_end)
700
8d079cee6822 Add option for unbuffered match template processing, which could cause excessive memory usage. Closes #190.
cmlenz
parents: 694
diff changeset
276 content = self._include(chain([event], inner, tail), ctxt)
8d079cee6822 Add option for unbuffered match template processing, which could cause excessive memory usage. Closes #190.
cmlenz
parents: 694
diff changeset
277 if 'not_buffered' not in hints:
8d079cee6822 Add option for unbuffered match template processing, which could cause excessive memory usage. Closes #190.
cmlenz
parents: 694
diff changeset
278 content = list(content)
336
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
279
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
280 # 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
281 # match template
772
cf0a0a066aec Ported [897] back to 0.5.x branch.
cmlenz
parents: 767
diff changeset
282 selected = [False]
336
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
283 def select(path):
772
cf0a0a066aec Ported [897] back to 0.5.x branch.
cmlenz
parents: 767
diff changeset
284 selected[0] = True
336
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
285 return Stream(content).select(path, namespaces, ctxt)
700
8d079cee6822 Add option for unbuffered match template processing, which could cause excessive memory usage. Closes #190.
cmlenz
parents: 694
diff changeset
286 vars = dict(select=select)
336
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
287
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
288 # Recursively process the output
700
8d079cee6822 Add option for unbuffered match template processing, which could cause excessive memory usage. Closes #190.
cmlenz
parents: 694
diff changeset
289 template = _apply_directives(template, directives, ctxt,
8d079cee6822 Add option for unbuffered match template processing, which could cause excessive memory usage. Closes #190.
cmlenz
parents: 694
diff changeset
290 **vars)
8d079cee6822 Add option for unbuffered match template processing, which could cause excessive memory usage. Closes #190.
cmlenz
parents: 694
diff changeset
291 for event in self._match(
8d079cee6822 Add option for unbuffered match template processing, which could cause excessive memory usage. Closes #190.
cmlenz
parents: 694
diff changeset
292 self._exec(
8d079cee6822 Add option for unbuffered match template processing, which could cause excessive memory usage. Closes #190.
cmlenz
parents: 694
diff changeset
293 self._eval(
8d079cee6822 Add option for unbuffered match template processing, which could cause excessive memory usage. Closes #190.
cmlenz
parents: 694
diff changeset
294 self._flatten(template, ctxt, **vars),
8d079cee6822 Add option for unbuffered match template processing, which could cause excessive memory usage. Closes #190.
cmlenz
parents: 694
diff changeset
295 ctxt, **vars),
8d079cee6822 Add option for unbuffered match template processing, which could cause excessive memory usage. Closes #190.
cmlenz
parents: 694
diff changeset
296 ctxt, **vars),
767
e694d3ad8e61 Ported [892] to 0.5.x branch.
cmlenz
parents: 759
diff changeset
297 ctxt, start=idx + 1, **vars):
336
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
298 yield event
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
299
772
cf0a0a066aec Ported [897] back to 0.5.x branch.
cmlenz
parents: 767
diff changeset
300 # If the match template did not actually call select to
cf0a0a066aec Ported [897] back to 0.5.x branch.
cmlenz
parents: 767
diff changeset
301 # consume the matched stream, the original events need to
cf0a0a066aec Ported [897] back to 0.5.x branch.
cmlenz
parents: 767
diff changeset
302 # be consumed here or they'll get appended to the output
cf0a0a066aec Ported [897] back to 0.5.x branch.
cmlenz
parents: 767
diff changeset
303 if not selected[0]:
cf0a0a066aec Ported [897] back to 0.5.x branch.
cmlenz
parents: 767
diff changeset
304 for event in content:
cf0a0a066aec Ported [897] back to 0.5.x branch.
cmlenz
parents: 767
diff changeset
305 pass
cf0a0a066aec Ported [897] back to 0.5.x branch.
cmlenz
parents: 767
diff changeset
306
cf0a0a066aec Ported [897] back to 0.5.x branch.
cmlenz
parents: 767
diff changeset
307 # Let the remaining match templates know about the last
cf0a0a066aec Ported [897] back to 0.5.x branch.
cmlenz
parents: 767
diff changeset
308 # event in the matched content, so they can update their
cf0a0a066aec Ported [897] back to 0.5.x branch.
cmlenz
parents: 767
diff changeset
309 # internal state accordingly
cf0a0a066aec Ported [897] back to 0.5.x branch.
cmlenz
parents: 767
diff changeset
310 for test in [mt[0] for mt in match_templates]:
cf0a0a066aec Ported [897] back to 0.5.x branch.
cmlenz
parents: 767
diff changeset
311 test(tail[0], namespaces, ctxt, updateonly=True)
cf0a0a066aec Ported [897] back to 0.5.x branch.
cmlenz
parents: 767
diff changeset
312
336
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
313 break
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
314
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
315 else: # no matches
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
316 yield event
Copyright (C) 2012-2017 Edgewall Software