ported to python 2.7 / >= 3.3 using six
authorThomas Waldmann <tw AT waldmann-edv DOT de>
Sun, 19 May 2013 20:37:50 +0200
changeset 1009d39d4bc2deb
parent 99 f35162dc24d4
child 101 a8c36202d0da
ported to python 2.7 / >= 3.3 using six

the port itself was half automated (using python-modernize) and half manual
fixes and cleanups.
emeraldtree/ElementInclude.py
emeraldtree/ElementPath.py
emeraldtree/html.py
emeraldtree/tests/test_html.py
emeraldtree/tests/test_tree.py
emeraldtree/tree.py
     1.1 --- a/emeraldtree/ElementInclude.py	Sun Dec 23 19:39:04 2012 +0100
     1.2 +++ b/emeraldtree/ElementInclude.py	Sun May 19 20:37:50 2013 +0200
     1.3 @@ -46,7 +46,7 @@
     1.4  ##
     1.5  
     1.6  import copy
     1.7 -import ElementTree
     1.8 +from . import ElementTree
     1.9  
    1.10  XINCLUDE = "{http://www.w3.org/2001/XInclude}"
    1.11  
     2.1 --- a/emeraldtree/ElementPath.py	Sun Dec 23 19:39:04 2012 +0100
     2.2 +++ b/emeraldtree/ElementPath.py	Sun May 19 20:37:50 2013 +0200
     2.3 @@ -50,6 +50,7 @@
     2.4  ##
     2.5  
     2.6  import re
     2.7 +import six
     2.8  
     2.9  xpath_tokenizer = re.compile(
    2.10      "("
    2.11 @@ -64,7 +65,7 @@
    2.12      ).findall
    2.13  
    2.14  def prepare_tag(next, token):
    2.15 -    from ElementTree import Element
    2.16 +    from .ElementTree import Element
    2.17      tag = token[1]
    2.18      def select(context, result):
    2.19          for elem in result:
    2.20 @@ -178,7 +179,7 @@
    2.21  
    2.22  def find(elem, path):
    2.23      try:
    2.24 -        return findall(elem, path).next()
    2.25 +        return next(findall(elem, path))
    2.26      except StopIteration:
    2.27          return None
    2.28  
    2.29 @@ -195,18 +196,17 @@
    2.30          if path[:1] == "/":
    2.31              raise SyntaxError("cannot use absolute path on element")
    2.32          stream = iter(xpath_tokenizer(path))
    2.33 -        next = stream.next
    2.34 -        token = next()
    2.35 +        token = next(stream)
    2.36          selector = []
    2.37          while 1:
    2.38              try:
    2.39 -                selector.append(ops[token[0]](next, token))
    2.40 +                selector.append(ops[token[0]](lambda: next(stream), token))
    2.41              except StopIteration:
    2.42                  raise SyntaxError("invalid path")
    2.43              try:
    2.44 -                token = next()
    2.45 +                token = next(stream)
    2.46                  if token[0] == "/":
    2.47 -                    token = next()
    2.48 +                    token = next(stream)
    2.49              except StopIteration:
    2.50                  break
    2.51          _cache[path] = selector
    2.52 @@ -222,7 +222,7 @@
    2.53  
    2.54  def findtext(elem, path, default=None):
    2.55      try:
    2.56 -        elem = findall(elem, path).next()
    2.57 +        elem = next(findall(elem, path))
    2.58          return elem.text
    2.59      except StopIteration:
    2.60          return default
     3.1 --- a/emeraldtree/html.py	Sun Dec 23 19:39:04 2012 +0100
     3.2 +++ b/emeraldtree/html.py	Sun May 19 20:37:50 2013 +0200
     3.3 @@ -31,10 +31,11 @@
     3.4  # Tools to build element trees from HTML files.
     3.5  ##
     3.6  
     3.7 -import htmlentitydefs
     3.8 -from HTMLParser import HTMLParser as HTMLParserBase
     3.9 -
    3.10  from . import tree
    3.11 +import six
    3.12 +from six.moves import html_entities
    3.13 +from six.moves import html_parser
    3.14 +HTMLParserBase = html_parser.HTMLParser
    3.15  
    3.16  
    3.17  ##
    3.18 @@ -148,7 +149,7 @@
    3.19      # (Internal) Handles entity references.
    3.20  
    3.21      def handle_entityref(self, name):
    3.22 -        entity = htmlentitydefs.entitydefs.get(name)
    3.23 +        entity = html_entities.entitydefs.get(name)
    3.24          if entity:
    3.25              if len(entity) == 1:
    3.26                  entity = ord(entity)
    3.27 @@ -165,9 +166,9 @@
    3.28      # (Internal) Handles character data.
    3.29  
    3.30      def handle_data(self, data):
    3.31 -        if isinstance(data, str):
    3.32 +        if isinstance(data, six.binary_type):
    3.33              # convert to unicode, but only if necessary
    3.34 -            data = unicode(data, self.encoding, "ignore")
    3.35 +            data = data.decode(self.encoding, "ignore")
    3.36          self.__builder.data(data)
    3.37  
    3.38      ##
     4.1 --- a/emeraldtree/tests/test_html.py	Sun Dec 23 19:39:04 2012 +0100
     4.2 +++ b/emeraldtree/tests/test_html.py	Sun May 19 20:37:50 2013 +0200
     4.3 @@ -1,9 +1,10 @@
     4.4  import py.test
     4.5  
     4.6  from .. import html, tree
     4.7 +import six
     4.8 +from six import StringIO
     4.9  
    4.10  def serialize(elem, method):
    4.11 -    from StringIO import StringIO
    4.12      file = StringIO()
    4.13      elem.write(file.write, method=method)
    4.14      return file.getvalue()
    4.15 @@ -26,7 +27,7 @@
    4.16      assert isinstance(elem, tree.Element)
    4.17      assert len(elem) == 1
    4.18      assert elem[0] == 'b'
    4.19 -    assert isinstance(elem[0], unicode)
    4.20 +    assert isinstance(elem[0], six.text_type)
    4.21  
    4.22  def test_read_text2():
    4.23      elem = html.HTML('<a>b<c>d</c>d</a>')
     5.1 --- a/emeraldtree/tests/test_tree.py	Sun Dec 23 19:39:04 2012 +0100
     5.2 +++ b/emeraldtree/tests/test_tree.py	Sun May 19 20:37:50 2013 +0200
     5.3 @@ -1,8 +1,9 @@
     5.4  import py.test
     5.5  from emeraldtree.tree import *
     5.6 +import six
     5.7 +from six import StringIO
     5.8  
     5.9  def serialize(elem, namespaces={}):
    5.10 -    from StringIO import StringIO
    5.11      file = StringIO()
    5.12      elem.write(file.write, namespaces=namespaces)
    5.13      return file.getvalue()
    5.14 @@ -343,19 +344,19 @@
    5.15      qname = QName(u'a')
    5.16      assert qname.uri is None
    5.17      assert qname.name == u'a'
    5.18 -    assert isinstance(qname.name, unicode)
    5.19 -    assert unicode(qname) == u'a'
    5.20 +    assert isinstance(qname.name, six.text_type)
    5.21 +    assert six.text_type(qname) == u'a'
    5.22  
    5.23      qname = QName(u'{b}a')
    5.24      assert qname.uri == u'b'
    5.25 -    assert isinstance(qname.uri, unicode)
    5.26 +    assert isinstance(qname.uri, six.text_type)
    5.27      assert qname.name == u'a'
    5.28 -    assert unicode(qname) == u'{b}a'
    5.29 +    assert six.text_type(qname) == u'{b}a'
    5.30  
    5.31      qname = QName(u'a', u'b')
    5.32      assert qname.uri == u'b'
    5.33      assert qname.name == u'a'
    5.34 -    assert unicode(qname) == u'{b}a'
    5.35 +    assert six.text_type(qname) == u'{b}a'
    5.36  
    5.37      py.test.raises(ValueError, QName, u'{bau')
    5.38      py.test.raises(ValueError, QName, u'{b}a', u'c')
    5.39 @@ -393,7 +394,7 @@
    5.40      assert isinstance(elem, Element)
    5.41      assert len(elem) == 1
    5.42      assert elem[0] == u'b'
    5.43 -    assert isinstance(elem[0], unicode)
    5.44 +    assert isinstance(elem[0], six.text_type)
    5.45  
    5.46  def test_XMLParser_text2():
    5.47      elem = XML(u'<a>b<c>d</c>d</a>')
     6.1 --- a/emeraldtree/tree.py	Sun Dec 23 19:39:04 2012 +0100
     6.2 +++ b/emeraldtree/tree.py	Sun May 19 20:37:50 2013 +0200
     6.3 @@ -24,6 +24,7 @@
     6.4  # OF THIS SOFTWARE.
     6.5  
     6.6  from __future__ import generators
     6.7 +import six
     6.8  
     6.9  __all__ = [
    6.10      # public symbols
    6.11 @@ -65,7 +66,7 @@
    6.12  # structure, and convert it from and to XML.
    6.13  ##
    6.14  
    6.15 -import ElementPath
    6.16 +from . import ElementPath
    6.17  
    6.18  class ParseError(SyntaxError):
    6.19      pass
    6.20 @@ -129,7 +130,7 @@
    6.21  
    6.22      @property
    6.23      def text(self):
    6.24 -        if len(self) and isinstance(self[0], basestring):
    6.25 +        if len(self) and isinstance(self[0], six.string_types):
    6.26              return self[0]
    6.27  
    6.28      ##
    6.29 @@ -165,8 +166,9 @@
    6.30      def __len__(self):
    6.31          return len(self._children)
    6.32  
    6.33 -    def __nonzero__(self):
    6.34 +    def __bool__(self):
    6.35          return True
    6.36 +    __nonzero__ = __bool__
    6.37  
    6.38      ##
    6.39      # Returns the given subelement.
    6.40 @@ -371,7 +373,7 @@
    6.41              if isinstance(e, Element):
    6.42                  for s in e.itertext():
    6.43                      yield s
    6.44 -            elif isinstance(e, basestring):
    6.45 +            elif isinstance(e, six.string_types):
    6.46                  yield e
    6.47  
    6.48      def iter_elements(self):
    6.49 @@ -447,7 +449,7 @@
    6.50  
    6.51  PI = ProcessingInstruction
    6.52  
    6.53 -class QName(unicode):
    6.54 +class QName(six.text_type):
    6.55      """
    6.56      QName wrapper.  This can be used to wrap a QName attribute value, in
    6.57      order to get proper namespace handling on output.
    6.58 @@ -460,7 +462,7 @@
    6.59      __slots__ = 'name', 'uri'
    6.60  
    6.61      def __new__(cls, name, uri=None):
    6.62 -        text = name = unicode(name)
    6.63 +        text = name = six.text_type(name)
    6.64  
    6.65          if name[0] == '{':
    6.66              if uri is not None:
    6.67 @@ -472,12 +474,12 @@
    6.68              name = name[i + 1:]
    6.69  
    6.70          if uri is not None:
    6.71 -            uri = unicode(uri)
    6.72 +            uri = six.text_type(uri)
    6.73              text = '{' + uri + '}' + name
    6.74  
    6.75 -        ret = unicode.__new__(cls, text)
    6.76 -        unicode.__setattr__(ret, 'name', name)
    6.77 -        unicode.__setattr__(ret, 'uri', uri)
    6.78 +        ret = six.text_type.__new__(cls, text)
    6.79 +        six.text_type.__setattr__(ret, 'name', name)
    6.80 +        six.text_type.__setattr__(ret, 'uri', uri)
    6.81  
    6.82          return ret
    6.83  
    6.84 @@ -1105,7 +1107,7 @@
    6.85      def feed(self, data):
    6.86          try:
    6.87              self._parser.Parse(data, 0)
    6.88 -        except self._error, v:
    6.89 +        except self._error as v:
    6.90              self._raiseerror(v)
    6.91  
    6.92      ##
    6.93 @@ -1117,7 +1119,7 @@
    6.94      def close(self):
    6.95          try:
    6.96              self._parser.Parse("", 1) # end of data
    6.97 -        except self._error, v:
    6.98 +        except self._error as v:
    6.99              self._raiseerror(v)
   6.100          tree = self.target.close()
   6.101          del self.target, self._parser # get rid of circular references
   6.102 @@ -1192,15 +1194,15 @@
   6.103                  tag = elem.tag
   6.104                  if isinstance(tag, QName):
   6.105                      add_qname(tag)
   6.106 -                elif isinstance(tag, basestring):
   6.107 +                elif isinstance(tag, six.string_types):
   6.108                      add_qname(QName(tag))
   6.109                  elif tag is not None:
   6.110                      self._raise_serialization_error(tag)
   6.111  
   6.112 -                for key in elem.attrib.iterkeys():
   6.113 +                for key in six.iterkeys(elem.attrib):
   6.114                      if isinstance(key, QName):
   6.115                          add_qname(key)
   6.116 -                    elif isinstance(key, basestring):
   6.117 +                    elif isinstance(key, six.string_types):
   6.118                          add_qname(QName(key))
   6.119                      elif key is not None:
   6.120                          self._raise_serialization_error(key)
   6.121 @@ -1279,15 +1281,14 @@
   6.122          """create a attribute string from a dict d"""
   6.123          if not d:
   6.124              return u''
   6.125 -        items = d.items()
   6.126 -        items.sort(key=lambda x: x[0])
   6.127 +        items = sorted(d.items(), key=lambda x: x[0])
   6.128          result = []
   6.129          for k, v in items:
   6.130              k = qnames[k]
   6.131              if isinstance(v, QName):
   6.132                  v = qnames[v]
   6.133              else:
   6.134 -                v = self._escape_attrib(unicode(v))
   6.135 +                v = self._escape_attrib(six.text_type(v))
   6.136              # FIXME: handle boolean attributes for HTML
   6.137              result.append(u' %s="%s"' % (k, v))
   6.138          return u''.join(result)
   6.139 @@ -1296,8 +1297,7 @@
   6.140          """create a namespace string from a dict d"""
   6.141          if not d:
   6.142              return u''
   6.143 -        items = d.items()
   6.144 -        items.sort(key=lambda x: x[1]) # sort on prefix
   6.145 +        items = sorted(d.items(), key=lambda x: x[1]) # sort on prefix
   6.146          result = []
   6.147          for v, k in items:
   6.148              if k:
   6.149 @@ -1318,7 +1318,7 @@
   6.150          write(u"<?%s?>" % text)
   6.151  
   6.152      def _serialize_cdata(self, write, elem):
   6.153 -        write(self._escape_cdata(unicode(elem)))
   6.154 +        write(self._escape_cdata(six.text_type(elem)))
   6.155  
   6.156      def serialize(self, write, elem, qnames, namespaces={}):
   6.157          if isinstance(elem, Element):