Mercurial > genshi > genshi-test
annotate genshi/template/markup.py @ 874:fcf378812238
Fix for match template processing involving multiple match directives targetting the same element. Should close #370.
author | cmlenz |
---|---|
date | Thu, 15 Apr 2010 20:30:09 +0000 |
parents | 1ea88e82713d |
children | 52d7d6b7b6c1 |
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 # |
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
|
3 # Copyright (C) 2006-2009 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 |
715 | 73 if self.loader: |
496
782931585925
Fix bug introduced in [575]: includes weren't being processed inside match templates.
cmlenz
parents:
475
diff
changeset
|
74 self.filters.remove(self._include) |
609
237050080827
Add support for Python code blocks in text templates using the new syntax.
cmlenz
parents:
606
diff
changeset
|
75 self.filters += [self._match] |
715 | 76 if self.loader: |
496
782931585925
Fix bug introduced in [575]: includes weren't being processed inside match templates.
cmlenz
parents:
475
diff
changeset
|
77 self.filters.append(self._include) |
336
5f2c7782cd8a
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
78 |
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 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
|
80 if not isinstance(source, Stream): |
434
e065d7906b68
* Better method to propogate the full path to the template file on parse errors. Supersedes r513.
cmlenz
parents:
427
diff
changeset
|
81 source = XMLParser(source, filename=self.filename, |
374
ca46dc9c7761
`MarkupTemplate`s can now be instantiated from markup streams, in addition to strings and file-like objects. Thanks to David Fraser for the patch. Closes #69.
cmlenz
parents:
364
diff
changeset
|
82 encoding=encoding) |
790
1b6968d31089
Merged the custom-directives branch back into trunk.
cmlenz
parents:
783
diff
changeset
|
83 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
|
84 |
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
|
85 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
|
86 |
790
1b6968d31089
Merged the custom-directives branch back into trunk.
cmlenz
parents:
783
diff
changeset
|
87 if kind is TEXT: |
1b6968d31089
Merged the custom-directives branch back into trunk.
cmlenz
parents:
783
diff
changeset
|
88 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
|
89 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
|
90 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
|
91 |
790
1b6968d31089
Merged the custom-directives branch back into trunk.
cmlenz
parents:
783
diff
changeset
|
92 elif kind is PI and data[0] == 'python': |
1b6968d31089
Merged the custom-directives branch back into trunk.
cmlenz
parents:
783
diff
changeset
|
93 if not self.allow_exec: |
1b6968d31089
Merged the custom-directives branch back into trunk.
cmlenz
parents:
783
diff
changeset
|
94 raise TemplateSyntaxError('Python code blocks not allowed', |
1b6968d31089
Merged the custom-directives branch back into trunk.
cmlenz
parents:
783
diff
changeset
|
95 self.filepath, *pos[1:]) |
1b6968d31089
Merged the custom-directives branch back into trunk.
cmlenz
parents:
783
diff
changeset
|
96 try: |
1b6968d31089
Merged the custom-directives branch back into trunk.
cmlenz
parents:
783
diff
changeset
|
97 suite = Suite(data[1], self.filepath, pos[1], |
1b6968d31089
Merged the custom-directives branch back into trunk.
cmlenz
parents:
783
diff
changeset
|
98 lookup=self.lookup) |
1b6968d31089
Merged the custom-directives branch back into trunk.
cmlenz
parents:
783
diff
changeset
|
99 except SyntaxError, err: |
1b6968d31089
Merged the custom-directives branch back into trunk.
cmlenz
parents:
783
diff
changeset
|
100 raise TemplateSyntaxError(err, self.filepath, |
1b6968d31089
Merged the custom-directives branch back into trunk.
cmlenz
parents:
783
diff
changeset
|
101 pos[1] + (err.lineno or 1) - 1, |
1b6968d31089
Merged the custom-directives branch back into trunk.
cmlenz
parents:
783
diff
changeset
|
102 pos[2] + (err.offset or 0)) |
1b6968d31089
Merged the custom-directives branch back into trunk.
cmlenz
parents:
783
diff
changeset
|
103 stream.append((EXEC, suite, pos)) |
1b6968d31089
Merged the custom-directives branch back into trunk.
cmlenz
parents:
783
diff
changeset
|
104 |
1b6968d31089
Merged the custom-directives branch back into trunk.
cmlenz
parents:
783
diff
changeset
|
105 elif kind is COMMENT: |
1b6968d31089
Merged the custom-directives branch back into trunk.
cmlenz
parents:
783
diff
changeset
|
106 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
|
107 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
|
108 |
790
1b6968d31089
Merged the custom-directives branch back into trunk.
cmlenz
parents:
783
diff
changeset
|
109 else: |
1b6968d31089
Merged the custom-directives branch back into trunk.
cmlenz
parents:
783
diff
changeset
|
110 stream.append((kind, data, pos)) |
1b6968d31089
Merged the custom-directives branch back into trunk.
cmlenz
parents:
783
diff
changeset
|
111 |
1b6968d31089
Merged the custom-directives branch back into trunk.
cmlenz
parents:
783
diff
changeset
|
112 return stream |
1b6968d31089
Merged the custom-directives branch back into trunk.
cmlenz
parents:
783
diff
changeset
|
113 |
1b6968d31089
Merged the custom-directives branch back into trunk.
cmlenz
parents:
783
diff
changeset
|
114 def _extract_directives(self, stream, namespace, factory): |
1b6968d31089
Merged the custom-directives branch back into trunk.
cmlenz
parents:
783
diff
changeset
|
115 depth = 0 |
1b6968d31089
Merged the custom-directives branch back into trunk.
cmlenz
parents:
783
diff
changeset
|
116 dirmap = {} # temporary mapping of directives to elements |
1b6968d31089
Merged the custom-directives branch back into trunk.
cmlenz
parents:
783
diff
changeset
|
117 new_stream = [] |
1b6968d31089
Merged the custom-directives branch back into trunk.
cmlenz
parents:
783
diff
changeset
|
118 ns_prefix = {} # namespace prefixes in use |
1b6968d31089
Merged the custom-directives branch back into trunk.
cmlenz
parents:
783
diff
changeset
|
119 |
1b6968d31089
Merged the custom-directives branch back into trunk.
cmlenz
parents:
783
diff
changeset
|
120 for kind, data, pos in stream: |
1b6968d31089
Merged the custom-directives branch back into trunk.
cmlenz
parents:
783
diff
changeset
|
121 |
1b6968d31089
Merged the custom-directives branch back into trunk.
cmlenz
parents:
783
diff
changeset
|
122 if kind is START: |
363
caf7b68ab5dc
Parse template includes at parse time to avoid some runtime overhead.
cmlenz
parents:
362
diff
changeset
|
123 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
|
124 directives = [] |
5f2c7782cd8a
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
125 strip = False |
5f2c7782cd8a
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
126 |
790
1b6968d31089
Merged the custom-directives branch back into trunk.
cmlenz
parents:
783
diff
changeset
|
127 if tag.namespace == namespace: |
1b6968d31089
Merged the custom-directives branch back into trunk.
cmlenz
parents:
783
diff
changeset
|
128 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
|
129 if cls is None: |
790
1b6968d31089
Merged the custom-directives branch back into trunk.
cmlenz
parents:
783
diff
changeset
|
130 raise BadDirectiveError(tag.localname, |
1b6968d31089
Merged the custom-directives branch back into trunk.
cmlenz
parents:
783
diff
changeset
|
131 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
|
132 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
|
133 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
|
134 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
|
135 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
|
136 strip = True |
5f2c7782cd8a
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
137 |
363
caf7b68ab5dc
Parse template includes at parse time to avoid some runtime overhead.
cmlenz
parents:
362
diff
changeset
|
138 new_attrs = [] |
caf7b68ab5dc
Parse template includes at parse time to avoid some runtime overhead.
cmlenz
parents:
362
diff
changeset
|
139 for name, value in attrs: |
790
1b6968d31089
Merged the custom-directives branch back into trunk.
cmlenz
parents:
783
diff
changeset
|
140 if name.namespace == namespace: |
1b6968d31089
Merged the custom-directives branch back into trunk.
cmlenz
parents:
783
diff
changeset
|
141 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
|
142 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
|
143 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
|
144 self.filepath, pos[1]) |
790
1b6968d31089
Merged the custom-directives branch back into trunk.
cmlenz
parents:
783
diff
changeset
|
145 if type(value) is list and len(value) == 1: |
1b6968d31089
Merged the custom-directives branch back into trunk.
cmlenz
parents:
783
diff
changeset
|
146 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
|
147 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
|
148 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
|
149 else: |
363
caf7b68ab5dc
Parse template includes at parse time to avoid some runtime overhead.
cmlenz
parents:
362
diff
changeset
|
150 new_attrs.append((name, value)) |
caf7b68ab5dc
Parse template includes at parse time to avoid some runtime overhead.
cmlenz
parents:
362
diff
changeset
|
151 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
|
152 |
5f2c7782cd8a
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
153 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
|
154 directives.sort() |
790
1b6968d31089
Merged the custom-directives branch back into trunk.
cmlenz
parents:
783
diff
changeset
|
155 dirmap[(depth, tag)] = (directives, len(new_stream), |
1b6968d31089
Merged the custom-directives branch back into trunk.
cmlenz
parents:
783
diff
changeset
|
156 strip) |
336
5f2c7782cd8a
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
157 |
790
1b6968d31089
Merged the custom-directives branch back into trunk.
cmlenz
parents:
783
diff
changeset
|
158 new_stream.append((kind, (tag, new_attrs), pos)) |
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 |
1b6968d31089
Merged the custom-directives branch back into trunk.
cmlenz
parents:
783
diff
changeset
|
161 elif kind is END: |
1b6968d31089
Merged the custom-directives branch back into trunk.
cmlenz
parents:
783
diff
changeset
|
162 depth -= 1 |
1b6968d31089
Merged the custom-directives branch back into trunk.
cmlenz
parents:
783
diff
changeset
|
163 new_stream.append((kind, data, pos)) |
1b6968d31089
Merged the custom-directives branch back into trunk.
cmlenz
parents:
783
diff
changeset
|
164 |
1b6968d31089
Merged the custom-directives branch back into trunk.
cmlenz
parents:
783
diff
changeset
|
165 # If there have have directive attributes with the |
1b6968d31089
Merged the custom-directives branch back into trunk.
cmlenz
parents:
783
diff
changeset
|
166 # corresponding start tag, move the events inbetween into |
1b6968d31089
Merged the custom-directives branch back into trunk.
cmlenz
parents:
783
diff
changeset
|
167 # a "subprogram" |
1b6968d31089
Merged the custom-directives branch back into trunk.
cmlenz
parents:
783
diff
changeset
|
168 if (depth, data) in dirmap: |
1b6968d31089
Merged the custom-directives branch back into trunk.
cmlenz
parents:
783
diff
changeset
|
169 directives, offset, strip = dirmap.pop((depth, data)) |
1b6968d31089
Merged the custom-directives branch back into trunk.
cmlenz
parents:
783
diff
changeset
|
170 substream = new_stream[offset:] |
1b6968d31089
Merged the custom-directives branch back into trunk.
cmlenz
parents:
783
diff
changeset
|
171 if strip: |
1b6968d31089
Merged the custom-directives branch back into trunk.
cmlenz
parents:
783
diff
changeset
|
172 substream = substream[1:-1] |
1b6968d31089
Merged the custom-directives branch back into trunk.
cmlenz
parents:
783
diff
changeset
|
173 new_stream[offset:] = [ |
1b6968d31089
Merged the custom-directives branch back into trunk.
cmlenz
parents:
783
diff
changeset
|
174 (SUB, (directives, substream), pos) |
1b6968d31089
Merged the custom-directives branch back into trunk.
cmlenz
parents:
783
diff
changeset
|
175 ] |
1b6968d31089
Merged the custom-directives branch back into trunk.
cmlenz
parents:
783
diff
changeset
|
176 |
1b6968d31089
Merged the custom-directives branch back into trunk.
cmlenz
parents:
783
diff
changeset
|
177 elif kind is SUB: |
1b6968d31089
Merged the custom-directives branch back into trunk.
cmlenz
parents:
783
diff
changeset
|
178 directives, substream = data |
1b6968d31089
Merged the custom-directives branch back into trunk.
cmlenz
parents:
783
diff
changeset
|
179 substream = self._extract_directives(substream, namespace, |
1b6968d31089
Merged the custom-directives branch back into trunk.
cmlenz
parents:
783
diff
changeset
|
180 factory) |
1b6968d31089
Merged the custom-directives branch back into trunk.
cmlenz
parents:
783
diff
changeset
|
181 |
1b6968d31089
Merged the custom-directives branch back into trunk.
cmlenz
parents:
783
diff
changeset
|
182 if len(substream) == 1 and substream[0][0] is SUB: |
1b6968d31089
Merged the custom-directives branch back into trunk.
cmlenz
parents:
783
diff
changeset
|
183 added_directives, substream = substream[0][1] |
1b6968d31089
Merged the custom-directives branch back into trunk.
cmlenz
parents:
783
diff
changeset
|
184 directives += added_directives |
1b6968d31089
Merged the custom-directives branch back into trunk.
cmlenz
parents:
783
diff
changeset
|
185 |
1b6968d31089
Merged the custom-directives branch back into trunk.
cmlenz
parents:
783
diff
changeset
|
186 new_stream.append((kind, (directives, substream), pos)) |
1b6968d31089
Merged the custom-directives branch back into trunk.
cmlenz
parents:
783
diff
changeset
|
187 |
1b6968d31089
Merged the custom-directives branch back into trunk.
cmlenz
parents:
783
diff
changeset
|
188 elif kind is START_NS: |
1b6968d31089
Merged the custom-directives branch back into trunk.
cmlenz
parents:
783
diff
changeset
|
189 # Strip out the namespace declaration for template |
1b6968d31089
Merged the custom-directives branch back into trunk.
cmlenz
parents:
783
diff
changeset
|
190 # directives |
1b6968d31089
Merged the custom-directives branch back into trunk.
cmlenz
parents:
783
diff
changeset
|
191 prefix, uri = data |
1b6968d31089
Merged the custom-directives branch back into trunk.
cmlenz
parents:
783
diff
changeset
|
192 ns_prefix[prefix] = uri |
1b6968d31089
Merged the custom-directives branch back into trunk.
cmlenz
parents:
783
diff
changeset
|
193 if uri != namespace: |
1b6968d31089
Merged the custom-directives branch back into trunk.
cmlenz
parents:
783
diff
changeset
|
194 new_stream.append((kind, data, pos)) |
1b6968d31089
Merged the custom-directives branch back into trunk.
cmlenz
parents:
783
diff
changeset
|
195 |
1b6968d31089
Merged the custom-directives branch back into trunk.
cmlenz
parents:
783
diff
changeset
|
196 elif kind is END_NS: |
1b6968d31089
Merged the custom-directives branch back into trunk.
cmlenz
parents:
783
diff
changeset
|
197 uri = ns_prefix.pop(data, None) |
1b6968d31089
Merged the custom-directives branch back into trunk.
cmlenz
parents:
783
diff
changeset
|
198 if uri and uri != namespace: |
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 else: |
1b6968d31089
Merged the custom-directives branch back into trunk.
cmlenz
parents:
783
diff
changeset
|
202 new_stream.append((kind, data, pos)) |
1b6968d31089
Merged the custom-directives branch back into trunk.
cmlenz
parents:
783
diff
changeset
|
203 |
1b6968d31089
Merged the custom-directives branch back into trunk.
cmlenz
parents:
783
diff
changeset
|
204 return new_stream |
1b6968d31089
Merged the custom-directives branch back into trunk.
cmlenz
parents:
783
diff
changeset
|
205 |
1b6968d31089
Merged the custom-directives branch back into trunk.
cmlenz
parents:
783
diff
changeset
|
206 def _extract_includes(self, stream): |
1b6968d31089
Merged the custom-directives branch back into trunk.
cmlenz
parents:
783
diff
changeset
|
207 streams = [[]] # stacked lists of events of the "compiled" template |
1b6968d31089
Merged the custom-directives branch back into trunk.
cmlenz
parents:
783
diff
changeset
|
208 prefixes = {} |
1b6968d31089
Merged the custom-directives branch back into trunk.
cmlenz
parents:
783
diff
changeset
|
209 fallbacks = [] |
1b6968d31089
Merged the custom-directives branch back into trunk.
cmlenz
parents:
783
diff
changeset
|
210 includes = [] |
1b6968d31089
Merged the custom-directives branch back into trunk.
cmlenz
parents:
783
diff
changeset
|
211 xinclude_ns = Namespace(self.XINCLUDE_NAMESPACE) |
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 for kind, data, pos in stream: |
1b6968d31089
Merged the custom-directives branch back into trunk.
cmlenz
parents:
783
diff
changeset
|
214 stream = streams[-1] |
1b6968d31089
Merged the custom-directives branch back into trunk.
cmlenz
parents:
783
diff
changeset
|
215 |
1b6968d31089
Merged the custom-directives branch back into trunk.
cmlenz
parents:
783
diff
changeset
|
216 if kind is START: |
1b6968d31089
Merged the custom-directives branch back into trunk.
cmlenz
parents:
783
diff
changeset
|
217 # Record any directive attributes in start tags |
1b6968d31089
Merged the custom-directives branch back into trunk.
cmlenz
parents:
783
diff
changeset
|
218 tag, attrs = data |
1b6968d31089
Merged the custom-directives branch back into trunk.
cmlenz
parents:
783
diff
changeset
|
219 if tag in xinclude_ns: |
363
caf7b68ab5dc
Parse template includes at parse time to avoid some runtime overhead.
cmlenz
parents:
362
diff
changeset
|
220 if tag.localname == 'include': |
790
1b6968d31089
Merged the custom-directives branch back into trunk.
cmlenz
parents:
783
diff
changeset
|
221 include_href = attrs.get('href') |
363
caf7b68ab5dc
Parse template includes at parse time to avoid some runtime overhead.
cmlenz
parents:
362
diff
changeset
|
222 if not include_href: |
caf7b68ab5dc
Parse template includes at parse time to avoid some runtime overhead.
cmlenz
parents:
362
diff
changeset
|
223 raise TemplateSyntaxError('Include misses required ' |
422
95089b6e37ca
More work to include absolute file paths in exceptions.
cmlenz
parents:
421
diff
changeset
|
224 'attribute "href"', |
95089b6e37ca
More work to include absolute file paths in exceptions.
cmlenz
parents:
421
diff
changeset
|
225 self.filepath, *pos[1:]) |
790
1b6968d31089
Merged the custom-directives branch back into trunk.
cmlenz
parents:
783
diff
changeset
|
226 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
|
227 streams.append([]) |
363
caf7b68ab5dc
Parse template includes at parse time to avoid some runtime overhead.
cmlenz
parents:
362
diff
changeset
|
228 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
|
229 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
|
230 fallbacks.append(streams[-1]) |
363
caf7b68ab5dc
Parse template includes at parse time to avoid some runtime overhead.
cmlenz
parents:
362
diff
changeset
|
231 else: |
790
1b6968d31089
Merged the custom-directives branch back into trunk.
cmlenz
parents:
783
diff
changeset
|
232 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
|
233 |
5f2c7782cd8a
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
234 elif kind is END: |
790
1b6968d31089
Merged the custom-directives branch back into trunk.
cmlenz
parents:
783
diff
changeset
|
235 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
|
236 assert streams.pop() is fallbacks[-1] |
790
1b6968d31089
Merged the custom-directives branch back into trunk.
cmlenz
parents:
783
diff
changeset
|
237 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
|
238 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
|
239 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
|
240 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
|
241 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
|
242 # 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
|
243 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
|
244 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
|
245 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
|
246 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
|
247 '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
|
248 'text': NewTextTemplate |
6a37018199fd
* XInclude elements in markup templates now support the `parse` attribute; when set to "xml" (the default), the include is processed as before, but when set to "text", the included template is parsed as a text template using the new syntax (ticket #101).
cmlenz
parents:
609
diff
changeset
|
249 }[parse or 'xml'] |
6a37018199fd
* XInclude elements in markup templates now support the `parse` attribute; when set to "xml" (the default), the include is processed as before, but when set to "text", the included template is parsed as a text template using the new syntax (ticket #101).
cmlenz
parents:
609
diff
changeset
|
250 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
|
251 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
|
252 '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
|
253 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
|
254 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
|
255 else: |
caf7b68ab5dc
Parse template includes at parse time to avoid some runtime overhead.
cmlenz
parents:
362
diff
changeset
|
256 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
|
257 |
790
1b6968d31089
Merged the custom-directives branch back into trunk.
cmlenz
parents:
783
diff
changeset
|
258 elif kind is START_NS and data[1] == xinclude_ns: |
1b6968d31089
Merged the custom-directives branch back into trunk.
cmlenz
parents:
783
diff
changeset
|
259 # Strip out the XInclude namespace |
1b6968d31089
Merged the custom-directives branch back into trunk.
cmlenz
parents:
783
diff
changeset
|
260 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
|
261 |
790
1b6968d31089
Merged the custom-directives branch back into trunk.
cmlenz
parents:
783
diff
changeset
|
262 elif kind is END_NS and data in prefixes: |
1b6968d31089
Merged the custom-directives branch back into trunk.
cmlenz
parents:
783
diff
changeset
|
263 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
|
264 |
5f2c7782cd8a
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
265 else: |
5f2c7782cd8a
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
266 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
|
267 |
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
|
268 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
|
269 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
|
270 |
790
1b6968d31089
Merged the custom-directives branch back into trunk.
cmlenz
parents:
783
diff
changeset
|
271 def _interpolate_attrs(self, stream): |
1b6968d31089
Merged the custom-directives branch back into trunk.
cmlenz
parents:
783
diff
changeset
|
272 for kind, data, pos in stream: |
1b6968d31089
Merged the custom-directives branch back into trunk.
cmlenz
parents:
783
diff
changeset
|
273 |
1b6968d31089
Merged the custom-directives branch back into trunk.
cmlenz
parents:
783
diff
changeset
|
274 if kind is START: |
1b6968d31089
Merged the custom-directives branch back into trunk.
cmlenz
parents:
783
diff
changeset
|
275 # Record any directive attributes in start tags |
1b6968d31089
Merged the custom-directives branch back into trunk.
cmlenz
parents:
783
diff
changeset
|
276 tag, attrs = data |
1b6968d31089
Merged the custom-directives branch back into trunk.
cmlenz
parents:
783
diff
changeset
|
277 new_attrs = [] |
1b6968d31089
Merged the custom-directives branch back into trunk.
cmlenz
parents:
783
diff
changeset
|
278 for name, value in attrs: |
1b6968d31089
Merged the custom-directives branch back into trunk.
cmlenz
parents:
783
diff
changeset
|
279 if value: |
1b6968d31089
Merged the custom-directives branch back into trunk.
cmlenz
parents:
783
diff
changeset
|
280 value = list(interpolate(value, self.filepath, pos[1], |
1b6968d31089
Merged the custom-directives branch back into trunk.
cmlenz
parents:
783
diff
changeset
|
281 pos[2], lookup=self.lookup)) |
1b6968d31089
Merged the custom-directives branch back into trunk.
cmlenz
parents:
783
diff
changeset
|
282 if len(value) == 1 and value[0][0] is TEXT: |
1b6968d31089
Merged the custom-directives branch back into trunk.
cmlenz
parents:
783
diff
changeset
|
283 value = value[0][1] |
1b6968d31089
Merged the custom-directives branch back into trunk.
cmlenz
parents:
783
diff
changeset
|
284 new_attrs.append((name, value)) |
1b6968d31089
Merged the custom-directives branch back into trunk.
cmlenz
parents:
783
diff
changeset
|
285 data = tag, Attrs(new_attrs) |
1b6968d31089
Merged the custom-directives branch back into trunk.
cmlenz
parents:
783
diff
changeset
|
286 |
1b6968d31089
Merged the custom-directives branch back into trunk.
cmlenz
parents:
783
diff
changeset
|
287 yield kind, data, pos |
1b6968d31089
Merged the custom-directives branch back into trunk.
cmlenz
parents:
783
diff
changeset
|
288 |
1b6968d31089
Merged the custom-directives branch back into trunk.
cmlenz
parents:
783
diff
changeset
|
289 def _prepare(self, stream): |
1b6968d31089
Merged the custom-directives branch back into trunk.
cmlenz
parents:
783
diff
changeset
|
290 return Template._prepare(self, |
1b6968d31089
Merged the custom-directives branch back into trunk.
cmlenz
parents:
783
diff
changeset
|
291 self._extract_includes(self._interpolate_attrs(stream)) |
1b6968d31089
Merged the custom-directives branch back into trunk.
cmlenz
parents:
783
diff
changeset
|
292 ) |
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 def add_directives(self, namespace, factory): |
1b6968d31089
Merged the custom-directives branch back into trunk.
cmlenz
parents:
783
diff
changeset
|
295 """Register a custom `DirectiveFactory` for a given namespace. |
1b6968d31089
Merged the custom-directives branch back into trunk.
cmlenz
parents:
783
diff
changeset
|
296 |
1b6968d31089
Merged the custom-directives branch back into trunk.
cmlenz
parents:
783
diff
changeset
|
297 :param namespace: the namespace URI |
1b6968d31089
Merged the custom-directives branch back into trunk.
cmlenz
parents:
783
diff
changeset
|
298 :type namespace: `basestring` |
1b6968d31089
Merged the custom-directives branch back into trunk.
cmlenz
parents:
783
diff
changeset
|
299 :param factory: the directive factory to register |
1b6968d31089
Merged the custom-directives branch back into trunk.
cmlenz
parents:
783
diff
changeset
|
300 :type factory: `DirectiveFactory` |
1b6968d31089
Merged the custom-directives branch back into trunk.
cmlenz
parents:
783
diff
changeset
|
301 :since: version 0.6 |
1b6968d31089
Merged the custom-directives branch back into trunk.
cmlenz
parents:
783
diff
changeset
|
302 """ |
1b6968d31089
Merged the custom-directives branch back into trunk.
cmlenz
parents:
783
diff
changeset
|
303 assert not self._prepared, 'Too late for adding directives, ' \ |
1b6968d31089
Merged the custom-directives branch back into trunk.
cmlenz
parents:
783
diff
changeset
|
304 'template already prepared' |
1b6968d31089
Merged the custom-directives branch back into trunk.
cmlenz
parents:
783
diff
changeset
|
305 self._stream = self._extract_directives(self._stream, namespace, |
1b6968d31089
Merged the custom-directives branch back into trunk.
cmlenz
parents:
783
diff
changeset
|
306 factory) |
1b6968d31089
Merged the custom-directives branch back into trunk.
cmlenz
parents:
783
diff
changeset
|
307 |
766
584aa6bfbe54
Fix bug where in some cases match templates would incorrectly applied multiple times.
cmlenz
parents:
758
diff
changeset
|
308 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
|
309 """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
|
310 to the stream. |
5f2c7782cd8a
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
311 """ |
766
584aa6bfbe54
Fix bug where in some cases match templates would incorrectly applied multiple times.
cmlenz
parents:
758
diff
changeset
|
312 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
|
313 |
5f2c7782cd8a
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
314 tail = [] |
843
004f81b59d97
Refactored the template flattening method to be less recursive.
cmlenz
parents:
827
diff
changeset
|
315 def _strip(stream, append=tail.append): |
336
5f2c7782cd8a
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
316 depth = 1 |
843
004f81b59d97
Refactored the template flattening method to be less recursive.
cmlenz
parents:
827
diff
changeset
|
317 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
|
318 while 1: |
843
004f81b59d97
Refactored the template flattening method to be less recursive.
cmlenz
parents:
827
diff
changeset
|
319 event = next() |
336
5f2c7782cd8a
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
320 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
|
321 depth += 1 |
5f2c7782cd8a
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
322 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
|
323 depth -= 1 |
5f2c7782cd8a
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
324 if depth > 0: |
5f2c7782cd8a
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
325 yield event |
5f2c7782cd8a
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
326 else: |
843
004f81b59d97
Refactored the template flattening method to be less recursive.
cmlenz
parents:
827
diff
changeset
|
327 append(event) |
336
5f2c7782cd8a
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
328 break |
5f2c7782cd8a
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
329 |
5f2c7782cd8a
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
330 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
|
331 |
809 | 332 # 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
|
333 # We might care about namespace events in the future, though |
809 | 334 if not match_templates or (event[0] is not START and |
335 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
|
336 yield event |
5f2c7782cd8a
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
337 continue |
5f2c7782cd8a
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
338 |
602 | 339 for idx, (test, path, template, hints, namespaces, directives) \ |
340 in enumerate(match_templates): | |
766
584aa6bfbe54
Fix bug where in some cases match templates would incorrectly applied multiple times.
cmlenz
parents:
758
diff
changeset
|
341 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
|
342 continue |
336
5f2c7782cd8a
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
343 |
5f2c7782cd8a
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
344 if test(event, namespaces, ctxt) is True: |
602 | 345 if 'match_once' in hints: |
346 del match_templates[idx] | |
347 idx -= 1 | |
336
5f2c7782cd8a
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
348 |
5f2c7782cd8a
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
349 # 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
|
350 # 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
|
351 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
|
352 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
|
353 |
5f2c7782cd8a
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
354 # 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
|
355 # 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
|
356 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
|
357 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
|
358 pre_end -= 1 |
700
8d079cee6822
Add option for unbuffered match template processing, which could cause excessive memory usage. Closes #190.
cmlenz
parents:
694
diff
changeset
|
359 inner = _strip(stream) |
766
584aa6bfbe54
Fix bug where in some cases match templates would incorrectly applied multiple times.
cmlenz
parents:
758
diff
changeset
|
360 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
|
361 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
|
362 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
|
363 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
|
364 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
|
365 content = list(content) |
843
004f81b59d97
Refactored the template flattening method to be less recursive.
cmlenz
parents:
827
diff
changeset
|
366 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
|
367 |
5f2c7782cd8a
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
368 # 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
|
369 # 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
|
370 selected = [False] |
336
5f2c7782cd8a
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
371 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
|
372 selected[0] = True |
843
004f81b59d97
Refactored the template flattening method to be less recursive.
cmlenz
parents:
827
diff
changeset
|
373 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
|
374 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
|
375 |
5f2c7782cd8a
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
376 # 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
|
377 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
|
378 vars) |
813
3047d5d83ccc
Merge the internal template filters `_eval` and `_exec` into the `_flatten` function for slightly better performance.
cmlenz
parents:
809
diff
changeset
|
379 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
|
380 **vars), |
3047d5d83ccc
Merge the internal template filters `_eval` and `_exec` into the `_flatten` function for slightly better performance.
cmlenz
parents:
809
diff
changeset
|
381 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
|
382 yield event |
5f2c7782cd8a
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
383 |
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
|
384 # 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
|
385 # 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
|
386 # 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
|
387 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
|
388 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
|
389 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
|
390 |
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
|
391 # 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
|
392 # 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
|
393 # 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
|
394 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
|
395 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
|
396 |
336
5f2c7782cd8a
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
397 break |
5f2c7782cd8a
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
398 |
5f2c7782cd8a
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
399 else: # no matches |
5f2c7782cd8a
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
400 yield event |