1
2 u"""
3 :Copyright:
4
5 Copyright 2006 - 2013
6 Andr\xe9 Malo or his licensors, as applicable
7
8 :License:
9
10 Licensed under the Apache License, Version 2.0 (the "License");
11 you may not use this file except in compliance with the License.
12 You may obtain a copy of the License at
13
14 http://www.apache.org/licenses/LICENSE-2.0
15
16 Unless required by applicable law or agreed to in writing, software
17 distributed under the License is distributed on an "AS IS" BASIS,
18 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
19 See the License for the specific language governing permissions and
20 limitations under the License.
21
22 ========================
23 Template Builder Logic
24 ========================
25
26 This module provides the logic to build a nodetree out of parser
27 events.
28 """
29 __author__ = u"Andr\xe9 Malo"
30 __docformat__ = "restructuredtext en"
31
32 import codecs as _codecs
33
34 from tdi._exceptions import TemplateEncodingError
35 from tdi import interfaces as _interfaces
36 from tdi import nodetree as _nodetree
37 from tdi.markup import _analyzer
38
39
41 """
42 HTML Template tree builder
43
44 :IVariables:
45 `_tree` : `nodetree.Root`
46 The built subtree
47
48 `_text` : ``list``
49 The current text buffer
50
51 `_tagstack` : ``list``
52 The stack of currently nested tag names with associated nodes
53
54 `_nodestack` : ``list``
55 The stack of currently nested snippet parameters
56
57 `_devnull` : ``bool``
58 Are we inside a removed element?
59
60 `encoding` : ``str``
61 Template encoding
62
63 `encoder` : `EncoderInterface`
64 Encoder
65
66 `decoder` : `DecoderInterface`
67 Decoder
68
69 `analyze` : `AttributeAnalyzerInterface`
70 Attribute analyzer
71 """
72 __implements__ = [_interfaces.BuilderInterface,
73 _interfaces.BuildingListenerInterface]
74
75 encoding = 'ascii'
76
77 - def __init__(self, encoder, decoder, analyzer=None):
78 """
79 Initialization
80
81 :Parameters:
82 `encoder` : ``callable``
83 Encoder factory
84
85 `decoder` : ``callable``
86 Decoder factory
87
88 `analyzer` : `AttributeAnalyzerInterface`
89 Attribute analyzer
90 """
91 root = _nodetree.Root()
92 self._tree = root
93 self._text = []
94 self._tagstack = []
95 self._nodestack = [root]
96 self._devnull = False
97 self.encoder = encoder(self.encoding)
98 self.decoder = decoder(self.encoding)
99 if analyzer is None:
100 analyzer = _analyzer.DEFAULT_ANALYZER(self.decoder, hidden=False)
101 self.analyze = analyzer
102
103 - def _flush_text(self):
104 """ Flush current text buffer """
105 if self._text:
106 if not self._devnull:
107 self._nodestack[-1].append_text(''.join(self._text))
108 self._text = []
109
110
111
112
113
114 - def handle_text(self, data):
115 """ :see: `ListenerInterface` """
116 if not self._devnull:
117 self._text.append(data)
118
120 """ :see: `ListenerInterface` """
121 if not self._devnull:
122 self._flush_text()
123 self._nodestack[-1].append_escape(escaped, data)
124
126 """ :see: `ListenerInterface` """
127 starttag = self.decoder.normalize(name)
128
129 if not self._devnull:
130 attr, special = self.analyze(attr)
131 if special:
132 self._flush_text()
133 flags, tdi = special.get('attribute', ('', None))
134 if not closed and tdi is None and flags == '-':
135 self._devnull = True
136 self._tagstack.append((starttag, '-'))
137 self._nodestack.append('-')
138 return
139
140 node = self._nodestack[-1].append_node(
141 name, attr, special, closed
142 )
143 if not closed:
144 self._tagstack.append((starttag, node))
145 self._nodestack.append(node)
146 return
147
148
149 if not closed and len(self._nodestack) > 1:
150
151 self._tagstack.append((starttag, None))
152 self.handle_text(data)
153
155 """ :see: `ListenerInterface` """
156 endtag = self.decoder.normalize(name)
157 tagstack = self._tagstack
158 if tagstack:
159 starttag, node = tagstack[-1]
160 if starttag == endtag:
161 tagstack.pop()
162
163
164 if node is not None:
165 self._flush_text()
166 node = self._nodestack.pop()
167 if self._devnull:
168 self._devnull = False
169 else:
170 node.endtag = data
171 return
172
173 self.handle_text(data)
174
178
180 """ :see: `ListenerInterface` """
181
182 self.handle_text(data)
183
185 """ :see: `ListenerInterface` """
186
187 self.handle_text(data)
188
190 """ :see: `ListenerInterface` """
191 self.handle_text(data)
192
193
194
195
196
212
213
214
215
216
218 """ :See: `tdi.interfaces.BuilderInterface` """
219 self._flush_text()
220 self._tree.finalize(self.encoder, self.decoder)
221 return self._tree
222