aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/Lib/xml/dom/minidom.py
diff options
context:
space:
mode:
Diffstat (limited to 'Lib/xml/dom/minidom.py')
-rw-r--r--Lib/xml/dom/minidom.py91
1 files changed, 58 insertions, 33 deletions
diff --git a/Lib/xml/dom/minidom.py b/Lib/xml/dom/minidom.py
index 7e2898cd3ef..f23ad053333 100644
--- a/Lib/xml/dom/minidom.py
+++ b/Lib/xml/dom/minidom.py
@@ -14,6 +14,8 @@ Todo:
* SAX 2 namespaces
"""
+import codecs
+import io
import xml.dom
from xml.dom import EMPTY_NAMESPACE, EMPTY_PREFIX, XMLNS_NAMESPACE, domreg
@@ -38,26 +40,26 @@ class Node(xml.dom.Node):
prefix = EMPTY_PREFIX # non-null only for NS elements and attributes
- def __nonzero__(self):
+ def __bool__(self):
return True
- def toxml(self, encoding = None):
+ def toxml(self, encoding=None):
return self.toprettyxml("", "", encoding)
- def toprettyxml(self, indent="\t", newl="\n", encoding = None):
+ def toprettyxml(self, indent="\t", newl="\n", encoding=None):
# indent = the indentation string to prepend, per level
# newl = the newline string to append
- writer = _get_StringIO()
- if encoding is not None:
- import codecs
- # Can't use codecs.getwriter to preserve 2.0 compatibility
- writer = codecs.lookup(encoding)[3](writer)
+ use_encoding = "utf-8" if encoding is None else encoding
+ writer = codecs.getwriter(use_encoding)(io.BytesIO())
if self.nodeType == Node.DOCUMENT_NODE:
# Can pass encoding only to document, to put it into XML header
self.writexml(writer, "", indent, newl, encoding)
else:
self.writexml(writer, "", indent, newl)
- return writer.getvalue()
+ if encoding is None:
+ return writer.stream.getvalue().decode(use_encoding)
+ else:
+ return writer.stream.getvalue()
def hasChildNodes(self):
if self.childNodes:
@@ -251,7 +253,7 @@ class Node(xml.dom.Node):
def _call_user_data_handler(self, operation, src, dst):
if hasattr(self, "_user_data"):
- for key, (data, handler) in self._user_data.items():
+ for key, (data, handler) in list(self._user_data.items()):
if handler is not None:
handler.handle(operation, key, data, src, dst)
@@ -266,6 +268,14 @@ class Node(xml.dom.Node):
self.previousSibling = None
self.nextSibling = None
+ # A Node is its own context manager, to ensure that an unlink() call occurs.
+ # This is similar to how a file object works.
+ def __enter__(self):
+ return self
+
+ def __exit__(self, et, ev, tb):
+ self.unlink()
+
defproperty(Node, "firstChild", doc="First child node, or None.")
defproperty(Node, "lastChild", doc="Last child node, or None.")
defproperty(Node, "localName", doc="Namespace-local name of this node.")
@@ -355,6 +365,8 @@ 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]
def _get_name(self):
@@ -474,7 +486,7 @@ class NamedNodeMap(object):
def item(self, index):
try:
- return self[self._attrs.keys()[index]]
+ return self[list(self._attrs.keys())[index]]
except IndexError:
return None
@@ -490,8 +502,8 @@ class NamedNodeMap(object):
L.append(((node.namespaceURI, node.localName), node.value))
return L
- def has_key(self, key):
- if isinstance(key, StringTypes):
+ def __contains__(self, key):
+ if isinstance(key, str):
return key in self._attrs
else:
return key in self._attrsNS
@@ -510,12 +522,29 @@ class NamedNodeMap(object):
__len__ = _get_length
- __hash__ = None # Mutable type can't be correctly hashed
- def __cmp__(self, other):
+ def _cmp(self, other):
if self._attrs is getattr(other, "_attrs", None):
return 0
else:
- return cmp(id(self), id(other))
+ return (id(self) > id(other)) - (id(self) < id(other))
+
+ def __eq__(self, other):
+ return self._cmp(other) == 0
+
+ def __ge__(self, other):
+ return self._cmp(other) >= 0
+
+ def __gt__(self, other):
+ return self._cmp(other) > 0
+
+ def __le__(self, other):
+ return self._cmp(other) <= 0
+
+ def __lt__(self, other):
+ return self._cmp(other) < 0
+
+ def __ne__(self, other):
+ return self._cmp(other) != 0
def __getitem__(self, attname_or_tuple):
if isinstance(attname_or_tuple, tuple):
@@ -525,7 +554,7 @@ class NamedNodeMap(object):
# same as set
def __setitem__(self, attname, value):
- if isinstance(value, StringTypes):
+ if isinstance(value, str):
try:
node = self._attrs[attname]
except KeyError:
@@ -535,7 +564,7 @@ class NamedNodeMap(object):
node.value = value
else:
if not isinstance(value, Attr):
- raise TypeError, "value must be a string or Attr object"
+ raise TypeError("value must be a string or Attr object")
node = value
self.setNamedItem(node)
@@ -659,13 +688,15 @@ class Element(Node):
# namespaces.
def _get_localName(self):
+ if 'localName' in self.__dict__:
+ return self.__dict__['localName']
return self.tagName.split(":", 1)[-1]
def _get_tagName(self):
return self.tagName
def unlink(self):
- for attr in self._attrs.values():
+ for attr in list(self._attrs.values()):
attr.unlink()
self._attrs = None
self._attrsNS = None
@@ -798,8 +829,7 @@ class Element(Node):
writer.write(indent+"<" + self.tagName)
attrs = self._get_attributes()
- a_names = attrs.keys()
- a_names.sort()
+ a_names = sorted(attrs.keys())
for a_name in a_names:
writer.write(" %s=\"" % a_name)
@@ -1125,7 +1155,7 @@ def _get_containing_entref(node):
return None
-class Comment(Childless, CharacterData):
+class Comment(CharacterData):
nodeType = Node.COMMENT_NODE
nodeName = "#comment"
@@ -1182,7 +1212,7 @@ class ReadOnlySequentialNamedNodeMap(object):
else:
node = self.getNamedItem(name_or_tuple)
if node is None:
- raise KeyError, name_or_tuple
+ raise KeyError(name_or_tuple)
return node
def item(self, index):
@@ -1609,16 +1639,16 @@ class Document(Node, DocumentLS):
return e
def createTextNode(self, data):
- if not isinstance(data, StringTypes):
- raise TypeError, "node contents must be a string"
+ if not isinstance(data, str):
+ raise TypeError("node contents must be a string")
t = Text()
t.data = data
t.ownerDocument = self
return t
def createCDATASection(self, data):
- if not isinstance(data, StringTypes):
- raise TypeError, "node contents must be a string"
+ if not isinstance(data, str):
+ raise TypeError("node contents must be a string")
c = CDATASection()
c.data = data
c.ownerDocument = self
@@ -1901,11 +1931,6 @@ def _nssplit(qualifiedName):
return (None, fields[0])
-def _get_StringIO():
- # we can't use cStringIO since it doesn't support Unicode strings
- from StringIO import StringIO
- return StringIO()
-
def _do_pulldom_parse(func, args, kwargs):
events = func(*args, **kwargs)
toktype, rootNode = events.getEvent()
@@ -1935,7 +1960,7 @@ def parseString(string, parser=None):
def getDOMImplementation(features=None):
if features:
- if isinstance(features, StringTypes):
+ if isinstance(features, str):
features = domreg._parse_feature_string(features)
for f, v in features:
if not Document.implementation.hasFeature(f, v):