annotate genshi/template/markup.py @ 421:fbdbe27885e2 trunk

Template parsing passes the full path of the template to the XML parser so that it's included in parsing exceptions.
author cmlenz
date Tue, 20 Mar 2007 16:20:41 +0000
parents 4675d5cf6c67
children 5d08a744636e
rev   line source
336
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
1 # -*- coding: utf-8 -*-
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
2 #
408
4675d5cf6c67 Update copyright year for files modified this year.
cmlenz
parents: 407
diff changeset
3 # Copyright (C) 2006-2007 Edgewall Software
336
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
4 # All rights reserved.
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
5 #
7763f7aec949 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
7763f7aec949 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
7763f7aec949 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.
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
9 #
7763f7aec949 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
7763f7aec949 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
7763f7aec949 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/.
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
13
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
14 """Markup templating engine."""
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
15
7763f7aec949 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
5340931530e2 Support for Python code blocks using the `<?python ?>` processing instruction. Closes #84.
cmlenz
parents: 400
diff changeset
17 import sys
5340931530e2 Support for Python code blocks using the `<?python ?>` processing instruction. Closes #84.
cmlenz
parents: 400
diff changeset
18 from textwrap import dedent
336
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
19
363
37e4b4bb0b53 Parse template includes at parse time to avoid some runtime overhead.
cmlenz
parents: 362
diff changeset
20 from genshi.core import Attrs, Namespace, Stream, StreamEventKind
405
5340931530e2 Support for Python code blocks using the `<?python ?>` processing instruction. Closes #84.
cmlenz
parents: 400
diff changeset
21 from genshi.core import START, END, START_NS, END_NS, TEXT, PI, COMMENT
336
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
22 from genshi.input import XMLParser
400
e29a94b3ba0c Renamed `genshi.template.core` to `genshi.template.base`, mainly to avoid confusion with `genshi.core`.
cmlenz
parents: 381
diff changeset
23 from genshi.template.base import BadDirectiveError, Template, \
405
5340931530e2 Support for Python code blocks using the `<?python ?>` processing instruction. Closes #84.
cmlenz
parents: 400
diff changeset
24 TemplateSyntaxError, _apply_directives, SUB
5340931530e2 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
f37d8e6acdf2 Move string interpolation code into separate module (`genshi.template.interpolation`).
cmlenz
parents: 405
diff changeset
26 from genshi.template.interpolation import interpolate
363
37e4b4bb0b53 Parse template includes at parse time to avoid some runtime overhead.
cmlenz
parents: 362
diff changeset
27 from genshi.template.loader import TemplateNotFound
336
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
28 from genshi.template.directives import *
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
29
405
5340931530e2 Support for Python code blocks using the `<?python ?>` processing instruction. Closes #84.
cmlenz
parents: 400
diff changeset
30 if sys.version_info < (2, 4):
5340931530e2 Support for Python code blocks using the `<?python ?>` processing instruction. Closes #84.
cmlenz
parents: 400
diff changeset
31 _ctxt2dict = lambda ctxt: ctxt.frames[0]
5340931530e2 Support for Python code blocks using the `<?python ?>` processing instruction. Closes #84.
cmlenz
parents: 400
diff changeset
32 else:
5340931530e2 Support for Python code blocks using the `<?python ?>` processing instruction. Closes #84.
cmlenz
parents: 400
diff changeset
33 _ctxt2dict = lambda ctxt: ctxt
5340931530e2 Support for Python code blocks using the `<?python ?>` processing instruction. Closes #84.
cmlenz
parents: 400
diff changeset
34
336
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
35
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
36 class MarkupTemplate(Template):
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
37 """Implementation of the template language for XML-based templates.
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
38
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
39 >>> tmpl = MarkupTemplate('''<ul xmlns:py="http://genshi.edgewall.org/">
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
40 ... <li py:for="item in items">${item}</li>
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
41 ... </ul>''')
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
42 >>> print tmpl.generate(items=[1, 2, 3])
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
43 <ul>
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
44 <li>1</li><li>2</li><li>3</li>
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
45 </ul>
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
46 """
405
5340931530e2 Support for Python code blocks using the `<?python ?>` processing instruction. Closes #84.
cmlenz
parents: 400
diff changeset
47 EXEC = StreamEventKind('EXEC')
363
37e4b4bb0b53 Parse template includes at parse time to avoid some runtime overhead.
cmlenz
parents: 362
diff changeset
48 INCLUDE = StreamEventKind('INCLUDE')
37e4b4bb0b53 Parse template includes at parse time to avoid some runtime overhead.
cmlenz
parents: 362
diff changeset
49
37e4b4bb0b53 Parse template includes at parse time to avoid some runtime overhead.
cmlenz
parents: 362
diff changeset
50 DIRECTIVE_NAMESPACE = Namespace('http://genshi.edgewall.org/')
37e4b4bb0b53 Parse template includes at parse time to avoid some runtime overhead.
cmlenz
parents: 362
diff changeset
51 XINCLUDE_NAMESPACE = Namespace('http://www.w3.org/2001/XInclude')
336
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
52
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
53 directives = [('def', DefDirective),
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
54 ('match', MatchDirective),
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
55 ('when', WhenDirective),
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
56 ('otherwise', OtherwiseDirective),
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
57 ('for', ForDirective),
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
58 ('if', IfDirective),
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
59 ('choose', ChooseDirective),
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
60 ('with', WithDirective),
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
61 ('replace', ReplaceDirective),
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
62 ('content', ContentDirective),
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
63 ('attrs', AttrsDirective),
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
64 ('strip', StripDirective)]
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
65
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
66 def __init__(self, source, basedir=None, filename=None, loader=None,
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
67 encoding=None):
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
68 """Initialize a template from either a string or a file-like object."""
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
69 Template.__init__(self, source, basedir=basedir, filename=filename,
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
70 loader=loader, encoding=encoding)
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
71
405
5340931530e2 Support for Python code blocks using the `<?python ?>` processing instruction. Closes #84.
cmlenz
parents: 400
diff changeset
72 self.filters += [self._exec, self._match]
336
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
73 if loader:
363
37e4b4bb0b53 Parse template includes at parse time to avoid some runtime overhead.
cmlenz
parents: 362
diff changeset
74 self.filters.append(self._include)
336
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
75
374
b146277eb54a `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
76 def _parse(self, source, encoding):
336
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
77 """Parse the template from an XML document."""
381
b9fc7a1f76ca 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
78 streams = [[]] # stacked lists of events of the "compiled" template
336
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
79 dirmap = {} # temporary mapping of directives to elements
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
80 ns_prefix = {}
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
81 depth = 0
381
b9fc7a1f76ca 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 in_fallback = 0
363
37e4b4bb0b53 Parse template includes at parse time to avoid some runtime overhead.
cmlenz
parents: 362
diff changeset
83 include_href = None
336
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
84
374
b146277eb54a `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
85 if not isinstance(source, Stream):
421
fbdbe27885e2 Template parsing passes the full path of the template to the XML parser so that it's included in parsing exceptions.
cmlenz
parents: 408
diff changeset
86 source = XMLParser(source, filename=self.filepath,
374
b146277eb54a `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
87 encoding=encoding)
b146277eb54a `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
88
b146277eb54a `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 for kind, data, pos in source:
381
b9fc7a1f76ca 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
90 stream = streams[-1]
336
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
91
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
92 if kind is START_NS:
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
93 # Strip out the namespace declaration for template directives
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
94 prefix, uri = data
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
95 ns_prefix[prefix] = uri
363
37e4b4bb0b53 Parse template includes at parse time to avoid some runtime overhead.
cmlenz
parents: 362
diff changeset
96 if uri not in (self.DIRECTIVE_NAMESPACE,
37e4b4bb0b53 Parse template includes at parse time to avoid some runtime overhead.
cmlenz
parents: 362
diff changeset
97 self.XINCLUDE_NAMESPACE):
336
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
98 stream.append((kind, data, pos))
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
99
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
100 elif kind is END_NS:
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
101 uri = ns_prefix.pop(data, None)
363
37e4b4bb0b53 Parse template includes at parse time to avoid some runtime overhead.
cmlenz
parents: 362
diff changeset
102 if uri and uri not in (self.DIRECTIVE_NAMESPACE,
37e4b4bb0b53 Parse template includes at parse time to avoid some runtime overhead.
cmlenz
parents: 362
diff changeset
103 self.XINCLUDE_NAMESPACE):
336
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
104 stream.append((kind, data, pos))
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
105
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
106 elif kind is START:
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
107 # Record any directive attributes in start tags
363
37e4b4bb0b53 Parse template includes at parse time to avoid some runtime overhead.
cmlenz
parents: 362
diff changeset
108 tag, attrs = data
336
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
109 directives = []
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
110 strip = False
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
111
363
37e4b4bb0b53 Parse template includes at parse time to avoid some runtime overhead.
cmlenz
parents: 362
diff changeset
112 if tag in self.DIRECTIVE_NAMESPACE:
336
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
113 cls = self._dir_by_name.get(tag.localname)
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
114 if cls is None:
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
115 raise BadDirectiveError(tag.localname, self.filepath,
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
116 pos[1])
363
37e4b4bb0b53 Parse template includes at parse time to avoid some runtime overhead.
cmlenz
parents: 362
diff changeset
117 value = attrs.get(getattr(cls, 'ATTRIBUTE', None), '')
362
fe40d34fb71d 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
118 directives.append((cls, value, ns_prefix.copy(), pos))
336
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
119 strip = True
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
120
363
37e4b4bb0b53 Parse template includes at parse time to avoid some runtime overhead.
cmlenz
parents: 362
diff changeset
121 new_attrs = []
37e4b4bb0b53 Parse template includes at parse time to avoid some runtime overhead.
cmlenz
parents: 362
diff changeset
122 for name, value in attrs:
37e4b4bb0b53 Parse template includes at parse time to avoid some runtime overhead.
cmlenz
parents: 362
diff changeset
123 if name in self.DIRECTIVE_NAMESPACE:
336
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
124 cls = self._dir_by_name.get(name.localname)
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
125 if cls is None:
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
126 raise BadDirectiveError(name.localname,
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
127 self.filepath, pos[1])
362
fe40d34fb71d 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
128 directives.append((cls, value, ns_prefix.copy(), pos))
336
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
129 else:
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
130 if value:
407
f37d8e6acdf2 Move string interpolation code into separate module (`genshi.template.interpolation`).
cmlenz
parents: 405
diff changeset
131 value = list(interpolate(value, self.basedir, *pos))
336
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
132 if len(value) == 1 and value[0][0] is TEXT:
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
133 value = value[0][1]
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
134 else:
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
135 value = [(TEXT, u'', pos)]
363
37e4b4bb0b53 Parse template includes at parse time to avoid some runtime overhead.
cmlenz
parents: 362
diff changeset
136 new_attrs.append((name, value))
37e4b4bb0b53 Parse template includes at parse time to avoid some runtime overhead.
cmlenz
parents: 362
diff changeset
137 new_attrs = Attrs(new_attrs)
336
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
138
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
139 if directives:
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
140 index = self._dir_order.index
362
fe40d34fb71d 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
141 directives.sort(lambda a, b: cmp(index(a[0]), index(b[0])))
336
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
142 dirmap[(depth, tag)] = (directives, len(stream), strip)
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
143
363
37e4b4bb0b53 Parse template includes at parse time to avoid some runtime overhead.
cmlenz
parents: 362
diff changeset
144 if tag in self.XINCLUDE_NAMESPACE:
37e4b4bb0b53 Parse template includes at parse time to avoid some runtime overhead.
cmlenz
parents: 362
diff changeset
145 if tag.localname == 'include':
37e4b4bb0b53 Parse template includes at parse time to avoid some runtime overhead.
cmlenz
parents: 362
diff changeset
146 include_href = new_attrs.get('href')
37e4b4bb0b53 Parse template includes at parse time to avoid some runtime overhead.
cmlenz
parents: 362
diff changeset
147 if not include_href:
37e4b4bb0b53 Parse template includes at parse time to avoid some runtime overhead.
cmlenz
parents: 362
diff changeset
148 raise TemplateSyntaxError('Include misses required '
37e4b4bb0b53 Parse template includes at parse time to avoid some runtime overhead.
cmlenz
parents: 362
diff changeset
149 'attribute "href"', *pos)
381
b9fc7a1f76ca 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
37e4b4bb0b53 Parse template includes at parse time to avoid some runtime overhead.
cmlenz
parents: 362
diff changeset
151 elif tag.localname == 'fallback':
381
b9fc7a1f76ca 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
152 in_fallback += 1
363
37e4b4bb0b53 Parse template includes at parse time to avoid some runtime overhead.
cmlenz
parents: 362
diff changeset
153
37e4b4bb0b53 Parse template includes at parse time to avoid some runtime overhead.
cmlenz
parents: 362
diff changeset
154 else:
37e4b4bb0b53 Parse template includes at parse time to avoid some runtime overhead.
cmlenz
parents: 362
diff changeset
155 stream.append((kind, (tag, new_attrs), pos))
37e4b4bb0b53 Parse template includes at parse time to avoid some runtime overhead.
cmlenz
parents: 362
diff changeset
156
336
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
157 depth += 1
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
158
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
159 elif kind is END:
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
160 depth -= 1
363
37e4b4bb0b53 Parse template includes at parse time to avoid some runtime overhead.
cmlenz
parents: 362
diff changeset
161
381
b9fc7a1f76ca 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
162 if in_fallback and data == self.XINCLUDE_NAMESPACE['fallback']:
b9fc7a1f76ca 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
163 in_fallback -= 1
363
37e4b4bb0b53 Parse template includes at parse time to avoid some runtime overhead.
cmlenz
parents: 362
diff changeset
164 elif data == self.XINCLUDE_NAMESPACE['include']:
381
b9fc7a1f76ca 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
165 fallback = streams.pop()
b9fc7a1f76ca 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
166 stream = streams[-1]
b9fc7a1f76ca 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
167 stream.append((INCLUDE, (include_href, fallback), pos))
363
37e4b4bb0b53 Parse template includes at parse time to avoid some runtime overhead.
cmlenz
parents: 362
diff changeset
168 else:
37e4b4bb0b53 Parse template includes at parse time to avoid some runtime overhead.
cmlenz
parents: 362
diff changeset
169 stream.append((kind, data, pos))
336
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
170
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
171 # If there have have directive attributes with the corresponding
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
172 # start tag, move the events inbetween into a "subprogram"
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
173 if (depth, data) in dirmap:
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
174 directives, start_offset, strip = dirmap.pop((depth, data))
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
175 substream = stream[start_offset:]
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
176 if strip:
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
177 substream = substream[1:-1]
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
178 stream[start_offset:] = [(SUB, (directives, substream),
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
179 pos)]
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
180
405
5340931530e2 Support for Python code blocks using the `<?python ?>` processing instruction. Closes #84.
cmlenz
parents: 400
diff changeset
181 elif kind is PI and data[0] == 'python':
5340931530e2 Support for Python code blocks using the `<?python ?>` processing instruction. Closes #84.
cmlenz
parents: 400
diff changeset
182 try:
5340931530e2 Support for Python code blocks using the `<?python ?>` processing instruction. Closes #84.
cmlenz
parents: 400
diff changeset
183 # As Expat doesn't report whitespace between the PI target
5340931530e2 Support for Python code blocks using the `<?python ?>` processing instruction. Closes #84.
cmlenz
parents: 400
diff changeset
184 # and the data, we have to jump through some hoops here to
5340931530e2 Support for Python code blocks using the `<?python ?>` processing instruction. Closes #84.
cmlenz
parents: 400
diff changeset
185 # get correctly indented Python code
5340931530e2 Support for Python code blocks using the `<?python ?>` processing instruction. Closes #84.
cmlenz
parents: 400
diff changeset
186 # Unfortunately, we'll still probably not get the line
5340931530e2 Support for Python code blocks using the `<?python ?>` processing instruction. Closes #84.
cmlenz
parents: 400
diff changeset
187 # number quite right
5340931530e2 Support for Python code blocks using the `<?python ?>` processing instruction. Closes #84.
cmlenz
parents: 400
diff changeset
188 lines = [line.expandtabs() for line in data[1].splitlines()]
5340931530e2 Support for Python code blocks using the `<?python ?>` processing instruction. Closes #84.
cmlenz
parents: 400
diff changeset
189 first = lines[0]
5340931530e2 Support for Python code blocks using the `<?python ?>` processing instruction. Closes #84.
cmlenz
parents: 400
diff changeset
190 rest = dedent('\n'.join(lines[1:]))
5340931530e2 Support for Python code blocks using the `<?python ?>` processing instruction. Closes #84.
cmlenz
parents: 400
diff changeset
191 if first.rstrip().endswith(':') and not rest[0].isspace():
5340931530e2 Support for Python code blocks using the `<?python ?>` processing instruction. Closes #84.
cmlenz
parents: 400
diff changeset
192 rest = '\n'.join([' ' + line for line
5340931530e2 Support for Python code blocks using the `<?python ?>` processing instruction. Closes #84.
cmlenz
parents: 400
diff changeset
193 in rest.splitlines()])
5340931530e2 Support for Python code blocks using the `<?python ?>` processing instruction. Closes #84.
cmlenz
parents: 400
diff changeset
194 source = '\n'.join([first, rest])
5340931530e2 Support for Python code blocks using the `<?python ?>` processing instruction. Closes #84.
cmlenz
parents: 400
diff changeset
195 suite = Suite(source, self.filepath, pos[1])
5340931530e2 Support for Python code blocks using the `<?python ?>` processing instruction. Closes #84.
cmlenz
parents: 400
diff changeset
196 except SyntaxError, err:
5340931530e2 Support for Python code blocks using the `<?python ?>` processing instruction. Closes #84.
cmlenz
parents: 400
diff changeset
197 raise TemplateSyntaxError(err, self.filepath,
5340931530e2 Support for Python code blocks using the `<?python ?>` processing instruction. Closes #84.
cmlenz
parents: 400
diff changeset
198 pos[1] + (err.lineno or 1) - 1,
5340931530e2 Support for Python code blocks using the `<?python ?>` processing instruction. Closes #84.
cmlenz
parents: 400
diff changeset
199 pos[2] + (err.offset or 0))
5340931530e2 Support for Python code blocks using the `<?python ?>` processing instruction. Closes #84.
cmlenz
parents: 400
diff changeset
200 stream.append((EXEC, suite, pos))
5340931530e2 Support for Python code blocks using the `<?python ?>` processing instruction. Closes #84.
cmlenz
parents: 400
diff changeset
201
336
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
202 elif kind is TEXT:
407
f37d8e6acdf2 Move string interpolation code into separate module (`genshi.template.interpolation`).
cmlenz
parents: 405
diff changeset
203 for kind, data, pos in interpolate(data, self.basedir, *pos):
336
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
204 stream.append((kind, data, pos))
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
205
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
206 elif kind is COMMENT:
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
207 if not data.lstrip().startswith('!'):
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
208 stream.append((kind, data, pos))
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
209
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
210 else:
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
211 stream.append((kind, data, pos))
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
212
381
b9fc7a1f76ca 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
213 assert len(streams) == 1
b9fc7a1f76ca 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
214 return streams[0]
b9fc7a1f76ca 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
215
b9fc7a1f76ca 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
216 def _prepare(self, stream):
b9fc7a1f76ca 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
217 for kind, data, pos in Template._prepare(self, stream):
b9fc7a1f76ca 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
218 if kind is INCLUDE:
b9fc7a1f76ca 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
219 data = data[0], list(self._prepare(data[1]))
b9fc7a1f76ca 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
220 yield kind, data, pos
336
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
221
405
5340931530e2 Support for Python code blocks using the `<?python ?>` processing instruction. Closes #84.
cmlenz
parents: 400
diff changeset
222 def _exec(self, stream, ctxt):
5340931530e2 Support for Python code blocks using the `<?python ?>` processing instruction. Closes #84.
cmlenz
parents: 400
diff changeset
223 """Internal stream filter that executes code in <?python ?> processing
5340931530e2 Support for Python code blocks using the `<?python ?>` processing instruction. Closes #84.
cmlenz
parents: 400
diff changeset
224 instructions.
5340931530e2 Support for Python code blocks using the `<?python ?>` processing instruction. Closes #84.
cmlenz
parents: 400
diff changeset
225 """
5340931530e2 Support for Python code blocks using the `<?python ?>` processing instruction. Closes #84.
cmlenz
parents: 400
diff changeset
226 for event in stream:
5340931530e2 Support for Python code blocks using the `<?python ?>` processing instruction. Closes #84.
cmlenz
parents: 400
diff changeset
227 if event[0] is EXEC:
5340931530e2 Support for Python code blocks using the `<?python ?>` processing instruction. Closes #84.
cmlenz
parents: 400
diff changeset
228 event[1].execute(_ctxt2dict(ctxt))
5340931530e2 Support for Python code blocks using the `<?python ?>` processing instruction. Closes #84.
cmlenz
parents: 400
diff changeset
229 else:
5340931530e2 Support for Python code blocks using the `<?python ?>` processing instruction. Closes #84.
cmlenz
parents: 400
diff changeset
230 yield event
5340931530e2 Support for Python code blocks using the `<?python ?>` processing instruction. Closes #84.
cmlenz
parents: 400
diff changeset
231
363
37e4b4bb0b53 Parse template includes at parse time to avoid some runtime overhead.
cmlenz
parents: 362
diff changeset
232 def _include(self, stream, ctxt):
37e4b4bb0b53 Parse template includes at parse time to avoid some runtime overhead.
cmlenz
parents: 362
diff changeset
233 """Internal stream filter that performs inclusion of external
37e4b4bb0b53 Parse template includes at parse time to avoid some runtime overhead.
cmlenz
parents: 362
diff changeset
234 template files.
37e4b4bb0b53 Parse template includes at parse time to avoid some runtime overhead.
cmlenz
parents: 362
diff changeset
235 """
37e4b4bb0b53 Parse template includes at parse time to avoid some runtime overhead.
cmlenz
parents: 362
diff changeset
236 for event in stream:
37e4b4bb0b53 Parse template includes at parse time to avoid some runtime overhead.
cmlenz
parents: 362
diff changeset
237 if event[0] is INCLUDE:
37e4b4bb0b53 Parse template includes at parse time to avoid some runtime overhead.
cmlenz
parents: 362
diff changeset
238 href, fallback = event[1]
37e4b4bb0b53 Parse template includes at parse time to avoid some runtime overhead.
cmlenz
parents: 362
diff changeset
239 if not isinstance(href, basestring):
37e4b4bb0b53 Parse template includes at parse time to avoid some runtime overhead.
cmlenz
parents: 362
diff changeset
240 parts = []
37e4b4bb0b53 Parse template includes at parse time to avoid some runtime overhead.
cmlenz
parents: 362
diff changeset
241 for subkind, subdata, subpos in self._eval(href, ctxt):
37e4b4bb0b53 Parse template includes at parse time to avoid some runtime overhead.
cmlenz
parents: 362
diff changeset
242 if subkind is TEXT:
37e4b4bb0b53 Parse template includes at parse time to avoid some runtime overhead.
cmlenz
parents: 362
diff changeset
243 parts.append(subdata)
37e4b4bb0b53 Parse template includes at parse time to avoid some runtime overhead.
cmlenz
parents: 362
diff changeset
244 href = u''.join([x for x in parts if x is not None])
37e4b4bb0b53 Parse template includes at parse time to avoid some runtime overhead.
cmlenz
parents: 362
diff changeset
245 try:
37e4b4bb0b53 Parse template includes at parse time to avoid some runtime overhead.
cmlenz
parents: 362
diff changeset
246 tmpl = self.loader.load(href, relative_to=event[2][0])
37e4b4bb0b53 Parse template includes at parse time to avoid some runtime overhead.
cmlenz
parents: 362
diff changeset
247 for event in tmpl.generate(ctxt):
37e4b4bb0b53 Parse template includes at parse time to avoid some runtime overhead.
cmlenz
parents: 362
diff changeset
248 yield event
37e4b4bb0b53 Parse template includes at parse time to avoid some runtime overhead.
cmlenz
parents: 362
diff changeset
249 except TemplateNotFound:
37e4b4bb0b53 Parse template includes at parse time to avoid some runtime overhead.
cmlenz
parents: 362
diff changeset
250 if fallback is None:
37e4b4bb0b53 Parse template includes at parse time to avoid some runtime overhead.
cmlenz
parents: 362
diff changeset
251 raise
381
b9fc7a1f76ca 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
252 for filter_ in self.filters:
b9fc7a1f76ca 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
253 fallback = filter_(iter(fallback), ctxt)
363
37e4b4bb0b53 Parse template includes at parse time to avoid some runtime overhead.
cmlenz
parents: 362
diff changeset
254 for event in fallback:
37e4b4bb0b53 Parse template includes at parse time to avoid some runtime overhead.
cmlenz
parents: 362
diff changeset
255 yield event
37e4b4bb0b53 Parse template includes at parse time to avoid some runtime overhead.
cmlenz
parents: 362
diff changeset
256 else:
37e4b4bb0b53 Parse template includes at parse time to avoid some runtime overhead.
cmlenz
parents: 362
diff changeset
257 yield event
37e4b4bb0b53 Parse template includes at parse time to avoid some runtime overhead.
cmlenz
parents: 362
diff changeset
258
336
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
259 def _match(self, stream, ctxt, match_templates=None):
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
260 """Internal stream filter that applies any defined match templates
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
261 to the stream.
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
262 """
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
263 if match_templates is None:
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
264 match_templates = ctxt._match_templates
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
265
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
266 tail = []
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
267 def _strip(stream):
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
268 depth = 1
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
269 while 1:
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
270 event = stream.next()
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
271 if event[0] is START:
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
272 depth += 1
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
273 elif event[0] is END:
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
274 depth -= 1
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
275 if depth > 0:
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
276 yield event
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
277 else:
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
278 tail[:] = [event]
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
279 break
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
280
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
281 for event in stream:
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
282
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
283 # We (currently) only care about start and end events for matching
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
284 # We might care about namespace events in the future, though
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
285 if not match_templates or (event[0] is not START and
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
286 event[0] is not END):
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
287 yield event
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
288 continue
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
289
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
290 for idx, (test, path, template, namespaces, directives) in \
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
291 enumerate(match_templates):
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
292
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
293 if test(event, namespaces, ctxt) is True:
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
294
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
295 # Let the remaining match templates know about the event so
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
296 # they get a chance to update their internal state
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
297 for test in [mt[0] for mt in match_templates[idx + 1:]]:
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
298 test(event, namespaces, ctxt, updateonly=True)
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
299
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
300 # Consume and store all events until an end event
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
301 # corresponding to this start event is encountered
364
7dabedbb53fb Fix for #77: match templates were matching their own output.
cmlenz
parents: 363
diff changeset
302 content = chain([event],
7dabedbb53fb Fix for #77: match templates were matching their own output.
cmlenz
parents: 363
diff changeset
303 self._match(_strip(stream), ctxt,
7dabedbb53fb Fix for #77: match templates were matching their own output.
cmlenz
parents: 363
diff changeset
304 [match_templates[idx]]),
336
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
305 tail)
363
37e4b4bb0b53 Parse template includes at parse time to avoid some runtime overhead.
cmlenz
parents: 362
diff changeset
306 content = list(self._include(content, ctxt))
336
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
307
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
308 for test in [mt[0] for mt in match_templates]:
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
309 test(tail[0], namespaces, ctxt, updateonly=True)
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
310
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
311 # Make the select() function available in the body of the
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
312 # match template
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
313 def select(path):
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
314 return Stream(content).select(path, namespaces, ctxt)
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
315 ctxt.push(dict(select=select))
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
316
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
317 # Recursively process the output
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
318 template = _apply_directives(template, ctxt, directives)
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
319 for event in self._match(self._eval(self._flatten(template,
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
320 ctxt),
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
321 ctxt), ctxt,
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
322 match_templates[:idx] +
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
323 match_templates[idx + 1:]):
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
324 yield event
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
325
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
326 ctxt.pop()
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
327 break
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
328
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
329 else: # no matches
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
330 yield event
363
37e4b4bb0b53 Parse template includes at parse time to avoid some runtime overhead.
cmlenz
parents: 362
diff changeset
331
37e4b4bb0b53 Parse template includes at parse time to avoid some runtime overhead.
cmlenz
parents: 362
diff changeset
332
405
5340931530e2 Support for Python code blocks using the `<?python ?>` processing instruction. Closes #84.
cmlenz
parents: 400
diff changeset
333 EXEC = MarkupTemplate.EXEC
363
37e4b4bb0b53 Parse template includes at parse time to avoid some runtime overhead.
cmlenz
parents: 362
diff changeset
334 INCLUDE = MarkupTemplate.INCLUDE
Copyright (C) 2012-2017 Edgewall Software