Package ptree :: Module elements
[hide private]
[frames] | no frames]

Source Code for Module ptree.elements

  1  # 
  2  # ptree.elements -- Element implementations for (multi)parented trees 
  3  # 
  4  # -------------------------------------------------------------------- 
  5  # The ptree package is 
  6  # 
  7  # Copyright (c) 2007 by Edward Loper 
  8  # 
  9  # By obtaining, using, and/or copying this software and/or its 
 10  # associated documentation, you agree that you have read, understood, 
 11  # and will comply with the following terms and conditions: 
 12  # 
 13  # Permission to use, copy, modify, and distribute this software and 
 14  # its associated documentation for any purpose and without fee is 
 15  # hereby granted, provided that the above copyright notice appears in 
 16  # all copies, and that both that copyright notice and this permission 
 17  # notice appear in supporting documentation. 
 18  # 
 19  # THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, 
 20  # INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS.  IN 
 21  # NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, INDIRECT OR 
 22  # CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS 
 23  # OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, 
 24  # NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION 
 25  # WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 
 26  # -------------------------------------------------------------------- 
 27   
 28  """ 
 29  etree Element implementations for use with (multi)parented trees. 
 30  """ 
 31   
 32  from xml.etree import ElementTree as ET 
 33   
 34  __all__ = ['_ParentedElement', '_MultiParentedElement', 
 35             'is_parented_element', 'is_multiparented_element'] 
 36   
 37  ###################################################################### 
 38  # Parented Trees 
 39  ###################################################################### 
 40   
41 -class _AbstractParentedElement(ET._ElementInterface):
42 """ 43 An abstract base class for (multi)parented element tree Elements. 44 45 - Whenever a new child is added, L{_setparent} is called, 46 which should update that child's parent pointer to point 47 at self. 48 49 - Whenever a child is removed, L{_delparent} is called, which 50 should remove the child's parent pointer to self. 51 """
52 - def __repr__(self):
53 return "<%s %s at %x>" % (self.__class__.__name__, 54 self.tag, id(self))
55 56 #//////////////////////////////////////////////////////////// 57 # Parent management 58 #//////////////////////////////////////////////////////////// 59
60 - def _setparent(self, child):
61 """ 62 Update C{child}'s parent pointer to point to self. 63 """ 64 raise AssertionError, 'Abstract base class'
65
66 - def _delparent(self, child):
67 """ 68 Remove self from C{child}'s parent pointer. 69 """ 70 raise AssertionError, 'Abstract base class'
71 72 #//////////////////////////////////////////////////////////// 73 # Methods that add/remove children 74 #//////////////////////////////////////////////////////////// 75 # Every method that adds or removes a child must make 76 # appropriate calls to _setparent() and _delparent(). 77
78 - def __delitem__(self, index):
79 self._delparent(self[index]) 80 ET._ElementInterface.__delitem__(self, index)
81
82 - def __delslice__(self, start, stop):
83 for index in range(start, stop): self._delparent(self[index]) 84 ET._ElementInterface.__delslice__(self, start, stop)
85
86 - def __setitem__(self, index, element):
87 self._delparent(self[index]) 88 self._setparent(element) 89 ET._ElementInterface.__setitem__(self, index, element)
90
91 - def __setslice__(self, start, stop, elements):
92 for index in range(start, stop): self._delparent(self[index]) 93 for val in elements: self._setparent(val) 94 ET._ElementInterface.__setslice__(self, start, stop, elements)
95
96 - def append(self, element):
97 self._setparent(element) 98 ET._ElementInterface.append(self, element)
99
100 - def extend(self, elements):
101 for val in elements: self._setparent(val) 102 ET._ElementInterface.extend(self, elements)
103
104 - def insert(self, index, element):
105 self._setparent(element) 106 ET._ElementInterface.insert(self, index, element)
107
108 - def pop(self):
109 self._delparent(self[-1]) 110 return ET._ElementInterface.pop(self, )
111
112 - def remove(self, element):
113 index = self.index(element) 114 self._delparent(self[index]) 115 ET._ElementInterface.remove(self, element)
116 117
118 -class _ParentedElement(_AbstractParentedElement):
119 """ 120 A specialized version of etree.ElementTree.Element that keeps 121 track of a single parent pointer per element. 122 123 Each _ParentedElement may have at most one parent. In particular, 124 subtrees may not be shared. Any attempt to reuse a single 125 _ParentedElement as a child of more than one parent (or as 126 multiple children of the same parent) will cause a ValueError 127 exception to be raised. 128 129 _ParentedElements should never be used in the same tree as other 130 Element implementation classes. Mixing Element implementations 131 may result in incorrect parent pointers and in C{ValueError} 132 exceptions. 133 """
134 - def __init__(self, tag, attrib):
135 ET._ElementInterface.__init__(self, tag, attrib) 136 self._parent = None
137
138 - def parent(self):
139 return self._parent
140
141 - def _setparent(self, element):
142 assert is_parented_element(element) 143 if element._parent is not None: 144 raise ValueError, '%r already has a parent' % element 145 element._parent = self
146
147 - def _delparent(self, element):
148 assert is_parented_element(element) 149 assert element._parent == self 150 element._parent = None
151
152 - def makeelement(self, tag, attrib):
153 return _ParentedElement(tag, attrib)
154
155 -def is_parented_element(element):
156 return ET.iselement(element) and hasattr(element, '_parent')
157
158 -class _MultiParentedElement(_AbstractParentedElement):
159 """ 160 A specialized version of etree.ElementTree.Element that keeps 161 track of a list of parent pointers for each element. 162 163 Each _ParentedElement may have zero or more parents. In 164 particular, subtrees may be shared. If a single 165 _MultiParentedElement is used as multiple children of the same 166 parent, then that parent will appear multiple times in the parents 167 list. 168 169 _MultiParentedElements should never be used in the same tree as 170 other Element implementation classes. Mixing Element 171 implementations may result in incorrect parent pointers and in 172 C{ValueError} exceptions. 173 """
174 - def __init__(self, tag, attrib):
175 ET._ElementInterface.__init__(self, tag, attrib) 176 self._parents = []
177
178 - def parents(self):
179 return tuple(self._parents)
180
181 - def _setparent(self, element):
182 assert is_multiparented_element(element) 183 element._parent.append(self)
184
185 - def _delparent(self, element):
186 assert is_multiparented_element(element) 187 assert self in element._parents 188 element._parents.remove(self)
189
190 - def makeelement(self, tag, attrib):
191 return _ParentedElement(tag, attrib)
192
193 -def is_multiparented_element(element):
194 return ET.iselement(element) and hasattr(element, '_parents')
195