Mercurial > genshi > mirror
annotate genshi/template/markup.py @ 1032:56fd1ca051af stable-0.7.x
Merge r1257 from trunk (fix for infinite template inlining).
author | hodgestar |
---|---|
date | Wed, 19 Mar 2014 13:54:59 +0000 |
parents | 2069c7a0059c |
children |
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 # |
897 | 3 # Copyright (C) 2006-2010 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>''') |
853
f33ecf3c319e
Convert a bunch of print statements to py3k compatible syntax.
cmlenz
parents:
847
diff
changeset
|
39 >>> print(tmpl.generate(items=[1, 2, 3])) |
336
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 | 44 |
790
da90cee22560
Merged the custom-directives branch back into trunk.
cmlenz
parents:
783
diff
changeset
|
45 DIRECTIVE_NAMESPACE = 'http://genshi.edgewall.org/' |
da90cee22560
Merged the custom-directives branch back into trunk.
cmlenz
parents:
783
diff
changeset
|
46 XINCLUDE_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 |
790
da90cee22560
Merged the custom-directives branch back into trunk.
cmlenz
parents:
783
diff
changeset
|
63 def __init__(self, source, filepath=None, filename=None, loader=None, |
da90cee22560
Merged the custom-directives branch back into trunk.
cmlenz
parents:
783
diff
changeset
|
64 encoding=None, lookup='strict', allow_exec=True): |
da90cee22560
Merged the custom-directives branch back into trunk.
cmlenz
parents:
783
diff
changeset
|
65 Template.__init__(self, source, filepath=filepath, filename=filename, |
da90cee22560
Merged the custom-directives branch back into trunk.
cmlenz
parents:
783
diff
changeset
|
66 loader=loader, encoding=encoding, lookup=lookup, |
da90cee22560
Merged the custom-directives branch back into trunk.
cmlenz
parents:
783
diff
changeset
|
67 allow_exec=allow_exec) |
da90cee22560
Merged the custom-directives branch back into trunk.
cmlenz
parents:
783
diff
changeset
|
68 self.add_directives(self.DIRECTIVE_NAMESPACE, self) |
da90cee22560
Merged the custom-directives branch back into trunk.
cmlenz
parents:
783
diff
changeset
|
69 |
715 | 70 def _init_filters(self): |
71 Template._init_filters(self) | |
496
f56046e4b0de
Fix bug introduced in [575]: includes weren't being processed inside match templates.
cmlenz
parents:
475
diff
changeset
|
72 # Make sure the include filter comes after the match filter |
876
124b57282f81
Templates instantiated without a loader now get an implicit loader based on their file path, or the current directory as a fallback. Closes #320.
cmlenz
parents:
874
diff
changeset
|
73 self.filters.remove(self._include) |
124b57282f81
Templates instantiated without a loader now get an implicit loader based on their file path, or the current directory as a fallback. Closes #320.
cmlenz
parents:
874
diff
changeset
|
74 self.filters += [self._match, 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): |
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
|
77 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
|
78 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
|
79 encoding=encoding) |
790
da90cee22560
Merged the custom-directives branch back into trunk.
cmlenz
parents:
783
diff
changeset
|
80 stream = [] |
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
|
81 |
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
|
82 for kind, data, pos in source: |
336
7763f7aec949
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
83 |
790
da90cee22560
Merged the custom-directives branch back into trunk.
cmlenz
parents:
783
diff
changeset
|
84 if kind is TEXT: |
da90cee22560
Merged the custom-directives branch back into trunk.
cmlenz
parents:
783
diff
changeset
|
85 for kind, data, pos in interpolate(data, self.filepath, pos[1], |
da90cee22560
Merged the custom-directives branch back into trunk.
cmlenz
parents:
783
diff
changeset
|
86 pos[2], 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
|
87 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
|
88 |
790
da90cee22560
Merged the custom-directives branch back into trunk.
cmlenz
parents:
783
diff
changeset
|
89 elif kind is PI and data[0] == 'python': |
da90cee22560
Merged the custom-directives branch back into trunk.
cmlenz
parents:
783
diff
changeset
|
90 if not self.allow_exec: |
da90cee22560
Merged the custom-directives branch back into trunk.
cmlenz
parents:
783
diff
changeset
|
91 raise TemplateSyntaxError('Python code blocks not allowed', |
da90cee22560
Merged the custom-directives branch back into trunk.
cmlenz
parents:
783
diff
changeset
|
92 self.filepath, *pos[1:]) |
da90cee22560
Merged the custom-directives branch back into trunk.
cmlenz
parents:
783
diff
changeset
|
93 try: |
da90cee22560
Merged the custom-directives branch back into trunk.
cmlenz
parents:
783
diff
changeset
|
94 suite = Suite(data[1], self.filepath, pos[1], |
da90cee22560
Merged the custom-directives branch back into trunk.
cmlenz
parents:
783
diff
changeset
|
95 lookup=self.lookup) |
da90cee22560
Merged the custom-directives branch back into trunk.
cmlenz
parents:
783
diff
changeset
|
96 except SyntaxError, err: |
da90cee22560
Merged the custom-directives branch back into trunk.
cmlenz
parents:
783
diff
changeset
|
97 raise TemplateSyntaxError(err, self.filepath, |
da90cee22560
Merged the custom-directives branch back into trunk.
cmlenz
parents:
783
diff
changeset
|
98 pos[1] + (err.lineno or 1) - 1, |
da90cee22560
Merged the custom-directives branch back into trunk.
cmlenz
parents:
783
diff
changeset
|
99 pos[2] + (err.offset or 0)) |
da90cee22560
Merged the custom-directives branch back into trunk.
cmlenz
parents:
783
diff
changeset
|
100 stream.append((EXEC, suite, pos)) |
da90cee22560
Merged the custom-directives branch back into trunk.
cmlenz
parents:
783
diff
changeset
|
101 |
da90cee22560
Merged the custom-directives branch back into trunk.
cmlenz
parents:
783
diff
changeset
|
102 elif kind is COMMENT: |
da90cee22560
Merged the custom-directives branch back into trunk.
cmlenz
parents:
783
diff
changeset
|
103 if not data.lstrip().startswith('!'): |
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 |
790
da90cee22560
Merged the custom-directives branch back into trunk.
cmlenz
parents:
783
diff
changeset
|
106 else: |
da90cee22560
Merged the custom-directives branch back into trunk.
cmlenz
parents:
783
diff
changeset
|
107 stream.append((kind, data, pos)) |
da90cee22560
Merged the custom-directives branch back into trunk.
cmlenz
parents:
783
diff
changeset
|
108 |
da90cee22560
Merged the custom-directives branch back into trunk.
cmlenz
parents:
783
diff
changeset
|
109 return stream |
da90cee22560
Merged the custom-directives branch back into trunk.
cmlenz
parents:
783
diff
changeset
|
110 |
da90cee22560
Merged the custom-directives branch back into trunk.
cmlenz
parents:
783
diff
changeset
|
111 def _extract_directives(self, stream, namespace, factory): |
da90cee22560
Merged the custom-directives branch back into trunk.
cmlenz
parents:
783
diff
changeset
|
112 depth = 0 |
da90cee22560
Merged the custom-directives branch back into trunk.
cmlenz
parents:
783
diff
changeset
|
113 dirmap = {} # temporary mapping of directives to elements |
da90cee22560
Merged the custom-directives branch back into trunk.
cmlenz
parents:
783
diff
changeset
|
114 new_stream = [] |
da90cee22560
Merged the custom-directives branch back into trunk.
cmlenz
parents:
783
diff
changeset
|
115 ns_prefix = {} # namespace prefixes in use |
da90cee22560
Merged the custom-directives branch back into trunk.
cmlenz
parents:
783
diff
changeset
|
116 |
da90cee22560
Merged the custom-directives branch back into trunk.
cmlenz
parents:
783
diff
changeset
|
117 for kind, data, pos in stream: |
da90cee22560
Merged the custom-directives branch back into trunk.
cmlenz
parents:
783
diff
changeset
|
118 |
da90cee22560
Merged the custom-directives branch back into trunk.
cmlenz
parents:
783
diff
changeset
|
119 if kind is START: |
363
37e4b4bb0b53
Parse template includes at parse time to avoid some runtime overhead.
cmlenz
parents:
362
diff
changeset
|
120 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
|
121 directives = [] |
7763f7aec949
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
122 strip = False |
7763f7aec949
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
123 |
790
da90cee22560
Merged the custom-directives branch back into trunk.
cmlenz
parents:
783
diff
changeset
|
124 if tag.namespace == namespace: |
da90cee22560
Merged the custom-directives branch back into trunk.
cmlenz
parents:
783
diff
changeset
|
125 cls = factory.get_directive(tag.localname) |
336
7763f7aec949
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
126 if cls is None: |
790
da90cee22560
Merged the custom-directives branch back into trunk.
cmlenz
parents:
783
diff
changeset
|
127 raise BadDirectiveError(tag.localname, |
da90cee22560
Merged the custom-directives branch back into trunk.
cmlenz
parents:
783
diff
changeset
|
128 self.filepath, 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
|
129 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
|
130 in attrs if not name.namespace]) |
847
e16447a9605f
Backported a couple of templating core changes from the advanced-i18n branch, in particular considering the determination of directive ordering../set
cmlenz
parents:
843
diff
changeset
|
131 directives.append((factory.get_directive_index(cls), cls, |
e16447a9605f
Backported a couple of templating core changes from the advanced-i18n branch, in particular considering the determination of directive ordering../set
cmlenz
parents:
843
diff
changeset
|
132 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
|
133 strip = True |
7763f7aec949
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
134 |
363
37e4b4bb0b53
Parse template includes at parse time to avoid some runtime overhead.
cmlenz
parents:
362
diff
changeset
|
135 new_attrs = [] |
37e4b4bb0b53
Parse template includes at parse time to avoid some runtime overhead.
cmlenz
parents:
362
diff
changeset
|
136 for name, value in attrs: |
790
da90cee22560
Merged the custom-directives branch back into trunk.
cmlenz
parents:
783
diff
changeset
|
137 if name.namespace == namespace: |
da90cee22560
Merged the custom-directives branch back into trunk.
cmlenz
parents:
783
diff
changeset
|
138 cls = factory.get_directive(name.localname) |
336
7763f7aec949
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
139 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
|
140 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
|
141 self.filepath, pos[1]) |
790
da90cee22560
Merged the custom-directives branch back into trunk.
cmlenz
parents:
783
diff
changeset
|
142 if type(value) is list and len(value) == 1: |
da90cee22560
Merged the custom-directives branch back into trunk.
cmlenz
parents:
783
diff
changeset
|
143 value = value[0][1] |
847
e16447a9605f
Backported a couple of templating core changes from the advanced-i18n branch, in particular considering the determination of directive ordering../set
cmlenz
parents:
843
diff
changeset
|
144 directives.append((factory.get_directive_index(cls), |
e16447a9605f
Backported a couple of templating core changes from the advanced-i18n branch, in particular considering the determination of directive ordering../set
cmlenz
parents:
843
diff
changeset
|
145 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
|
146 else: |
363
37e4b4bb0b53
Parse template includes at parse time to avoid some runtime overhead.
cmlenz
parents:
362
diff
changeset
|
147 new_attrs.append((name, value)) |
37e4b4bb0b53
Parse template includes at parse time to avoid some runtime overhead.
cmlenz
parents:
362
diff
changeset
|
148 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
|
149 |
7763f7aec949
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
150 if directives: |
847
e16447a9605f
Backported a couple of templating core changes from the advanced-i18n branch, in particular considering the determination of directive ordering../set
cmlenz
parents:
843
diff
changeset
|
151 directives.sort() |
790
da90cee22560
Merged the custom-directives branch back into trunk.
cmlenz
parents:
783
diff
changeset
|
152 dirmap[(depth, tag)] = (directives, len(new_stream), |
da90cee22560
Merged the custom-directives branch back into trunk.
cmlenz
parents:
783
diff
changeset
|
153 strip) |
336
7763f7aec949
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
154 |
790
da90cee22560
Merged the custom-directives branch back into trunk.
cmlenz
parents:
783
diff
changeset
|
155 new_stream.append((kind, (tag, new_attrs), pos)) |
da90cee22560
Merged the custom-directives branch back into trunk.
cmlenz
parents:
783
diff
changeset
|
156 depth += 1 |
da90cee22560
Merged the custom-directives branch back into trunk.
cmlenz
parents:
783
diff
changeset
|
157 |
da90cee22560
Merged the custom-directives branch back into trunk.
cmlenz
parents:
783
diff
changeset
|
158 elif kind is END: |
da90cee22560
Merged the custom-directives branch back into trunk.
cmlenz
parents:
783
diff
changeset
|
159 depth -= 1 |
da90cee22560
Merged the custom-directives branch back into trunk.
cmlenz
parents:
783
diff
changeset
|
160 new_stream.append((kind, data, pos)) |
da90cee22560
Merged the custom-directives branch back into trunk.
cmlenz
parents:
783
diff
changeset
|
161 |
da90cee22560
Merged the custom-directives branch back into trunk.
cmlenz
parents:
783
diff
changeset
|
162 # If there have have directive attributes with the |
da90cee22560
Merged the custom-directives branch back into trunk.
cmlenz
parents:
783
diff
changeset
|
163 # corresponding start tag, move the events inbetween into |
da90cee22560
Merged the custom-directives branch back into trunk.
cmlenz
parents:
783
diff
changeset
|
164 # a "subprogram" |
da90cee22560
Merged the custom-directives branch back into trunk.
cmlenz
parents:
783
diff
changeset
|
165 if (depth, data) in dirmap: |
da90cee22560
Merged the custom-directives branch back into trunk.
cmlenz
parents:
783
diff
changeset
|
166 directives, offset, strip = dirmap.pop((depth, data)) |
da90cee22560
Merged the custom-directives branch back into trunk.
cmlenz
parents:
783
diff
changeset
|
167 substream = new_stream[offset:] |
da90cee22560
Merged the custom-directives branch back into trunk.
cmlenz
parents:
783
diff
changeset
|
168 if strip: |
da90cee22560
Merged the custom-directives branch back into trunk.
cmlenz
parents:
783
diff
changeset
|
169 substream = substream[1:-1] |
da90cee22560
Merged the custom-directives branch back into trunk.
cmlenz
parents:
783
diff
changeset
|
170 new_stream[offset:] = [ |
da90cee22560
Merged the custom-directives branch back into trunk.
cmlenz
parents:
783
diff
changeset
|
171 (SUB, (directives, substream), pos) |
da90cee22560
Merged the custom-directives branch back into trunk.
cmlenz
parents:
783
diff
changeset
|
172 ] |
da90cee22560
Merged the custom-directives branch back into trunk.
cmlenz
parents:
783
diff
changeset
|
173 |
da90cee22560
Merged the custom-directives branch back into trunk.
cmlenz
parents:
783
diff
changeset
|
174 elif kind is SUB: |
da90cee22560
Merged the custom-directives branch back into trunk.
cmlenz
parents:
783
diff
changeset
|
175 directives, substream = data |
da90cee22560
Merged the custom-directives branch back into trunk.
cmlenz
parents:
783
diff
changeset
|
176 substream = self._extract_directives(substream, namespace, |
da90cee22560
Merged the custom-directives branch back into trunk.
cmlenz
parents:
783
diff
changeset
|
177 factory) |
da90cee22560
Merged the custom-directives branch back into trunk.
cmlenz
parents:
783
diff
changeset
|
178 |
da90cee22560
Merged the custom-directives branch back into trunk.
cmlenz
parents:
783
diff
changeset
|
179 if len(substream) == 1 and substream[0][0] is SUB: |
da90cee22560
Merged the custom-directives branch back into trunk.
cmlenz
parents:
783
diff
changeset
|
180 added_directives, substream = substream[0][1] |
da90cee22560
Merged the custom-directives branch back into trunk.
cmlenz
parents:
783
diff
changeset
|
181 directives += added_directives |
da90cee22560
Merged the custom-directives branch back into trunk.
cmlenz
parents:
783
diff
changeset
|
182 |
da90cee22560
Merged the custom-directives branch back into trunk.
cmlenz
parents:
783
diff
changeset
|
183 new_stream.append((kind, (directives, substream), pos)) |
da90cee22560
Merged the custom-directives branch back into trunk.
cmlenz
parents:
783
diff
changeset
|
184 |
da90cee22560
Merged the custom-directives branch back into trunk.
cmlenz
parents:
783
diff
changeset
|
185 elif kind is START_NS: |
da90cee22560
Merged the custom-directives branch back into trunk.
cmlenz
parents:
783
diff
changeset
|
186 # Strip out the namespace declaration for template |
da90cee22560
Merged the custom-directives branch back into trunk.
cmlenz
parents:
783
diff
changeset
|
187 # directives |
da90cee22560
Merged the custom-directives branch back into trunk.
cmlenz
parents:
783
diff
changeset
|
188 prefix, uri = data |
da90cee22560
Merged the custom-directives branch back into trunk.
cmlenz
parents:
783
diff
changeset
|
189 ns_prefix[prefix] = uri |
da90cee22560
Merged the custom-directives branch back into trunk.
cmlenz
parents:
783
diff
changeset
|
190 if uri != namespace: |
da90cee22560
Merged the custom-directives branch back into trunk.
cmlenz
parents:
783
diff
changeset
|
191 new_stream.append((kind, data, pos)) |
da90cee22560
Merged the custom-directives branch back into trunk.
cmlenz
parents:
783
diff
changeset
|
192 |
da90cee22560
Merged the custom-directives branch back into trunk.
cmlenz
parents:
783
diff
changeset
|
193 elif kind is END_NS: |
da90cee22560
Merged the custom-directives branch back into trunk.
cmlenz
parents:
783
diff
changeset
|
194 uri = ns_prefix.pop(data, None) |
da90cee22560
Merged the custom-directives branch back into trunk.
cmlenz
parents:
783
diff
changeset
|
195 if uri and uri != namespace: |
da90cee22560
Merged the custom-directives branch back into trunk.
cmlenz
parents:
783
diff
changeset
|
196 new_stream.append((kind, data, pos)) |
da90cee22560
Merged the custom-directives branch back into trunk.
cmlenz
parents:
783
diff
changeset
|
197 |
da90cee22560
Merged the custom-directives branch back into trunk.
cmlenz
parents:
783
diff
changeset
|
198 else: |
da90cee22560
Merged the custom-directives branch back into trunk.
cmlenz
parents:
783
diff
changeset
|
199 new_stream.append((kind, data, pos)) |
da90cee22560
Merged the custom-directives branch back into trunk.
cmlenz
parents:
783
diff
changeset
|
200 |
da90cee22560
Merged the custom-directives branch back into trunk.
cmlenz
parents:
783
diff
changeset
|
201 return new_stream |
da90cee22560
Merged the custom-directives branch back into trunk.
cmlenz
parents:
783
diff
changeset
|
202 |
da90cee22560
Merged the custom-directives branch back into trunk.
cmlenz
parents:
783
diff
changeset
|
203 def _extract_includes(self, stream): |
da90cee22560
Merged the custom-directives branch back into trunk.
cmlenz
parents:
783
diff
changeset
|
204 streams = [[]] # stacked lists of events of the "compiled" template |
da90cee22560
Merged the custom-directives branch back into trunk.
cmlenz
parents:
783
diff
changeset
|
205 prefixes = {} |
da90cee22560
Merged the custom-directives branch back into trunk.
cmlenz
parents:
783
diff
changeset
|
206 fallbacks = [] |
da90cee22560
Merged the custom-directives branch back into trunk.
cmlenz
parents:
783
diff
changeset
|
207 includes = [] |
da90cee22560
Merged the custom-directives branch back into trunk.
cmlenz
parents:
783
diff
changeset
|
208 xinclude_ns = Namespace(self.XINCLUDE_NAMESPACE) |
da90cee22560
Merged the custom-directives branch back into trunk.
cmlenz
parents:
783
diff
changeset
|
209 |
da90cee22560
Merged the custom-directives branch back into trunk.
cmlenz
parents:
783
diff
changeset
|
210 for kind, data, pos in stream: |
da90cee22560
Merged the custom-directives branch back into trunk.
cmlenz
parents:
783
diff
changeset
|
211 stream = streams[-1] |
da90cee22560
Merged the custom-directives branch back into trunk.
cmlenz
parents:
783
diff
changeset
|
212 |
da90cee22560
Merged the custom-directives branch back into trunk.
cmlenz
parents:
783
diff
changeset
|
213 if kind is START: |
da90cee22560
Merged the custom-directives branch back into trunk.
cmlenz
parents:
783
diff
changeset
|
214 # Record any directive attributes in start tags |
da90cee22560
Merged the custom-directives branch back into trunk.
cmlenz
parents:
783
diff
changeset
|
215 tag, attrs = data |
da90cee22560
Merged the custom-directives branch back into trunk.
cmlenz
parents:
783
diff
changeset
|
216 if tag in xinclude_ns: |
363
37e4b4bb0b53
Parse template includes at parse time to avoid some runtime overhead.
cmlenz
parents:
362
diff
changeset
|
217 if tag.localname == 'include': |
790
da90cee22560
Merged the custom-directives branch back into trunk.
cmlenz
parents:
783
diff
changeset
|
218 include_href = attrs.get('href') |
363
37e4b4bb0b53
Parse template includes at parse time to avoid some runtime overhead.
cmlenz
parents:
362
diff
changeset
|
219 if not include_href: |
37e4b4bb0b53
Parse template includes at parse time to avoid some runtime overhead.
cmlenz
parents:
362
diff
changeset
|
220 raise TemplateSyntaxError('Include misses required ' |
422
5d08a744636e
More work to include absolute file paths in exceptions.
cmlenz
parents:
421
diff
changeset
|
221 'attribute "href"', |
5d08a744636e
More work to include absolute file paths in exceptions.
cmlenz
parents:
421
diff
changeset
|
222 self.filepath, *pos[1:]) |
790
da90cee22560
Merged the custom-directives branch back into trunk.
cmlenz
parents:
783
diff
changeset
|
223 includes.append((include_href, 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
|
224 streams.append([]) |
363
37e4b4bb0b53
Parse template includes at parse time to avoid some runtime overhead.
cmlenz
parents:
362
diff
changeset
|
225 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
|
226 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
|
227 fallbacks.append(streams[-1]) |
363
37e4b4bb0b53
Parse template includes at parse time to avoid some runtime overhead.
cmlenz
parents:
362
diff
changeset
|
228 else: |
790
da90cee22560
Merged the custom-directives branch back into trunk.
cmlenz
parents:
783
diff
changeset
|
229 stream.append((kind, (tag, attrs), pos)) |
336
7763f7aec949
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
230 |
7763f7aec949
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
231 elif kind is END: |
790
da90cee22560
Merged the custom-directives branch back into trunk.
cmlenz
parents:
783
diff
changeset
|
232 if fallbacks and data == xinclude_ns['fallback']: |
1014
2069c7a0059c
Merge r1239 from trunk (fix assert with side-effect in xi:fallback directive processing).
hodgestar
parents:
945
diff
changeset
|
233 fallback_stream = streams.pop() |
2069c7a0059c
Merge r1239 from trunk (fix assert with side-effect in xi:fallback directive processing).
hodgestar
parents:
945
diff
changeset
|
234 assert fallback_stream is fallbacks[-1] |
790
da90cee22560
Merged the custom-directives branch back into trunk.
cmlenz
parents:
783
diff
changeset
|
235 elif data == xinclude_ns['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
|
236 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
|
237 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
|
238 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
|
239 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
|
240 # 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
|
241 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
|
242 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
|
243 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
|
244 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
|
245 '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
|
246 'text': NewTextTemplate |
880
aaaf6bb7bf96
Default XInclude-included template class to the class of the including template. Closes #302.
cmlenz
parents:
876
diff
changeset
|
247 }.get(parse) or self.__class__ |
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
|
248 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
|
249 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
|
250 '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
|
251 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
|
252 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
|
253 else: |
37e4b4bb0b53
Parse template includes at parse time to avoid some runtime overhead.
cmlenz
parents:
362
diff
changeset
|
254 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
|
255 |
790
da90cee22560
Merged the custom-directives branch back into trunk.
cmlenz
parents:
783
diff
changeset
|
256 elif kind is START_NS and data[1] == xinclude_ns: |
da90cee22560
Merged the custom-directives branch back into trunk.
cmlenz
parents:
783
diff
changeset
|
257 # Strip out the XInclude namespace |
da90cee22560
Merged the custom-directives branch back into trunk.
cmlenz
parents:
783
diff
changeset
|
258 prefixes[data[0]] = data[1] |
336
7763f7aec949
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
259 |
790
da90cee22560
Merged the custom-directives branch back into trunk.
cmlenz
parents:
783
diff
changeset
|
260 elif kind is END_NS and data in prefixes: |
da90cee22560
Merged the custom-directives branch back into trunk.
cmlenz
parents:
783
diff
changeset
|
261 prefixes.pop(data) |
336
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 else: |
7763f7aec949
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
264 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
|
265 |
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
|
266 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
|
267 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
|
268 |
790
da90cee22560
Merged the custom-directives branch back into trunk.
cmlenz
parents:
783
diff
changeset
|
269 def _interpolate_attrs(self, stream): |
da90cee22560
Merged the custom-directives branch back into trunk.
cmlenz
parents:
783
diff
changeset
|
270 for kind, data, pos in stream: |
da90cee22560
Merged the custom-directives branch back into trunk.
cmlenz
parents:
783
diff
changeset
|
271 |
da90cee22560
Merged the custom-directives branch back into trunk.
cmlenz
parents:
783
diff
changeset
|
272 if kind is START: |
da90cee22560
Merged the custom-directives branch back into trunk.
cmlenz
parents:
783
diff
changeset
|
273 # Record any directive attributes in start tags |
da90cee22560
Merged the custom-directives branch back into trunk.
cmlenz
parents:
783
diff
changeset
|
274 tag, attrs = data |
da90cee22560
Merged the custom-directives branch back into trunk.
cmlenz
parents:
783
diff
changeset
|
275 new_attrs = [] |
da90cee22560
Merged the custom-directives branch back into trunk.
cmlenz
parents:
783
diff
changeset
|
276 for name, value in attrs: |
da90cee22560
Merged the custom-directives branch back into trunk.
cmlenz
parents:
783
diff
changeset
|
277 if value: |
da90cee22560
Merged the custom-directives branch back into trunk.
cmlenz
parents:
783
diff
changeset
|
278 value = list(interpolate(value, self.filepath, pos[1], |
da90cee22560
Merged the custom-directives branch back into trunk.
cmlenz
parents:
783
diff
changeset
|
279 pos[2], lookup=self.lookup)) |
da90cee22560
Merged the custom-directives branch back into trunk.
cmlenz
parents:
783
diff
changeset
|
280 if len(value) == 1 and value[0][0] is TEXT: |
da90cee22560
Merged the custom-directives branch back into trunk.
cmlenz
parents:
783
diff
changeset
|
281 value = value[0][1] |
da90cee22560
Merged the custom-directives branch back into trunk.
cmlenz
parents:
783
diff
changeset
|
282 new_attrs.append((name, value)) |
da90cee22560
Merged the custom-directives branch back into trunk.
cmlenz
parents:
783
diff
changeset
|
283 data = tag, Attrs(new_attrs) |
da90cee22560
Merged the custom-directives branch back into trunk.
cmlenz
parents:
783
diff
changeset
|
284 |
da90cee22560
Merged the custom-directives branch back into trunk.
cmlenz
parents:
783
diff
changeset
|
285 yield kind, data, pos |
da90cee22560
Merged the custom-directives branch back into trunk.
cmlenz
parents:
783
diff
changeset
|
286 |
1032
56fd1ca051af
Merge r1257 from trunk (fix for infinite template inlining).
hodgestar
parents:
1014
diff
changeset
|
287 def _prepare(self, stream, inlined=None): |
56fd1ca051af
Merge r1257 from trunk (fix for infinite template inlining).
hodgestar
parents:
1014
diff
changeset
|
288 return Template._prepare( |
56fd1ca051af
Merge r1257 from trunk (fix for infinite template inlining).
hodgestar
parents:
1014
diff
changeset
|
289 self, self._extract_includes(self._interpolate_attrs(stream)), |
56fd1ca051af
Merge r1257 from trunk (fix for infinite template inlining).
hodgestar
parents:
1014
diff
changeset
|
290 inlined=inlined) |
790
da90cee22560
Merged the custom-directives branch back into trunk.
cmlenz
parents:
783
diff
changeset
|
291 |
da90cee22560
Merged the custom-directives branch back into trunk.
cmlenz
parents:
783
diff
changeset
|
292 def add_directives(self, namespace, factory): |
da90cee22560
Merged the custom-directives branch back into trunk.
cmlenz
parents:
783
diff
changeset
|
293 """Register a custom `DirectiveFactory` for a given namespace. |
da90cee22560
Merged the custom-directives branch back into trunk.
cmlenz
parents:
783
diff
changeset
|
294 |
da90cee22560
Merged the custom-directives branch back into trunk.
cmlenz
parents:
783
diff
changeset
|
295 :param namespace: the namespace URI |
da90cee22560
Merged the custom-directives branch back into trunk.
cmlenz
parents:
783
diff
changeset
|
296 :type namespace: `basestring` |
da90cee22560
Merged the custom-directives branch back into trunk.
cmlenz
parents:
783
diff
changeset
|
297 :param factory: the directive factory to register |
da90cee22560
Merged the custom-directives branch back into trunk.
cmlenz
parents:
783
diff
changeset
|
298 :type factory: `DirectiveFactory` |
da90cee22560
Merged the custom-directives branch back into trunk.
cmlenz
parents:
783
diff
changeset
|
299 :since: version 0.6 |
da90cee22560
Merged the custom-directives branch back into trunk.
cmlenz
parents:
783
diff
changeset
|
300 """ |
da90cee22560
Merged the custom-directives branch back into trunk.
cmlenz
parents:
783
diff
changeset
|
301 assert not self._prepared, 'Too late for adding directives, ' \ |
da90cee22560
Merged the custom-directives branch back into trunk.
cmlenz
parents:
783
diff
changeset
|
302 'template already prepared' |
da90cee22560
Merged the custom-directives branch back into trunk.
cmlenz
parents:
783
diff
changeset
|
303 self._stream = self._extract_directives(self._stream, namespace, |
da90cee22560
Merged the custom-directives branch back into trunk.
cmlenz
parents:
783
diff
changeset
|
304 factory) |
da90cee22560
Merged the custom-directives branch back into trunk.
cmlenz
parents:
783
diff
changeset
|
305 |
766
b5b4b465e84c
Fix bug where in some cases match templates would incorrectly applied multiple times.
cmlenz
parents:
758
diff
changeset
|
306 def _match(self, stream, ctxt, start=0, end=None, **vars): |
336
7763f7aec949
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
307 """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
|
308 to the stream. |
7763f7aec949
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
309 """ |
766
b5b4b465e84c
Fix bug where in some cases match templates would incorrectly applied multiple times.
cmlenz
parents:
758
diff
changeset
|
310 match_templates = ctxt._match_templates |
336
7763f7aec949
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
311 |
924 | 312 def _strip(stream, append): |
336
7763f7aec949
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
313 depth = 1 |
843
d10e5bceaa1f
Refactored the template flattening method to be less recursive.
cmlenz
parents:
827
diff
changeset
|
314 next = stream.next |
336
7763f7aec949
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
315 while 1: |
843
d10e5bceaa1f
Refactored the template flattening method to be less recursive.
cmlenz
parents:
827
diff
changeset
|
316 event = next() |
336
7763f7aec949
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
317 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
|
318 depth += 1 |
7763f7aec949
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
319 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
|
320 depth -= 1 |
7763f7aec949
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
321 if depth > 0: |
7763f7aec949
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
322 yield event |
7763f7aec949
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
323 else: |
843
d10e5bceaa1f
Refactored the template flattening method to be less recursive.
cmlenz
parents:
827
diff
changeset
|
324 append(event) |
336
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 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
|
328 |
809 | 329 # We (currently) only care about start and end events for matching |
336
7763f7aec949
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
330 # We might care about namespace events in the future, though |
809 | 331 if not match_templates or (event[0] is not START and |
332 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
|
333 yield event |
7763f7aec949
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
334 continue |
7763f7aec949
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
335 |
602 | 336 for idx, (test, path, template, hints, namespaces, directives) \ |
337 in enumerate(match_templates): | |
766
b5b4b465e84c
Fix bug where in some cases match templates would incorrectly applied multiple times.
cmlenz
parents:
758
diff
changeset
|
338 if idx < start or end is not None and idx >= end: |
758
9f28d17b1f72
Fix problem with nested match templates not being applied when buffering on the outer `py:match` is disabled. Thanks to Erik Bray for reporting the problem and providing a test case.
cmlenz
parents:
719
diff
changeset
|
339 continue |
336
7763f7aec949
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
340 |
7763f7aec949
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
341 if test(event, namespaces, ctxt) is True: |
602 | 342 if 'match_once' in hints: |
343 del match_templates[idx] | |
344 idx -= 1 | |
336
7763f7aec949
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
345 |
7763f7aec949
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
346 # 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
|
347 # 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
|
348 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
|
349 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
|
350 |
7763f7aec949
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
351 # 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
|
352 # corresponding to this start event is encountered |
766
b5b4b465e84c
Fix bug where in some cases match templates would incorrectly applied multiple times.
cmlenz
parents:
758
diff
changeset
|
353 pre_end = idx + 1 |
694
07e3f6f0ef57
Match templates are now applied in a more controlled fashion: in the order they are declared in the template source, all match templates up to (and including) the matching template itself are applied to the matched content, whereas the match templates declared after the matching template are only applied to the generated content. Fixes #186. Many thanks to Matt Chaput for reporting the problem and providing a test case.
cmlenz
parents:
650
diff
changeset
|
354 if 'match_once' not in hints and 'not_recursive' in hints: |
766
b5b4b465e84c
Fix bug where in some cases match templates would incorrectly applied multiple times.
cmlenz
parents:
758
diff
changeset
|
355 pre_end -= 1 |
924 | 356 tail = [] |
357 inner = _strip(stream, tail.append) | |
766
b5b4b465e84c
Fix bug where in some cases match templates would incorrectly applied multiple times.
cmlenz
parents:
758
diff
changeset
|
358 if pre_end > 0: |
870
c52e2bf11edc
Apply patch Felix Schwarz that finally fixes the duplicated output in match template processing. Thanks so much!
cmlenz
parents:
853
diff
changeset
|
359 inner = self._match(inner, ctxt, start=start, |
c52e2bf11edc
Apply patch Felix Schwarz that finally fixes the duplicated output in match template processing. Thanks so much!
cmlenz
parents:
853
diff
changeset
|
360 end=pre_end, **vars) |
700
08f22328303d
Add option for unbuffered match template processing, which could cause excessive memory usage. Closes #190.
cmlenz
parents:
694
diff
changeset
|
361 content = self._include(chain([event], inner, tail), ctxt) |
08f22328303d
Add option for unbuffered match template processing, which could cause excessive memory usage. Closes #190.
cmlenz
parents:
694
diff
changeset
|
362 if 'not_buffered' not in hints: |
08f22328303d
Add option for unbuffered match template processing, which could cause excessive memory usage. Closes #190.
cmlenz
parents:
694
diff
changeset
|
363 content = list(content) |
843
d10e5bceaa1f
Refactored the template flattening method to be less recursive.
cmlenz
parents:
827
diff
changeset
|
364 content = Stream(content) |
336
7763f7aec949
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
365 |
7763f7aec949
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
366 # 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
|
367 # match template |
771
2c2e9e685424
Unbuffered match templates could result in parts of the matched content being included in the output if the match template didn't actually consume it via one or more calls to the `select()` function. Closes #243. Thanks to Felix Schwarz for the report and test case.
cmlenz
parents:
766
diff
changeset
|
368 selected = [False] |
336
7763f7aec949
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
369 def select(path): |
771
2c2e9e685424
Unbuffered match templates could result in parts of the matched content being included in the output if the match template didn't actually consume it via one or more calls to the `select()` function. Closes #243. Thanks to Felix Schwarz for the report and test case.
cmlenz
parents:
766
diff
changeset
|
370 selected[0] = True |
843
d10e5bceaa1f
Refactored the template flattening method to be less recursive.
cmlenz
parents:
827
diff
changeset
|
371 return content.select(path, namespaces, ctxt) |
700
08f22328303d
Add option for unbuffered match template processing, which could cause excessive memory usage. Closes #190.
cmlenz
parents:
694
diff
changeset
|
372 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
|
373 |
7763f7aec949
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
374 # Recursively process the output |
700
08f22328303d
Add option for unbuffered match template processing, which could cause excessive memory usage. Closes #190.
cmlenz
parents:
694
diff
changeset
|
375 template = _apply_directives(template, directives, ctxt, |
827
bebc68529176
Avoid varargs on internal functions in template processing for slightly better performance.
cmlenz
parents:
814
diff
changeset
|
376 vars) |
813
ae8727f7e1e1
Merge the internal template filters `_eval` and `_exec` into the `_flatten` function for slightly better performance.
cmlenz
parents:
809
diff
changeset
|
377 for event in self._match(self._flatten(template, ctxt, |
ae8727f7e1e1
Merge the internal template filters `_eval` and `_exec` into the `_flatten` function for slightly better performance.
cmlenz
parents:
809
diff
changeset
|
378 **vars), |
ae8727f7e1e1
Merge the internal template filters `_eval` and `_exec` into the `_flatten` function for slightly better performance.
cmlenz
parents:
809
diff
changeset
|
379 ctxt, start=idx + 1, **vars): |
336
7763f7aec949
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
380 yield event |
7763f7aec949
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
381 |
771
2c2e9e685424
Unbuffered match templates could result in parts of the matched content being included in the output if the match template didn't actually consume it via one or more calls to the `select()` function. Closes #243. Thanks to Felix Schwarz for the report and test case.
cmlenz
parents:
766
diff
changeset
|
382 # If the match template did not actually call select to |
2c2e9e685424
Unbuffered match templates could result in parts of the matched content being included in the output if the match template didn't actually consume it via one or more calls to the `select()` function. Closes #243. Thanks to Felix Schwarz for the report and test case.
cmlenz
parents:
766
diff
changeset
|
383 # consume the matched stream, the original events need to |
2c2e9e685424
Unbuffered match templates could result in parts of the matched content being included in the output if the match template didn't actually consume it via one or more calls to the `select()` function. Closes #243. Thanks to Felix Schwarz for the report and test case.
cmlenz
parents:
766
diff
changeset
|
384 # be consumed here or they'll get appended to the output |
2c2e9e685424
Unbuffered match templates could result in parts of the matched content being included in the output if the match template didn't actually consume it via one or more calls to the `select()` function. Closes #243. Thanks to Felix Schwarz for the report and test case.
cmlenz
parents:
766
diff
changeset
|
385 if not selected[0]: |
2c2e9e685424
Unbuffered match templates could result in parts of the matched content being included in the output if the match template didn't actually consume it via one or more calls to the `select()` function. Closes #243. Thanks to Felix Schwarz for the report and test case.
cmlenz
parents:
766
diff
changeset
|
386 for event in content: |
2c2e9e685424
Unbuffered match templates could result in parts of the matched content being included in the output if the match template didn't actually consume it via one or more calls to the `select()` function. Closes #243. Thanks to Felix Schwarz for the report and test case.
cmlenz
parents:
766
diff
changeset
|
387 pass |
2c2e9e685424
Unbuffered match templates could result in parts of the matched content being included in the output if the match template didn't actually consume it via one or more calls to the `select()` function. Closes #243. Thanks to Felix Schwarz for the report and test case.
cmlenz
parents:
766
diff
changeset
|
388 |
945
d1edb246cc61
Fix out-by-one error introduced in r1097 that led to match templates missing the last event from the stream they were processing.
hodgestar
parents:
924
diff
changeset
|
389 # Let this match template and the remaining match |
d1edb246cc61
Fix out-by-one error introduced in r1097 that led to match templates missing the last event from the stream they were processing.
hodgestar
parents:
924
diff
changeset
|
390 # templates know about the last event in the |
d1edb246cc61
Fix out-by-one error introduced in r1097 that led to match templates missing the last event from the stream they were processing.
hodgestar
parents:
924
diff
changeset
|
391 # matched content, so they can update their |
771
2c2e9e685424
Unbuffered match templates could result in parts of the matched content being included in the output if the match template didn't actually consume it via one or more calls to the `select()` function. Closes #243. Thanks to Felix Schwarz for the report and test case.
cmlenz
parents:
766
diff
changeset
|
392 # internal state accordingly |
945
d1edb246cc61
Fix out-by-one error introduced in r1097 that led to match templates missing the last event from the stream they were processing.
hodgestar
parents:
924
diff
changeset
|
393 for test in [mt[0] for mt in match_templates[idx:]]: |
771
2c2e9e685424
Unbuffered match templates could result in parts of the matched content being included in the output if the match template didn't actually consume it via one or more calls to the `select()` function. Closes #243. Thanks to Felix Schwarz for the report and test case.
cmlenz
parents:
766
diff
changeset
|
394 test(tail[0], namespaces, ctxt, updateonly=True) |
2c2e9e685424
Unbuffered match templates could result in parts of the matched content being included in the output if the match template didn't actually consume it via one or more calls to the `select()` function. Closes #243. Thanks to Felix Schwarz for the report and test case.
cmlenz
parents:
766
diff
changeset
|
395 |
336
7763f7aec949
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
396 break |
7763f7aec949
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
397 |
7763f7aec949
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
398 else: # no matches |
7763f7aec949
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
399 yield event |