Package tdi :: Package markup :: Package text :: Module builder
[frames] | no frames]

Source Code for Module tdi.markup.text.builder

  1  # -*- coding: ascii -*- 
  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   
40 -class TextBuilder(object):
41 """ 42 Text 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 = 'utf-8' 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=True) 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 ### ListenerInterface ################################################### 112 ######################################################################### 113
114 - def handle_text(self, data):
115 """ :see: `ListenerInterface` """ 116 if not self._devnull: 117 self._text.append(data)
118
119 - def handle_escape(self, escaped, data):
120 """ :see: `ListenerInterface` """ 121 if not self._devnull: 122 self._flush_text() 123 self._nodestack[-1].append_escape(escaped, data)
124
125 - def handle_starttag(self, name, attr, closed, data):
126 """ :see: `ListenerInterface` """ 127 starttag = self.decoder.normalize(name) 128 129 if not self._devnull: 130 attr, special = self.analyze(attr, name=name) 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 # Else: handle literal stuff. 149 if not closed and len(self._nodestack) > 1: 150 # need that for proper (un-)nesting 151 self._tagstack.append((starttag, None)) 152 self.handle_text(data)
153
154 - def handle_endtag(self, name, data):
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 # Handle endtag of processable node. 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
175 - def handle_comment(self, data):
176 """ :see: `ListenerInterface` """ 177 pass
178
179 - def handle_pi(self, data):
180 """ :see: `ListenerInterface` """ 181 pass
182
183 - def handle_msection(self, name, value, data):
184 """ :see: `ListenerInterface` """ 185 # pylint: disable = W0613 186 self.handle_text(data)
187
188 - def handle_decl(self, name, value, data):
189 """ :see: `ListenerInterface` """ 190 # pylint: disable = W0613 191 self.handle_text(data)
192 193 ######################################################################### 194 ### BuildingListenerInterface Extension ################################# 195 ######################################################################### 196
197 - def handle_encoding(self, encoding):
198 """ 199 :See: `tdi.interfaces.BuildingListenerInterface` 200 201 :Exceptions: 202 - `TemplateEncodingError` : encoding was not recognized 203 """ 204 try: 205 _codecs.lookup(encoding) 206 except LookupError, e: 207 raise TemplateEncodingError(str(e)) 208 if self.encoding != encoding: 209 self.encoding = encoding 210 self.encoder.encoding = encoding 211 self.decoder.encoding = encoding
212 213 ######################################################################### 214 ### BuilderInterface #################################################### 215 ######################################################################### 216
217 - def finalize(self):
218 """ :See: `tdi.interfaces.BuilderInterface` """ 219 self._flush_text() 220 self._tree.finalize(self.encoder, self.decoder) 221 return self._tree
222