1616import re
1717import sys
1818
19+ try :
20+ from collections .abc import MutableMapping
21+ except ImportError :
22+ from collections import MutableMapping
23+
1924from . import base
2025from ..constants import DataLossWarning
2126from .. import constants
2227from . import etree as etree_builders
2328from .. import _ihatexml
2429
2530import lxml .etree as etree
31+ from six import PY3 , binary_type
2632
2733
2834fullTree = True
@@ -189,26 +195,37 @@ def __init__(self, namespaceHTMLElements, fullTree=False):
189195 infosetFilter = self .infosetFilter = _ihatexml .InfosetFilter (preventDoubleDashComments = True )
190196 self .namespaceHTMLElements = namespaceHTMLElements
191197
192- class Attributes (dict ):
193- def __init__ (self , element , value = None ):
194- if value is None :
195- value = {}
198+ class Attributes (MutableMapping ):
199+ def __init__ (self , element ):
196200 self ._element = element
197- dict .__init__ (self , value ) # pylint:disable=non-parent-init-called
198- for key , value in self .items ():
199- if isinstance (key , tuple ):
200- name = "{%s}%s" % (key [2 ], infosetFilter .coerceAttribute (key [1 ]))
201- else :
202- name = infosetFilter .coerceAttribute (key )
203- self ._element ._element .attrib [name ] = value
204201
205- def __setitem__ (self , key , value ):
206- dict .__setitem__ (self , key , value )
202+ def _coerceKey (self , key ):
207203 if isinstance (key , tuple ):
208204 name = "{%s}%s" % (key [2 ], infosetFilter .coerceAttribute (key [1 ]))
209205 else :
210206 name = infosetFilter .coerceAttribute (key )
211- self ._element ._element .attrib [name ] = value
207+ return name
208+
209+ def __getitem__ (self , key ):
210+ value = self ._element ._element .attrib [self ._coerceKey (key )]
211+ if not PY3 and isinstance (value , binary_type ):
212+ value = value .decode ("ascii" )
213+ return value
214+
215+ def __setitem__ (self , key , value ):
216+ self ._element ._element .attrib [self ._coerceKey (key )] = value
217+
218+ def __delitem__ (self , key ):
219+ del self ._element ._element .attrib [self ._coerceKey (key )]
220+
221+ def __iter__ (self ):
222+ return iter (self ._element ._element .attrib )
223+
224+ def __len__ (self ):
225+ return len (self ._element ._element .attrib )
226+
227+ def clear (self ):
228+ return self ._element ._element .attrib .clear ()
212229
213230 class Element (builder .Element ):
214231 def __init__ (self , name , namespace ):
@@ -229,17 +246,22 @@ def _getName(self):
229246 def _getAttributes (self ):
230247 return self ._attributes
231248
232- def _setAttributes (self , attributes ):
233- self ._attributes = Attributes (self , attributes )
249+ def _setAttributes (self , value ):
250+ attributes = self .attributes
251+ attributes .clear ()
252+ attributes .update (value )
234253
235254 attributes = property (_getAttributes , _setAttributes )
236255
237256 def insertText (self , data , insertBefore = None ):
238257 data = infosetFilter .coerceCharacters (data )
239258 builder .Element .insertText (self , data , insertBefore )
240259
241- def appendChild (self , child ):
242- builder .Element .appendChild (self , child )
260+ def cloneNode (self ):
261+ element = type (self )(self .name , self .namespace )
262+ if self ._element .attrib :
263+ element ._element .attrib .update (self ._element .attrib )
264+ return element
243265
244266 class Comment (builder .Comment ):
245267 def __init__ (self , data ):
0 commit comments