annotate genshi/template/markup.py @ 704:422d0607ba85 experimental-match-fastpaths

further performance improvements to MatchSet functionality - factor out MatchSet's State so that we dont' have to keep copying over the state every time we create a new child MatchSet. Also fixes a bug where we could get duplicate match indexes when a new match is created while evaluating an existing match Also, try to be lazy about creating the first MatchSet so that we don't hurt bigtable performance (i.e. when there are no py:matches in play at all)
author aflett
date Fri, 04 Apr 2008 16:57:27 +0000
parents af57b12e3dd2
children 0e8b92905741
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
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
17
636
699601cce3cc 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
5340931530e2 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
7763f7aec949 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
e29a94b3ba0c 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
b373f80f7763 Added include directive for text templates (#115). Thanks to Alastair for the original patch.
cmlenz
parents: 442
diff changeset
22 TemplateSyntaxError, _apply_directives, \
609
6d4877844e28 Add support for Python code blocks in text templates using the new syntax.
cmlenz
parents: 606
diff changeset
23 EXEC, INCLUDE, SUB
405
5340931530e2 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
f37d8e6acdf2 Move string interpolation code into separate module (`genshi.template.interpolation`).
cmlenz
parents: 405
diff changeset
25 from genshi.template.interpolation import interpolate
336
7763f7aec949 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
5e358de79e4c * 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
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
28
425
073640758a42 Try to use proper reStructuredText for docstrings throughout.
cmlenz
parents: 422
diff changeset
29 __all__ = ['MarkupTemplate']
073640758a42 Try to use proper reStructuredText for docstrings throughout.
cmlenz
parents: 422
diff changeset
30 __docformat__ = 'restructuredtext en'
073640758a42 Try to use proper reStructuredText for docstrings throughout.
cmlenz
parents: 422
diff changeset
31
336
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
32
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
33 class MarkupTemplate(Template):
7763f7aec949 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.
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 >>> 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
37 ... <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
38 ... </ul>''')
7763f7aec949 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])
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
40 <ul>
7763f7aec949 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>
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
42 </ul>
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
43 """
427
55c574767df2 More API documentation.
cmlenz
parents: 425
diff changeset
44
363
37e4b4bb0b53 Parse template includes at parse time to avoid some runtime overhead.
cmlenz
parents: 362
diff changeset
45 DIRECTIVE_NAMESPACE = Namespace('http://genshi.edgewall.org/')
37e4b4bb0b53 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
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
47
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
48 directives = [('def', DefDirective),
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
49 ('match', MatchDirective),
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
50 ('when', WhenDirective),
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
51 ('otherwise', OtherwiseDirective),
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
52 ('for', ForDirective),
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
53 ('if', IfDirective),
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
54 ('choose', ChooseDirective),
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
55 ('with', WithDirective),
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
56 ('replace', ReplaceDirective),
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
57 ('content', ContentDirective),
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
58 ('attrs', AttrsDirective),
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
59 ('strip', StripDirective)]
605
d0345c64da65 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
699601cce3cc 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
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
62
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
63 def __init__(self, source, basedir=None, filename=None, loader=None,
606
37ff75bb4301 Changed the default error handling mode to "strict".
cmlenz
parents: 605
diff changeset
64 encoding=None, lookup='strict', allow_exec=True):
336
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
65 Template.__init__(self, source, basedir=basedir, filename=filename,
545
619340e2d805 Support for Python code blocks in templates can now be disabled. Closes #123.
cmlenz
parents: 520
diff changeset
66 loader=loader, encoding=encoding, lookup=lookup,
619340e2d805 Support for Python code blocks in templates can now be disabled. Closes #123.
cmlenz
parents: 520
diff changeset
67 allow_exec=allow_exec)
496
f56046e4b0de Fix bug introduced in [575]: includes weren't being processed inside match templates.
cmlenz
parents: 475
diff changeset
68 # Make sure the include filter comes after the match filter
f56046e4b0de Fix bug introduced in [575]: includes weren't being processed inside match templates.
cmlenz
parents: 475
diff changeset
69 if loader:
f56046e4b0de Fix bug introduced in [575]: includes weren't being processed inside match templates.
cmlenz
parents: 475
diff changeset
70 self.filters.remove(self._include)
609
6d4877844e28 Add support for Python code blocks in text templates using the new syntax.
cmlenz
parents: 606
diff changeset
71 self.filters += [self._match]
496
f56046e4b0de Fix bug introduced in [575]: includes weren't being processed inside match templates.
cmlenz
parents: 475
diff changeset
72 if loader:
f56046e4b0de Fix bug introduced in [575]: includes weren't being processed inside match templates.
cmlenz
parents: 475
diff changeset
73 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
74
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
75 def _parse(self, source, encoding):
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
76 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
77 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
78 ns_prefix = {}
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
79 depth = 0
590
36b5a03534a0 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
80 fallbacks = []
36b5a03534a0 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
81 includes = []
336
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
82
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
83 if not isinstance(source, Stream):
434
5692bc32ba5f * Better method to propogate the full path to the template file on parse errors. Supersedes r513.
cmlenz
parents: 427
diff changeset
84 source = XMLParser(source, filename=self.filename,
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 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
86
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 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
88 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
89
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
90 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
91 # 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
92 prefix, uri = data
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
93 ns_prefix[prefix] = uri
363
37e4b4bb0b53 Parse template includes at parse time to avoid some runtime overhead.
cmlenz
parents: 362
diff changeset
94 if uri not in (self.DIRECTIVE_NAMESPACE,
37e4b4bb0b53 Parse template includes at parse time to avoid some runtime overhead.
cmlenz
parents: 362
diff changeset
95 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
96 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
97
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
98 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
99 uri = ns_prefix.pop(data, None)
363
37e4b4bb0b53 Parse template includes at parse time to avoid some runtime overhead.
cmlenz
parents: 362
diff changeset
100 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
101 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
102 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
103
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
104 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
105 # 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
106 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
107 directives = []
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
108 strip = False
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
109
363
37e4b4bb0b53 Parse template includes at parse time to avoid some runtime overhead.
cmlenz
parents: 362
diff changeset
110 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
111 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
112 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
113 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
114 pos[1])
552
b59d99d2f631 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
115 args = dict([(name.localname, value) for name, value
b59d99d2f631 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
116 in attrs if not name.namespace])
b59d99d2f631 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
117 directives.append((cls, args, 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
118 strip = True
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
119
363
37e4b4bb0b53 Parse template includes at parse time to avoid some runtime overhead.
cmlenz
parents: 362
diff changeset
120 new_attrs = []
37e4b4bb0b53 Parse template includes at parse time to avoid some runtime overhead.
cmlenz
parents: 362
diff changeset
121 for name, value in attrs:
37e4b4bb0b53 Parse template includes at parse time to avoid some runtime overhead.
cmlenz
parents: 362
diff changeset
122 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
123 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
124 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
125 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
126 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
127 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
128 else:
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
129 if value:
442
97544725bb7f 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
130 value = list(interpolate(value, self.basedir,
97544725bb7f 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
131 pos[0], pos[1], pos[2],
97544725bb7f 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
132 lookup=self.lookup))
336
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
133 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
134 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
135 else:
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
136 value = [(TEXT, u'', pos)]
363
37e4b4bb0b53 Parse template includes at parse time to avoid some runtime overhead.
cmlenz
parents: 362
diff changeset
137 new_attrs.append((name, value))
37e4b4bb0b53 Parse template includes at parse time to avoid some runtime overhead.
cmlenz
parents: 362
diff changeset
138 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
139
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
140 if directives:
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
141 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
142 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
143 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
144
363
37e4b4bb0b53 Parse template includes at parse time to avoid some runtime overhead.
cmlenz
parents: 362
diff changeset
145 if tag in self.XINCLUDE_NAMESPACE:
37e4b4bb0b53 Parse template includes at parse time to avoid some runtime overhead.
cmlenz
parents: 362
diff changeset
146 if tag.localname == 'include':
37e4b4bb0b53 Parse template includes at parse time to avoid some runtime overhead.
cmlenz
parents: 362
diff changeset
147 include_href = new_attrs.get('href')
37e4b4bb0b53 Parse template includes at parse time to avoid some runtime overhead.
cmlenz
parents: 362
diff changeset
148 if not include_href:
37e4b4bb0b53 Parse template includes at parse time to avoid some runtime overhead.
cmlenz
parents: 362
diff changeset
149 raise TemplateSyntaxError('Include misses required '
422
5d08a744636e More work to include absolute file paths in exceptions.
cmlenz
parents: 421
diff changeset
150 'attribute "href"',
5d08a744636e More work to include absolute file paths in exceptions.
cmlenz
parents: 421
diff changeset
151 self.filepath, *pos[1:])
610
5e358de79e4c * 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
152 includes.append((include_href, new_attrs.get('parse')))
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
153 streams.append([])
363
37e4b4bb0b53 Parse template includes at parse time to avoid some runtime overhead.
cmlenz
parents: 362
diff changeset
154 elif tag.localname == 'fallback':
590
36b5a03534a0 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
155 streams.append([])
36b5a03534a0 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
156 fallbacks.append(streams[-1])
363
37e4b4bb0b53 Parse template includes at parse time to avoid some runtime overhead.
cmlenz
parents: 362
diff changeset
157
37e4b4bb0b53 Parse template includes at parse time to avoid some runtime overhead.
cmlenz
parents: 362
diff changeset
158 else:
37e4b4bb0b53 Parse template includes at parse time to avoid some runtime overhead.
cmlenz
parents: 362
diff changeset
159 stream.append((kind, (tag, new_attrs), pos))
37e4b4bb0b53 Parse template includes at parse time to avoid some runtime overhead.
cmlenz
parents: 362
diff changeset
160
336
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
161 depth += 1
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
162
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
163 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
164 depth -= 1
363
37e4b4bb0b53 Parse template includes at parse time to avoid some runtime overhead.
cmlenz
parents: 362
diff changeset
165
590
36b5a03534a0 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 if fallbacks and data == self.XINCLUDE_NAMESPACE['fallback']:
36b5a03534a0 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 assert streams.pop() is fallbacks[-1]
363
37e4b4bb0b53 Parse template includes at parse time to avoid some runtime overhead.
cmlenz
parents: 362
diff changeset
168 elif data == self.XINCLUDE_NAMESPACE['include']:
590
36b5a03534a0 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 fallback = None
36b5a03534a0 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 if len(fallbacks) == len(includes):
36b5a03534a0 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
171 fallback = fallbacks.pop()
36b5a03534a0 Fix includes so that they again raise an exception when the included template is not found and no fallback has been provided.
cmlenz
parents: 552
diff changeset
172 streams.pop() # discard anything between the include tags
36b5a03534a0 Fix includes so that they again raise an exception when the included template is not found and no fallback has been provided.
cmlenz
parents: 552
diff changeset
173 # and the fallback element
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
174 stream = streams[-1]
610
5e358de79e4c * 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 href, parse = includes.pop()
5e358de79e4c * 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 try:
5e358de79e4c * 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 cls = {
5e358de79e4c * 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 'xml': MarkupTemplate,
5e358de79e4c * 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 'text': NewTextTemplate
5e358de79e4c * 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 }[parse or 'xml']
5e358de79e4c * 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 except KeyError:
5e358de79e4c * 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 raise TemplateSyntaxError('Invalid value for "parse" '
5e358de79e4c * 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
183 'attribute of include',
5e358de79e4c * 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
184 self.filepath, *pos[1:])
5e358de79e4c * 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
185 stream.append((INCLUDE, (href, cls, fallback), pos))
363
37e4b4bb0b53 Parse template includes at parse time to avoid some runtime overhead.
cmlenz
parents: 362
diff changeset
186 else:
37e4b4bb0b53 Parse template includes at parse time to avoid some runtime overhead.
cmlenz
parents: 362
diff changeset
187 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
188
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
189 # 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
190 # 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
191 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
192 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
193 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
194 if strip:
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
195 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
196 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
197 pos)]
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
198
405
5340931530e2 Support for Python code blocks using the `<?python ?>` processing instruction. Closes #84.
cmlenz
parents: 400
diff changeset
199 elif kind is PI and data[0] == 'python':
545
619340e2d805 Support for Python code blocks in templates can now be disabled. Closes #123.
cmlenz
parents: 520
diff changeset
200 if not self.allow_exec:
619340e2d805 Support for Python code blocks in templates can now be disabled. Closes #123.
cmlenz
parents: 520
diff changeset
201 raise TemplateSyntaxError('Python code blocks not allowed',
619340e2d805 Support for Python code blocks in templates can now be disabled. Closes #123.
cmlenz
parents: 520
diff changeset
202 self.filepath, *pos[1:])
405
5340931530e2 Support for Python code blocks using the `<?python ?>` processing instruction. Closes #84.
cmlenz
parents: 400
diff changeset
203 try:
601
59fbd7586454 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
204 suite = Suite(data[1], self.filepath, pos[1],
442
97544725bb7f 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
205 lookup=self.lookup)
405
5340931530e2 Support for Python code blocks using the `<?python ?>` processing instruction. Closes #84.
cmlenz
parents: 400
diff changeset
206 except SyntaxError, err:
5340931530e2 Support for Python code blocks using the `<?python ?>` processing instruction. Closes #84.
cmlenz
parents: 400
diff changeset
207 raise TemplateSyntaxError(err, self.filepath,
5340931530e2 Support for Python code blocks using the `<?python ?>` processing instruction. Closes #84.
cmlenz
parents: 400
diff changeset
208 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
209 pos[2] + (err.offset or 0))
5340931530e2 Support for Python code blocks using the `<?python ?>` processing instruction. Closes #84.
cmlenz
parents: 400
diff changeset
210 stream.append((EXEC, suite, pos))
5340931530e2 Support for Python code blocks using the `<?python ?>` processing instruction. Closes #84.
cmlenz
parents: 400
diff changeset
211
336
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
212 elif kind is TEXT:
442
97544725bb7f 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
213 for kind, data, pos in interpolate(data, self.basedir, pos[0],
97544725bb7f 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
214 pos[1], pos[2],
97544725bb7f 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
215 lookup=self.lookup):
336
7763f7aec949 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))
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
217
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
218 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
219 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
220 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
221
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
222 else:
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
223 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
224
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
225 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
226 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
227
703
af57b12e3dd2 merge in trunk up through r818 - fundamentally changed the way MatchSet works, but actually is more consistent now
aflett
parents: 690
diff changeset
228 def _match(self, stream, ctxt, match_set=None, **vars):
336
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
229 """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
230 to the stream.
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
231 """
687
3d7288f373bd land first cut at fast-path matching - needs some cleanup
aflett
parents: 650
diff changeset
232 if match_set is None:
3d7288f373bd land first cut at fast-path matching - needs some cleanup
aflett
parents: 650
diff changeset
233 match_set = ctxt._match_set
336
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
234
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
235 tail = []
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
236 def _strip(stream):
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
237 depth = 1
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
238 while 1:
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
239 event = stream.next()
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
240 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
241 depth += 1
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
242 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
243 depth -= 1
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
244 if depth > 0:
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
245 yield event
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
246 else:
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
247 tail[:] = [event]
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
248 break
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
249
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
250 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
251
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
252 # 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
253 # We might care about namespace events in the future, though
687
3d7288f373bd land first cut at fast-path matching - needs some cleanup
aflett
parents: 650
diff changeset
254 if not match_set or (event[0] is not START and
3d7288f373bd land first cut at fast-path matching - needs some cleanup
aflett
parents: 650
diff changeset
255 event[0] is not END):
336
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
256 yield event
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
257 continue
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
258
687
3d7288f373bd land first cut at fast-path matching - needs some cleanup
aflett
parents: 650
diff changeset
259 match_candidates = list(match_set.find_matches(event))
3d7288f373bd land first cut at fast-path matching - needs some cleanup
aflett
parents: 650
diff changeset
260 for idx, match_template in enumerate(match_candidates):
3d7288f373bd land first cut at fast-path matching - needs some cleanup
aflett
parents: 650
diff changeset
261
3d7288f373bd land first cut at fast-path matching - needs some cleanup
aflett
parents: 650
diff changeset
262 (test, path, template, hints, namespaces, directives) = \
3d7288f373bd land first cut at fast-path matching - needs some cleanup
aflett
parents: 650
diff changeset
263 match_template
336
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
264 if test(event, namespaces, ctxt) is True:
703
af57b12e3dd2 merge in trunk up through r818 - fundamentally changed the way MatchSet works, but actually is more consistent now
aflett
parents: 690
diff changeset
265 post_match_templates = \
af57b12e3dd2 merge in trunk up through r818 - fundamentally changed the way MatchSet works, but actually is more consistent now
aflett
parents: 690
diff changeset
266 match_set.after_template(match_template)
af57b12e3dd2 merge in trunk up through r818 - fundamentally changed the way MatchSet works, but actually is more consistent now
aflett
parents: 690
diff changeset
267
602
d7b957e92ea9 Add runtime optimization hints for match templates.
cmlenz
parents: 601
diff changeset
268 if 'match_once' in hints:
703
af57b12e3dd2 merge in trunk up through r818 - fundamentally changed the way MatchSet works, but actually is more consistent now
aflett
parents: 690
diff changeset
269
af57b12e3dd2 merge in trunk up through r818 - fundamentally changed the way MatchSet works, but actually is more consistent now
aflett
parents: 690
diff changeset
270 # need to save this before we nuke
af57b12e3dd2 merge in trunk up through r818 - fundamentally changed the way MatchSet works, but actually is more consistent now
aflett
parents: 690
diff changeset
271 # match_template from match_set
af57b12e3dd2 merge in trunk up through r818 - fundamentally changed the way MatchSet works, but actually is more consistent now
aflett
parents: 690
diff changeset
272 pre_match_templates = \
af57b12e3dd2 merge in trunk up through r818 - fundamentally changed the way MatchSet works, but actually is more consistent now
aflett
parents: 690
diff changeset
273 match_set.before_template(match_template, False)
af57b12e3dd2 merge in trunk up through r818 - fundamentally changed the way MatchSet works, but actually is more consistent now
aflett
parents: 690
diff changeset
274
af57b12e3dd2 merge in trunk up through r818 - fundamentally changed the way MatchSet works, but actually is more consistent now
aflett
parents: 690
diff changeset
275 # forcibly remove this template from this and
af57b12e3dd2 merge in trunk up through r818 - fundamentally changed the way MatchSet works, but actually is more consistent now
aflett
parents: 690
diff changeset
276 # all child match sets
687
3d7288f373bd land first cut at fast-path matching - needs some cleanup
aflett
parents: 650
diff changeset
277 match_set.remove(match_template)
3d7288f373bd land first cut at fast-path matching - needs some cleanup
aflett
parents: 650
diff changeset
278 del match_candidates[idx]
602
d7b957e92ea9 Add runtime optimization hints for match templates.
cmlenz
parents: 601
diff changeset
279 idx -= 1
703
af57b12e3dd2 merge in trunk up through r818 - fundamentally changed the way MatchSet works, but actually is more consistent now
aflett
parents: 690
diff changeset
280 else:
af57b12e3dd2 merge in trunk up through r818 - fundamentally changed the way MatchSet works, but actually is more consistent now
aflett
parents: 690
diff changeset
281 inclusive = True
af57b12e3dd2 merge in trunk up through r818 - fundamentally changed the way MatchSet works, but actually is more consistent now
aflett
parents: 690
diff changeset
282 if 'not_recursive' in hints:
af57b12e3dd2 merge in trunk up through r818 - fundamentally changed the way MatchSet works, but actually is more consistent now
aflett
parents: 690
diff changeset
283 inclusive=False
af57b12e3dd2 merge in trunk up through r818 - fundamentally changed the way MatchSet works, but actually is more consistent now
aflett
parents: 690
diff changeset
284 pre_match_templates = match_set.before_template(match_template, inclusive)
336
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
285
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
286 # 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
287 # they get a chance to update their internal state
687
3d7288f373bd land first cut at fast-path matching - needs some cleanup
aflett
parents: 650
diff changeset
288 for test in [mt[0] for mt in match_candidates[idx + 1:]]:
336
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
289 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
290
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
291 # 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
292 # corresponding to this start event is encountered
602
d7b957e92ea9 Add runtime optimization hints for match templates.
cmlenz
parents: 601
diff changeset
293 inner = _strip(stream)
703
af57b12e3dd2 merge in trunk up through r818 - fundamentally changed the way MatchSet works, but actually is more consistent now
aflett
parents: 690
diff changeset
294 if pre_match_templates:
af57b12e3dd2 merge in trunk up through r818 - fundamentally changed the way MatchSet works, but actually is more consistent now
aflett
parents: 690
diff changeset
295 inner = self._match(inner, ctxt, pre_match_templates)
af57b12e3dd2 merge in trunk up through r818 - fundamentally changed the way MatchSet works, but actually is more consistent now
aflett
parents: 690
diff changeset
296 content = self._include(chain([event], inner, tail), ctxt)
af57b12e3dd2 merge in trunk up through r818 - fundamentally changed the way MatchSet works, but actually is more consistent now
aflett
parents: 690
diff changeset
297 if 'not_buffered' not in hints:
af57b12e3dd2 merge in trunk up through r818 - fundamentally changed the way MatchSet works, but actually is more consistent now
aflett
parents: 690
diff changeset
298 content = list(content)
336
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
299
687
3d7288f373bd land first cut at fast-path matching - needs some cleanup
aflett
parents: 650
diff changeset
300 # Now tell all the match templates about the
3d7288f373bd land first cut at fast-path matching - needs some cleanup
aflett
parents: 650
diff changeset
301 # END event (tail[0])
703
af57b12e3dd2 merge in trunk up through r818 - fundamentally changed the way MatchSet works, but actually is more consistent now
aflett
parents: 690
diff changeset
302 if tail:
af57b12e3dd2 merge in trunk up through r818 - fundamentally changed the way MatchSet works, but actually is more consistent now
aflett
parents: 690
diff changeset
303 for test in [mt[0] for mt in match_candidates]:
af57b12e3dd2 merge in trunk up through r818 - fundamentally changed the way MatchSet works, but actually is more consistent now
aflett
parents: 690
diff changeset
304 test(tail[0], namespaces, ctxt, updateonly=True)
336
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
305
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
306 # 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
307 # match template
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
308 def select(path):
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
309 return Stream(content).select(path, namespaces, ctxt)
703
af57b12e3dd2 merge in trunk up through r818 - fundamentally changed the way MatchSet works, but actually is more consistent now
aflett
parents: 690
diff changeset
310 vars = dict(select=select)
336
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
311
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
312 # Recursively process the output
703
af57b12e3dd2 merge in trunk up through r818 - fundamentally changed the way MatchSet works, but actually is more consistent now
aflett
parents: 690
diff changeset
313 template = _apply_directives(template, directives, ctxt,
af57b12e3dd2 merge in trunk up through r818 - fundamentally changed the way MatchSet works, but actually is more consistent now
aflett
parents: 690
diff changeset
314 **vars)
af57b12e3dd2 merge in trunk up through r818 - fundamentally changed the way MatchSet works, but actually is more consistent now
aflett
parents: 690
diff changeset
315 for event in self._match(
af57b12e3dd2 merge in trunk up through r818 - fundamentally changed the way MatchSet works, but actually is more consistent now
aflett
parents: 690
diff changeset
316 self._exec(
af57b12e3dd2 merge in trunk up through r818 - fundamentally changed the way MatchSet works, but actually is more consistent now
aflett
parents: 690
diff changeset
317 self._eval(
af57b12e3dd2 merge in trunk up through r818 - fundamentally changed the way MatchSet works, but actually is more consistent now
aflett
parents: 690
diff changeset
318 self._flatten(template, ctxt, **vars),
af57b12e3dd2 merge in trunk up through r818 - fundamentally changed the way MatchSet works, but actually is more consistent now
aflett
parents: 690
diff changeset
319 ctxt, **vars),
af57b12e3dd2 merge in trunk up through r818 - fundamentally changed the way MatchSet works, but actually is more consistent now
aflett
parents: 690
diff changeset
320 ctxt, **vars),
af57b12e3dd2 merge in trunk up through r818 - fundamentally changed the way MatchSet works, but actually is more consistent now
aflett
parents: 690
diff changeset
321 ctxt, post_match_templates,
af57b12e3dd2 merge in trunk up through r818 - fundamentally changed the way MatchSet works, but actually is more consistent now
aflett
parents: 690
diff changeset
322 **vars):
336
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
323 yield event
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
324
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
325 break
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
326
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
327 else: # no matches
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
328 yield event
Copyright (C) 2012-2017 Edgewall Software