diff options
author | Martin v. Löwis <martin@v.loewis.de> | 2012-02-19 19:25:12 (GMT) |
---|---|---|
committer | Martin v. Löwis <martin@v.loewis.de> | 2012-02-19 19:25:12 (GMT) |
commit | 14aa280de23ecb6c31ffbde4a12c1a0a6f5493e0 (patch) | |
tree | a6272d0d650f428339f265e22b8687df767b600f | |
parent | 32ac92cd4a341fc2503305b3017d2262c203558e (diff) | |
download | cpython-14aa280de23ecb6c31ffbde4a12c1a0a6f5493e0.zip cpython-14aa280de23ecb6c31ffbde4a12c1a0a6f5493e0.tar.gz cpython-14aa280de23ecb6c31ffbde4a12c1a0a6f5493e0.tar.bz2 |
Use __slots__ throughout instead of __dict__, to reduce the memory usage.
-rw-r--r-- | Lib/xml/dom/expatbuilder.py | 39 | ||||
-rw-r--r-- | Lib/xml/dom/minidom.py | 216 |
2 files changed, 114 insertions, 141 deletions
diff --git a/Lib/xml/dom/expatbuilder.py b/Lib/xml/dom/expatbuilder.py index a98fe03..b4b28e4 100644 --- a/Lib/xml/dom/expatbuilder.py +++ b/Lib/xml/dom/expatbuilder.py @@ -283,27 +283,23 @@ class ExpatBuilder: elif childNodes and childNodes[-1].nodeType == TEXT_NODE: node = childNodes[-1] value = node.data + data - d = node.__dict__ - d['data'] = d['nodeValue'] = value + node.data = value return else: node = minidom.Text() - d = node.__dict__ - d['data'] = d['nodeValue'] = data - d['ownerDocument'] = self.document + node.data = data + node.ownerDocument = self.document _append_child(self.curNode, node) def character_data_handler(self, data): childNodes = self.curNode.childNodes if childNodes and childNodes[-1].nodeType == TEXT_NODE: node = childNodes[-1] - d = node.__dict__ - d['data'] = d['nodeValue'] = node.data + data + node.data = node.data + data return node = minidom.Text() - d = node.__dict__ - d['data'] = d['nodeValue'] = node.data + data - d['ownerDocument'] = self.document + node.data = node.data + data + node.ownerDocument = self.document _append_child(self.curNode, node) def entity_decl_handler(self, entityName, is_parameter_entity, value, @@ -363,11 +359,8 @@ class ExpatBuilder: a = minidom.Attr(attributes[i], EMPTY_NAMESPACE, None, EMPTY_PREFIX) value = attributes[i+1] - d = a.childNodes[0].__dict__ - d['data'] = d['nodeValue'] = value - d = a.__dict__ - d['value'] = d['nodeValue'] = value - d['ownerDocument'] = self.document + a.value = value + a.ownerDocument = self.document _set_attribute_node(node, a) if node is not self.document.documentElement: @@ -761,11 +754,8 @@ class Namespaces: else: a = minidom.Attr("xmlns", XMLNS_NAMESPACE, "xmlns", EMPTY_PREFIX) - d = a.childNodes[0].__dict__ - d['data'] = d['nodeValue'] = uri - d = a.__dict__ - d['value'] = d['nodeValue'] = uri - d['ownerDocument'] = self.document + a.value = uri + a.ownerDocuemnt = self.document _set_attribute_node(node, a) del self._ns_ordered_prefixes[:] @@ -785,12 +775,9 @@ class Namespaces: aname, EMPTY_PREFIX) _attrs[aname] = a _attrsNS[(EMPTY_NAMESPACE, aname)] = a - d = a.childNodes[0].__dict__ - d['data'] = d['nodeValue'] = value - d = a.__dict__ - d['ownerDocument'] = self.document - d['value'] = d['nodeValue'] = value - d['ownerElement'] = node + a.ownerDocument = self.document + a.value = value + a.ownerElement = node if __debug__: # This only adds some asserts to the original diff --git a/Lib/xml/dom/minidom.py b/Lib/xml/dom/minidom.py index f23ad05..c7de12c 100644 --- a/Lib/xml/dom/minidom.py +++ b/Lib/xml/dom/minidom.py @@ -286,10 +286,10 @@ def _append_child(self, node): childNodes = self.childNodes if childNodes: last = childNodes[-1] - node.__dict__["previousSibling"] = last - last.__dict__["nextSibling"] = node + node.previousSibling = last + last.nextSibling = node childNodes.append(node) - node.__dict__["parentNode"] = self + node.parentNode = self def _in_document(node): # return True iff node is part of a document tree @@ -342,9 +342,10 @@ class DocumentFragment(Node): class Attr(Node): + __slots__=('_name', '_value', 'namespaceURI', + '_prefix', 'childNodes', '_localName', 'ownerDocument', 'ownerElement') nodeType = Node.ATTRIBUTE_NODE attributes = None - ownerElement = None specified = False _is_id = False @@ -352,12 +353,11 @@ class Attr(Node): def __init__(self, qName, namespaceURI=EMPTY_NAMESPACE, localName=None, prefix=None): - # skip setattr for performance - d = self.__dict__ - d["nodeName"] = d["name"] = qName - d["namespaceURI"] = namespaceURI - d["prefix"] = prefix - d['childNodes'] = NodeList() + self.ownerElement = None + self._name = qName + self.namespaceURI = namespaceURI + self._prefix = prefix + self.childNodes = NodeList() # Add the single child node that represents the value of the attr self.childNodes.append(Text()) @@ -365,9 +365,10 @@ class Attr(Node): # nodeValue and value are set elsewhere def _get_localName(self): - if 'localName' in self.__dict__: - return self.__dict__['localName'] - return self.nodeName.split(":", 1)[-1] + try: + return self._localName + except AttributeError: + return self.nodeName.split(":", 1)[-1] def _get_name(self): return self.name @@ -375,20 +376,30 @@ class Attr(Node): def _get_specified(self): return self.specified - def __setattr__(self, name, value): - d = self.__dict__ - if name in ("value", "nodeValue"): - d["value"] = d["nodeValue"] = value - d2 = self.childNodes[0].__dict__ - d2["data"] = d2["nodeValue"] = value - if self.ownerElement is not None: - _clear_id_cache(self.ownerElement) - elif name in ("name", "nodeName"): - d["name"] = d["nodeName"] = value - if self.ownerElement is not None: - _clear_id_cache(self.ownerElement) - else: - d[name] = value + def _get_name(self): + return self._name + + def _set_name(self, value): + self._name = value + if self.ownerElement is not None: + _clear_id_cache(self.ownerElement) + + nodeName = name = property(_get_name, _set_name) + + def _get_value(self): + return self._value + + def _set_value(self, value): + self._value = value + self.childNodes[0].data = value + if self.ownerElement is not None: + _clear_id_cache(self.ownerElement) + self.childNodes[0].data = value + + nodeValue = value = property(_get_value, _set_value) + + def _get_prefix(self): + return self._prefix def _set_prefix(self, prefix): nsuri = self.namespaceURI @@ -396,22 +407,16 @@ class Attr(Node): if nsuri and nsuri != XMLNS_NAMESPACE: raise xml.dom.NamespaceErr( "illegal use of 'xmlns' prefix for the wrong namespace") - d = self.__dict__ - d['prefix'] = prefix + self._prefix = prefix if prefix is None: newName = self.localName else: newName = "%s:%s" % (prefix, self.localName) if self.ownerElement: _clear_id_cache(self.ownerElement) - d['nodeName'] = d['name'] = newName + self.name = newName - def _set_value(self, value): - d = self.__dict__ - d['value'] = d['nodeValue'] = value - if self.ownerElement: - _clear_id_cache(self.ownerElement) - self.childNodes[0].data = value + prefix = property(_get_prefix, _set_prefix) def unlink(self): # This implementation does not call the base implementation @@ -586,8 +591,8 @@ class NamedNodeMap(object): _clear_id_cache(self._ownerElement) del self._attrs[n.nodeName] del self._attrsNS[(n.namespaceURI, n.localName)] - if 'ownerElement' in n.__dict__: - n.__dict__['ownerElement'] = None + if hasattr(n, 'ownerElement'): + n.ownerElement = None return n else: raise xml.dom.NotFoundErr() @@ -598,8 +603,8 @@ class NamedNodeMap(object): _clear_id_cache(self._ownerElement) del self._attrsNS[(n.namespaceURI, n.localName)] del self._attrs[n.nodeName] - if 'ownerElement' in n.__dict__: - n.__dict__['ownerElement'] = None + if hasattr(n, 'ownerElement'): + n.ownerElement = None return n else: raise xml.dom.NotFoundErr() @@ -659,6 +664,9 @@ class TypeInfo(object): _no_type = TypeInfo(None, None) class Element(Node): + __slots__=('ownerDocument', 'parentNode', 'tagName', 'nodeName', 'prefix', + 'namespaceURI', '_localName', 'childNodes', '_attrs', '_attrsNS', + 'nextSibling', 'previousSibling') nodeType = Node.ELEMENT_NODE nodeValue = None schemaType = _no_type @@ -674,10 +682,12 @@ class Element(Node): def __init__(self, tagName, namespaceURI=EMPTY_NAMESPACE, prefix=None, localName=None): + self.parentNode = None self.tagName = self.nodeName = tagName self.prefix = prefix self.namespaceURI = namespaceURI self.childNodes = NodeList() + self.nextSibling = self.previousSibling = None self._attrs = {} # attributes are double-indexed: self._attrsNS = {} # tagName -> Attribute @@ -688,9 +698,10 @@ class Element(Node): # namespaces. def _get_localName(self): - if 'localName' in self.__dict__: - return self.__dict__['localName'] - return self.tagName.split(":", 1)[-1] + try: + return self._localName + except AttributeError: + return self.tagName.split(":", 1)[-1] def _get_tagName(self): return self.tagName @@ -718,14 +729,11 @@ class Element(Node): attr = self.getAttributeNode(attname) if attr is None: attr = Attr(attname) - # for performance - d = attr.__dict__ - d["value"] = d["nodeValue"] = value - d["ownerDocument"] = self.ownerDocument + attr.value = value # also sets nodeValue + attr.ownerDocument = self.ownerDocument self.setAttributeNode(attr) elif value != attr.value: - d = attr.__dict__ - d["value"] = d["nodeValue"] = value + attr.value = value if attr.isId: _clear_id_cache(self) @@ -733,23 +741,18 @@ class Element(Node): prefix, localname = _nssplit(qualifiedName) attr = self.getAttributeNodeNS(namespaceURI, localname) if attr is None: - # for performance attr = Attr(qualifiedName, namespaceURI, localname, prefix) - d = attr.__dict__ - d["prefix"] = prefix - d["nodeName"] = qualifiedName - d["value"] = d["nodeValue"] = value - d["ownerDocument"] = self.ownerDocument + attr.value = value + attr.ownerDocument = self.ownerDocument self.setAttributeNode(attr) else: - d = attr.__dict__ if value != attr.value: - d["value"] = d["nodeValue"] = value + attr.value = value if attr.isId: _clear_id_cache(self) if attr.prefix != prefix: - d["prefix"] = prefix - d["nodeName"] = qualifiedName + attr.prefix = prefix + attr.nodeName = qualifiedName def getAttributeNode(self, attrname): return self._attrs.get(attrname) @@ -874,7 +877,7 @@ class Element(Node): if _get_containing_entref(self) is not None: raise xml.dom.NoModificationAllowedErr() if not idAttr._is_id: - idAttr.__dict__['_is_id'] = True + idAttr._is_id = True self._magic_id_nodes += 1 self.ownerDocument._magic_id_count += 1 _clear_id_cache(self) @@ -893,8 +896,7 @@ def _set_attribute_node(element, attr): # This creates a circular reference, but Element.unlink() # breaks the cycle since the references to the attribute # dictionaries are tossed. - attr.__dict__['ownerElement'] = element - + attr.ownerElement = element class Childless: """Mixin that makes childless-ness easy to implement and avoids @@ -938,54 +940,49 @@ class Childless: class ProcessingInstruction(Childless, Node): nodeType = Node.PROCESSING_INSTRUCTION_NODE + __slots__ = ('target', 'data') def __init__(self, target, data): - self.target = self.nodeName = target - self.data = self.nodeValue = data + self.target = target + self.data = data - def _get_data(self): + # nodeValue is an alias for data + def _get_nodeValue(self): return self.data - def _set_data(self, value): - d = self.__dict__ - d['data'] = d['nodeValue'] = value + def _set_nodeValue(self, value): + self.data = data + nodeValue = property(_get_nodeValue, _set_nodeValue) - def _get_target(self): + # nodeName is an alias for target + def _get_nodeName(self): return self.target - def _set_target(self, value): - d = self.__dict__ - d['target'] = d['nodeName'] = value - - def __setattr__(self, name, value): - if name == "data" or name == "nodeValue": - self.__dict__['data'] = self.__dict__['nodeValue'] = value - elif name == "target" or name == "nodeName": - self.__dict__['target'] = self.__dict__['nodeName'] = value - else: - self.__dict__[name] = value + def _set_nodeName(self, value): + self.target = value + nodeName = property(_get_nodeName, _set_nodeName) def writexml(self, writer, indent="", addindent="", newl=""): writer.write("%s<?%s %s?>%s" % (indent,self.target, self.data, newl)) class CharacterData(Childless, Node): + __slots__=('_data', 'ownerDocument','parentNode', 'previousSibling', 'nextSibling') + + def __init__(self): + self.ownerDocument = self.parentNode = None + self.previousSibling = self.nextSibling = None + self._data = '' + Node.__init__(self) + def _get_length(self): return len(self.data) __len__ = _get_length def _get_data(self): - return self.__dict__['data'] + return self._data def _set_data(self, data): - d = self.__dict__ - d['data'] = d['nodeValue'] = data + self._data = data - _get_nodeValue = _get_data - _set_nodeValue = _set_data - - def __setattr__(self, name, value): - if name == "data" or name == "nodeValue": - self.__dict__['data'] = self.__dict__['nodeValue'] = value - else: - self.__dict__[name] = value + data = nodeValue = property(_get_data, _set_data) def __repr__(self): data = self.data @@ -1042,11 +1039,6 @@ defproperty(CharacterData, "length", doc="Length of the string data.") class Text(CharacterData): - # Make sure we don't add an instance __dict__ if we don't already - # have one, at least when that's possible: - # XXX this does not work, CharacterData is an old-style class - # __slots__ = () - nodeType = Node.TEXT_NODE nodeName = "#text" attributes = None @@ -1112,9 +1104,7 @@ class Text(CharacterData): else: break if content: - d = self.__dict__ - d['data'] = content - d['nodeValue'] = content + self.data = content return self else: return None @@ -1160,7 +1150,8 @@ class Comment(CharacterData): nodeName = "#comment" def __init__(self, data): - self.data = self.nodeValue = data + CharacterData.__init__(self) + self._data = data def writexml(self, writer, indent="", addindent="", newl=""): if "--" in self.data: @@ -1169,11 +1160,6 @@ class Comment(CharacterData): class CDATASection(Text): - # Make sure we don't add an instance __dict__ if we don't already - # have one, at least when that's possible: - # XXX this does not work, Text is an old-style class - # __slots__ = () - nodeType = Node.CDATA_SECTION_NODE nodeName = "#cdata-section" @@ -1504,18 +1490,19 @@ def _clear_id_cache(node): node.ownerDocument._id_search_stack= None class Document(Node, DocumentLS): + __slots__ = ('_elem_info', 'doctype', + '_id_search_stack', 'childNodes', '_id_cache') _child_node_types = (Node.ELEMENT_NODE, Node.PROCESSING_INSTRUCTION_NODE, Node.COMMENT_NODE, Node.DOCUMENT_TYPE_NODE) + implementation = DOMImplementation() nodeType = Node.DOCUMENT_NODE nodeName = "#document" nodeValue = None attributes = None - doctype = None parentNode = None previousSibling = nextSibling = None - implementation = DOMImplementation() # Document attributes from Level 3 (WD 9 April 2002) @@ -1530,6 +1517,7 @@ class Document(Node, DocumentLS): _magic_id_count = 0 def __init__(self): + self.doctype = None self.childNodes = NodeList() # mapping of (namespaceURI, localName) -> ElementInfo # and tagName -> ElementInfo @@ -1815,17 +1803,15 @@ class Document(Node, DocumentLS): element.removeAttributeNode(n) else: element = None - # avoid __setattr__ - d = n.__dict__ - d['prefix'] = prefix - d['localName'] = localName - d['namespaceURI'] = namespaceURI - d['nodeName'] = name + n.prefix = prefix + n._localName = localName + n.namespaceURI = namespaceURI + n.nodeName = name if n.nodeType == Node.ELEMENT_NODE: - d['tagName'] = name + n.tagName = name else: # attribute node - d['name'] = name + n.name = name if element is not None: element.setAttributeNode(n) if is_id: |