Mercurial > genshi > genshi-test
annotate genshi/template/markup.py @ 924:3c09c8d8a578
Pull up r1146 to trunk.
Addresses #399
author | jruigrok |
---|---|
date | Mon, 13 Dec 2010 19:07:59 +0000 |
parents | 85e4678337cf |
children |
rev | line source |
---|---|
336
5f2c7782cd8a
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
1 # -*- coding: utf-8 -*- |
5f2c7782cd8a
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
2 # |
897 | 3 # Copyright (C) 2006-2010 Edgewall Software |
336
5f2c7782cd8a
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
4 # All rights reserved. |
5f2c7782cd8a
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
5 # |
5f2c7782cd8a
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
6 # This software is licensed as described in the file COPYING, which |
5f2c7782cd8a
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
7 # you should have received as part of this distribution. The terms |
5f2c7782cd8a
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
8 # are also available at http://genshi.edgewall.org/wiki/License. |
5f2c7782cd8a
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
9 # |
5f2c7782cd8a
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
10 # This software consists of voluntary contributions made by many |
5f2c7782cd8a
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
11 # individuals. For the exact contribution history, see the revision |
5f2c7782cd8a
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
12 # history and logs, available at http://genshi.edgewall.org/log/. |
5f2c7782cd8a
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
13 |
5f2c7782cd8a
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
14 """Markup templating engine.""" |
5f2c7782cd8a
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
15 |
5f2c7782cd8a
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
16 from itertools import chain |
5f2c7782cd8a
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
17 |
636
e0f12a6f3612
Follow-up to [751]: applying the optimization to text templates was actually slowing them down, so only do it for markup templates.
cmlenz
parents:
629
diff
changeset
|
18 from genshi.core import Attrs, Markup, Namespace, Stream, StreamEventKind |
405
bd5da099c113
Support for Python code blocks using the `<?python ?>` processing instruction. Closes #84.
cmlenz
parents:
400
diff
changeset
|
19 from genshi.core import START, END, START_NS, END_NS, TEXT, PI, COMMENT |
336
5f2c7782cd8a
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
20 from genshi.input import XMLParser |
400
8dd0d34a9fb7
Renamed `genshi.template.core` to `genshi.template.base`, mainly to avoid confusion with `genshi.core`.
cmlenz
parents:
381
diff
changeset
|
21 from genshi.template.base import BadDirectiveError, Template, \ |
475
bb939ed3058c
Added include directive for text templates (#115). Thanks to Alastair for the original patch.
cmlenz
parents:
442
diff
changeset
|
22 TemplateSyntaxError, _apply_directives, \ |
609
237050080827
Add support for Python code blocks in text templates using the new syntax.
cmlenz
parents:
606
diff
changeset
|
23 EXEC, INCLUDE, SUB |
405
bd5da099c113
Support for Python code blocks using the `<?python ?>` processing instruction. Closes #84.
cmlenz
parents:
400
diff
changeset
|
24 from genshi.template.eval import Suite |
407
ea71a51e0258
Move string interpolation code into separate module (`genshi.template.interpolation`).
cmlenz
parents:
405
diff
changeset
|
25 from genshi.template.interpolation import interpolate |
336
5f2c7782cd8a
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
26 from genshi.template.directives import * |
610
6a37018199fd
* XInclude elements in markup templates now support the `parse` attribute; when set to "xml" (the default), the include is processed as before, but when set to "text", the included template is parsed as a text template using the new syntax (ticket #101).
cmlenz
parents:
609
diff
changeset
|
27 from genshi.template.text import NewTextTemplate |
336
5f2c7782cd8a
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
28 |
425
5b248708bbed
Try to use proper reStructuredText for docstrings throughout.
cmlenz
parents:
422
diff
changeset
|
29 __all__ = ['MarkupTemplate'] |
5b248708bbed
Try to use proper reStructuredText for docstrings throughout.
cmlenz
parents:
422
diff
changeset
|
30 __docformat__ = 'restructuredtext en' |
5b248708bbed
Try to use proper reStructuredText for docstrings throughout.
cmlenz
parents:
422
diff
changeset
|
31 |
336
5f2c7782cd8a
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
32 |
5f2c7782cd8a
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
33 class MarkupTemplate(Template): |
5f2c7782cd8a
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
34 """Implementation of the template language for XML-based templates. |
5f2c7782cd8a
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
35 |
5f2c7782cd8a
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
36 >>> tmpl = MarkupTemplate('''<ul xmlns:py="http://genshi.edgewall.org/"> |
5f2c7782cd8a
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
37 ... <li py:for="item in items">${item}</li> |
5f2c7782cd8a
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
38 ... </ul>''') |
853
4376010bb97e
Convert a bunch of print statements to py3k compatible syntax.
cmlenz
parents:
847
diff
changeset
|
39 >>> print(tmpl.generate(items=[1, 2, 3])) |
336
5f2c7782cd8a
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
40 <ul> |
5f2c7782cd8a
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
41 <li>1</li><li>2</li><li>3</li> |
5f2c7782cd8a
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
42 </ul> |
5f2c7782cd8a
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
43 """ |
427 | 44 |
790
1b6968d31089
Merged the custom-directives branch back into trunk.
cmlenz
parents:
783
diff
changeset
|
45 DIRECTIVE_NAMESPACE = 'http://genshi.edgewall.org/' |
1b6968d31089
Merged the custom-directives branch back into trunk.
cmlenz
parents:
783
diff
changeset
|
46 XINCLUDE_NAMESPACE = 'http://www.w3.org/2001/XInclude' |
336
5f2c7782cd8a
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
47 |
5f2c7782cd8a
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
48 directives = [('def', DefDirective), |
5f2c7782cd8a
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
49 ('match', MatchDirective), |
5f2c7782cd8a
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
50 ('when', WhenDirective), |
5f2c7782cd8a
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
51 ('otherwise', OtherwiseDirective), |
5f2c7782cd8a
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
52 ('for', ForDirective), |
5f2c7782cd8a
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
53 ('if', IfDirective), |
5f2c7782cd8a
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
54 ('choose', ChooseDirective), |
5f2c7782cd8a
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
55 ('with', WithDirective), |
5f2c7782cd8a
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
56 ('replace', ReplaceDirective), |
5f2c7782cd8a
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
57 ('content', ContentDirective), |
5f2c7782cd8a
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
58 ('attrs', AttrsDirective), |
5f2c7782cd8a
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
59 ('strip', StripDirective)] |
605
bc5faca93699
Text templates now default to rendering as plain text; it is no longer necessary to explicitly specify the "text" method to the `render()` or `serialize()` method of the generated markup stream. See tickets #62 and #118.
cmlenz
parents:
602
diff
changeset
|
60 serializer = 'xml' |
636
e0f12a6f3612
Follow-up to [751]: applying the optimization to text templates was actually slowing them down, so only do it for markup templates.
cmlenz
parents:
629
diff
changeset
|
61 _number_conv = Markup |
336
5f2c7782cd8a
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
62 |
790
1b6968d31089
Merged the custom-directives branch back into trunk.
cmlenz
parents:
783
diff
changeset
|
63 def __init__(self, source, filepath=None, filename=None, loader=None, |
1b6968d31089
Merged the custom-directives branch back into trunk.
cmlenz
parents:
783
diff
changeset
|
64 encoding=None, lookup='strict', allow_exec=True): |
1b6968d31089
Merged the custom-directives branch back into trunk.
cmlenz
parents:
783
diff
changeset
|
65 Template.__init__(self, source, filepath=filepath, filename=filename, |
1b6968d31089
Merged the custom-directives branch back into trunk.
cmlenz
parents:
783
diff
changeset
|
66 loader=loader, encoding=encoding, lookup=lookup, |
1b6968d31089
Merged the custom-directives branch back into trunk.
cmlenz
parents:
783
diff
changeset
|
67 allow_exec=allow_exec) |
1b6968d31089
Merged the custom-directives branch back into trunk.
cmlenz
parents:
783
diff
changeset
|
68 self.add_directives(self.DIRECTIVE_NAMESPACE, self) |
1b6968d31089
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
782931585925
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
52d7d6b7b6c1
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) |
52d7d6b7b6c1
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
5f2c7782cd8a
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
75 |
374
ca46dc9c7761
`MarkupTemplate`s can now be instantiated from markup streams, in addition to strings and file-like objects. Thanks to David Fraser for the patch. Closes #69.
cmlenz
parents:
364
diff
changeset
|
76 def _parse(self, source, encoding): |
ca46dc9c7761
`MarkupTemplate`s can now be instantiated from markup streams, in addition to strings and file-like objects. Thanks to David Fraser for the patch. Closes #69.
cmlenz
parents:
364
diff
changeset
|
77 if not isinstance(source, Stream): |
434
e065d7906b68
* Better method to propogate the full path to the template file on parse errors. Supersedes r513.
cmlenz
parents:
427
diff
changeset
|
78 source = XMLParser(source, filename=self.filename, |
374
ca46dc9c7761
`MarkupTemplate`s can now be instantiated from markup streams, in addition to strings and file-like objects. Thanks to David Fraser for the patch. Closes #69.
cmlenz
parents:
364
diff
changeset
|
79 encoding=encoding) |
790
1b6968d31089
Merged the custom-directives branch back into trunk.
cmlenz
parents:
783
diff
changeset
|
80 stream = [] |
374
ca46dc9c7761
`MarkupTemplate`s can now be instantiated from markup streams, in addition to strings and file-like objects. Thanks to David Fraser for the patch. Closes #69.
cmlenz
parents:
364
diff
changeset
|
81 |
ca46dc9c7761
`MarkupTemplate`s can now be instantiated from markup streams, in addition to strings and file-like objects. Thanks to David Fraser for the patch. Closes #69.
cmlenz
parents:
364
diff
changeset
|
82 for kind, data, pos in source: |
336
5f2c7782cd8a
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
83 |
790
1b6968d31089
Merged the custom-directives branch back into trunk.
cmlenz
parents:
783
diff
changeset
|
84 if kind is TEXT: |
1b6968d31089
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], |
1b6968d31089
Merged the custom-directives branch back into trunk.
cmlenz
parents:
783
diff
changeset
|
86 pos[2], lookup=self.lookup): |
336
5f2c7782cd8a
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
87 stream.append((kind, data, pos)) |
5f2c7782cd8a
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
88 |
790
1b6968d31089
Merged the custom-directives branch back into trunk.
cmlenz
parents:
783
diff
changeset
|
89 elif kind is PI and data[0] == 'python': |
1b6968d31089
Merged the custom-directives branch back into trunk.
cmlenz
parents:
783
diff
changeset
|
90 if not self.allow_exec: |
1b6968d31089
Merged the custom-directives branch back into trunk.
cmlenz
parents:
783
diff
changeset
|
91 raise TemplateSyntaxError('Python code blocks not allowed', |
1b6968d31089
Merged the custom-directives branch back into trunk.
cmlenz
parents:
783
diff
changeset
|
92 self.filepath, *pos[1:]) |
1b6968d31089
Merged the custom-directives branch back into trunk.
cmlenz
parents:
783
diff
changeset
|
93 try: |
1b6968d31089
Merged the custom-directives branch back into trunk.
cmlenz
parents:
783
diff
changeset
|
94 suite = Suite(data[1], self.filepath, pos[1], |
1b6968d31089
Merged the custom-directives branch back into trunk.
cmlenz
parents:
783
diff
changeset
|
95 lookup=self.lookup) |
1b6968d31089
Merged the custom-directives branch back into trunk.
cmlenz
parents:
783
diff
changeset
|
96 except SyntaxError, err: |
1b6968d31089
Merged the custom-directives branch back into trunk.
cmlenz
parents:
783
diff
changeset
|
97 raise TemplateSyntaxError(err, self.filepath, |
1b6968d31089
Merged the custom-directives branch back into trunk.
cmlenz
parents:
783
diff
changeset
|
98 pos[1] + (err.lineno or 1) - 1, |
1b6968d31089
Merged the custom-directives branch back into trunk.
cmlenz
parents:
783
diff
changeset
|
99 pos[2] + (err.offset or 0)) |
1b6968d31089
Merged the custom-directives branch back into trunk.
cmlenz
parents:
783
diff
changeset
|
100 stream.append((EXEC, suite, pos)) |
1b6968d31089
Merged the custom-directives branch back into trunk.
cmlenz
parents:
783
diff
changeset
|
101 |
1b6968d31089
Merged the custom-directives branch back into trunk.
cmlenz
parents:
783
diff
changeset
|
102 elif kind is COMMENT: |
1b6968d31089
Merged the custom-directives branch back into trunk.
cmlenz
parents:
783
diff
changeset
|
103 if not data.lstrip().startswith('!'): |
336
5f2c7782cd8a
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)) |
5f2c7782cd8a
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
105 |
790
1b6968d31089
Merged the custom-directives branch back into trunk.
cmlenz
parents:
783
diff
changeset
|
106 else: |
1b6968d31089
Merged the custom-directives branch back into trunk.
cmlenz
parents:
783
diff
changeset
|
107 stream.append((kind, data, pos)) |
1b6968d31089
Merged the custom-directives branch back into trunk.
cmlenz
parents:
783
diff
changeset
|
108 |
1b6968d31089
Merged the custom-directives branch back into trunk.
cmlenz
parents:
783
diff
changeset
|
109 return stream |
1b6968d31089
Merged the custom-directives branch back into trunk.
cmlenz
parents:
783
diff
changeset
|
110 |
1b6968d31089
Merged the custom-directives branch back into trunk.
cmlenz
parents:
783
diff
changeset
|
111 def _extract_directives(self, stream, namespace, factory): |
1b6968d31089
Merged the custom-directives branch back into trunk.
cmlenz
parents:
783
diff
changeset
|
112 depth = 0 |
1b6968d31089
Merged the custom-directives branch back into trunk.
cmlenz
parents:
783
diff
changeset
|
113 dirmap = {} # temporary mapping of directives to elements |
1b6968d31089
Merged the custom-directives branch back into trunk.
cmlenz
parents:
783
diff
changeset
|
114 new_stream = [] |
1b6968d31089
Merged the custom-directives branch back into trunk.
cmlenz
parents:
783
diff
changeset
|
115 ns_prefix = {} # namespace prefixes in use |
1b6968d31089
Merged the custom-directives branch back into trunk.
cmlenz
parents:
783
diff
changeset
|
116 |
1b6968d31089
Merged the custom-directives branch back into trunk.
cmlenz
parents:
783
diff
changeset
|
117 for kind, data, pos in stream: |
1b6968d31089
Merged the custom-directives branch back into trunk.
cmlenz
parents:
783
diff
changeset
|
118 |
1b6968d31089
Merged the custom-directives branch back into trunk.
cmlenz
parents:
783
diff
changeset
|
119 if kind is START: |
363
caf7b68ab5dc
Parse template includes at parse time to avoid some runtime overhead.
cmlenz
parents:
362
diff
changeset
|
120 tag, attrs = data |
336
5f2c7782cd8a
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
121 directives = [] |
5f2c7782cd8a
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
122 strip = False |
5f2c7782cd8a
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
123 |
790
1b6968d31089
Merged the custom-directives branch back into trunk.
cmlenz
parents:
783
diff
changeset
|
124 if tag.namespace == namespace: |
1b6968d31089
Merged the custom-directives branch back into trunk.
cmlenz
parents:
783
diff
changeset
|
125 cls = factory.get_directive(tag.localname) |
336
5f2c7782cd8a
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
1b6968d31089
Merged the custom-directives branch back into trunk.
cmlenz
parents:
783
diff
changeset
|
127 raise BadDirectiveError(tag.localname, |
1b6968d31089
Merged the custom-directives branch back into trunk.
cmlenz
parents:
783
diff
changeset
|
128 self.filepath, pos[1]) |
552
5458a4e8814c
For directives used as elements, pass all attributes without a namespace to the directive class. This enables adding optional extra attributes to directives.
cmlenz
parents:
545
diff
changeset
|
129 args = dict([(name.localname, value) for name, value |
5458a4e8814c
For directives used as elements, pass all attributes without a namespace to the directive class. This enables adding optional extra attributes to directives.
cmlenz
parents:
545
diff
changeset
|
130 in attrs if not name.namespace]) |
847
4f9e5e6f1aab
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, |
4f9e5e6f1aab
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
5f2c7782cd8a
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
133 strip = True |
5f2c7782cd8a
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
134 |
363
caf7b68ab5dc
Parse template includes at parse time to avoid some runtime overhead.
cmlenz
parents:
362
diff
changeset
|
135 new_attrs = [] |
caf7b68ab5dc
Parse template includes at parse time to avoid some runtime overhead.
cmlenz
parents:
362
diff
changeset
|
136 for name, value in attrs: |
790
1b6968d31089
Merged the custom-directives branch back into trunk.
cmlenz
parents:
783
diff
changeset
|
137 if name.namespace == namespace: |
1b6968d31089
Merged the custom-directives branch back into trunk.
cmlenz
parents:
783
diff
changeset
|
138 cls = factory.get_directive(name.localname) |
336
5f2c7782cd8a
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: |
5f2c7782cd8a
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, |
5f2c7782cd8a
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
1b6968d31089
Merged the custom-directives branch back into trunk.
cmlenz
parents:
783
diff
changeset
|
142 if type(value) is list and len(value) == 1: |
1b6968d31089
Merged the custom-directives branch back into trunk.
cmlenz
parents:
783
diff
changeset
|
143 value = value[0][1] |
847
4f9e5e6f1aab
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), |
4f9e5e6f1aab
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
5f2c7782cd8a
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
146 else: |
363
caf7b68ab5dc
Parse template includes at parse time to avoid some runtime overhead.
cmlenz
parents:
362
diff
changeset
|
147 new_attrs.append((name, value)) |
caf7b68ab5dc
Parse template includes at parse time to avoid some runtime overhead.
cmlenz
parents:
362
diff
changeset
|
148 new_attrs = Attrs(new_attrs) |
336
5f2c7782cd8a
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
149 |
5f2c7782cd8a
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
150 if directives: |
847
4f9e5e6f1aab
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
1b6968d31089
Merged the custom-directives branch back into trunk.
cmlenz
parents:
783
diff
changeset
|
152 dirmap[(depth, tag)] = (directives, len(new_stream), |
1b6968d31089
Merged the custom-directives branch back into trunk.
cmlenz
parents:
783
diff
changeset
|
153 strip) |
336
5f2c7782cd8a
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
154 |
790
1b6968d31089
Merged the custom-directives branch back into trunk.
cmlenz
parents:
783
diff
changeset
|
155 new_stream.append((kind, (tag, new_attrs), pos)) |
1b6968d31089
Merged the custom-directives branch back into trunk.
cmlenz
parents:
783
diff
changeset
|
156 depth += 1 |
1b6968d31089
Merged the custom-directives branch back into trunk.
cmlenz
parents:
783
diff
changeset
|
157 |
1b6968d31089
Merged the custom-directives branch back into trunk.
cmlenz
parents:
783
diff
changeset
|
158 elif kind is END: |
1b6968d31089
Merged the custom-directives branch back into trunk.
cmlenz
parents:
783
diff
changeset
|
159 depth -= 1 |
1b6968d31089
Merged the custom-directives branch back into trunk.
cmlenz
parents:
783
diff
changeset
|
160 new_stream.append((kind, data, pos)) |
1b6968d31089
Merged the custom-directives branch back into trunk.
cmlenz
parents:
783
diff
changeset
|
161 |
1b6968d31089
Merged the custom-directives branch back into trunk.
cmlenz
parents:
783
diff
changeset
|
162 # If there have have directive attributes with the |
1b6968d31089
Merged the custom-directives branch back into trunk.
cmlenz
parents:
783
diff
changeset
|
163 # corresponding start tag, move the events inbetween into |
1b6968d31089
Merged the custom-directives branch back into trunk.
cmlenz
parents:
783
diff
changeset
|
164 # a "subprogram" |
1b6968d31089
Merged the custom-directives branch back into trunk.
cmlenz
parents:
783
diff
changeset
|
165 if (depth, data) in dirmap: |
1b6968d31089
Merged the custom-directives branch back into trunk.
cmlenz
parents:
783
diff
changeset
|
166 directives, offset, strip = dirmap.pop((depth, data)) |
1b6968d31089
Merged the custom-directives branch back into trunk.
cmlenz
parents:
783
diff
changeset
|
167 substream = new_stream[offset:] |
1b6968d31089
Merged the custom-directives branch back into trunk.
cmlenz
parents:
783
diff
changeset
|
168 if strip: |
1b6968d31089
Merged the custom-directives branch back into trunk.
cmlenz
parents:
783
diff
changeset
|
169 substream = substream[1:-1] |
1b6968d31089
Merged the custom-directives branch back into trunk.
cmlenz
parents:
783
diff
changeset
|
170 new_stream[offset:] = [ |
1b6968d31089
Merged the custom-directives branch back into trunk.
cmlenz
parents:
783
diff
changeset
|
171 (SUB, (directives, substream), pos) |
1b6968d31089
Merged the custom-directives branch back into trunk.
cmlenz
parents:
783
diff
changeset
|
172 ] |
1b6968d31089
Merged the custom-directives branch back into trunk.
cmlenz
parents:
783
diff
changeset
|
173 |
1b6968d31089
Merged the custom-directives branch back into trunk.
cmlenz
parents:
783
diff
changeset
|
174 elif kind is SUB: |
1b6968d31089
Merged the custom-directives branch back into trunk.
cmlenz
parents:
783
diff
changeset
|
175 directives, substream = data |
1b6968d31089
Merged the custom-directives branch back into trunk.
cmlenz
parents:
783
diff
changeset
|
176 substream = self._extract_directives(substream, namespace, |
1b6968d31089
Merged the custom-directives branch back into trunk.
cmlenz
parents:
783
diff
changeset
|
177 factory) |
1b6968d31089
Merged the custom-directives branch back into trunk.
cmlenz
parents:
783
diff
changeset
|
178 |
1b6968d31089
Merged the custom-directives branch back into trunk.
cmlenz
parents:
783
diff
changeset
|
179 if len(substream) == 1 and substream[0][0] is SUB: |
1b6968d31089
Merged the custom-directives branch back into trunk.
cmlenz
parents:
783
diff
changeset
|
180 added_directives, substream = substream[0][1] |
1b6968d31089
Merged the custom-directives branch back into trunk.
cmlenz
parents:
783
diff
changeset
|
181 directives += added_directives |
1b6968d31089
Merged the custom-directives branch back into trunk.
cmlenz
parents:
783
diff
changeset
|
182 |
1b6968d31089
Merged the custom-directives branch back into trunk.
cmlenz
parents:
783
diff
changeset
|
183 new_stream.append((kind, (directives, substream), pos)) |
1b6968d31089
Merged the custom-directives branch back into trunk.
cmlenz
parents:
783
diff
changeset
|
184 |
1b6968d31089
Merged the custom-directives branch back into trunk.
cmlenz
parents:
783
diff
changeset
|
185 elif kind is START_NS: |
1b6968d31089
Merged the custom-directives branch back into trunk.
cmlenz
parents:
783
diff
changeset
|
186 # Strip out the namespace declaration for template |
1b6968d31089
Merged the custom-directives branch back into trunk.
cmlenz
parents:
783
diff
changeset
|
187 # directives |
1b6968d31089
Merged the custom-directives branch back into trunk.
cmlenz
parents:
783
diff
changeset
|
188 prefix, uri = data |
1b6968d31089
Merged the custom-directives branch back into trunk.
cmlenz
parents:
783
diff
changeset
|
189 ns_prefix[prefix] = uri |
1b6968d31089
Merged the custom-directives branch back into trunk.
cmlenz
parents:
783
diff
changeset
|
190 if uri != namespace: |
1b6968d31089
Merged the custom-directives branch back into trunk.
cmlenz
parents:
783
diff
changeset
|
191 new_stream.append((kind, data, pos)) |
1b6968d31089
Merged the custom-directives branch back into trunk.
cmlenz
parents:
783
diff
changeset
|
192 |
1b6968d31089
Merged the custom-directives branch back into trunk.
cmlenz
parents:
783
diff
changeset
|
193 elif kind is END_NS: |
1b6968d31089
Merged the custom-directives branch back into trunk.
cmlenz
parents:
783
diff
changeset
|
194 uri = ns_prefix.pop(data, None) |
1b6968d31089
Merged the custom-directives branch back into trunk.
cmlenz
parents:
783
diff
changeset
|
195 if uri and uri != namespace: |
1b6968d31089
Merged the custom-directives branch back into trunk.
cmlenz
parents:
783
diff
changeset
|
196 new_stream.append((kind, data, pos)) |
1b6968d31089
Merged the custom-directives branch back into trunk.
cmlenz
parents:
783
diff
changeset
|
197 |
1b6968d31089
Merged the custom-directives branch back into trunk.
cmlenz
parents:
783
diff
changeset
|
198 else: |
1b6968d31089
Merged the custom-directives branch back into trunk.
cmlenz
parents:
783
diff
changeset
|
199 new_stream.append((kind, data, pos)) |
1b6968d31089
Merged the custom-directives branch back into trunk.
cmlenz
parents:
783
diff
changeset
|
200 |
1b6968d31089
Merged the custom-directives branch back into trunk.
cmlenz
parents:
783
diff
changeset
|
201 return new_stream |
1b6968d31089
Merged the custom-directives branch back into trunk.
cmlenz
parents:
783
diff
changeset
|
202 |
1b6968d31089
Merged the custom-directives branch back into trunk.
cmlenz
parents:
783
diff
changeset
|
203 def _extract_includes(self, stream): |
1b6968d31089
Merged the custom-directives branch back into trunk.
cmlenz
parents:
783
diff
changeset
|
204 streams = [[]] # stacked lists of events of the "compiled" template |
1b6968d31089
Merged the custom-directives branch back into trunk.
cmlenz
parents:
783
diff
changeset
|
205 prefixes = {} |
1b6968d31089
Merged the custom-directives branch back into trunk.
cmlenz
parents:
783
diff
changeset
|
206 fallbacks = [] |
1b6968d31089
Merged the custom-directives branch back into trunk.
cmlenz
parents:
783
diff
changeset
|
207 includes = [] |
1b6968d31089
Merged the custom-directives branch back into trunk.
cmlenz
parents:
783
diff
changeset
|
208 xinclude_ns = Namespace(self.XINCLUDE_NAMESPACE) |
1b6968d31089
Merged the custom-directives branch back into trunk.
cmlenz
parents:
783
diff
changeset
|
209 |
1b6968d31089
Merged the custom-directives branch back into trunk.
cmlenz
parents:
783
diff
changeset
|
210 for kind, data, pos in stream: |
1b6968d31089
Merged the custom-directives branch back into trunk.
cmlenz
parents:
783
diff
changeset
|
211 stream = streams[-1] |
1b6968d31089
Merged the custom-directives branch back into trunk.
cmlenz
parents:
783
diff
changeset
|
212 |
1b6968d31089
Merged the custom-directives branch back into trunk.
cmlenz
parents:
783
diff
changeset
|
213 if kind is START: |
1b6968d31089
Merged the custom-directives branch back into trunk.
cmlenz
parents:
783
diff
changeset
|
214 # Record any directive attributes in start tags |
1b6968d31089
Merged the custom-directives branch back into trunk.
cmlenz
parents:
783
diff
changeset
|
215 tag, attrs = data |
1b6968d31089
Merged the custom-directives branch back into trunk.
cmlenz
parents:
783
diff
changeset
|
216 if tag in xinclude_ns: |
363
caf7b68ab5dc
Parse template includes at parse time to avoid some runtime overhead.
cmlenz
parents:
362
diff
changeset
|
217 if tag.localname == 'include': |
790
1b6968d31089
Merged the custom-directives branch back into trunk.
cmlenz
parents:
783
diff
changeset
|
218 include_href = attrs.get('href') |
363
caf7b68ab5dc
Parse template includes at parse time to avoid some runtime overhead.
cmlenz
parents:
362
diff
changeset
|
219 if not include_href: |
caf7b68ab5dc
Parse template includes at parse time to avoid some runtime overhead.
cmlenz
parents:
362
diff
changeset
|
220 raise TemplateSyntaxError('Include misses required ' |
422
95089b6e37ca
More work to include absolute file paths in exceptions.
cmlenz
parents:
421
diff
changeset
|
221 'attribute "href"', |
95089b6e37ca
More work to include absolute file paths in exceptions.
cmlenz
parents:
421
diff
changeset
|
222 self.filepath, *pos[1:]) |
790
1b6968d31089
Merged the custom-directives branch back into trunk.
cmlenz
parents:
783
diff
changeset
|
223 includes.append((include_href, attrs.get('parse'))) |
381
a6c2a9cd2e92
Fix for #80: fallback only shown when the template to include wasn't found. In addition, the nesting of includes and fallback content should work correctly, and directives/expressions/etc inside fallback content are processed. Thanks to Christian Boos for the original patch and unit tests.
cmlenz
parents:
374
diff
changeset
|
224 streams.append([]) |
363
caf7b68ab5dc
Parse template includes at parse time to avoid some runtime overhead.
cmlenz
parents:
362
diff
changeset
|
225 elif tag.localname == 'fallback': |
590
880b1a75d046
Fix includes so that they again raise an exception when the included template is not found and no fallback has been provided.
cmlenz
parents:
552
diff
changeset
|
226 streams.append([]) |
880b1a75d046
Fix includes so that they again raise an exception when the included template is not found and no fallback has been provided.
cmlenz
parents:
552
diff
changeset
|
227 fallbacks.append(streams[-1]) |
363
caf7b68ab5dc
Parse template includes at parse time to avoid some runtime overhead.
cmlenz
parents:
362
diff
changeset
|
228 else: |
790
1b6968d31089
Merged the custom-directives branch back into trunk.
cmlenz
parents:
783
diff
changeset
|
229 stream.append((kind, (tag, attrs), pos)) |
336
5f2c7782cd8a
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
230 |
5f2c7782cd8a
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
1b6968d31089
Merged the custom-directives branch back into trunk.
cmlenz
parents:
783
diff
changeset
|
232 if fallbacks and data == xinclude_ns['fallback']: |
590
880b1a75d046
Fix includes so that they again raise an exception when the included template is not found and no fallback has been provided.
cmlenz
parents:
552
diff
changeset
|
233 assert streams.pop() is fallbacks[-1] |
790
1b6968d31089
Merged the custom-directives branch back into trunk.
cmlenz
parents:
783
diff
changeset
|
234 elif data == xinclude_ns['include']: |
590
880b1a75d046
Fix includes so that they again raise an exception when the included template is not found and no fallback has been provided.
cmlenz
parents:
552
diff
changeset
|
235 fallback = None |
880b1a75d046
Fix includes so that they again raise an exception when the included template is not found and no fallback has been provided.
cmlenz
parents:
552
diff
changeset
|
236 if len(fallbacks) == len(includes): |
880b1a75d046
Fix includes so that they again raise an exception when the included template is not found and no fallback has been provided.
cmlenz
parents:
552
diff
changeset
|
237 fallback = fallbacks.pop() |
880b1a75d046
Fix includes so that they again raise an exception when the included template is not found and no fallback has been provided.
cmlenz
parents:
552
diff
changeset
|
238 streams.pop() # discard anything between the include tags |
880b1a75d046
Fix includes so that they again raise an exception when the included template is not found and no fallback has been provided.
cmlenz
parents:
552
diff
changeset
|
239 # and the fallback element |
381
a6c2a9cd2e92
Fix for #80: fallback only shown when the template to include wasn't found. In addition, the nesting of includes and fallback content should work correctly, and directives/expressions/etc inside fallback content are processed. Thanks to Christian Boos for the original patch and unit tests.
cmlenz
parents:
374
diff
changeset
|
240 stream = streams[-1] |
610
6a37018199fd
* XInclude elements in markup templates now support the `parse` attribute; when set to "xml" (the default), the include is processed as before, but when set to "text", the included template is parsed as a text template using the new syntax (ticket #101).
cmlenz
parents:
609
diff
changeset
|
241 href, parse = includes.pop() |
6a37018199fd
* XInclude elements in markup templates now support the `parse` attribute; when set to "xml" (the default), the include is processed as before, but when set to "text", the included template is parsed as a text template using the new syntax (ticket #101).
cmlenz
parents:
609
diff
changeset
|
242 try: |
6a37018199fd
* XInclude elements in markup templates now support the `parse` attribute; when set to "xml" (the default), the include is processed as before, but when set to "text", the included template is parsed as a text template using the new syntax (ticket #101).
cmlenz
parents:
609
diff
changeset
|
243 cls = { |
6a37018199fd
* XInclude elements in markup templates now support the `parse` attribute; when set to "xml" (the default), the include is processed as before, but when set to "text", the included template is parsed as a text template using the new syntax (ticket #101).
cmlenz
parents:
609
diff
changeset
|
244 'xml': MarkupTemplate, |
6a37018199fd
* XInclude elements in markup templates now support the `parse` attribute; when set to "xml" (the default), the include is processed as before, but when set to "text", the included template is parsed as a text template using the new syntax (ticket #101).
cmlenz
parents:
609
diff
changeset
|
245 'text': NewTextTemplate |
880
3b16d762445b
Default XInclude-included template class to the class of the including template. Closes #302.
cmlenz
parents:
876
diff
changeset
|
246 }.get(parse) or self.__class__ |
610
6a37018199fd
* XInclude elements in markup templates now support the `parse` attribute; when set to "xml" (the default), the include is processed as before, but when set to "text", the included template is parsed as a text template using the new syntax (ticket #101).
cmlenz
parents:
609
diff
changeset
|
247 except KeyError: |
6a37018199fd
* XInclude elements in markup templates now support the `parse` attribute; when set to "xml" (the default), the include is processed as before, but when set to "text", the included template is parsed as a text template using the new syntax (ticket #101).
cmlenz
parents:
609
diff
changeset
|
248 raise TemplateSyntaxError('Invalid value for "parse" ' |
6a37018199fd
* XInclude elements in markup templates now support the `parse` attribute; when set to "xml" (the default), the include is processed as before, but when set to "text", the included template is parsed as a text template using the new syntax (ticket #101).
cmlenz
parents:
609
diff
changeset
|
249 'attribute of include', |
6a37018199fd
* XInclude elements in markup templates now support the `parse` attribute; when set to "xml" (the default), the include is processed as before, but when set to "text", the included template is parsed as a text template using the new syntax (ticket #101).
cmlenz
parents:
609
diff
changeset
|
250 self.filepath, *pos[1:]) |
6a37018199fd
* XInclude elements in markup templates now support the `parse` attribute; when set to "xml" (the default), the include is processed as before, but when set to "text", the included template is parsed as a text template using the new syntax (ticket #101).
cmlenz
parents:
609
diff
changeset
|
251 stream.append((INCLUDE, (href, cls, fallback), pos)) |
363
caf7b68ab5dc
Parse template includes at parse time to avoid some runtime overhead.
cmlenz
parents:
362
diff
changeset
|
252 else: |
caf7b68ab5dc
Parse template includes at parse time to avoid some runtime overhead.
cmlenz
parents:
362
diff
changeset
|
253 stream.append((kind, data, pos)) |
336
5f2c7782cd8a
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
254 |
790
1b6968d31089
Merged the custom-directives branch back into trunk.
cmlenz
parents:
783
diff
changeset
|
255 elif kind is START_NS and data[1] == xinclude_ns: |
1b6968d31089
Merged the custom-directives branch back into trunk.
cmlenz
parents:
783
diff
changeset
|
256 # Strip out the XInclude namespace |
1b6968d31089
Merged the custom-directives branch back into trunk.
cmlenz
parents:
783
diff
changeset
|
257 prefixes[data[0]] = data[1] |
336
5f2c7782cd8a
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
258 |
790
1b6968d31089
Merged the custom-directives branch back into trunk.
cmlenz
parents:
783
diff
changeset
|
259 elif kind is END_NS and data in prefixes: |
1b6968d31089
Merged the custom-directives branch back into trunk.
cmlenz
parents:
783
diff
changeset
|
260 prefixes.pop(data) |
336
5f2c7782cd8a
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
261 |
5f2c7782cd8a
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
262 else: |
5f2c7782cd8a
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
263 stream.append((kind, data, pos)) |
5f2c7782cd8a
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
264 |
381
a6c2a9cd2e92
Fix for #80: fallback only shown when the template to include wasn't found. In addition, the nesting of includes and fallback content should work correctly, and directives/expressions/etc inside fallback content are processed. Thanks to Christian Boos for the original patch and unit tests.
cmlenz
parents:
374
diff
changeset
|
265 assert len(streams) == 1 |
a6c2a9cd2e92
Fix for #80: fallback only shown when the template to include wasn't found. In addition, the nesting of includes and fallback content should work correctly, and directives/expressions/etc inside fallback content are processed. Thanks to Christian Boos for the original patch and unit tests.
cmlenz
parents:
374
diff
changeset
|
266 return streams[0] |
a6c2a9cd2e92
Fix for #80: fallback only shown when the template to include wasn't found. In addition, the nesting of includes and fallback content should work correctly, and directives/expressions/etc inside fallback content are processed. Thanks to Christian Boos for the original patch and unit tests.
cmlenz
parents:
374
diff
changeset
|
267 |
790
1b6968d31089
Merged the custom-directives branch back into trunk.
cmlenz
parents:
783
diff
changeset
|
268 def _interpolate_attrs(self, stream): |
1b6968d31089
Merged the custom-directives branch back into trunk.
cmlenz
parents:
783
diff
changeset
|
269 for kind, data, pos in stream: |
1b6968d31089
Merged the custom-directives branch back into trunk.
cmlenz
parents:
783
diff
changeset
|
270 |
1b6968d31089
Merged the custom-directives branch back into trunk.
cmlenz
parents:
783
diff
changeset
|
271 if kind is START: |
1b6968d31089
Merged the custom-directives branch back into trunk.
cmlenz
parents:
783
diff
changeset
|
272 # Record any directive attributes in start tags |
1b6968d31089
Merged the custom-directives branch back into trunk.
cmlenz
parents:
783
diff
changeset
|
273 tag, attrs = data |
1b6968d31089
Merged the custom-directives branch back into trunk.
cmlenz
parents:
783
diff
changeset
|
274 new_attrs = [] |
1b6968d31089
Merged the custom-directives branch back into trunk.
cmlenz
parents:
783
diff
changeset
|
275 for name, value in attrs: |
1b6968d31089
Merged the custom-directives branch back into trunk.
cmlenz
parents:
783
diff
changeset
|
276 if value: |
1b6968d31089
Merged the custom-directives branch back into trunk.
cmlenz
parents:
783
diff
changeset
|
277 value = list(interpolate(value, self.filepath, pos[1], |
1b6968d31089
Merged the custom-directives branch back into trunk.
cmlenz
parents:
783
diff
changeset
|
278 pos[2], lookup=self.lookup)) |
1b6968d31089
Merged the custom-directives branch back into trunk.
cmlenz
parents:
783
diff
changeset
|
279 if len(value) == 1 and value[0][0] is TEXT: |
1b6968d31089
Merged the custom-directives branch back into trunk.
cmlenz
parents:
783
diff
changeset
|
280 value = value[0][1] |
1b6968d31089
Merged the custom-directives branch back into trunk.
cmlenz
parents:
783
diff
changeset
|
281 new_attrs.append((name, value)) |
1b6968d31089
Merged the custom-directives branch back into trunk.
cmlenz
parents:
783
diff
changeset
|
282 data = tag, Attrs(new_attrs) |
1b6968d31089
Merged the custom-directives branch back into trunk.
cmlenz
parents:
783
diff
changeset
|
283 |
1b6968d31089
Merged the custom-directives branch back into trunk.
cmlenz
parents:
783
diff
changeset
|
284 yield kind, data, pos |
1b6968d31089
Merged the custom-directives branch back into trunk.
cmlenz
parents:
783
diff
changeset
|
285 |
1b6968d31089
Merged the custom-directives branch back into trunk.
cmlenz
parents:
783
diff
changeset
|
286 def _prepare(self, stream): |
1b6968d31089
Merged the custom-directives branch back into trunk.
cmlenz
parents:
783
diff
changeset
|
287 return Template._prepare(self, |
1b6968d31089
Merged the custom-directives branch back into trunk.
cmlenz
parents:
783
diff
changeset
|
288 self._extract_includes(self._interpolate_attrs(stream)) |
1b6968d31089
Merged the custom-directives branch back into trunk.
cmlenz
parents:
783
diff
changeset
|
289 ) |
1b6968d31089
Merged the custom-directives branch back into trunk.
cmlenz
parents:
783
diff
changeset
|
290 |
1b6968d31089
Merged the custom-directives branch back into trunk.
cmlenz
parents:
783
diff
changeset
|
291 def add_directives(self, namespace, factory): |
1b6968d31089
Merged the custom-directives branch back into trunk.
cmlenz
parents:
783
diff
changeset
|
292 """Register a custom `DirectiveFactory` for a given namespace. |
1b6968d31089
Merged the custom-directives branch back into trunk.
cmlenz
parents:
783
diff
changeset
|
293 |
1b6968d31089
Merged the custom-directives branch back into trunk.
cmlenz
parents:
783
diff
changeset
|
294 :param namespace: the namespace URI |
1b6968d31089
Merged the custom-directives branch back into trunk.
cmlenz
parents:
783
diff
changeset
|
295 :type namespace: `basestring` |
1b6968d31089
Merged the custom-directives branch back into trunk.
cmlenz
parents:
783
diff
changeset
|
296 :param factory: the directive factory to register |
1b6968d31089
Merged the custom-directives branch back into trunk.
cmlenz
parents:
783
diff
changeset
|
297 :type factory: `DirectiveFactory` |
1b6968d31089
Merged the custom-directives branch back into trunk.
cmlenz
parents:
783
diff
changeset
|
298 :since: version 0.6 |
1b6968d31089
Merged the custom-directives branch back into trunk.
cmlenz
parents:
783
diff
changeset
|
299 """ |
1b6968d31089
Merged the custom-directives branch back into trunk.
cmlenz
parents:
783
diff
changeset
|
300 assert not self._prepared, 'Too late for adding directives, ' \ |
1b6968d31089
Merged the custom-directives branch back into trunk.
cmlenz
parents:
783
diff
changeset
|
301 'template already prepared' |
1b6968d31089
Merged the custom-directives branch back into trunk.
cmlenz
parents:
783
diff
changeset
|
302 self._stream = self._extract_directives(self._stream, namespace, |
1b6968d31089
Merged the custom-directives branch back into trunk.
cmlenz
parents:
783
diff
changeset
|
303 factory) |
1b6968d31089
Merged the custom-directives branch back into trunk.
cmlenz
parents:
783
diff
changeset
|
304 |
766
584aa6bfbe54
Fix bug where in some cases match templates would incorrectly applied multiple times.
cmlenz
parents:
758
diff
changeset
|
305 def _match(self, stream, ctxt, start=0, end=None, **vars): |
336
5f2c7782cd8a
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
306 """Internal stream filter that applies any defined match templates |
5f2c7782cd8a
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
307 to the stream. |
5f2c7782cd8a
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
308 """ |
766
584aa6bfbe54
Fix bug where in some cases match templates would incorrectly applied multiple times.
cmlenz
parents:
758
diff
changeset
|
309 match_templates = ctxt._match_templates |
336
5f2c7782cd8a
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
310 |
924 | 311 def _strip(stream, append): |
336
5f2c7782cd8a
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
312 depth = 1 |
843
004f81b59d97
Refactored the template flattening method to be less recursive.
cmlenz
parents:
827
diff
changeset
|
313 next = stream.next |
336
5f2c7782cd8a
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
314 while 1: |
843
004f81b59d97
Refactored the template flattening method to be less recursive.
cmlenz
parents:
827
diff
changeset
|
315 event = next() |
336
5f2c7782cd8a
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
316 if event[0] is START: |
5f2c7782cd8a
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
317 depth += 1 |
5f2c7782cd8a
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
318 elif event[0] is END: |
5f2c7782cd8a
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
319 depth -= 1 |
5f2c7782cd8a
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
320 if depth > 0: |
5f2c7782cd8a
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
321 yield event |
5f2c7782cd8a
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
322 else: |
843
004f81b59d97
Refactored the template flattening method to be less recursive.
cmlenz
parents:
827
diff
changeset
|
323 append(event) |
336
5f2c7782cd8a
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
324 break |
5f2c7782cd8a
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
325 |
5f2c7782cd8a
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
326 for event in stream: |
5f2c7782cd8a
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
327 |
809 | 328 # We (currently) only care about start and end events for matching |
336
5f2c7782cd8a
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
329 # We might care about namespace events in the future, though |
809 | 330 if not match_templates or (event[0] is not START and |
331 event[0] is not END): | |
336
5f2c7782cd8a
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
332 yield event |
5f2c7782cd8a
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
333 continue |
5f2c7782cd8a
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
334 |
602 | 335 for idx, (test, path, template, hints, namespaces, directives) \ |
336 in enumerate(match_templates): | |
766
584aa6bfbe54
Fix bug where in some cases match templates would incorrectly applied multiple times.
cmlenz
parents:
758
diff
changeset
|
337 if idx < start or end is not None and idx >= end: |
758
0ea32786b624
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
|
338 continue |
336
5f2c7782cd8a
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
339 |
5f2c7782cd8a
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
340 if test(event, namespaces, ctxt) is True: |
602 | 341 if 'match_once' in hints: |
342 del match_templates[idx] | |
343 idx -= 1 | |
336
5f2c7782cd8a
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
344 |
5f2c7782cd8a
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
345 # Let the remaining match templates know about the event so |
5f2c7782cd8a
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
346 # they get a chance to update their internal state |
5f2c7782cd8a
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
347 for test in [mt[0] for mt in match_templates[idx + 1:]]: |
5f2c7782cd8a
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
348 test(event, namespaces, ctxt, updateonly=True) |
5f2c7782cd8a
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
349 |
5f2c7782cd8a
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
350 # Consume and store all events until an end event |
5f2c7782cd8a
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
351 # corresponding to this start event is encountered |
766
584aa6bfbe54
Fix bug where in some cases match templates would incorrectly applied multiple times.
cmlenz
parents:
758
diff
changeset
|
352 pre_end = idx + 1 |
694
812671b40022
Match templates are now applied in a more controlled fashion: in the order they are declared in the template source, all match templates up to (and including) the matching template itself are applied to the matched content, whereas the match templates declared after the matching template are only applied to the generated content. Fixes #186. Many thanks to Matt Chaput for reporting the problem and providing a test case.
cmlenz
parents:
650
diff
changeset
|
353 if 'match_once' not in hints and 'not_recursive' in hints: |
766
584aa6bfbe54
Fix bug where in some cases match templates would incorrectly applied multiple times.
cmlenz
parents:
758
diff
changeset
|
354 pre_end -= 1 |
924 | 355 tail = [] |
356 inner = _strip(stream, tail.append) | |
766
584aa6bfbe54
Fix bug where in some cases match templates would incorrectly applied multiple times.
cmlenz
parents:
758
diff
changeset
|
357 if pre_end > 0: |
870
1ea88e82713d
Apply patch Felix Schwarz that finally fixes the duplicated output in match template processing. Thanks so much!
cmlenz
parents:
853
diff
changeset
|
358 inner = self._match(inner, ctxt, start=start, |
1ea88e82713d
Apply patch Felix Schwarz that finally fixes the duplicated output in match template processing. Thanks so much!
cmlenz
parents:
853
diff
changeset
|
359 end=pre_end, **vars) |
700
8d079cee6822
Add option for unbuffered match template processing, which could cause excessive memory usage. Closes #190.
cmlenz
parents:
694
diff
changeset
|
360 content = self._include(chain([event], inner, tail), ctxt) |
8d079cee6822
Add option for unbuffered match template processing, which could cause excessive memory usage. Closes #190.
cmlenz
parents:
694
diff
changeset
|
361 if 'not_buffered' not in hints: |
8d079cee6822
Add option for unbuffered match template processing, which could cause excessive memory usage. Closes #190.
cmlenz
parents:
694
diff
changeset
|
362 content = list(content) |
843
004f81b59d97
Refactored the template flattening method to be less recursive.
cmlenz
parents:
827
diff
changeset
|
363 content = Stream(content) |
336
5f2c7782cd8a
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
364 |
5f2c7782cd8a
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
365 # Make the select() function available in the body of the |
5f2c7782cd8a
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
366 # match template |
771
b4c973fbe6f5
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
|
367 selected = [False] |
336
5f2c7782cd8a
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
368 def select(path): |
771
b4c973fbe6f5
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
|
369 selected[0] = True |
843
004f81b59d97
Refactored the template flattening method to be less recursive.
cmlenz
parents:
827
diff
changeset
|
370 return content.select(path, namespaces, ctxt) |
700
8d079cee6822
Add option for unbuffered match template processing, which could cause excessive memory usage. Closes #190.
cmlenz
parents:
694
diff
changeset
|
371 vars = dict(select=select) |
336
5f2c7782cd8a
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
372 |
5f2c7782cd8a
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
373 # Recursively process the output |
700
8d079cee6822
Add option for unbuffered match template processing, which could cause excessive memory usage. Closes #190.
cmlenz
parents:
694
diff
changeset
|
374 template = _apply_directives(template, directives, ctxt, |
827
0319a8874510
Avoid varargs on internal functions in template processing for slightly better performance.
cmlenz
parents:
814
diff
changeset
|
375 vars) |
813
3047d5d83ccc
Merge the internal template filters `_eval` and `_exec` into the `_flatten` function for slightly better performance.
cmlenz
parents:
809
diff
changeset
|
376 for event in self._match(self._flatten(template, ctxt, |
3047d5d83ccc
Merge the internal template filters `_eval` and `_exec` into the `_flatten` function for slightly better performance.
cmlenz
parents:
809
diff
changeset
|
377 **vars), |
3047d5d83ccc
Merge the internal template filters `_eval` and `_exec` into the `_flatten` function for slightly better performance.
cmlenz
parents:
809
diff
changeset
|
378 ctxt, start=idx + 1, **vars): |
336
5f2c7782cd8a
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
379 yield event |
5f2c7782cd8a
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
380 |
771
b4c973fbe6f5
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
|
381 # If the match template did not actually call select to |
b4c973fbe6f5
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 # consume the matched stream, the original events need to |
b4c973fbe6f5
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 # be consumed here or they'll get appended to the output |
b4c973fbe6f5
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 if not selected[0]: |
b4c973fbe6f5
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 for event in content: |
b4c973fbe6f5
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 pass |
b4c973fbe6f5
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 |
b4c973fbe6f5
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 # Let the remaining match templates know about the last |
b4c973fbe6f5
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
|
389 # event in the matched content, so they can update their |
b4c973fbe6f5
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
|
390 # internal state accordingly |
874
fcf378812238
Fix for match template processing involving multiple match directives targetting the same element. Should close #370.
cmlenz
parents:
870
diff
changeset
|
391 for test in [mt[0] for mt in match_templates[idx + 1:]]: |
771
b4c973fbe6f5
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 test(tail[0], namespaces, ctxt, updateonly=True) |
b4c973fbe6f5
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
|
393 |
336
5f2c7782cd8a
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
394 break |
5f2c7782cd8a
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
395 |
5f2c7782cd8a
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
396 else: # no matches |
5f2c7782cd8a
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
397 yield event |